github.com/aavshr/aws-sdk-go@v1.41.3/internal/ini/literal_tokens.go (about)

     1  package ini
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  )
     8  
     9  var (
    10  	runesTrue  = []rune("true")
    11  	runesFalse = []rune("false")
    12  )
    13  
    14  var literalValues = [][]rune{
    15  	runesTrue,
    16  	runesFalse,
    17  }
    18  
    19  func isBoolValue(b []rune) bool {
    20  	for _, lv := range literalValues {
    21  		if isLitValue(lv, b) {
    22  			return true
    23  		}
    24  	}
    25  	return false
    26  }
    27  
    28  func isLitValue(want, have []rune) bool {
    29  	if len(have) < len(want) {
    30  		return false
    31  	}
    32  
    33  	for i := 0; i < len(want); i++ {
    34  		if want[i] != have[i] {
    35  			return false
    36  		}
    37  	}
    38  
    39  	return true
    40  }
    41  
    42  // isNumberValue will return whether not the leading characters in
    43  // a byte slice is a number. A number is delimited by whitespace or
    44  // the newline token.
    45  //
    46  // A number is defined to be in a binary, octal, decimal (int | float), hex format,
    47  // or in scientific notation.
    48  func isNumberValue(b []rune) bool {
    49  	negativeIndex := 0
    50  	helper := numberHelper{}
    51  	needDigit := false
    52  
    53  	for i := 0; i < len(b); i++ {
    54  		negativeIndex++
    55  
    56  		switch b[i] {
    57  		case '-':
    58  			if helper.IsNegative() || negativeIndex != 1 {
    59  				return false
    60  			}
    61  			helper.Determine(b[i])
    62  			needDigit = true
    63  			continue
    64  		case 'e', 'E':
    65  			if err := helper.Determine(b[i]); err != nil {
    66  				return false
    67  			}
    68  			negativeIndex = 0
    69  			needDigit = true
    70  			continue
    71  		case 'b':
    72  			if helper.numberFormat == hex {
    73  				break
    74  			}
    75  			fallthrough
    76  		case 'o', 'x':
    77  			needDigit = true
    78  			if i == 0 {
    79  				return false
    80  			}
    81  
    82  			fallthrough
    83  		case '.':
    84  			if err := helper.Determine(b[i]); err != nil {
    85  				return false
    86  			}
    87  			needDigit = true
    88  			continue
    89  		}
    90  
    91  		if i > 0 && (isNewline(b[i:]) || isWhitespace(b[i])) {
    92  			return !needDigit
    93  		}
    94  
    95  		if !helper.CorrectByte(b[i]) {
    96  			return false
    97  		}
    98  		needDigit = false
    99  	}
   100  
   101  	return !needDigit
   102  }
   103  
   104  func isValid(b []rune) (bool, int, error) {
   105  	if len(b) == 0 {
   106  		// TODO: should probably return an error
   107  		return false, 0, nil
   108  	}
   109  
   110  	return isValidRune(b[0]), 1, nil
   111  }
   112  
   113  func isValidRune(r rune) bool {
   114  	return r != ':' && r != '=' && r != '[' && r != ']' && r != ' ' && r != '\n'
   115  }
   116  
   117  // ValueType is an enum that will signify what type
   118  // the Value is
   119  type ValueType int
   120  
   121  func (v ValueType) String() string {
   122  	switch v {
   123  	case NoneType:
   124  		return "NONE"
   125  	case DecimalType:
   126  		return "FLOAT"
   127  	case IntegerType:
   128  		return "INT"
   129  	case StringType:
   130  		return "STRING"
   131  	case BoolType:
   132  		return "BOOL"
   133  	}
   134  
   135  	return ""
   136  }
   137  
   138  // ValueType enums
   139  const (
   140  	NoneType = ValueType(iota)
   141  	DecimalType
   142  	IntegerType
   143  	StringType
   144  	QuotedStringType
   145  	BoolType
   146  )
   147  
   148  // Value is a union container
   149  type Value struct {
   150  	Type ValueType
   151  	raw  []rune
   152  
   153  	integer int64
   154  	decimal float64
   155  	boolean bool
   156  	str     string
   157  }
   158  
   159  func newValue(t ValueType, base int, raw []rune) (Value, error) {
   160  	v := Value{
   161  		Type: t,
   162  		raw:  raw,
   163  	}
   164  	var err error
   165  
   166  	switch t {
   167  	case DecimalType:
   168  		v.decimal, err = strconv.ParseFloat(string(raw), 64)
   169  	case IntegerType:
   170  		if base != 10 {
   171  			raw = raw[2:]
   172  		}
   173  
   174  		v.integer, err = strconv.ParseInt(string(raw), base, 64)
   175  	case StringType:
   176  		v.str = string(raw)
   177  	case QuotedStringType:
   178  		v.str = string(raw[1 : len(raw)-1])
   179  	case BoolType:
   180  		v.boolean = runeCompare(v.raw, runesTrue)
   181  	}
   182  
   183  	// issue 2253
   184  	//
   185  	// if the value trying to be parsed is too large, then we will use
   186  	// the 'StringType' and raw value instead.
   187  	if nerr, ok := err.(*strconv.NumError); ok && nerr.Err == strconv.ErrRange {
   188  		v.Type = StringType
   189  		v.str = string(raw)
   190  		err = nil
   191  	}
   192  
   193  	return v, err
   194  }
   195  
   196  // Append will append values and change the type to a string
   197  // type.
   198  func (v *Value) Append(tok Token) {
   199  	r := tok.Raw()
   200  	if v.Type != QuotedStringType {
   201  		v.Type = StringType
   202  		r = tok.raw[1 : len(tok.raw)-1]
   203  	}
   204  	if tok.Type() != TokenLit {
   205  		v.raw = append(v.raw, tok.Raw()...)
   206  	} else {
   207  		v.raw = append(v.raw, r...)
   208  	}
   209  }
   210  
   211  func (v Value) String() string {
   212  	switch v.Type {
   213  	case DecimalType:
   214  		return fmt.Sprintf("decimal: %f", v.decimal)
   215  	case IntegerType:
   216  		return fmt.Sprintf("integer: %d", v.integer)
   217  	case StringType:
   218  		return fmt.Sprintf("string: %s", string(v.raw))
   219  	case QuotedStringType:
   220  		return fmt.Sprintf("quoted string: %s", string(v.raw))
   221  	case BoolType:
   222  		return fmt.Sprintf("bool: %t", v.boolean)
   223  	default:
   224  		return "union not set"
   225  	}
   226  }
   227  
   228  func newLitToken(b []rune) (Token, int, error) {
   229  	n := 0
   230  	var err error
   231  
   232  	token := Token{}
   233  	if b[0] == '"' {
   234  		n, err = getStringValue(b)
   235  		if err != nil {
   236  			return token, n, err
   237  		}
   238  
   239  		token = newToken(TokenLit, b[:n], QuotedStringType)
   240  	} else if isNumberValue(b) {
   241  		var base int
   242  		base, n, err = getNumericalValue(b)
   243  		if err != nil {
   244  			return token, 0, err
   245  		}
   246  
   247  		value := b[:n]
   248  		vType := IntegerType
   249  		if contains(value, '.') || hasExponent(value) {
   250  			vType = DecimalType
   251  		}
   252  		token = newToken(TokenLit, value, vType)
   253  		token.base = base
   254  	} else if isBoolValue(b) {
   255  		n, err = getBoolValue(b)
   256  
   257  		token = newToken(TokenLit, b[:n], BoolType)
   258  	} else {
   259  		n, err = getValue(b)
   260  		token = newToken(TokenLit, b[:n], StringType)
   261  	}
   262  
   263  	return token, n, err
   264  }
   265  
   266  // IntValue returns an integer value
   267  func (v Value) IntValue() int64 {
   268  	return v.integer
   269  }
   270  
   271  // FloatValue returns a float value
   272  func (v Value) FloatValue() float64 {
   273  	return v.decimal
   274  }
   275  
   276  // BoolValue returns a bool value
   277  func (v Value) BoolValue() bool {
   278  	return v.boolean
   279  }
   280  
   281  func isTrimmable(r rune) bool {
   282  	switch r {
   283  	case '\n', ' ':
   284  		return true
   285  	}
   286  	return false
   287  }
   288  
   289  // StringValue returns the string value
   290  func (v Value) StringValue() string {
   291  	switch v.Type {
   292  	case StringType:
   293  		return strings.TrimFunc(string(v.raw), isTrimmable)
   294  	case QuotedStringType:
   295  		// preserve all characters in the quotes
   296  		return string(removeEscapedCharacters(v.raw[1 : len(v.raw)-1]))
   297  	default:
   298  		return strings.TrimFunc(string(v.raw), isTrimmable)
   299  	}
   300  }
   301  
   302  func contains(runes []rune, c rune) bool {
   303  	for i := 0; i < len(runes); i++ {
   304  		if runes[i] == c {
   305  			return true
   306  		}
   307  	}
   308  
   309  	return false
   310  }
   311  
   312  func runeCompare(v1 []rune, v2 []rune) bool {
   313  	if len(v1) != len(v2) {
   314  		return false
   315  	}
   316  
   317  	for i := 0; i < len(v1); i++ {
   318  		if v1[i] != v2[i] {
   319  			return false
   320  		}
   321  	}
   322  
   323  	return true
   324  }