1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.allanbank.mongodb.bson.io;
21
22 import java.nio.charset.Charset;
23 import java.util.List;
24
25 import com.allanbank.mongodb.bson.Document;
26 import com.allanbank.mongodb.bson.Element;
27 import com.allanbank.mongodb.bson.ElementType;
28 import com.allanbank.mongodb.bson.Visitor;
29 import com.allanbank.mongodb.bson.element.BinaryElement;
30 import com.allanbank.mongodb.bson.element.ObjectId;
31
32
33
34
35
36
37
38
39 public class SizeOfVisitor implements Visitor {
40
41 public final static Charset UTF8 = StringDecoder.UTF8;
42
43
44 private int mySize;
45
46
47 private final StringEncoder myStringEncoder;
48
49
50
51
52 public SizeOfVisitor() {
53 this(null);
54 }
55
56
57
58
59
60
61
62 public SizeOfVisitor(final StringEncoder encoder) {
63 super();
64 mySize = 0;
65 myStringEncoder = encoder;
66 }
67
68
69
70
71
72
73
74
75 public int computeCStringSize(final String string) {
76 return utf8Size(string) + 1;
77 }
78
79
80
81
82
83
84
85
86 public int computeStringSize(final String string) {
87 return 4 + utf8Size(string) + 1;
88 }
89
90
91
92
93
94
95 public int getSize() {
96 return mySize;
97 }
98
99
100
101
102
103
104 public void reset() {
105 mySize = 0;
106 }
107
108
109
110
111
112 public void rewind() {
113 mySize = 0;
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 public int utf8Size(final String string) {
138 if (myStringEncoder != null) {
139 return myStringEncoder.encodeSize(string);
140 }
141 return StringEncoder.utf8Size(string);
142 }
143
144
145
146
147 @Override
148 public void visit(final List<Element> elements) {
149 mySize += 4;
150 for (final Element element : elements) {
151
152 if (element.getType() == ElementType.BINARY) {
153 final BinaryElement be = (BinaryElement) element;
154 doVisitBinary(be.getName(), be.getSubType(), be.length());
155 }
156 else {
157 element.accept(this);
158 }
159 }
160 mySize += 1;
161 }
162
163
164
165
166 @Override
167 public void visitArray(final String name, final List<Element> elements) {
168
169 mySize += 1;
170 mySize += computeCStringSize(name);
171 visit(elements);
172 }
173
174
175
176
177 @Override
178 public void visitBinary(final String name, final byte subType,
179 final byte[] data) {
180
181 final int dataLength = data.length;
182
183 doVisitBinary(name, subType, dataLength);
184 }
185
186
187
188
189 @Override
190 public void visitBoolean(final String name, final boolean value) {
191
192 mySize += 1;
193 mySize += computeCStringSize(name);
194 mySize += 1;
195 }
196
197
198
199
200 @Override
201 public void visitDBPointer(final String name, final String databaseName,
202 final String collectionName, final ObjectId id) {
203 mySize += 1;
204 mySize += computeCStringSize(name);
205 mySize += computeStringSize(databaseName + "." + collectionName);
206 mySize += (4 + 8);
207 }
208
209
210
211
212 @Override
213 public void visitDocument(final String name, final List<Element> elements) {
214 mySize += 1;
215 mySize += computeCStringSize(name);
216 visit(elements);
217 }
218
219
220
221
222 @Override
223 public void visitDouble(final String name, final double value) {
224 mySize += 1;
225 mySize += computeCStringSize(name);
226 mySize += 8;
227 }
228
229
230
231
232 @Override
233 public void visitInteger(final String name, final int value) {
234 mySize += 1;
235 mySize += computeCStringSize(name);
236 mySize += 4;
237 }
238
239
240
241
242 @Override
243 public void visitJavaScript(final String name, final String code) {
244 mySize += 1;
245 mySize += computeCStringSize(name);
246 mySize += computeStringSize(code);
247 }
248
249
250
251
252 @Override
253 public void visitJavaScript(final String name, final String code,
254 final Document scope) {
255 mySize += 1;
256 mySize += computeCStringSize(name);
257
258 mySize += 4;
259 mySize += computeStringSize(code);
260
261 scope.accept(this);
262 }
263
264
265
266
267 @Override
268 public void visitLong(final String name, final long value) {
269 mySize += 1;
270 mySize += computeCStringSize(name);
271 mySize += 8;
272 }
273
274
275
276
277 @Override
278 public void visitMaxKey(final String name) {
279 mySize += 1;
280 mySize += computeCStringSize(name);
281 }
282
283
284
285
286 @Override
287 public void visitMinKey(final String name) {
288 mySize += 1;
289 mySize += computeCStringSize(name);
290 }
291
292
293
294
295 @Override
296 public void visitMongoTimestamp(final String name, final long value) {
297 mySize += 1;
298 mySize += computeCStringSize(name);
299 mySize += 8;
300 }
301
302
303
304
305 @Override
306 public void visitNull(final String name) {
307 mySize += 1;
308 mySize += computeCStringSize(name);
309 }
310
311
312
313
314 @Override
315 public void visitObjectId(final String name, final ObjectId id) {
316 mySize += 1;
317 mySize += computeCStringSize(name);
318 mySize += (4 + 8);
319 }
320
321
322
323
324 @Override
325 public void visitRegularExpression(final String name, final String pattern,
326 final String options) {
327 mySize += 1;
328 mySize += computeCStringSize(name);
329 mySize += computeCStringSize(pattern);
330 mySize += computeCStringSize(options);
331 }
332
333
334
335
336 @Override
337 public void visitString(final String name, final String value) {
338 mySize += 1;
339 mySize += computeCStringSize(name);
340 mySize += computeStringSize(value);
341 }
342
343
344
345
346 @Override
347 public void visitSymbol(final String name, final String symbol) {
348 mySize += 1;
349 mySize += computeCStringSize(name);
350 mySize += computeStringSize(symbol);
351 }
352
353
354
355
356 @Override
357 public void visitTimestamp(final String name, final long timestamp) {
358 mySize += 1;
359 mySize += computeCStringSize(name);
360 mySize += 8;
361 }
362
363
364
365
366
367
368
369
370
371
372
373
374 private void doVisitBinary(final String name, final byte subType,
375 final int dataLength) {
376 mySize += 1;
377 mySize += computeCStringSize(name);
378
379 switch (subType) {
380 case 2: {
381 mySize += (4 + 1 + 4 + dataLength);
382 break;
383
384 }
385 case 0:
386 default:
387 mySize += (4 + 1 + dataLength);
388 break;
389 }
390 }
391 }