-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathiterator.go
109 lines (93 loc) · 2.35 KB
/
iterator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package toolbox
import (
"reflect"
"time"
)
//Iterator represents generic iterator.
type Iterator interface {
//HasNext returns true if iterator has next element.
HasNext() bool
//Next sets item pointer with next element.
Next(itemPointer interface{}) error
}
type sliceIterator struct {
sliceValue reflect.Value
index int
}
func (i *sliceIterator) HasNext() bool {
return i.index < i.sliceValue.Len()
}
func (i *sliceIterator) Next(itemPointer interface{}) error {
value := i.sliceValue.Index(i.index)
i.index++
itemPointerValue := reflect.ValueOf(itemPointer)
itemPointerValue.Elem().Set(value)
return nil
}
type stringSliceIterator struct {
sliceValue []string
index int
}
func (i *stringSliceIterator) HasNext() bool {
return i.index < len(i.sliceValue)
}
func (i *stringSliceIterator) Next(itemPointer interface{}) error {
value := i.sliceValue[i.index]
i.index++
if stringPointer, ok := itemPointer.(*string); ok {
*stringPointer = value
return nil
}
interfacePointer := itemPointer.(*interface{})
*interfacePointer = value
return nil
}
type interfaceSliceIterator struct {
sliceValue []interface{}
index int
}
func (i *interfaceSliceIterator) HasNext() bool {
return i.index < len(i.sliceValue)
}
func (i *interfaceSliceIterator) Next(itemPointer interface{}) error {
value := i.sliceValue[i.index]
i.index++
switch actual := itemPointer.(type) {
case *interface{}:
*actual = value
return nil
case *string:
*actual = AsString(value)
return nil
case *int:
*actual = AsInt(value)
return nil
case *int64:
*actual = int64(AsInt(value))
return nil
case *time.Time:
var timestamp = AsTime(value, DefaultDateLayout)
if timestamp != nil {
*actual = *timestamp
}
return nil
}
itemPointerValue := reflect.ValueOf(itemPointer)
if value != nil {
itemPointerValue.Elem().Set(reflect.ValueOf(value))
} else {
itemPointerValue.Elem().Set(reflect.Zero(reflect.TypeOf(itemPointer).Elem()))
}
return nil
}
//NewSliceIterator creates a new slice iterator.
func NewSliceIterator(slice interface{}) Iterator {
if aSlice, ok := slice.([]interface{}); ok {
return &interfaceSliceIterator{aSlice, 0}
}
if aSlice, ok := slice.([]string); ok {
return &stringSliceIterator{aSlice, 0}
}
sliceValue := DiscoverValueByKind(reflect.ValueOf(slice), reflect.Slice)
return &sliceIterator{sliceValue: sliceValue}
}