Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  make_strings.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package parser

import (
 "fmt"
 "strings"
 "unicode"
 "unicode/utf8"
)

// A MakeString is a string that may contain variable substitutions in it.
// It can be considered as an alternating list of raw Strings and variable
// substitutions, where the first and last entries in the list must be raw
// Strings (possibly empty). The entirety of the text before the first variable,
// between two variables, and after the last variable will be considered a
// single String value. A MakeString that starts with a variable will have an
// empty first raw string, and a MakeString that ends with a  variable will have
// an empty last raw string.  Two sequential Variables will have an empty raw
// string between them.
//
// The MakeString is stored as two lists, a list of raw Strings and a list
// of Variables.  The raw string list is always one longer than the variable
// list.
//
// For example, "$(FOO)/bar/baz" will be represented as the
// following lists:
//
// {
//   Strings: ["", "/bar/baz"],
//   Variables: ["FOO"]
// }
type MakeString struct {
 StringPos Pos
 Strings   []string
 Variables []Variable
}

func SimpleMakeString(s string, pos Pos) *MakeString {
 return &MakeString{
  StringPos: pos,
  Strings:   []string{s},
 }
}

func (ms *MakeString) Clone() (result *MakeString) {
 clone := *ms
 return &clone
}

func (ms *MakeString) Pos() Pos {
 return ms.StringPos
}

func (ms *MakeString) End() Pos {
 pos := ms.StringPos
 if len(ms.Strings) > 1 {
  pos = ms.Variables[len(ms.Variables)-1].End()
 }
 return Pos(int(pos) + len(ms.Strings[len(ms.Strings)-1]))
}

func (ms *MakeString) appendString(s string) {
 if len(ms.Strings) == 0 {
  ms.Strings = []string{s}
  return
 } else {
  ms.Strings[len(ms.Strings)-1] += s
 }
}

func (ms *MakeString) appendVariable(v Variable) {
 if len(ms.Strings) == 0 {
  ms.Strings = []string{"", ""}
  ms.Variables = []Variable{v}
 } else {
  ms.Strings = append(ms.Strings, "")
  ms.Variables = append(ms.Variables, v)
 }
}

func (ms *MakeString) appendMakeString(other *MakeString) {
 last := len(ms.Strings) - 1
 ms.Strings[last] += other.Strings[0]
 ms.Strings = append(ms.Strings, other.Strings[1:]...)
 ms.Variables = append(ms.Variables, other.Variables...)
}

func (ms *MakeString) Value(scope Scope) string {
 if len(ms.Strings) == 0 {
  return ""
 } else {
  ret := unescape(ms.Strings[0])
  for i := range ms.Strings[1:] {
   ret += ms.Variables[i].Value(scope)
   ret += unescape(ms.Strings[i+1])
  }
  return ret
 }
}

func (ms *MakeString) Dump() string {
 if len(ms.Strings) == 0 {
  return ""
 } else {
  ret := ms.Strings[0]
  for i := range ms.Strings[1:] {
   ret += ms.Variables[i].Dump()
   ret += ms.Strings[i+1]
  }
  return ret
 }
}

func (ms *MakeString) Const() bool {
 return len(ms.Strings) <= 1
}

func (ms *MakeString) Empty() bool {
 return len(ms.Strings) == 0 || (len(ms.Strings) == 1 && ms.Strings[0] == "")
}

func (ms *MakeString) Split(sep string) []*MakeString {
 return ms.SplitN(sep, -1)
}

func (ms *MakeString) SplitN(sep string, n int) []*MakeString {
 return ms.splitNFunc(n, func(s string, n int) []string {
  return splitAnyN(s, sep, n)
 })
}

