vendor/github.com/pelletier/go-toml/toml.go
changeset 256 6d9efbef00a9
parent 251 1c52a0eeb952
child 260 445e01aede7e
equal deleted inserted replaced
255:4f153a23adab 256:6d9efbef00a9
    13 type tomlValue struct {
    13 type tomlValue struct {
    14 	value     interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list
    14 	value     interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list
    15 	comment   string
    15 	comment   string
    16 	commented bool
    16 	commented bool
    17 	multiline bool
    17 	multiline bool
       
    18 	literal   bool
    18 	position  Position
    19 	position  Position
    19 }
    20 }
    20 
    21 
    21 // Tree is the result of the parsing of a TOML file.
    22 // Tree is the result of the parsing of a TOML file.
    22 type Tree struct {
    23 type Tree struct {
    23 	values    map[string]interface{} // string -> *tomlValue, *Tree, []*Tree
    24 	values    map[string]interface{} // string -> *tomlValue, *Tree, []*Tree
    24 	comment   string
    25 	comment   string
    25 	commented bool
    26 	commented bool
       
    27 	inline    bool
    26 	position  Position
    28 	position  Position
    27 }
    29 }
    28 
    30 
    29 func newTree() *Tree {
    31 func newTree() *Tree {
    30 	return newTreeWithPosition(Position{})
    32 	return newTreeWithPosition(Position{})
   119 	default:
   121 	default:
   120 		return node
   122 		return node
   121 	}
   123 	}
   122 }
   124 }
   123 
   125 
       
   126 // GetArray returns the value at key in the Tree.
       
   127 // It returns []string, []int64, etc type if key has homogeneous lists
       
   128 // Key is a dot-separated path (e.g. a.b.c) without single/double quoted strings.
       
   129 // Returns nil if the path does not exist in the tree.
       
   130 // If keys is of length zero, the current tree is returned.
       
   131 func (t *Tree) GetArray(key string) interface{} {
       
   132 	if key == "" {
       
   133 		return t
       
   134 	}
       
   135 	return t.GetArrayPath(strings.Split(key, "."))
       
   136 }
       
   137 
       
   138 // GetArrayPath returns the element in the tree indicated by 'keys'.
       
   139 // If keys is of length zero, the current tree is returned.
       
   140 func (t *Tree) GetArrayPath(keys []string) interface{} {
       
   141 	if len(keys) == 0 {
       
   142 		return t
       
   143 	}
       
   144 	subtree := t
       
   145 	for _, intermediateKey := range keys[:len(keys)-1] {
       
   146 		value, exists := subtree.values[intermediateKey]
       
   147 		if !exists {
       
   148 			return nil
       
   149 		}
       
   150 		switch node := value.(type) {
       
   151 		case *Tree:
       
   152 			subtree = node
       
   153 		case []*Tree:
       
   154 			// go to most recent element
       
   155 			if len(node) == 0 {
       
   156 				return nil
       
   157 			}
       
   158 			subtree = node[len(node)-1]
       
   159 		default:
       
   160 			return nil // cannot navigate through other node types
       
   161 		}
       
   162 	}
       
   163 	// branch based on final node type
       
   164 	switch node := subtree.values[keys[len(keys)-1]].(type) {
       
   165 	case *tomlValue:
       
   166 		switch n := node.value.(type) {
       
   167 		case []interface{}:
       
   168 			return getArray(n)
       
   169 		default:
       
   170 			return node.value
       
   171 		}
       
   172 	default:
       
   173 		return node
       
   174 	}
       
   175 }
       
   176 
       
   177 // if homogeneous array, then return slice type object over []interface{}
       
   178 func getArray(n []interface{}) interface{} {
       
   179 	var s []string
       
   180 	var i64 []int64
       
   181 	var f64 []float64
       
   182 	var bl []bool
       
   183 	for _, value := range n {
       
   184 		switch v := value.(type) {
       
   185 		case string:
       
   186 			s = append(s, v)
       
   187 		case int64:
       
   188 			i64 = append(i64, v)
       
   189 		case float64:
       
   190 			f64 = append(f64, v)
       
   191 		case bool:
       
   192 			bl = append(bl, v)
       
   193 		default:
       
   194 			return n
       
   195 		}
       
   196 	}
       
   197 	if len(s) == len(n) {
       
   198 		return s
       
   199 	} else if len(i64) == len(n) {
       
   200 		return i64
       
   201 	} else if len(f64) == len(n) {
       
   202 		return f64
       
   203 	} else if len(bl) == len(n) {
       
   204 		return bl
       
   205 	}
       
   206 	return n
       
   207 }
       
   208 
   124 // GetPosition returns the position of the given key.
   209 // GetPosition returns the position of the given key.
   125 func (t *Tree) GetPosition(key string) Position {
   210 func (t *Tree) GetPosition(key string) Position {
   126 	if key == "" {
   211 	if key == "" {
   127 		return t.position
   212 		return t.position
   128 	}
   213 	}
   129 	return t.GetPositionPath(strings.Split(key, "."))
   214 	return t.GetPositionPath(strings.Split(key, "."))
       
   215 }
       
   216 
       
   217 // SetPositionPath sets the position of element in the tree indicated by 'keys'.
       
   218 // If keys is of length zero, the current tree position is set.
       
   219 func (t *Tree) SetPositionPath(keys []string, pos Position) {
       
   220 	if len(keys) == 0 {
       
   221 		t.position = pos
       
   222 		return
       
   223 	}
       
   224 	subtree := t
       
   225 	for _, intermediateKey := range keys[:len(keys)-1] {
       
   226 		value, exists := subtree.values[intermediateKey]
       
   227 		if !exists {
       
   228 			return
       
   229 		}
       
   230 		switch node := value.(type) {
       
   231 		case *Tree:
       
   232 			subtree = node
       
   233 		case []*Tree:
       
   234 			// go to most recent element
       
   235 			if len(node) == 0 {
       
   236 				return
       
   237 			}
       
   238 			subtree = node[len(node)-1]
       
   239 		default:
       
   240 			return
       
   241 		}
       
   242 	}
       
   243 	// branch based on final node type
       
   244 	switch node := subtree.values[keys[len(keys)-1]].(type) {
       
   245 	case *tomlValue:
       
   246 		node.position = pos
       
   247 		return
       
   248 	case *Tree:
       
   249 		node.position = pos
       
   250 		return
       
   251 	case []*Tree:
       
   252 		// go to most recent element
       
   253 		if len(node) == 0 {
       
   254 			return
       
   255 		}
       
   256 		node[len(node)-1].position = pos
       
   257 		return
       
   258 	}
   130 }
   259 }
   131 
   260 
   132 // GetPositionPath returns the element in the tree indicated by 'keys'.
   261 // GetPositionPath returns the element in the tree indicated by 'keys'.
   133 // If keys is of length zero, the current tree is returned.
   262 // If keys is of length zero, the current tree is returned.
   134 func (t *Tree) GetPositionPath(keys []string) Position {
   263 func (t *Tree) GetPositionPath(keys []string) Position {
   184 // The default values within the struct are valid default options.
   313 // The default values within the struct are valid default options.
   185 type SetOptions struct {
   314 type SetOptions struct {
   186 	Comment   string
   315 	Comment   string
   187 	Commented bool
   316 	Commented bool
   188 	Multiline bool
   317 	Multiline bool
       
   318 	Literal   bool
   189 }
   319 }
   190 
   320 
   191 // SetWithOptions is the same as Set, but allows you to provide formatting
   321 // SetWithOptions is the same as Set, but allows you to provide formatting
   192 // instructions to the key, that will be used by Marshal().
   322 // instructions to the key, that will be used by Marshal().
   193 func (t *Tree) SetWithOptions(key string, opts SetOptions, value interface{}) {
   323 func (t *Tree) SetWithOptions(key string, opts SetOptions, value interface{}) {
   209 			subtree = node
   339 			subtree = node
   210 		case []*Tree:
   340 		case []*Tree:
   211 			// go to most recent element
   341 			// go to most recent element
   212 			if len(node) == 0 {
   342 			if len(node) == 0 {
   213 				// create element if it does not exist
   343 				// create element if it does not exist
   214 				subtree.values[intermediateKey] = append(node, newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}))
   344 				node = append(node, newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}))
       
   345 				subtree.values[intermediateKey] = node
   215 			}
   346 			}
   216 			subtree = node[len(node)-1]
   347 			subtree = node[len(node)-1]
   217 		}
   348 		}
   218 	}
   349 	}
   219 
   350 
   220 	var toInsert interface{}
   351 	var toInsert interface{}
   221 
   352 
   222 	switch v := value.(type) {
   353 	switch v := value.(type) {
   223 	case *Tree:
   354 	case *Tree:
   224 		v.comment = opts.Comment
   355 		v.comment = opts.Comment
       
   356 		v.commented = opts.Commented
   225 		toInsert = value
   357 		toInsert = value
   226 	case []*Tree:
   358 	case []*Tree:
       
   359 		for i := range v {
       
   360 			v[i].commented = opts.Commented
       
   361 		}
   227 		toInsert = value
   362 		toInsert = value
   228 	case *tomlValue:
   363 	case *tomlValue:
   229 		v.comment = opts.Comment
   364 		v.comment = opts.Comment
       
   365 		v.commented = opts.Commented
       
   366 		v.multiline = opts.Multiline
       
   367 		v.literal = opts.Literal
   230 		toInsert = v
   368 		toInsert = v
   231 	default:
   369 	default:
   232 		toInsert = &tomlValue{value: value,
   370 		toInsert = &tomlValue{value: value,
   233 			comment:   opts.Comment,
   371 			comment:   opts.Comment,
   234 			commented: opts.Commented,
   372 			commented: opts.Commented,
   235 			multiline: opts.Multiline,
   373 			multiline: opts.Multiline,
       
   374 			literal:   opts.Literal,
   236 			position:  Position{Line: subtree.position.Line + len(subtree.values) + 1, Col: subtree.position.Col}}
   375 			position:  Position{Line: subtree.position.Line + len(subtree.values) + 1, Col: subtree.position.Col}}
   237 	}
   376 	}
   238 
   377 
   239 	subtree.values[keys[len(keys)-1]] = toInsert
   378 	subtree.values[keys[len(keys)-1]] = toInsert
   240 }
   379 }
   305 	for i, intermediateKey := range keys {
   444 	for i, intermediateKey := range keys {
   306 		nextTree, exists := subtree.values[intermediateKey]
   445 		nextTree, exists := subtree.values[intermediateKey]
   307 		if !exists {
   446 		if !exists {
   308 			tree := newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col})
   447 			tree := newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col})
   309 			tree.position = pos
   448 			tree.position = pos
       
   449 			tree.inline = subtree.inline
   310 			subtree.values[intermediateKey] = tree
   450 			subtree.values[intermediateKey] = tree
   311 			nextTree = tree
   451 			nextTree = tree
   312 		}
   452 		}
   313 
   453 
   314 		switch node := nextTree.(type) {
   454 		switch node := nextTree.(type) {