Branch data Line data Source code
1 : : // $Id: CompHash.cc 6219 2008-10-01 05:39:07Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include "CompHash.h"
8 : : #include "Val.h"
9 : :
10 : 14743 : CompositeHash::CompositeHash(TypeList* composite_type)
11 : : {
12 : 14743 : type = composite_type;
13 : 14743 : Ref(type);
14 : :
15 : : // If the only element is a record, don't treat it as a
16 : : // singleton, since it needs to be evaluated specially.
17 : :
18 [ + + # # ]: 14743 : if ( type->Types()->length() == 1 )
19 : : {
20 [ + + ][ # # ]: 13316 : if ( (*type->Types())[0]->Tag() == TYPE_RECORD )
21 : : {
22 : 52 : is_complex_type = 1;
23 : 52 : is_singleton = 0;
24 : : }
25 : : else
26 : : {
27 : 13264 : is_complex_type = 0;
28 : 13316 : is_singleton = 1;
29 : : }
30 : : }
31 : :
32 : : else
33 : : {
34 : 1427 : is_singleton = 0;
35 : 1427 : is_complex_type = 0;
36 : : }
37 : :
38 [ + + ][ # # ]: 14743 : if ( is_singleton )
39 : : {
40 : : // Don't do any further key computations - we'll do them
41 : : // via the singleton later.
42 : 13264 : singleton_tag = (*type->Types())[0]->InternalType();
43 : 13264 : size = 0;
44 : 13264 : key = 0;
45 : : }
46 : :
47 : : else
48 : : {
49 : 1479 : size = ComputeKeySize();
50 : :
51 [ + + # # ]: 1479 : if ( size > 0 )
52 : : // Fixed size. Make sure what we get is fully aligned.
53 : : key = reinterpret_cast<char*>
54 : 92 : (new double[size/sizeof(double) + 1]);
55 : : else
56 : 1387 : key = 0;
57 : : }
58 : 14743 : }
59 : :
60 : 14101 : CompositeHash::~CompositeHash()
61 : : {
62 : 14101 : Unref(type);
63 [ + + # # ]: 14101 : delete [] key;
64 : 14101 : }
65 : :
66 : : // Computes the piece of the hash for Val*, returning the new kp.
67 : : char* CompositeHash::SingleValHash(int type_check, char* kp0,
68 : 125873 : BroType* bt, Val* v) const
69 : : {
70 : 125873 : char* kp1 = 0;
71 : 125873 : InternalTypeTag t = bt->InternalType();
72 : :
73 [ + + ]: 125873 : if ( type_check )
74 : : {
75 : 124421 : InternalTypeTag vt = v->Type()->InternalType();
76 [ - + ]: 124421 : if ( vt != t )
77 : 0 : return 0;
78 : : }
79 : :
80 [ + + + - - : 125873 : switch ( t ) {
+ + - - ]
81 : : case TYPE_INTERNAL_INT:
82 : : {
83 : 9 : bro_int_t* kp = AlignAndPadType<bro_int_t>(kp0);
84 : 9 : *kp = v->ForceAsInt();
85 : 9 : kp1 = reinterpret_cast<char*>(kp+1);
86 : : }
87 : 9 : break;
88 : :
89 : : case TYPE_INTERNAL_UNSIGNED:
90 : : {
91 : 50708 : bro_uint_t* kp = AlignAndPadType<bro_uint_t>(kp0);
92 : 50708 : *kp = v->ForceAsUInt();
93 : 50708 : kp1 = reinterpret_cast<char*>(kp+1);
94 : : }
95 : 50708 : break;
96 : :
97 : : case TYPE_INTERNAL_ADDR:
98 : : {
99 : : // Use uint32 instead of int, because 'int' is not
100 : : // guaranteed to be 32-bit.
101 : 49610 : uint32* kp = AlignAndPadType<uint32>(kp0);
102 : : #ifdef BROv6
103 : : const addr_type av = v->AsAddr();
104 : : kp[0] = av[0];
105 : : kp[1] = av[1];
106 : : kp[2] = av[2];
107 : : kp[3] = av[3];
108 : : kp1 = reinterpret_cast<char*>(kp+4);
109 : : #else
110 : 49610 : *kp = v->AsAddr();
111 : 49610 : kp1 = reinterpret_cast<char*>(kp+1);
112 : : #endif
113 : : }
114 : 49610 : break;
115 : :
116 : : case TYPE_INTERNAL_SUBNET:
117 : : {
118 : 0 : uint32* kp = AlignAndPadType<uint32>(kp0);
119 : : #ifdef BROv6
120 : : const subnet_type* sv = v->AsSubNet();
121 : : kp[0] = sv->net[0];
122 : : kp[1] = sv->net[1];
123 : : kp[2] = sv->net[2];
124 : : kp[3] = sv->net[3];
125 : : kp[4] = sv->width;
126 : : kp1 = reinterpret_cast<char*>(kp+5);
127 : : #else
128 : 0 : const subnet_type* sv = v->AsSubNet();
129 : 0 : kp[0] = sv->net;
130 : 0 : kp[1] = sv->width;
131 : 0 : kp1 = reinterpret_cast<char*>(kp+2);
132 : : #endif
133 : : }
134 : 0 : break;
135 : :
136 : : case TYPE_INTERNAL_DOUBLE:
137 : : {
138 : 0 : double* kp = AlignAndPadType<double>(kp0);
139 : 0 : *kp = v->InternalDouble();
140 : 0 : kp1 = reinterpret_cast<char*>(kp+1);
141 : : }
142 : 0 : break;
143 : :
144 : : case TYPE_INTERNAL_VOID:
145 : : case TYPE_INTERNAL_OTHER:
146 : : {
147 [ + + ]: 24816 : if ( v->Type()->Tag() == TYPE_FUNC )
148 : : {
149 : 6 : Val** kp = AlignAndPadType<Val*>(kp0);
150 : 6 : v->Ref();
151 : : // Ref((BroObj*) v->AsFunc());
152 : 6 : *kp = v;
153 : 6 : kp1 = reinterpret_cast<char*>(kp+1);
154 : : }
155 : :
156 [ + - ]: 24810 : else if ( v->Type()->Tag() == TYPE_RECORD )
157 : : {
158 : 24810 : char* kp = kp0;
159 : 24810 : RecordVal* rv = v->AsRecordVal();
160 : 24810 : RecordType* rt = v->Type()->AsRecordType();
161 : 24810 : int num_fields = rt->NumFields();
162 : :
163 [ + + ]: 124044 : for ( int i = 0; i < num_fields; ++i )
164 : : {
165 : 99234 : Val* rv_i = rv->Lookup(i);
166 [ - + ]: 99234 : if ( ! rv_i )
167 : 0 : return 0;
168 : :
169 [ - + ]: 99234 : if ( ! (kp = SingleValHash(type_check, kp,
170 : : rt->FieldType(i),
171 : : rv_i)) )
172 : 0 : return 0;
173 : : }
174 : :
175 : 24810 : kp1 = kp;
176 : : }
177 : : else
178 : : {
179 : 0 : internal_error("bad index type in CompositeHash::SingleValHash");
180 : : return 0;
181 : : }
182 : : }
183 : 24816 : break;
184 : :
185 : : case TYPE_INTERNAL_STRING:
186 : : {
187 : : // Align to int for the length field.
188 : 730 : int* kp = AlignAndPadType<int>(kp0);
189 : 730 : const BroString* sval = v->AsString();
190 : :
191 : 730 : *kp = sval->Len(); // so we can recover the value
192 : :
193 : 730 : kp1 = reinterpret_cast<char*>(kp+1);
194 : :
195 : 730 : memcpy(kp1, sval->Bytes(), sval->Len());
196 : 730 : kp1 += sval->Len();
197 : : }
198 : 730 : break;
199 : :
200 : : case TYPE_INTERNAL_ERROR:
201 : 0 : return 0;
202 : : }
203 : :
204 : 125873 : return kp1;
205 : : }
206 : :
207 : :
208 : 120279 : HashKey* CompositeHash::ComputeHash(const Val* v, int type_check) const
209 : : {
210 [ + + ]: 120279 : if ( is_singleton )
211 : 85324 : return ComputeSingletonHash(v, type_check);
212 : :
213 [ + + ][ + + ]: 34955 : if ( is_complex_type && v->Type()->Tag() != TYPE_LIST )
[ + + ]
214 : : {
215 : 9419 : ListVal lv(TYPE_ANY);
216 : :
217 : : // Cast away const to use ListVal - but since we
218 : : // re-introduce const on the recursive call, it should
219 : : // be okay; the only thing is that the ListVal unref's it.
220 : 9419 : Val* ncv = (Val*) v;
221 : 9419 : ncv->Ref();
222 : 9419 : lv.Append(ncv);
223 : 9419 : HashKey* hk = ComputeHash(&lv, type_check);
224 : 9419 : return hk;
225 : : }
226 : :
227 : 25536 : char* k = key;
228 : :
229 [ + + ]: 25536 : if ( ! k )
230 : : {
231 : 726 : int sz = ComputeKeySize(v, type_check);
232 [ - + ]: 726 : if ( sz == 0 )
233 : 0 : return 0;
234 : :
235 : 726 : k = reinterpret_cast<char*>(new double[sz/sizeof(double) + 1]);
236 : 726 : type_check = 0; // no need to type-check again.
237 : : }
238 : :
239 : 25536 : const type_list* tl = type->Types();
240 : :
241 [ + + - + ]: 25536 : if ( type_check && v->Type()->Tag() != TYPE_LIST )
[ - + ]
242 : 0 : return 0;
243 : :
244 : 25536 : const val_list* vl = v->AsListVal()->Vals();
245 [ + + - + ]: 25536 : if ( type_check && vl->length() != tl->length() )
[ - + ]
246 : 0 : return 0;
247 : :
248 : 25536 : char* kp = k;
249 [ + + ]: 52175 : loop_over_list(*tl, i)
250 : : {
251 : 26639 : kp = SingleValHash(type_check, kp, (*tl)[i], (*vl)[i]);
252 [ - + ]: 26639 : if ( ! kp )
253 : 0 : return 0;
254 : : }
255 : :
256 : 120279 : return new HashKey((k == key), (void*) k, kp - k);
257 : : }
258 : :
259 : 85324 : HashKey* CompositeHash::ComputeSingletonHash(const Val* v, int type_check) const
260 : : {
261 [ + + ]: 85324 : if ( v->Type()->Tag() == TYPE_LIST )
262 : : {
263 : 82370 : const val_list* vl = v->AsListVal()->Vals();
264 [ + - - + ]: 82370 : if ( type_check && vl->length() != 1 )
[ - + ]
265 : 0 : return 0;
266 : :
267 : 82370 : v = (*vl)[0];
268 : : }
269 : :
270 [ + - ][ - + ]: 85324 : if ( type_check && v->Type()->InternalType() != singleton_tag )
[ - + ]
271 : 0 : return 0;
272 : :
273 : : uint32 tmp_addr;
274 [ + + + - - : 85324 : switch ( singleton_tag ) {
+ - - ]
275 : : case TYPE_INTERNAL_INT:
276 : : case TYPE_INTERNAL_UNSIGNED:
277 : 22411 : return new HashKey(v->ForceAsInt());
278 : :
279 : : case TYPE_INTERNAL_ADDR:
280 : : #ifdef BROv6
281 : : return new HashKey(v->AsAddr(), 4);
282 : : #else
283 : 3893 : return new HashKey(v->AsAddr());
284 : : #endif
285 : :
286 : : case TYPE_INTERNAL_SUBNET:
287 : : #ifdef BROv6
288 : : return new HashKey((const uint32*) v->AsSubNet(), 5);
289 : : #else
290 : 14 : return new HashKey((const uint32*) v->AsSubNet(), 2);
291 : :
292 : : #endif
293 : :
294 : : case TYPE_INTERNAL_DOUBLE:
295 : 0 : return new HashKey(v->InternalDouble());
296 : :
297 : : case TYPE_INTERNAL_VOID:
298 : : case TYPE_INTERNAL_OTHER:
299 [ # # ]: 0 : if ( v->Type()->Tag() == TYPE_FUNC )
300 : 0 : return new HashKey(v);
301 : :
302 : 0 : internal_error("bad index type in CompositeHash::ComputeSingletonHash");
303 : : return 0;
304 : :
305 : : case TYPE_INTERNAL_STRING:
306 : 59006 : return new HashKey(v->AsString());
307 : :
308 : : case TYPE_INTERNAL_ERROR:
309 : 0 : return 0;
310 : :
311 : : default:
312 : 85324 : internal_error("bad internal type in CompositeHash::ComputeSingletonHash");
313 : : return 0;
314 : : }
315 : : }
316 : :
317 : : int CompositeHash::SingleTypeKeySize(BroType* bt, const Val* v,
318 : 1895 : int type_check, int sz) const
319 : : {
320 : 1895 : InternalTypeTag t = bt->InternalType();
321 : :
322 [ + - + + ]: 1895 : if ( type_check && v )
323 : : {
324 : 1452 : InternalTypeTag vt = v->Type()->InternalType();
325 [ - + ]: 1452 : if ( vt != t )
326 : 0 : return 0;
327 : : }
328 : :
329 [ + + - - + : 1895 : switch ( t ) {
+ - - ]
330 : : case TYPE_INTERNAL_INT:
331 : : case TYPE_INTERNAL_UNSIGNED:
332 : 877 : sz = SizeAlign(sz, sizeof(bro_int_t));
333 : 877 : break;
334 : :
335 : : case TYPE_INTERNAL_ADDR:
336 : : #ifdef BROv6
337 : : sz = SizeAlign(sz, sizeof(uint32));
338 : : sz += sizeof(uint32) * 3; // to make a total of 4 words
339 : : #else
340 : 192 : sz = SizeAlign(sz, sizeof(uint32));
341 : : #endif
342 : 192 : break;
343 : :
344 : : case TYPE_INTERNAL_SUBNET:
345 : : #ifdef BROv6
346 : : sz = SizeAlign(sz, sizeof(uint32));
347 : : sz += sizeof(uint32) * 4; // to make a total of 5 words
348 : : #else
349 : 0 : sz = SizeAlign(sz, sizeof(uint32));
350 : 0 : sz += sizeof(uint32); // make room for width
351 : : #endif
352 : 0 : break;
353 : :
354 : : case TYPE_INTERNAL_DOUBLE:
355 : 0 : sz = SizeAlign(sz, sizeof(double));
356 : 0 : break;
357 : :
358 : : case TYPE_INTERNAL_VOID:
359 : : case TYPE_INTERNAL_OTHER:
360 : : {
361 [ + + ]: 59 : if ( bt->Tag() == TYPE_FUNC )
362 : 4 : sz = SizeAlign(sz, sizeof(Val*));
363 : :
364 [ + - ]: 55 : else if ( bt->Tag() == TYPE_RECORD )
365 : : {
366 [ - + ]: 55 : const RecordVal* rv = v ? v->AsRecordVal() : 0;
367 : 55 : RecordType* rt = bt->AsRecordType();
368 : 55 : int num_fields = rt->NumFields();
369 : :
370 [ + + ]: 267 : for ( int i = 0; i < num_fields; ++i )
371 : : {
372 : : sz = SingleTypeKeySize(rt->FieldType(i),
373 : : rv ? rv->Lookup(i) : 0,
374 [ - + ]: 214 : type_check, sz);
375 [ + + ]: 214 : if ( ! sz )
376 : 2 : return 0;
377 : : }
378 : : }
379 : : else
380 : : {
381 : 0 : internal_error("bad index type in CompositeHash::CompositeHash");
382 : : return 0;
383 : : }
384 : : }
385 : 57 : break;
386 : :
387 : : case TYPE_INTERNAL_STRING:
388 [ + + ]: 767 : if ( ! v )
389 : 37 : return 0;
390 : :
391 : : // Factor in length field.
392 : 730 : sz = SizeAlign(sz, sizeof(int));
393 : 730 : sz += v->AsString()->Len();
394 : 730 : break;
395 : :
396 : : case TYPE_INTERNAL_ERROR:
397 : 0 : return 0;
398 : : }
399 : :
400 : 1895 : return sz;
401 : : }
402 : :
403 : 2205 : int CompositeHash::ComputeKeySize(const Val* v, int type_check) const
404 : : {
405 : 2205 : const type_list* tl = type->Types();
406 : 2205 : const val_list* vl = 0;
407 [ + + ]: 2205 : if ( v )
408 : : {
409 [ + - ][ - + ]: 726 : if ( type_check && v->Type()->Tag() != TYPE_LIST )
[ - + ]
410 : 0 : return 0;
411 : :
412 : 726 : vl = v->AsListVal()->Vals();
413 [ + - - + ]: 726 : if ( type_check && vl->length() != tl->length() )
[ - + ]
414 : 0 : return 0;
415 : : }
416 : :
417 : 2205 : int sz = 0;
418 [ + + ]: 3849 : loop_over_list(*tl, i)
419 : : {
420 : : sz = SingleTypeKeySize((*tl)[i], v ? v->AsListVal()->Index(i) : 0,
421 [ + + ]: 1681 : type_check, sz);
422 [ + + ]: 1681 : if ( ! sz )
423 : 37 : return 0;
424 : : }
425 : :
426 : 2205 : return sz;
427 : : }
428 : :
429 : : namespace
430 : : {
431 : 107234 : inline bool is_power_of_2(bro_uint_t x)
432 : : {
433 : 107234 : return ((x - 1) & x) == 0;
434 : : }
435 : : }
436 : :
437 : 4368 : const void* CompositeHash::Align(const char* ptr, unsigned int size) const
438 : : {
439 [ - + ]: 4368 : if ( ! size )
440 : 0 : return ptr;
441 : :
442 [ - + ]: 4368 : ASSERT(is_power_of_2(size));
443 : :
444 : 4368 : unsigned int mask = size - 1; // Assume size is a power of 2.
445 : 4368 : unsigned long l_ptr = reinterpret_cast<unsigned long>(ptr);
446 : 4368 : unsigned long offset = l_ptr & mask;
447 : :
448 [ + + ]: 4368 : if ( offset > 0 )
449 : 36 : return reinterpret_cast<const void*>(ptr - offset + size);
450 : : else
451 : 4368 : return reinterpret_cast<const void*>(ptr);
452 : : }
453 : :
454 : 101063 : void* CompositeHash::AlignAndPad(char* ptr, unsigned int size) const
455 : : {
456 [ - + ]: 101063 : if ( ! size )
457 : 0 : return ptr;
458 : :
459 [ - + ]: 101063 : ASSERT(is_power_of_2(size));
460 : :
461 : 101063 : unsigned int mask = size - 1; // Assume size is a power of 2.
462 [ + + ]: 299914 : while ( (reinterpret_cast<unsigned long>(ptr) & mask) != 0 )
463 : : // Not aligned - zero pad.
464 : 198851 : *ptr++ = '\0';
465 : :
466 : 101063 : return reinterpret_cast<void *>(ptr);
467 : : }
468 : :
469 : 1803 : int CompositeHash::SizeAlign(int offset, unsigned int size) const
470 : : {
471 [ - + ]: 1803 : if ( ! size )
472 : 0 : return offset;
473 : :
474 [ - + ]: 1803 : ASSERT(is_power_of_2(size));
475 : :
476 : 1803 : unsigned int mask = size - 1; // Assume size is a power of 2.
477 [ + + ]: 1803 : if ( offset & mask )
478 : : {
479 : 293 : offset &= ~mask; // Round down.
480 : 293 : offset += size; // Round up.
481 : : }
482 : :
483 : 1803 : offset += size; // Add in size.
484 : :
485 : 1803 : return offset;
486 : : }
487 : :
488 : 1605 : ListVal* CompositeHash::RecoverVals(const HashKey* k) const
489 : : {
490 : 1605 : ListVal* l = new ListVal(TYPE_ANY);
491 : 1605 : const type_list* tl = type->Types();
492 : 1605 : const char* kp = (const char*) k->Key();
493 : 1605 : const char* const k_end = kp + k->Size();
494 : :
495 [ + + ]: 3210 : loop_over_list(*tl, i)
496 : : {
497 : : Val* v;
498 : 1605 : kp = RecoverOneVal(k, kp, k_end, (*tl)[i], v);
499 [ - + ]: 1605 : ASSERT(v);
500 : 1605 : l->Append(v);
501 : : }
502 : :
503 [ - + ]: 1605 : if ( kp != k_end )
504 : 0 : internal_error("under-ran key in CompositeHash::DescribeKey");
505 : :
506 : 1605 : return l;
507 : : }
508 : :
509 : : const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0,
510 : : const char* const k_end, BroType* t,
511 : 5814 : Val*& pval) const
512 : : {
513 : : // k->Size() == 0 for a single empty string.
514 [ - + ][ # # ]: 5814 : if ( kp0 >= k_end && k->Size() > 0 )
[ - + ]
515 : 0 : internal_error("over-ran key in CompositeHash::RecoverVals");
516 : :
517 : 5814 : TypeTag tag = t->Tag();
518 : 5814 : InternalTypeTag it = t->InternalType();
519 : :
520 : 5814 : const char* kp1 = 0;
521 : :
522 [ + + - + - : 5814 : switch ( it ) {
+ + - ]
523 : : case TYPE_INTERNAL_INT:
524 : : {
525 : 1379 : const bro_int_t* const kp = AlignType<bro_int_t>(kp0);
526 : 1379 : kp1 = reinterpret_cast<const char*>(kp+1);
527 : :
528 [ + - ]: 1379 : if ( tag == TYPE_ENUM )
529 : 1379 : pval = new EnumVal(*kp, t->AsEnumType());
530 : : else
531 : 0 : pval = new Val(*kp, tag);
532 : : }
533 : 1379 : break;
534 : :
535 : : case TYPE_INTERNAL_UNSIGNED:
536 : : {
537 : 1509 : const bro_uint_t* const kp = AlignType<bro_uint_t>(kp0);
538 : 1509 : kp1 = reinterpret_cast<const char*>(kp+1);
539 : :
540 [ + + - ]: 1509 : switch ( tag ) {
541 : : case TYPE_COUNT:
542 : : case TYPE_COUNTER:
543 : 1385 : pval = new Val(*kp, tag);
544 : 1385 : break;
545 : :
546 : : case TYPE_PORT:
547 : 124 : pval = new PortVal(*kp);
548 : 124 : break;
549 : :
550 : : default:
551 : 0 : internal_error("bad internal unsigned int in CompositeHash::RecoverOneVal()");
552 : : pval = 0;
553 : : break;
554 : : }
555 : : }
556 : 1509 : break;
557 : :
558 : : case TYPE_INTERNAL_DOUBLE:
559 : : {
560 : 0 : const double* const kp = AlignType<double>(kp0);
561 : 0 : kp1 = reinterpret_cast<const char*>(kp+1);
562 : :
563 [ # # ]: 0 : if ( tag == TYPE_INTERVAL )
564 : 0 : pval = new IntervalVal(*kp, 1.0);
565 : : else
566 : 0 : pval = new Val(*kp, tag);
567 : : }
568 : 0 : break;
569 : :
570 : : case TYPE_INTERNAL_ADDR:
571 : : {
572 : 101 : const uint32* const kp = AlignType<uint32>(kp0);
573 : : #ifdef BROv6
574 : : const_addr_type addr_val = kp;
575 : : kp1 = reinterpret_cast<const char*>(kp+4);
576 : : #else
577 : 101 : const_addr_type addr_val = *kp;
578 : 101 : kp1 = reinterpret_cast<const char*>(kp+1);
579 : : #endif
580 [ + - - ]: 101 : switch ( tag ) {
581 : : case TYPE_ADDR:
582 : 101 : pval = new AddrVal(addr_val);
583 : 101 : break;
584 : :
585 : : case TYPE_NET:
586 : 0 : pval = new NetVal(addr_val);
587 : 0 : break;
588 : :
589 : : default:
590 : 0 : internal_error("bad internal address in CompositeHash::RecoverOneVal()");
591 : : pval = 0;
592 : : break;
593 : : }
594 : : }
595 : 101 : break;
596 : :
597 : : case TYPE_INTERNAL_SUBNET:
598 : : {
599 : : const subnet_type* const kp =
600 : : reinterpret_cast<const subnet_type*>(
601 : 0 : AlignType<uint32>(kp0));
602 : 0 : kp1 = reinterpret_cast<const char*>(kp+1);
603 : :
604 : 0 : pval = new SubNetVal(kp->net, kp->width);
605 : : }
606 : 0 : break;
607 : :
608 : : case TYPE_INTERNAL_VOID:
609 : : case TYPE_INTERNAL_OTHER:
610 : : {
611 [ + + ]: 2776 : if ( t->Tag() == TYPE_FUNC )
612 : : {
613 : 1379 : Val* const * const kp = AlignType<Val*>(kp0);
614 : 1379 : kp1 = reinterpret_cast<const char*>(kp+1);
615 : :
616 : 1379 : Val* v = *kp;
617 : :
618 [ + - - + ]: 1379 : if ( ! v || ! v->Type() )
[ - + ]
619 : 0 : internal_error("bad aggregate Val in CompositeHash::RecoverOneVal()");
620 : :
621 [ - + ][ # # ]: 1379 : if ( t->Tag() != TYPE_FUNC &&
[ - + ]
622 : : // ### Maybe fix later, but may be fundamentally
623 : : // un-checkable --US
624 : : ! same_type(v->Type(), t) )
625 : : {
626 : 0 : internal_error("inconsistent aggregate Val in CompositeHash::RecoverOneVal()");
627 : : }
628 : :
629 : : // ### A crude approximation for now.
630 [ + - ][ - + ]: 1379 : if ( t->Tag() == TYPE_FUNC &&
[ - + ]
631 : : v->Type()->Tag() != TYPE_FUNC )
632 : : {
633 : 0 : internal_error("inconsistent aggregate Val in CompositeHash::RecoverOneVal()");
634 : : }
635 : :
636 : 1379 : pval = v->Ref();
637 : : }
638 : :
639 [ + - ]: 1397 : else if ( t->Tag() == TYPE_RECORD )
640 : : {
641 : 1397 : const char* kp = kp0;
642 : 1397 : RecordType* rt = t->AsRecordType();
643 : 1397 : int num_fields = rt->NumFields();
644 : :
645 : 1397 : vector<Val*> values;
646 : : int i;
647 [ + + ]: 5606 : for ( i = 0; i < num_fields; ++i )
648 : : {
649 : : Val* v;
650 : : kp = RecoverOneVal(k, kp, k_end,
651 : 4209 : rt->FieldType(i), v);
652 [ - + ]: 4209 : if ( ! v )
653 : : {
654 : 0 : internal_error("didn't recover expected number of fields from HashKey");
655 : : pval = 0;
656 : : break;
657 : : }
658 : :
659 : 4209 : values.push_back(v);
660 : : }
661 : :
662 [ - + ]: 1397 : ASSERT(int(values.size()) == num_fields);
663 : :
664 : 1397 : RecordVal* rv = new RecordVal(rt);
665 : :
666 [ + + ]: 5606 : for ( int i = 0; i < num_fields; ++i )
667 : 4209 : rv->Assign(i, values[i]);
668 : :
669 : 1397 : pval = rv;
670 : 1397 : kp1 = kp;
671 : : }
672 : : else
673 : : {
674 : 0 : internal_error("bad index type in CompositeHash::DescribeKey");
675 : : }
676 : : }
677 : 2776 : break;
678 : :
679 : : case TYPE_INTERNAL_STRING:
680 : : {
681 : : // There is a minor issue here -- the pointer does not have to
682 : : // be aligned by int in the singleton case.
683 : :
684 : : int n;
685 [ + - ]: 49 : if ( is_singleton )
686 : : {
687 : 49 : kp1 = kp0;
688 : 49 : n = k->Size();
689 : : }
690 : : else
691 : : {
692 : 0 : const int* const kp = AlignType<int>(kp0);
693 : 0 : n = *kp;
694 : 0 : kp1 = reinterpret_cast<const char*>(kp+1);
695 : : }
696 : :
697 : 49 : pval = new StringVal(new BroString((const byte_vec) kp1, n, 1));
698 : 49 : kp1 += n;
699 : : }
700 : : break;
701 : :
702 : : case TYPE_INTERNAL_ERROR:
703 : : break;
704 : : }
705 : :
706 : 5814 : return kp1;
707 [ + - ][ + - ]: 6 : }
|