// Words splits MakeString into multiple makeStrings separated by whitespace.
// Thus, " a $(X)b  c " will be split into ["a", "$(X)b", "c"].
// Splitting a MakeString consisting solely of whitespace yields empty array.
func (ms *MakeString) Words() []*MakeString {
 var ch rune    // current character
 const EOF = -1 // no more characters
 const EOS = -2 // at the end of a string chunk

 // Next character's chunk and position
 iString := 0
 iChar := 0

 var words []*MakeString
 word := SimpleMakeString("", ms.Pos())

 nextChar := func() {
  if iString >= len(ms.Strings) {
   ch = EOF
  } else if iChar >= len(ms.Strings[iString]) {
   iString++
   iChar = 0
   ch = EOS
  } else {
   var w int
   ch, w = utf8.DecodeRuneInString(ms.Strings[iString][iChar:])
   iChar += w
  }
 }

 appendVariableAndAdvance := func() {
  if iString-1 < len(ms.Variables) {
   word.appendVariable(ms.Variables[iString-1])
  }
  nextChar()
 }

 appendCharAndAdvance := func(c rune) {
  if c != EOF {
   word.appendString(string(c))
  }
  nextChar()
 }

 nextChar()
 for ch != EOF {
  // Skip whitespace
  for ch == ' ' || ch == '\t' {
   nextChar()
  }
  if ch == EOS {
   // "... $(X)... " case. The current word should be empty.
   if !word.Empty() {
    panic(fmt.Errorf("%q: EOS while current word %q is not empty, iString=%d",
     ms.Dump(), word.Dump(), iString))
   }
   appendVariableAndAdvance()
  }
  // Copy word
  for ch != EOF {
   if ch == ' ' || ch == '\t' {
    words = append(words, word)
    word = SimpleMakeString("", ms.Pos())
    break
   }
   if ch == EOS {
    // "...a$(X)..." case. Append variable to the current word
    appendVariableAndAdvance()
   } else {
    if ch == '\\' {
     appendCharAndAdvance('\\')
    }
    appendCharAndAdvance(ch)
   }
  }
 }
 if !word.Empty() {
  words = append(words, word)
 }
 return words
}

func (ms *MakeString) splitNFunc(n int, splitFunc func(s string, n int) []string) []*MakeString {
 ret := []*MakeString{}

 curMs := SimpleMakeString("", ms.Pos())

 var i int
 var s string
 for i, s = range ms.Strings {
  if n != 0 {
   split := splitFunc(s, n)
   if n != -1 {
    if len(split) > n || len(split) == 0 {
     panic("oops!")
    } else {
     n -= len(split) - 1
    }
   }
   curMs.appendString(split[0])

   for _, r := range split[1:] {
    ret = append(ret, curMs)
    curMs = SimpleMakeString(r, ms.Pos())
   }
  } else {
   curMs.appendString(s)
  }

  if i < len(ms.Strings)-1 {
   curMs.appendVariable(ms.Variables[i])
  }
 }

 ret = append(ret, curMs)
 return ret
}

func (ms *MakeString) TrimLeftSpaces() {
 l := len(ms.Strings[0])
 ms.Strings[0] = strings.TrimLeftFunc(ms.Strings[0], unicode.IsSpace)
 ms.StringPos += Pos(len(ms.Strings[0]) - l)
}

func (ms *MakeString) TrimRightSpaces() {
 last := len(ms.Strings) - 1
 ms.Strings[last] = strings.TrimRightFunc(ms.Strings[last], unicode.IsSpace)
}

func (ms *MakeString) TrimRightOne() {
 last := len(ms.Strings) - 1
 if len(ms.Strings[last]) > 1 {
  ms.Strings[last] = ms.Strings[last][0 : len(ms.Strings[last])-1]
 }
}

func (ms *MakeString) EndsWith(ch rune) bool {
 s := ms.Strings[len(ms.Strings)-1]
 return len(s) > 0 && s[len(s)-1] == uint8(ch)
}

func (ms *MakeString) ReplaceLiteral(input string, output string) {
 for i := range ms.Strings {
  ms.Strings[i] = strings.Replace(ms.Strings[i], input, output, -1)
 }
}

// If MakeString is $(var) after trimming, returns var
func (ms *MakeString) SingleVariable() (*MakeString, bool) {
 if len(ms.Strings) != 2 || strings.TrimSpace(ms.Strings[0]) != "" ||
  strings.TrimSpace(ms.Strings[1]) != "" {
  return nil, false
 }
 return ms.Variables[0].Name, true
}

func splitAnyN(s, sep string, n int) []string {
 ret := []string{}
 for n == -1 || n > 1 {
  index := strings.IndexAny(s, sep)
  if index >= 0 {
   ret = append(ret, s[0:index])
   s = s[index+1:]
   if n > 0 {
    n--
   }
  } else {
   break
  }
 }
 ret = append(ret, s)
 return ret
}

func unescape(s string) string {
 ret := ""
 for {
  index := strings.IndexByte(s, '\\')
  if index < 0 {
   break
  }

  if index+1 == len(s) {
   break
  }

  switch s[index+1] {
  case ' ', '\\', '#', ':', '*', '[', '|', '\t', '\n', '\r':
   ret += s[:index] + s[index+1:index+2]
  default:
   ret += s[:index+2]
  }
  s = s[index+2:]
 }
 return ret + s
}

[Dauer der Verarbeitung: 0.20 Sekunden, vorverarbeitet 2026-06-28]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik