LCOV - code coverage report
Current view: top level - src - CompHash.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 240 304 78.9 %
Date: 2010-12-13 Functions: 15 17 88.2 %
Branches: 139 227 61.2 %

           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 :         }

Generated by: LCOV version 1.8