10 runesTrue = []rune("true")
11 runesFalse = []rune("false")
14 var literalValues = [][]rune{
19 func isBoolValue(b []rune) bool {
20 for _, lv := range literalValues {
21 if isLitValue(lv, b) {
28 func isLitValue(want, have []rune) bool {
29 if len(have) < len(want) {
33 for i := 0; i < len(want); i++ {
34 if want[i] != have[i] {
42 // isNumberValue will return whether not the leading characters in
43 // a byte slice is a number. A number is delimited by whitespace or
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 {
50 helper := numberHelper{}
53 for i := 0; i < len(b); i++ {
58 if helper.IsNegative() || negativeIndex != 1 {
61 helper.Determine(b[i])
65 if err := helper.Determine(b[i]); err != nil {
72 if helper.numberFormat == hex {
84 if err := helper.Determine(b[i]); err != nil {
91 if i > 0 && (isNewline(b[i:]) || isWhitespace(b[i])) {
95 if !helper.CorrectByte(b[i]) {
104 func isValid(b []rune) (bool, int, error) {
106 // TODO: should probably return an error
110 return isValidRune(b[0]), 1, nil
113 func isValidRune(r rune) bool {
114 return r != ':' && r != '=' && r != '[' && r != ']' && r != ' ' && r != '\n'
117 // ValueType is an enum that will signify what type
121 func (v ValueType) String() string {
140 NoneType = ValueType(iota)
148 // Value is a union container
159 func newValue(t ValueType, base int, raw []rune) (Value, error) {
168 v.decimal, err = strconv.ParseFloat(string(raw), 64)
174 v.integer, err = strconv.ParseInt(string(raw), base, 64)
177 case QuotedStringType:
178 v.str = string(raw[1 : len(raw)-1])
180 v.boolean = runeCompare(v.raw, runesTrue)
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 {
196 // Append will append values and change the type to a string
198 func (v *Value) Append(tok Token) {
200 if v.Type != QuotedStringType {
202 r = tok.raw[1 : len(tok.raw)-1]
204 if tok.Type() != TokenLit {
205 v.raw = append(v.raw, tok.Raw()...)
207 v.raw = append(v.raw, r...)
211 func (v Value) String() string {
214 return fmt.Sprintf("decimal: %f", v.decimal)
216 return fmt.Sprintf("integer: %d", v.integer)
218 return fmt.Sprintf("string: %s", string(v.raw))
219 case QuotedStringType:
220 return fmt.Sprintf("quoted string: %s", string(v.raw))
222 return fmt.Sprintf("bool: %t", v.boolean)
224 return "union not set"
228 func newLitToken(b []rune) (Token, int, error) {
234 n, err = getStringValue(b)
239 token = newToken(TokenLit, b[:n], QuotedStringType)
240 } else if isNumberValue(b) {
242 base, n, err = getNumericalValue(b)
249 if contains(value, '.') || hasExponent(value) {
252 token = newToken(TokenLit, value, vType)
254 } else if isBoolValue(b) {
255 n, err = getBoolValue(b)
257 token = newToken(TokenLit, b[:n], BoolType)
260 token = newToken(TokenLit, b[:n], StringType)
266 // IntValue returns an integer value
267 func (v Value) IntValue() int64 {
271 // FloatValue returns a float value
272 func (v Value) FloatValue() float64 {
276 // BoolValue returns a bool value
277 func (v Value) BoolValue() bool {
281 func isTrimmable(r rune) bool {
289 // StringValue returns the string value
290 func (v Value) StringValue() string {
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]))
298 return strings.TrimFunc(string(v.raw), isTrimmable)
302 func contains(runes []rune, c rune) bool {
303 for i := 0; i < len(runes); i++ {
312 func runeCompare(v1 []rune, v2 []rune) bool {
313 if len(v1) != len(v2) {
317 for i := 0; i < len(v1); i++ {