blob: f8681098bd863600d4912370bb52accf65926a46 [file] [log] [blame]
Christian Lavoieafc6d8f2011-02-20 02:39:19 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20package thrift
21
22import (
23 "container/list"
24)
25
26/**
27 * Helper class that encapsulates set metadata.
28 *
29 */
30type TSet interface {
31 TContainer
32 ElemType() TType
33 Add(data interface{})
34 Remove(data interface{})
35 Less(other interface{}) bool
36 Front() *list.Element
37 Back() *list.Element
38 Values() []interface{}
39}
40
41type tSet struct {
42 elemType TType
43 size int
44 l *list.List
45}
46
47func NewTSet(t TType, s int) TSet {
48 return &tSet{elemType: t, size: s, l: list.New()}
49}
50
51func NewTSetDefault() TSet {
52 return NewTSet(STOP, 0)
53}
54
55func (p *tSet) ElemType() TType {
56 return p.elemType
57}
58
59func (p *tSet) Front() *list.Element {
60 return p.l.Front()
61}
62
63func (p *tSet) Back() *list.Element {
64 return p.l.Back()
65}
66
67func (p *tSet) Len() int {
68 if p.l.Len() != 0 {
69 return p.l.Len()
70 }
71 return p.size
72}
73
74func (p *tSet) Contains(data interface{}) bool {
75 return p.find(data) != nil
76}
77
78func (p *tSet) Add(other interface{}) {
79 if data, ok := p.elemType.CoerceData(other); ok {
80 for elem := p.l.Front(); elem != nil; elem = elem.Next() {
81 if cmp, ok := p.elemType.Compare(data, elem.Value); ok && cmp >= 0 {
82 if cmp > 0 {
83 p.l.InsertBefore(data, elem)
84 }
85 return
86 }
87 }
88 }
89}
90
91func (p *tSet) Remove(data interface{}) {
92 elem := p.find(data)
93 if elem != nil {
94 p.l.Remove(elem)
95 }
96}
97
98func (p *tSet) Less(other interface{}) bool {
99 cmp, ok := p.CompareTo(other)
100 return ok && cmp > 0
101}
102
103func (p *tSet) Equals(other interface{}) bool {
104 c, cok := p.CompareTo(other)
105 return cok && c == 0
106}
107
108func (p *tSet) CompareTo(other interface{}) (int, bool) {
109 return TType(SET).Compare(p, other)
110}
111
112func (p *tSet) find(data interface{}) *list.Element {
113 if data == nil {
114 for elem := p.l.Front(); elem != nil; elem = elem.Next() {
115 if elem.Value == nil {
116 return elem
117 }
118 }
119 return nil
120 }
121 data, ok := p.elemType.CoerceData(data)
122 if data == nil || !ok {
123 return nil
124 }
125 if p.elemType.IsBaseType() || p.elemType.IsEnum() {
126 for elem := p.l.Front(); elem != nil; elem = elem.Next() {
127 if data == elem.Value {
128 return elem
129 }
130 }
131 return nil
132 }
133 if cmp, ok := data.(EqualsOtherInterface); ok {
134 for elem := p.l.Front(); elem != nil; elem = elem.Next() {
135 if cmp.Equals(elem.Value) {
136 return elem
137 }
138 }
139 return nil
140 }
141 switch p.elemType {
142 case MAP:
143 if cmp, ok := data.(EqualsMap); ok {
144 for elem := p.l.Front(); elem != nil; elem = elem.Next() {
145 v := elem.Value
146 if v == nil {
147 continue
148 }
149 if cmp.Equals(v.(TMap)) {
150 return elem
151 }
152 }
153 return nil
154 }
155 case SET:
156 if cmp, ok := data.(EqualsSet); ok {
157 for elem := p.l.Front(); elem != nil; elem = elem.Next() {
158 v := elem.Value
159 if v == nil {
160 continue
161 }
162 if cmp.Equals(v.(TSet)) {
163 return elem
164 }
165 }
166 return nil
167 }
168 case LIST:
169 if cmp, ok := data.(EqualsList); ok {
170 for elem := p.l.Front(); elem != nil; elem = elem.Next() {
171 v := elem.Value
172 if v == nil {
173 continue
174 }
175 if cmp.Equals(v.(TList)) {
176 return elem
177 }
178 }
179 return nil
180 }
181 case STRUCT:
182 if cmp, ok := data.(EqualsStruct); ok {
183 for elem := p.l.Front(); elem != nil; elem = elem.Next() {
184 v := elem.Value
185 if v == nil {
186 continue
187 }
188 if cmp.Equals(v.(TStruct)) {
189 return elem
190 }
191 }
192 return nil
193 }
194 }
195 return nil
196}
197
198func (p *tSet) Values() []interface{} {
199 size := p.l.Len()
200 values := make([]interface{}, size, size)
201 i := 0
202 for v := p.l.Front(); v != nil; v = v.Next() {
203 values[i] = v.Value
204 i++
205 }
206 return values
207}