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  }