Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / imdario / mergo / mergo.go
1 // Copyright 2013 Dario Castañé. All rights reserved.
2 // Copyright 2009 The Go Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file.
5
6 // Based on src/pkg/reflect/deepequal.go from official
7 // golang's stdlib.
8
9 package mergo
10
11 import (
12         "errors"
13         "reflect"
14 )
15
16 // Errors reported by Mergo when it finds invalid arguments.
17 var (
18         ErrNilArguments                = errors.New("src and dst must not be nil")
19         ErrDifferentArgumentsTypes     = errors.New("src and dst must be of same type")
20         ErrNotSupported                = errors.New("only structs and maps are supported")
21         ErrExpectedMapAsDestination    = errors.New("dst was expected to be a map")
22         ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct")
23 )
24
25 // During deepMerge, must keep track of checks that are
26 // in progress.  The comparison algorithm assumes that all
27 // checks in progress are true when it reencounters them.
28 // Visited are stored in a map indexed by 17 * a1 + a2;
29 type visit struct {
30         ptr  uintptr
31         typ  reflect.Type
32         next *visit
33 }
34
35 // From src/pkg/encoding/json.
36 func isEmptyValue(v reflect.Value) bool {
37         switch v.Kind() {
38         case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
39                 return v.Len() == 0
40         case reflect.Bool:
41                 return !v.Bool()
42         case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
43                 return v.Int() == 0
44         case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
45                 return v.Uint() == 0
46         case reflect.Float32, reflect.Float64:
47                 return v.Float() == 0
48         case reflect.Interface, reflect.Ptr:
49                 return v.IsNil()
50         }
51         return false
52 }
53
54 func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) {
55         if dst == nil || src == nil {
56                 err = ErrNilArguments
57                 return
58         }
59         vDst = reflect.ValueOf(dst).Elem()
60         if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map {
61                 err = ErrNotSupported
62                 return
63         }
64         vSrc = reflect.ValueOf(src)
65         // We check if vSrc is a pointer to dereference it.
66         if vSrc.Kind() == reflect.Ptr {
67                 vSrc = vSrc.Elem()
68         }
69         return
70 }
71
72 // Traverses recursively both values, assigning src's fields values to dst.
73 // The map argument tracks comparisons that have already been seen, which allows
74 // short circuiting on recursive types.
75 func deeper(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) {
76         if dst.CanAddr() {
77                 addr := dst.UnsafeAddr()
78                 h := 17 * addr
79                 seen := visited[h]
80                 typ := dst.Type()
81                 for p := seen; p != nil; p = p.next {
82                         if p.ptr == addr && p.typ == typ {
83                                 return nil
84                         }
85                 }
86                 // Remember, remember...
87                 visited[h] = &visit{addr, typ, seen}
88         }
89         return // TODO refactor
90 }