Mercurial > hg > Members > sugi > MessagePack-java
comparison src/main/java/org/msgpack/type/SequentialMapValueImpl.java @ 0:cb825acd883a
first commit
author | sugi |
---|---|
date | Sat, 18 Oct 2014 15:06:15 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:cb825acd883a |
---|---|
1 // | |
2 // MessagePack for Java | |
3 // | |
4 // Copyright (C) 2009 - 2013 FURUHASHI Sadayuki | |
5 // | |
6 // Licensed under the Apache License, Version 2.0 (the "License"); | |
7 // you may not use this file except in compliance with the License. | |
8 // 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, software | |
13 // distributed under the License is distributed on an "AS IS" BASIS, | |
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 // See the License for the specific language governing permissions and | |
16 // limitations under the License. | |
17 // | |
18 package org.msgpack.type; | |
19 | |
20 import java.util.Map; | |
21 import java.util.Set; | |
22 import java.util.Collection; | |
23 import java.util.Iterator; | |
24 import java.util.AbstractMap; | |
25 import java.util.AbstractSet; | |
26 import java.util.AbstractCollection; | |
27 import java.util.NoSuchElementException; | |
28 import java.io.IOException; | |
29 import org.msgpack.packer.Packer; | |
30 import org.msgpack.util.android.PortedImmutableEntry; | |
31 | |
32 class SequentialMapValueImpl extends AbstractMapValue { | |
33 private static SequentialMapValueImpl emptyInstance = new SequentialMapValueImpl(new Value[0], true); | |
34 | |
35 public static MapValue getEmptyInstance() { | |
36 return emptyInstance; | |
37 } | |
38 | |
39 private Value[] array; | |
40 | |
41 @Override | |
42 public Value[] getKeyValueArray() { | |
43 return array; | |
44 } | |
45 | |
46 SequentialMapValueImpl(Value[] array, boolean gift) { | |
47 if (array.length % 2 != 0) { | |
48 throw new IllegalArgumentException(); // TODO message | |
49 } | |
50 if (gift) { | |
51 this.array = array; | |
52 } else { | |
53 this.array = new Value[array.length]; | |
54 System.arraycopy(array, 0, this.array, 0, array.length); | |
55 } | |
56 } | |
57 | |
58 @Override | |
59 public Value get(Object key) { | |
60 if (key == null) { | |
61 return null; | |
62 } | |
63 for (int i = array.length - 2; i >= 0; i -= 2) { | |
64 if (array[i].equals(key)) { | |
65 return array[i + 1]; | |
66 } | |
67 } | |
68 return null; | |
69 } | |
70 | |
71 private static class EntrySet extends AbstractSet<Map.Entry<Value, Value>> { | |
72 private Value[] array; | |
73 | |
74 EntrySet(Value[] array) { | |
75 this.array = array; | |
76 } | |
77 | |
78 @Override | |
79 public int size() { | |
80 return array.length / 2; | |
81 } | |
82 | |
83 @Override | |
84 public Iterator<Map.Entry<Value, Value>> iterator() { | |
85 return new EntrySetIterator(array); | |
86 } | |
87 } | |
88 | |
89 private static class EntrySetIterator implements | |
90 Iterator<Map.Entry<Value, Value>> { | |
91 private Value[] array; | |
92 private int pos; | |
93 private static final boolean hasDefaultImmutableEntry; | |
94 static { | |
95 boolean hasIt = true; | |
96 try { | |
97 Class.forName("java.util.AbstractMap.SimpleImmutableEntry"); | |
98 } catch (ClassNotFoundException e) { | |
99 hasIt = false; | |
100 } finally { | |
101 hasDefaultImmutableEntry = hasIt; | |
102 } | |
103 } | |
104 | |
105 EntrySetIterator(Value[] array) { | |
106 this.array = array; | |
107 this.pos = 0; | |
108 } | |
109 | |
110 @Override | |
111 public boolean hasNext() { | |
112 return pos < array.length; | |
113 } | |
114 | |
115 @Override | |
116 public Map.Entry<Value, Value> next() { | |
117 if (pos >= array.length) { | |
118 throw new NoSuchElementException(); // TODO message | |
119 } | |
120 | |
121 Value key = array[pos]; | |
122 Value value = array[pos + 1]; | |
123 /** | |
124 * @see https://github.com/msgpack/msgpack-java/pull/27 | |
125 * | |
126 * msgpack-java was crashed on Android 2.2 or below because | |
127 * the method calls java.util.AbstractMap$SimpleImmutableEntry | |
128 * that doesn't exist in Android 2.2 or below. | |
129 */ | |
130 Map.Entry<Value, Value> pair = hasDefaultImmutableEntry ? | |
131 new AbstractMap.SimpleImmutableEntry<Value, Value>(key, value) : | |
132 new PortedImmutableEntry<Value, Value>(key, value); | |
133 | |
134 pos += 2; | |
135 return pair; | |
136 } | |
137 | |
138 @Override | |
139 public void remove() { | |
140 throw new UnsupportedOperationException(); // TODO message | |
141 } | |
142 } | |
143 | |
144 private static class KeySet extends AbstractSet<Value> { | |
145 private Value[] array; | |
146 | |
147 KeySet(Value[] array) { | |
148 this.array = array; | |
149 } | |
150 | |
151 @Override | |
152 public int size() { | |
153 return array.length / 2; | |
154 } | |
155 | |
156 @Override | |
157 public Iterator<Value> iterator() { | |
158 return new ValueIterator(array, 0); | |
159 } | |
160 } | |
161 | |
162 private static class ValueCollection extends AbstractCollection<Value> { | |
163 private Value[] array; | |
164 | |
165 ValueCollection(Value[] array) { | |
166 this.array = array; | |
167 } | |
168 | |
169 @Override | |
170 public int size() { | |
171 return array.length / 2; | |
172 } | |
173 | |
174 @Override | |
175 public Iterator<Value> iterator() { | |
176 return new ValueIterator(array, 1); | |
177 } | |
178 } | |
179 | |
180 private static class ValueIterator implements Iterator<Value> { | |
181 private Value[] array; | |
182 private int pos; | |
183 | |
184 ValueIterator(Value[] array, int offset) { | |
185 this.array = array; | |
186 this.pos = offset; | |
187 } | |
188 | |
189 @Override | |
190 public boolean hasNext() { | |
191 return pos < array.length; | |
192 } | |
193 | |
194 @Override | |
195 public Value next() { | |
196 if (pos >= array.length) { | |
197 throw new NoSuchElementException(); // TODO message | |
198 } | |
199 Value v = array[pos]; | |
200 pos += 2; | |
201 return v; | |
202 } | |
203 | |
204 @Override | |
205 public void remove() { | |
206 throw new UnsupportedOperationException(); // TODO message | |
207 } | |
208 } | |
209 | |
210 @Override | |
211 public Set<Map.Entry<Value, Value>> entrySet() { | |
212 return new EntrySet(array); | |
213 } | |
214 | |
215 @Override | |
216 public Set<Value> keySet() { | |
217 return new KeySet(array); | |
218 } | |
219 | |
220 @Override | |
221 public Collection<Value> values() { | |
222 return new ValueCollection(array); | |
223 } | |
224 | |
225 @Override | |
226 public void writeTo(Packer pk) throws IOException { | |
227 pk.writeMapBegin(array.length / 2); | |
228 for (int i = 0; i < array.length; i++) { | |
229 array[i].writeTo(pk); | |
230 } | |
231 pk.writeMapEnd(); | |
232 } | |
233 | |
234 @Override | |
235 public boolean equals(Object o) { | |
236 if (o == this) { | |
237 return true; | |
238 } | |
239 if (!(o instanceof Value)) { | |
240 return false; | |
241 } | |
242 Value v = (Value) o; | |
243 if (!v.isMapValue()) { | |
244 return false; | |
245 } | |
246 | |
247 Map<Value, Value> om = v.asMapValue(); | |
248 if (om.size() != array.length / 2) { | |
249 return false; | |
250 } | |
251 | |
252 try { | |
253 for (int i = 0; i < array.length; i += 2) { | |
254 Value key = array[i]; | |
255 Value value = array[i + 1]; | |
256 if (!value.equals(om.get(key))) { | |
257 return false; | |
258 } | |
259 } | |
260 } catch (ClassCastException ex) { | |
261 return false; | |
262 } catch (NullPointerException ex) { | |
263 return false; | |
264 } | |
265 | |
266 return true; | |
267 } | |
268 | |
269 // private boolean equals(SequentialMapValueImpl o) { | |
270 // if(array.length != o.array.length) { | |
271 // return false; | |
272 // } | |
273 // for(int i=0; i < array.length; i+=2) { | |
274 // if(!equalsValue(o.array, array[i], array[i+1], i)) { | |
275 // return false; | |
276 // } | |
277 // } | |
278 // return true; | |
279 // } | |
280 | |
281 // private boolean equalsValue(Value[] oarray, Value key, Value val, int hint) { | |
282 // for(int j=hint; j < array.length; j+=2) { | |
283 // if(key.equals(oarray[j])) { | |
284 // if(val.equals(oarray[j+1])) { | |
285 // return true; | |
286 // } else { | |
287 // return false; | |
288 // } | |
289 // } | |
290 // } | |
291 // for(int j=0; j < hint; j+=2) { | |
292 // if(key.equals(oarray[j])) { | |
293 // if(val.equals(oarray[j+1])) { | |
294 // return true; | |
295 // } else { | |
296 // return false; | |
297 // } | |
298 // } | |
299 // } | |
300 // return false; | |
301 // } | |
302 | |
303 // TODO compareTo? | |
304 | |
305 @Override | |
306 public int hashCode() { | |
307 int h = 0; | |
308 for (int i = 0; i < array.length; i += 2) { | |
309 h += array[i].hashCode() ^ array[i + 1].hashCode(); | |
310 } | |
311 return h; | |
312 } | |
313 | |
314 @Override | |
315 public String toString() { | |
316 return toString(new StringBuilder()).toString(); | |
317 } | |
318 | |
319 @Override | |
320 public StringBuilder toString(StringBuilder sb) { | |
321 if (array.length == 0) { | |
322 return sb.append("{}"); | |
323 } | |
324 sb.append("{"); | |
325 sb.append(array[0]); | |
326 sb.append(":"); | |
327 sb.append(array[1]); | |
328 for (int i = 2; i < array.length; i += 2) { | |
329 sb.append(","); | |
330 array[i].toString(sb); | |
331 sb.append(":"); | |
332 array[i + 1].toString(sb); | |
333 } | |
334 sb.append("}"); | |
335 return sb; | |
336 } | |
337 } |