vendor/github.com/pelletier/go-toml/toml.go
changeset 251 1c52a0eeb952
parent 242 2a9ec03fe5a1
child 256 6d9efbef00a9
equal deleted inserted replaced
250:c040f992052f 251:1c52a0eeb952
    25 	commented bool
    25 	commented bool
    26 	position  Position
    26 	position  Position
    27 }
    27 }
    28 
    28 
    29 func newTree() *Tree {
    29 func newTree() *Tree {
       
    30 	return newTreeWithPosition(Position{})
       
    31 }
       
    32 
       
    33 func newTreeWithPosition(pos Position) *Tree {
    30 	return &Tree{
    34 	return &Tree{
    31 		values:   make(map[string]interface{}),
    35 		values:   make(map[string]interface{}),
    32 		position: Position{},
    36 		position: pos,
    33 	}
    37 	}
    34 }
    38 }
    35 
    39 
    36 // TreeFromMap initializes a new Tree object using the given map.
    40 // TreeFromMap initializes a new Tree object using the given map.
    37 func TreeFromMap(m map[string]interface{}) (*Tree, error) {
    41 func TreeFromMap(m map[string]interface{}) (*Tree, error) {
   192 
   196 
   193 // SetPathWithOptions is the same as SetPath, but allows you to provide
   197 // SetPathWithOptions is the same as SetPath, but allows you to provide
   194 // formatting instructions to the key, that will be reused by Marshal().
   198 // formatting instructions to the key, that will be reused by Marshal().
   195 func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interface{}) {
   199 func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interface{}) {
   196 	subtree := t
   200 	subtree := t
   197 	for _, intermediateKey := range keys[:len(keys)-1] {
   201 	for i, intermediateKey := range keys[:len(keys)-1] {
   198 		nextTree, exists := subtree.values[intermediateKey]
   202 		nextTree, exists := subtree.values[intermediateKey]
   199 		if !exists {
   203 		if !exists {
   200 			nextTree = newTree()
   204 			nextTree = newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col})
   201 			subtree.values[intermediateKey] = nextTree // add new element here
   205 			subtree.values[intermediateKey] = nextTree // add new element here
   202 		}
   206 		}
   203 		switch node := nextTree.(type) {
   207 		switch node := nextTree.(type) {
   204 		case *Tree:
   208 		case *Tree:
   205 			subtree = node
   209 			subtree = node
   206 		case []*Tree:
   210 		case []*Tree:
   207 			// go to most recent element
   211 			// go to most recent element
   208 			if len(node) == 0 {
   212 			if len(node) == 0 {
   209 				// create element if it does not exist
   213 				// create element if it does not exist
   210 				subtree.values[intermediateKey] = append(node, newTree())
   214 				subtree.values[intermediateKey] = append(node, newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}))
   211 			}
   215 			}
   212 			subtree = node[len(node)-1]
   216 			subtree = node[len(node)-1]
   213 		}
   217 		}
   214 	}
   218 	}
   215 
   219 
   216 	var toInsert interface{}
   220 	var toInsert interface{}
   217 
   221 
   218 	switch value.(type) {
   222 	switch v := value.(type) {
   219 	case *Tree:
   223 	case *Tree:
   220 		tt := value.(*Tree)
   224 		v.comment = opts.Comment
   221 		tt.comment = opts.Comment
       
   222 		toInsert = value
   225 		toInsert = value
   223 	case []*Tree:
   226 	case []*Tree:
   224 		toInsert = value
   227 		toInsert = value
   225 	case *tomlValue:
   228 	case *tomlValue:
   226 		tt := value.(*tomlValue)
   229 		v.comment = opts.Comment
   227 		tt.comment = opts.Comment
   230 		toInsert = v
   228 		toInsert = tt
       
   229 	default:
   231 	default:
   230 		toInsert = &tomlValue{value: value, comment: opts.Comment, commented: opts.Commented, multiline: opts.Multiline}
   232 		toInsert = &tomlValue{value: value,
       
   233 			comment:   opts.Comment,
       
   234 			commented: opts.Commented,
       
   235 			multiline: opts.Multiline,
       
   236 			position:  Position{Line: subtree.position.Line + len(subtree.values) + 1, Col: subtree.position.Col}}
   231 	}
   237 	}
   232 
   238 
   233 	subtree.values[keys[len(keys)-1]] = toInsert
   239 	subtree.values[keys[len(keys)-1]] = toInsert
   234 }
   240 }
   235 
   241 
   254 }
   260 }
   255 
   261 
   256 // SetPathWithComment is the same as SetPath, but allows you to provide comment
   262 // SetPathWithComment is the same as SetPath, but allows you to provide comment
   257 // information to the key, that will be reused by Marshal().
   263 // information to the key, that will be reused by Marshal().
   258 func (t *Tree) SetPathWithComment(keys []string, comment string, commented bool, value interface{}) {
   264 func (t *Tree) SetPathWithComment(keys []string, comment string, commented bool, value interface{}) {
   259 	subtree := t
   265 	t.SetPathWithOptions(keys, SetOptions{Comment: comment, Commented: commented}, value)
   260 	for _, intermediateKey := range keys[:len(keys)-1] {
   266 }
   261 		nextTree, exists := subtree.values[intermediateKey]
   267 
   262 		if !exists {
   268 // Delete removes a key from the tree.
   263 			nextTree = newTree()
   269 // Key is a dot-separated path (e.g. a.b.c).
   264 			subtree.values[intermediateKey] = nextTree // add new element here
   270 func (t *Tree) Delete(key string) error {
   265 		}
   271 	keys, err := parseKey(key)
   266 		switch node := nextTree.(type) {
   272 	if err != nil {
   267 		case *Tree:
   273 		return err
   268 			subtree = node
   274 	}
   269 		case []*Tree:
   275 	return t.DeletePath(keys)
   270 			// go to most recent element
   276 }
   271 			if len(node) == 0 {
   277 
   272 				// create element if it does not exist
   278 // DeletePath removes a key from the tree.
   273 				subtree.values[intermediateKey] = append(node, newTree())
   279 // Keys is an array of path elements (e.g. {"a","b","c"}).
   274 			}
   280 func (t *Tree) DeletePath(keys []string) error {
   275 			subtree = node[len(node)-1]
   281 	keyLen := len(keys)
   276 		}
   282 	if keyLen == 1 {
   277 	}
   283 		delete(t.values, keys[0])
   278 
   284 		return nil
   279 	var toInsert interface{}
   285 	}
   280 
   286 	tree := t.GetPath(keys[:keyLen-1])
   281 	switch value.(type) {
   287 	item := keys[keyLen-1]
       
   288 	switch node := tree.(type) {
   282 	case *Tree:
   289 	case *Tree:
   283 		tt := value.(*Tree)
   290 		delete(node.values, item)
   284 		tt.comment = comment
   291 		return nil
   285 		toInsert = value
   292 	}
   286 	case []*Tree:
   293 	return errors.New("no such key to delete")
   287 		toInsert = value
       
   288 	case *tomlValue:
       
   289 		tt := value.(*tomlValue)
       
   290 		tt.comment = comment
       
   291 		toInsert = tt
       
   292 	default:
       
   293 		toInsert = &tomlValue{value: value, comment: comment, commented: commented}
       
   294 	}
       
   295 
       
   296 	subtree.values[keys[len(keys)-1]] = toInsert
       
   297 }
   294 }
   298 
   295 
   299 // createSubTree takes a tree and a key and create the necessary intermediate
   296 // createSubTree takes a tree and a key and create the necessary intermediate
   300 // subtrees to create a subtree at that point. In-place.
   297 // subtrees to create a subtree at that point. In-place.
   301 //
   298 //
   303 // and tree[a][b][c]
   300 // and tree[a][b][c]
   304 //
   301 //
   305 // Returns nil on success, error object on failure
   302 // Returns nil on success, error object on failure
   306 func (t *Tree) createSubTree(keys []string, pos Position) error {
   303 func (t *Tree) createSubTree(keys []string, pos Position) error {
   307 	subtree := t
   304 	subtree := t
   308 	for _, intermediateKey := range keys {
   305 	for i, intermediateKey := range keys {
   309 		nextTree, exists := subtree.values[intermediateKey]
   306 		nextTree, exists := subtree.values[intermediateKey]
   310 		if !exists {
   307 		if !exists {
   311 			tree := newTree()
   308 			tree := newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col})
   312 			tree.position = pos
   309 			tree.position = pos
   313 			subtree.values[intermediateKey] = tree
   310 			subtree.values[intermediateKey] = tree
   314 			nextTree = tree
   311 			nextTree = tree
   315 		}
   312 		}
   316 
   313 
   335 				panic(r)
   332 				panic(r)
   336 			}
   333 			}
   337 			err = errors.New(r.(string))
   334 			err = errors.New(r.(string))
   338 		}
   335 		}
   339 	}()
   336 	}()
       
   337 
       
   338 	if len(b) >= 4 && (hasUTF32BigEndianBOM4(b) || hasUTF32LittleEndianBOM4(b)) {
       
   339 		b = b[4:]
       
   340 	} else if len(b) >= 3 && hasUTF8BOM3(b) {
       
   341 		b = b[3:]
       
   342 	} else if len(b) >= 2 && (hasUTF16BigEndianBOM2(b) || hasUTF16LittleEndianBOM2(b)) {
       
   343 		b = b[2:]
       
   344 	}
       
   345 
   340 	tree = parseToml(lexToml(b))
   346 	tree = parseToml(lexToml(b))
   341 	return
   347 	return
       
   348 }
       
   349 
       
   350 func hasUTF16BigEndianBOM2(b []byte) bool {
       
   351 	return b[0] == 0xFE && b[1] == 0xFF
       
   352 }
       
   353 
       
   354 func hasUTF16LittleEndianBOM2(b []byte) bool {
       
   355 	return b[0] == 0xFF && b[1] == 0xFE
       
   356 }
       
   357 
       
   358 func hasUTF8BOM3(b []byte) bool {
       
   359 	return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
       
   360 }
       
   361 
       
   362 func hasUTF32BigEndianBOM4(b []byte) bool {
       
   363 	return b[0] == 0x00 && b[1] == 0x00 && b[2] == 0xFE && b[3] == 0xFF
       
   364 }
       
   365 
       
   366 func hasUTF32LittleEndianBOM4(b []byte) bool {
       
   367 	return b[0] == 0xFF && b[1] == 0xFE && b[2] == 0x00 && b[3] == 0x00
   342 }
   368 }
   343 
   369 
   344 // LoadReader creates a Tree from any io.Reader.
   370 // LoadReader creates a Tree from any io.Reader.
   345 func LoadReader(reader io.Reader) (tree *Tree, err error) {
   371 func LoadReader(reader io.Reader) (tree *Tree, err error) {
   346 	inputBytes, err := ioutil.ReadAll(reader)
   372 	inputBytes, err := ioutil.ReadAll(reader)