...
1
2
3
4
5 package cldr
6
7 import (
8 "fmt"
9 "reflect"
10 "sort"
11 )
12
13
14
15
16 type Slice struct {
17 ptr reflect.Value
18 typ reflect.Type
19 }
20
21
22 func (s *Slice) Value() reflect.Value {
23 return s.ptr.Elem()
24 }
25
26
27
28
29
30 func MakeSlice(slicePtr interface{}) Slice {
31 ptr := reflect.ValueOf(slicePtr)
32 if ptr.Kind() != reflect.Ptr {
33 panic(fmt.Sprintf("MakeSlice: argument must be pointer to slice, found %v", ptr.Type()))
34 }
35 sl := ptr.Elem()
36 if sl.Kind() != reflect.Slice {
37 panic(fmt.Sprintf("MakeSlice: argument must point to a slice, found %v", sl.Type()))
38 }
39 intf := reflect.TypeOf((*Elem)(nil)).Elem()
40 if !sl.Type().Elem().Implements(intf) {
41 panic(fmt.Sprintf("MakeSlice: element type of slice (%v) does not implement Elem", sl.Type().Elem()))
42 }
43 nsl := reflect.MakeSlice(sl.Type(), sl.Len(), sl.Len())
44 reflect.Copy(nsl, sl)
45 sl.Set(nsl)
46 return Slice{
47 ptr: ptr,
48 typ: sl.Type().Elem().Elem(),
49 }
50 }
51
52 func (s Slice) indexForAttr(a string) []int {
53 for i := iter(reflect.Zero(s.typ)); !i.done(); i.next() {
54 if n, _ := xmlName(i.field()); n == a {
55 return i.index
56 }
57 }
58 panic(fmt.Sprintf("MakeSlice: no attribute %q for type %v", a, s.typ))
59 }
60
61
62 func (s Slice) Filter(fn func(e Elem) bool) {
63 k := 0
64 sl := s.Value()
65 for i := 0; i < sl.Len(); i++ {
66 vi := sl.Index(i)
67 if fn(vi.Interface().(Elem)) {
68 sl.Index(k).Set(vi)
69 k++
70 }
71 }
72 sl.Set(sl.Slice(0, k))
73 }
74
75
76
77 func (s Slice) Group(fn func(e Elem) string) []Slice {
78 m := make(map[string][]reflect.Value)
79 sl := s.Value()
80 for i := 0; i < sl.Len(); i++ {
81 vi := sl.Index(i)
82 key := fn(vi.Interface().(Elem))
83 m[key] = append(m[key], vi)
84 }
85 keys := []string{}
86 for k, _ := range m {
87 keys = append(keys, k)
88 }
89 sort.Strings(keys)
90 res := []Slice{}
91 for _, k := range keys {
92 nsl := reflect.New(sl.Type())
93 nsl.Elem().Set(reflect.Append(nsl.Elem(), m[k]...))
94 res = append(res, MakeSlice(nsl.Interface()))
95 }
96 return res
97 }
98
99
100
101 func (s Slice) SelectAnyOf(attr string, values ...string) {
102 index := s.indexForAttr(attr)
103 s.Filter(func(e Elem) bool {
104 vf := reflect.ValueOf(e).Elem().FieldByIndex(index)
105 return in(values, vf.String())
106 })
107 }
108
109
110
111
112
113
114 func (s Slice) SelectOnePerGroup(a string, v []string) {
115 index := s.indexForAttr(a)
116 grouped := s.Group(func(e Elem) string { return Key(e, a) })
117 sl := s.Value()
118 sl.Set(sl.Slice(0, 0))
119 for _, g := range grouped {
120 e := reflect.Value{}
121 found := len(v)
122 gsl := g.Value()
123 for i := 0; i < gsl.Len(); i++ {
124 vi := gsl.Index(i).Elem().FieldByIndex(index)
125 j := 0
126 for ; j < len(v) && v[j] != vi.String(); j++ {
127 }
128 if j < found {
129 found = j
130 e = gsl.Index(i)
131 }
132 }
133 if found < len(v) {
134 sl.Set(reflect.Append(sl, e))
135 }
136 }
137 }
138
139
140
141
142 func (s Slice) SelectDraft(d Draft) {
143 s.SelectOnePerGroup("draft", drafts[len(drafts)-2-int(d):])
144 }
145
View as plain text