mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-09-19 01:29:57 +00:00
961c878e0d
Switch to using Go modules. This migrates our vendor.json to use Go 1.11's modules system, and replaces the vendor folder with the output of go mod vendor. The vendored code should remain basically the same; I believe some tree shaking of packages and support scripts/licenses/READMEs/etc. happened. This also fixes Travis and our Makefile to no longer use govendor.
325 lines
5.8 KiB
Go
325 lines
5.8 KiB
Go
package ini
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
runesTrue = []rune("true")
|
|
runesFalse = []rune("false")
|
|
)
|
|
|
|
var literalValues = [][]rune{
|
|
runesTrue,
|
|
runesFalse,
|
|
}
|
|
|
|
func isBoolValue(b []rune) bool {
|
|
for _, lv := range literalValues {
|
|
if isLitValue(lv, b) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isLitValue(want, have []rune) bool {
|
|
if len(have) < len(want) {
|
|
return false
|
|
}
|
|
|
|
for i := 0; i < len(want); i++ {
|
|
if want[i] != have[i] {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// isNumberValue will return whether not the leading characters in
|
|
// a byte slice is a number. A number is delimited by whitespace or
|
|
// the newline token.
|
|
//
|
|
// A number is defined to be in a binary, octal, decimal (int | float), hex format,
|
|
// or in scientific notation.
|
|
func isNumberValue(b []rune) bool {
|
|
negativeIndex := 0
|
|
helper := numberHelper{}
|
|
needDigit := false
|
|
|
|
for i := 0; i < len(b); i++ {
|
|
negativeIndex++
|
|
|
|
switch b[i] {
|
|
case '-':
|
|
if helper.IsNegative() || negativeIndex != 1 {
|
|
return false
|
|
}
|
|
helper.Determine(b[i])
|
|
needDigit = true
|
|
continue
|
|
case 'e', 'E':
|
|
if err := helper.Determine(b[i]); err != nil {
|
|
return false
|
|
}
|
|
negativeIndex = 0
|
|
needDigit = true
|
|
continue
|
|
case 'b':
|
|
if helper.numberFormat == hex {
|
|
break
|
|
}
|
|
fallthrough
|
|
case 'o', 'x':
|
|
needDigit = true
|
|
if i == 0 {
|
|
return false
|
|
}
|
|
|
|
fallthrough
|
|
case '.':
|
|
if err := helper.Determine(b[i]); err != nil {
|
|
return false
|
|
}
|
|
needDigit = true
|
|
continue
|
|
}
|
|
|
|
if i > 0 && (isNewline(b[i:]) || isWhitespace(b[i])) {
|
|
return !needDigit
|
|
}
|
|
|
|
if !helper.CorrectByte(b[i]) {
|
|
return false
|
|
}
|
|
needDigit = false
|
|
}
|
|
|
|
return !needDigit
|
|
}
|
|
|
|
func isValid(b []rune) (bool, int, error) {
|
|
if len(b) == 0 {
|
|
// TODO: should probably return an error
|
|
return false, 0, nil
|
|
}
|
|
|
|
return isValidRune(b[0]), 1, nil
|
|
}
|
|
|
|
func isValidRune(r rune) bool {
|
|
return r != ':' && r != '=' && r != '[' && r != ']' && r != ' ' && r != '\n'
|
|
}
|
|
|
|
// ValueType is an enum that will signify what type
|
|
// the Value is
|
|
type ValueType int
|
|
|
|
func (v ValueType) String() string {
|
|
switch v {
|
|
case NoneType:
|
|
return "NONE"
|
|
case DecimalType:
|
|
return "FLOAT"
|
|
case IntegerType:
|
|
return "INT"
|
|
case StringType:
|
|
return "STRING"
|
|
case BoolType:
|
|
return "BOOL"
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// ValueType enums
|
|
const (
|
|
NoneType = ValueType(iota)
|
|
DecimalType
|
|
IntegerType
|
|
StringType
|
|
QuotedStringType
|
|
BoolType
|
|
)
|
|
|
|
// Value is a union container
|
|
type Value struct {
|
|
Type ValueType
|
|
raw []rune
|
|
|
|
integer int64
|
|
decimal float64
|
|
boolean bool
|
|
str string
|
|
}
|
|
|
|
func newValue(t ValueType, base int, raw []rune) (Value, error) {
|
|
v := Value{
|
|
Type: t,
|
|
raw: raw,
|
|
}
|
|
var err error
|
|
|
|
switch t {
|
|
case DecimalType:
|
|
v.decimal, err = strconv.ParseFloat(string(raw), 64)
|
|
case IntegerType:
|
|
if base != 10 {
|
|
raw = raw[2:]
|
|
}
|
|
|
|
v.integer, err = strconv.ParseInt(string(raw), base, 64)
|
|
case StringType:
|
|
v.str = string(raw)
|
|
case QuotedStringType:
|
|
v.str = string(raw[1 : len(raw)-1])
|
|
case BoolType:
|
|
v.boolean = runeCompare(v.raw, runesTrue)
|
|
}
|
|
|
|
// issue 2253
|
|
//
|
|
// if the value trying to be parsed is too large, then we will use
|
|
// the 'StringType' and raw value instead.
|
|
if nerr, ok := err.(*strconv.NumError); ok && nerr.Err == strconv.ErrRange {
|
|
v.Type = StringType
|
|
v.str = string(raw)
|
|
err = nil
|
|
}
|
|
|
|
return v, err
|
|
}
|
|
|
|
// Append will append values and change the type to a string
|
|
// type.
|
|
func (v *Value) Append(tok Token) {
|
|
r := tok.Raw()
|
|
if v.Type != QuotedStringType {
|
|
v.Type = StringType
|
|
r = tok.raw[1 : len(tok.raw)-1]
|
|
}
|
|
if tok.Type() != TokenLit {
|
|
v.raw = append(v.raw, tok.Raw()...)
|
|
} else {
|
|
v.raw = append(v.raw, r...)
|
|
}
|
|
}
|
|
|
|
func (v Value) String() string {
|
|
switch v.Type {
|
|
case DecimalType:
|
|
return fmt.Sprintf("decimal: %f", v.decimal)
|
|
case IntegerType:
|
|
return fmt.Sprintf("integer: %d", v.integer)
|
|
case StringType:
|
|
return fmt.Sprintf("string: %s", string(v.raw))
|
|
case QuotedStringType:
|
|
return fmt.Sprintf("quoted string: %s", string(v.raw))
|
|
case BoolType:
|
|
return fmt.Sprintf("bool: %t", v.boolean)
|
|
default:
|
|
return "union not set"
|
|
}
|
|
}
|
|
|
|
func newLitToken(b []rune) (Token, int, error) {
|
|
n := 0
|
|
var err error
|
|
|
|
token := Token{}
|
|
if b[0] == '"' {
|
|
n, err = getStringValue(b)
|
|
if err != nil {
|
|
return token, n, err
|
|
}
|
|
|
|
token = newToken(TokenLit, b[:n], QuotedStringType)
|
|
} else if isNumberValue(b) {
|
|
var base int
|
|
base, n, err = getNumericalValue(b)
|
|
if err != nil {
|
|
return token, 0, err
|
|
}
|
|
|
|
value := b[:n]
|
|
vType := IntegerType
|
|
if contains(value, '.') || hasExponent(value) {
|
|
vType = DecimalType
|
|
}
|
|
token = newToken(TokenLit, value, vType)
|
|
token.base = base
|
|
} else if isBoolValue(b) {
|
|
n, err = getBoolValue(b)
|
|
|
|
token = newToken(TokenLit, b[:n], BoolType)
|
|
} else {
|
|
n, err = getValue(b)
|
|
token = newToken(TokenLit, b[:n], StringType)
|
|
}
|
|
|
|
return token, n, err
|
|
}
|
|
|
|
// IntValue returns an integer value
|
|
func (v Value) IntValue() int64 {
|
|
return v.integer
|
|
}
|
|
|
|
// FloatValue returns a float value
|
|
func (v Value) FloatValue() float64 {
|
|
return v.decimal
|
|
}
|
|
|
|
// BoolValue returns a bool value
|
|
func (v Value) BoolValue() bool {
|
|
return v.boolean
|
|
}
|
|
|
|
func isTrimmable(r rune) bool {
|
|
switch r {
|
|
case '\n', ' ':
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// StringValue returns the string value
|
|
func (v Value) StringValue() string {
|
|
switch v.Type {
|
|
case StringType:
|
|
return strings.TrimFunc(string(v.raw), isTrimmable)
|
|
case QuotedStringType:
|
|
// preserve all characters in the quotes
|
|
return string(removeEscapedCharacters(v.raw[1 : len(v.raw)-1]))
|
|
default:
|
|
return strings.TrimFunc(string(v.raw), isTrimmable)
|
|
}
|
|
}
|
|
|
|
func contains(runes []rune, c rune) bool {
|
|
for i := 0; i < len(runes); i++ {
|
|
if runes[i] == c {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func runeCompare(v1 []rune, v2 []rune) bool {
|
|
if len(v1) != len(v2) {
|
|
return false
|
|
}
|
|
|
|
for i := 0; i < len(v1); i++ {
|
|
if v1[i] != v2[i] {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|