OSDN Git Service

fix commands
[bytom/shuttle.git] / vendor / github.com / bytom / vendor / github.com / hashicorp / hcl / hcl / strconv / quote.go
diff --git a/vendor/github.com/bytom/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go b/vendor/github.com/bytom/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go
new file mode 100644 (file)
index 0000000..5f981ea
--- /dev/null
@@ -0,0 +1,241 @@
+package strconv
+
+import (
+       "errors"
+       "unicode/utf8"
+)
+
+// ErrSyntax indicates that a value does not have the right syntax for the target type.
+var ErrSyntax = errors.New("invalid syntax")
+
+// Unquote interprets s as a single-quoted, double-quoted,
+// or backquoted Go string literal, returning the string value
+// that s quotes.  (If s is single-quoted, it would be a Go
+// character literal; Unquote returns the corresponding
+// one-character string.)
+func Unquote(s string) (t string, err error) {
+       n := len(s)
+       if n < 2 {
+               return "", ErrSyntax
+       }
+       quote := s[0]
+       if quote != s[n-1] {
+               return "", ErrSyntax
+       }
+       s = s[1 : n-1]
+
+       if quote != '"' {
+               return "", ErrSyntax
+       }
+       if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') {
+               return "", ErrSyntax
+       }
+
+       // Is it trivial?  Avoid allocation.
+       if !contains(s, '\\') && !contains(s, quote) && !contains(s, '$') {
+               switch quote {
+               case '"':
+                       return s, nil
+               case '\'':
+                       r, size := utf8.DecodeRuneInString(s)
+                       if size == len(s) && (r != utf8.RuneError || size != 1) {
+                               return s, nil
+                       }
+               }
+       }
+
+       var runeTmp [utf8.UTFMax]byte
+       buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.
+       for len(s) > 0 {
+               // If we're starting a '${}' then let it through un-unquoted.
+               // Specifically: we don't unquote any characters within the `${}`
+               // section.
+               if s[0] == '$' && len(s) > 1 && s[1] == '{' {
+                       buf = append(buf, '$', '{')
+                       s = s[2:]
+
+                       // Continue reading until we find the closing brace, copying as-is
+                       braces := 1
+                       for len(s) > 0 && braces > 0 {
+                               r, size := utf8.DecodeRuneInString(s)
+                               if r == utf8.RuneError {
+                                       return "", ErrSyntax
+                               }
+
+                               s = s[size:]
+
+                               n := utf8.EncodeRune(runeTmp[:], r)
+                               buf = append(buf, runeTmp[:n]...)
+
+                               switch r {
+                               case '{':
+                                       braces++
+                               case '}':
+                                       braces--
+                               }
+                       }
+                       if braces != 0 {
+                               return "", ErrSyntax
+                       }
+                       if len(s) == 0 {
+                               // If there's no string left, we're done!
+                               break
+                       } else {
+                               // If there's more left, we need to pop back up to the top of the loop
+                               // in case there's another interpolation in this string.
+                               continue
+                       }
+               }
+
+               if s[0] == '\n' {
+                       return "", ErrSyntax
+               }
+
+               c, multibyte, ss, err := unquoteChar(s, quote)
+               if err != nil {
+                       return "", err
+               }
+               s = ss
+               if c < utf8.RuneSelf || !multibyte {
+                       buf = append(buf, byte(c))
+               } else {
+                       n := utf8.EncodeRune(runeTmp[:], c)
+                       buf = append(buf, runeTmp[:n]...)
+               }
+               if quote == '\'' && len(s) != 0 {
+                       // single-quoted must be single character
+                       return "", ErrSyntax
+               }
+       }
+       return string(buf), nil
+}
+
+// contains reports whether the string contains the byte c.
+func contains(s string, c byte) bool {
+       for i := 0; i < len(s); i++ {
+               if s[i] == c {
+                       return true
+               }
+       }
+       return false
+}
+
+func unhex(b byte) (v rune, ok bool) {
+       c := rune(b)
+       switch {
+       case '0' <= c && c <= '9':
+               return c - '0', true
+       case 'a' <= c && c <= 'f':
+               return c - 'a' + 10, true
+       case 'A' <= c && c <= 'F':
+               return c - 'A' + 10, true
+       }
+       return
+}
+
+func unquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) {
+       // easy cases
+       switch c := s[0]; {
+       case c == quote && (quote == '\'' || quote == '"'):
+               err = ErrSyntax
+               return
+       case c >= utf8.RuneSelf:
+               r, size := utf8.DecodeRuneInString(s)
+               return r, true, s[size:], nil
+       case c != '\\':
+               return rune(s[0]), false, s[1:], nil
+       }
+
+       // hard case: c is backslash
+       if len(s) <= 1 {
+               err = ErrSyntax
+               return
+       }
+       c := s[1]
+       s = s[2:]
+
+       switch c {
+       case 'a':
+               value = '\a'
+       case 'b':
+               value = '\b'
+       case 'f':
+               value = '\f'
+       case 'n':
+               value = '\n'
+       case 'r':
+               value = '\r'
+       case 't':
+               value = '\t'
+       case 'v':
+               value = '\v'
+       case 'x', 'u', 'U':
+               n := 0
+               switch c {
+               case 'x':
+                       n = 2
+               case 'u':
+                       n = 4
+               case 'U':
+                       n = 8
+               }
+               var v rune
+               if len(s) < n {
+                       err = ErrSyntax
+                       return
+               }
+               for j := 0; j < n; j++ {
+                       x, ok := unhex(s[j])
+                       if !ok {
+                               err = ErrSyntax
+                               return
+                       }
+                       v = v<<4 | x
+               }
+               s = s[n:]
+               if c == 'x' {
+                       // single-byte string, possibly not UTF-8
+                       value = v
+                       break
+               }
+               if v > utf8.MaxRune {
+                       err = ErrSyntax
+                       return
+               }
+               value = v
+               multibyte = true
+       case '0', '1', '2', '3', '4', '5', '6', '7':
+               v := rune(c) - '0'
+               if len(s) < 2 {
+                       err = ErrSyntax
+                       return
+               }
+               for j := 0; j < 2; j++ { // one digit already; two more
+                       x := rune(s[j]) - '0'
+                       if x < 0 || x > 7 {
+                               err = ErrSyntax
+                               return
+                       }
+                       v = (v << 3) | x
+               }
+               s = s[2:]
+               if v > 255 {
+                       err = ErrSyntax
+                       return
+               }
+               value = v
+       case '\\':
+               value = '\\'
+       case '\'', '"':
+               if c != quote {
+                       err = ErrSyntax
+                       return
+               }
+               value = rune(c)
+       default:
+               err = ErrSyntax
+               return
+       }
+       tail = s
+       return
+}