github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/androidmk/parser/make_strings.go (about) 1 // Copyright 2017 Google Inc. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package parser 16 17 import ( 18 "strings" 19 "unicode" 20 ) 21 22 // A MakeString is a string that may contain variable substitutions in it. 23 // It can be considered as an alternating list of raw Strings and variable 24 // substitutions, where the first and last entries in the list must be raw 25 // Strings (possibly empty). A MakeString that starts with a variable 26 // will have an empty first raw string, and a MakeString that ends with a 27 // variable will have an empty last raw string. Two sequential Variables 28 // will have an empty raw string between them. 29 // 30 // The MakeString is stored as two lists, a list of raw Strings and a list 31 // of Variables. The raw string list is always one longer than the variable 32 // list. 33 type MakeString struct { 34 StringPos Pos 35 Strings []string 36 Variables []Variable 37 } 38 39 func SimpleMakeString(s string, pos Pos) *MakeString { 40 return &MakeString{ 41 StringPos: pos, 42 Strings: []string{s}, 43 } 44 } 45 46 func (ms *MakeString) Clone() (result *MakeString) { 47 clone := *ms 48 return &clone 49 } 50 51 func (ms *MakeString) Pos() Pos { 52 return ms.StringPos 53 } 54 55 func (ms *MakeString) End() Pos { 56 pos := ms.StringPos 57 if len(ms.Strings) > 1 { 58 pos = ms.Variables[len(ms.Variables)-1].End() 59 } 60 return Pos(int(pos) + len(ms.Strings[len(ms.Strings)-1])) 61 } 62 63 func (ms *MakeString) appendString(s string) { 64 if len(ms.Strings) == 0 { 65 ms.Strings = []string{s} 66 return 67 } else { 68 ms.Strings[len(ms.Strings)-1] += s 69 } 70 } 71 72 func (ms *MakeString) appendVariable(v Variable) { 73 if len(ms.Strings) == 0 { 74 ms.Strings = []string{"", ""} 75 ms.Variables = []Variable{v} 76 } else { 77 ms.Strings = append(ms.Strings, "") 78 ms.Variables = append(ms.Variables, v) 79 } 80 } 81 82 func (ms *MakeString) appendMakeString(other *MakeString) { 83 last := len(ms.Strings) - 1 84 ms.Strings[last] += other.Strings[0] 85 ms.Strings = append(ms.Strings, other.Strings[1:]...) 86 ms.Variables = append(ms.Variables, other.Variables...) 87 } 88 89 func (ms *MakeString) Value(scope Scope) string { 90 if len(ms.Strings) == 0 { 91 return "" 92 } else { 93 ret := ms.Strings[0] 94 for i := range ms.Strings[1:] { 95 ret += ms.Variables[i].Value(scope) 96 ret += ms.Strings[i+1] 97 } 98 return ret 99 } 100 } 101 102 func (ms *MakeString) Dump() string { 103 if len(ms.Strings) == 0 { 104 return "" 105 } else { 106 ret := ms.Strings[0] 107 for i := range ms.Strings[1:] { 108 ret += ms.Variables[i].Dump() 109 ret += ms.Strings[i+1] 110 } 111 return ret 112 } 113 } 114 115 func (ms *MakeString) Const() bool { 116 return len(ms.Strings) <= 1 117 } 118 119 func (ms *MakeString) Empty() bool { 120 return len(ms.Strings) == 0 || (len(ms.Strings) == 1 && ms.Strings[0] == "") 121 } 122 123 func (ms *MakeString) Split(sep string) []*MakeString { 124 return ms.SplitN(sep, -1) 125 } 126 127 func (ms *MakeString) SplitN(sep string, n int) []*MakeString { 128 ret := []*MakeString{} 129 130 curMs := SimpleMakeString("", ms.Pos()) 131 132 var i int 133 var s string 134 for i, s = range ms.Strings { 135 if n != 0 { 136 split := splitAnyN(s, sep, n) 137 if n != -1 { 138 if len(split) > n { 139 panic("oops!") 140 } else { 141 n -= len(split) 142 } 143 } 144 curMs.appendString(split[0]) 145 146 for _, r := range split[1:] { 147 ret = append(ret, curMs) 148 curMs = SimpleMakeString(r, ms.Pos()) 149 } 150 } else { 151 curMs.appendString(s) 152 } 153 154 if i < len(ms.Strings)-1 { 155 curMs.appendVariable(ms.Variables[i]) 156 } 157 } 158 159 ret = append(ret, curMs) 160 return ret 161 } 162 163 func (ms *MakeString) TrimLeftSpaces() { 164 l := len(ms.Strings[0]) 165 ms.Strings[0] = strings.TrimLeftFunc(ms.Strings[0], unicode.IsSpace) 166 ms.StringPos += Pos(len(ms.Strings[0]) - l) 167 } 168 169 func (ms *MakeString) TrimRightSpaces() { 170 last := len(ms.Strings) - 1 171 ms.Strings[last] = strings.TrimRightFunc(ms.Strings[last], unicode.IsSpace) 172 } 173 174 func (ms *MakeString) TrimRightOne() { 175 last := len(ms.Strings) - 1 176 if len(ms.Strings[last]) > 1 { 177 ms.Strings[last] = ms.Strings[last][0 : len(ms.Strings[last])-1] 178 } 179 } 180 181 func (ms *MakeString) EndsWith(ch rune) bool { 182 s := ms.Strings[len(ms.Strings)-1] 183 return s[len(s)-1] == uint8(ch) 184 } 185 186 func (ms *MakeString) ReplaceLiteral(input string, output string) { 187 for i := range ms.Strings { 188 ms.Strings[i] = strings.Replace(ms.Strings[i], input, output, -1) 189 } 190 } 191 192 func splitAnyN(s, sep string, n int) []string { 193 ret := []string{} 194 for n == -1 || n > 1 { 195 index := strings.IndexAny(s, sep) 196 if index >= 0 { 197 ret = append(ret, s[0:index]) 198 s = s[index+1:] 199 if n > 0 { 200 n-- 201 } 202 } else { 203 break 204 } 205 } 206 ret = append(ret, s) 207 return ret 208 }