cmd/go: check for another GCC error message
[official-gcc.git] / libgo / go / cmd / go / internal / str / str.go
blob0413ed8e69e19992effa8e68a7ff57e2222cc2fd
1 // Copyright 2017 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package str provides string manipulation utilities.
6 package str
8 import (
9 "bytes"
10 "fmt"
11 "unicode"
12 "unicode/utf8"
15 // StringList flattens its arguments into a single []string.
16 // Each argument in args must have type string or []string.
17 func StringList(args ...interface{}) []string {
18 var x []string
19 for _, arg := range args {
20 switch arg := arg.(type) {
21 case []string:
22 x = append(x, arg...)
23 case string:
24 x = append(x, arg)
25 default:
26 panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg))
29 return x
32 // ToFold returns a string with the property that
33 // strings.EqualFold(s, t) iff ToFold(s) == ToFold(t)
34 // This lets us test a large set of strings for fold-equivalent
35 // duplicates without making a quadratic number of calls
36 // to EqualFold. Note that strings.ToUpper and strings.ToLower
37 // do not have the desired property in some corner cases.
38 func ToFold(s string) string {
39 // Fast path: all ASCII, no upper case.
40 // Most paths look like this already.
41 for i := 0; i < len(s); i++ {
42 c := s[i]
43 if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' {
44 goto Slow
47 return s
49 Slow:
50 var buf bytes.Buffer
51 for _, r := range s {
52 // SimpleFold(x) cycles to the next equivalent rune > x
53 // or wraps around to smaller values. Iterate until it wraps,
54 // and we've found the minimum value.
55 for {
56 r0 := r
57 r = unicode.SimpleFold(r0)
58 if r <= r0 {
59 break
62 // Exception to allow fast path above: A-Z => a-z
63 if 'A' <= r && r <= 'Z' {
64 r += 'a' - 'A'
66 buf.WriteRune(r)
68 return buf.String()
71 // FoldDup reports a pair of strings from the list that are
72 // equal according to strings.EqualFold.
73 // It returns "", "" if there are no such strings.
74 func FoldDup(list []string) (string, string) {
75 clash := map[string]string{}
76 for _, s := range list {
77 fold := ToFold(s)
78 if t := clash[fold]; t != "" {
79 if s > t {
80 s, t = t, s
82 return s, t
84 clash[fold] = s
86 return "", ""
89 // Contains reports whether x contains s.
90 func Contains(x []string, s string) bool {
91 for _, t := range x {
92 if t == s {
93 return true
96 return false
99 func isSpaceByte(c byte) bool {
100 return c == ' ' || c == '\t' || c == '\n' || c == '\r'
103 // SplitQuotedFields splits s into a list of fields,
104 // allowing single or double quotes around elements.
105 // There is no unescaping or other processing within
106 // quoted fields.
107 func SplitQuotedFields(s string) ([]string, error) {
108 // Split fields allowing '' or "" around elements.
109 // Quotes further inside the string do not count.
110 var f []string
111 for len(s) > 0 {
112 for len(s) > 0 && isSpaceByte(s[0]) {
113 s = s[1:]
115 if len(s) == 0 {
116 break
118 // Accepted quoted string. No unescaping inside.
119 if s[0] == '"' || s[0] == '\'' {
120 quote := s[0]
121 s = s[1:]
122 i := 0
123 for i < len(s) && s[i] != quote {
126 if i >= len(s) {
127 return nil, fmt.Errorf("unterminated %c string", quote)
129 f = append(f, s[:i])
130 s = s[i+1:]
131 continue
133 i := 0
134 for i < len(s) && !isSpaceByte(s[i]) {
137 f = append(f, s[:i])
138 s = s[i:]
140 return f, nil