Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
15747 anikendra 1
// included by json_value.cpp
2
// everything is within Json namespace
3
 
4
// //////////////////////////////////////////////////////////////////
5
// //////////////////////////////////////////////////////////////////
6
// //////////////////////////////////////////////////////////////////
7
// class ValueInternalMap
8
// //////////////////////////////////////////////////////////////////
9
// //////////////////////////////////////////////////////////////////
10
// //////////////////////////////////////////////////////////////////
11
 
12
/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
13
   * This optimization is used by the fast allocator.
14
   */
15
ValueInternalLink::ValueInternalLink()
16
   : previous_( 0 )
17
   , next_( 0 )
18
{
19
}
20
 
21
ValueInternalLink::~ValueInternalLink()
22
{ 
23
   for ( int index =0; index < itemPerLink; ++index )
24
   {
25
      if ( !items_[index].isItemAvailable() )
26
      {
27
         if ( !items_[index].isMemberNameStatic() )
28
            free( keys_[index] );
29
      }
30
      else
31
         break;
32
   }
33
}
34
 
35
 
36
 
37
ValueMapAllocator::~ValueMapAllocator()
38
{
39
}
40
 
41
#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
42
class DefaultValueMapAllocator : public ValueMapAllocator
43
{
44
public: // overridden from ValueMapAllocator
45
   virtual ValueInternalMap *newMap()
46
   {
47
      return new ValueInternalMap();
48
   }
49
 
50
   virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
51
   {
52
      return new ValueInternalMap( other );
53
   }
54
 
55
   virtual void destructMap( ValueInternalMap *map )
56
   {
57
      delete map;
58
   }
59
 
60
   virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
61
   {
62
      return new ValueInternalLink[size];
63
   }
64
 
65
   virtual void releaseMapBuckets( ValueInternalLink *links )
66
   {
67
      delete [] links;
68
   }
69
 
70
   virtual ValueInternalLink *allocateMapLink()
71
   {
72
      return new ValueInternalLink();
73
   }
74
 
75
   virtual void releaseMapLink( ValueInternalLink *link )
76
   {
77
      delete link;
78
   }
79
};
80
#else
81
/// @todo make this thread-safe (lock when accessign batch allocator)
82
class DefaultValueMapAllocator : public ValueMapAllocator
83
{
84
public: // overridden from ValueMapAllocator
85
   virtual ValueInternalMap *newMap()
86
   {
87
      ValueInternalMap *map = mapsAllocator_.allocate();
88
      new (map) ValueInternalMap(); // placement new
89
      return map;
90
   }
91
 
92
   virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
93
   {
94
      ValueInternalMap *map = mapsAllocator_.allocate();
95
      new (map) ValueInternalMap( other ); // placement new
96
      return map;
97
   }
98
 
99
   virtual void destructMap( ValueInternalMap *map )
100
   {
101
      if ( map )
102
      {
103
         map->~ValueInternalMap();
104
         mapsAllocator_.release( map );
105
      }
106
   }
107
 
108
   virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
109
   {
110
      return new ValueInternalLink[size];
111
   }
112
 
113
   virtual void releaseMapBuckets( ValueInternalLink *links )
114
   {
115
      delete [] links;
116
   }
117
 
118
   virtual ValueInternalLink *allocateMapLink()
119
   {
120
      ValueInternalLink *link = linksAllocator_.allocate();
121
      memset( link, 0, sizeof(ValueInternalLink) );
122
      return link;
123
   }
124
 
125
   virtual void releaseMapLink( ValueInternalLink *link )
126
   {
127
      link->~ValueInternalLink();
128
      linksAllocator_.release( link );
129
   }
130
private:
131
   BatchAllocator<ValueInternalMap,1> mapsAllocator_;
132
   BatchAllocator<ValueInternalLink,1> linksAllocator_;
133
};
134
#endif
135
 
136
static ValueMapAllocator *&mapAllocator()
137
{
138
   static DefaultValueMapAllocator defaultAllocator;
139
   static ValueMapAllocator *mapAllocator = &defaultAllocator;
140
   return mapAllocator;
141
}
142
 
143
static struct DummyMapAllocatorInitializer {
144
   DummyMapAllocatorInitializer() 
145
   {
146
      mapAllocator();      // ensure mapAllocator() statics are initialized before main().
147
   }
148
} dummyMapAllocatorInitializer;
149
 
150
 
151
 
152
// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
153
 
154
/*
155
use linked list hash map. 
156
buckets array is a container.
157
linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
158
value have extra state: valid, available, deleted
159
*/
160
 
161
 
162
ValueInternalMap::ValueInternalMap()
163
   : buckets_( 0 )
164
   , tailLink_( 0 )
165
   , bucketsSize_( 0 )
166
   , itemCount_( 0 )
167
{
168
}
169
 
170
 
171
ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
172
   : buckets_( 0 )
173
   , tailLink_( 0 )
174
   , bucketsSize_( 0 )
175
   , itemCount_( 0 )
176
{
177
   reserve( other.itemCount_ );
178
   IteratorState it;
179
   IteratorState itEnd;
180
   other.makeBeginIterator( it );
181
   other.makeEndIterator( itEnd );
182
   for ( ; !equals(it,itEnd); increment(it) )
183
   {
184
      bool isStatic;
185
      const char *memberName = key( it, isStatic );
186
      const Value &aValue = value( it );
187
      resolveReference(memberName, isStatic) = aValue;
188
   }
189
}
190
 
191
 
192
ValueInternalMap &
193
ValueInternalMap::operator =( const ValueInternalMap &other )
194
{
195
   ValueInternalMap dummy( other );
196
   swap( dummy );
197
   return *this;
198
}
199
 
200
 
201
ValueInternalMap::~ValueInternalMap()
202
{
203
   if ( buckets_ )
204
   {
205
      for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
206
      {
207
         ValueInternalLink *link = buckets_[bucketIndex].next_;
208
         while ( link )
209
         {
210
            ValueInternalLink *linkToRelease = link;
211
            link = link->next_;
212
            mapAllocator()->releaseMapLink( linkToRelease );
213
         }
214
      }
215
      mapAllocator()->releaseMapBuckets( buckets_ );
216
   }
217
}
218
 
219
 
220
void 
221
ValueInternalMap::swap( ValueInternalMap &other )
222
{
223
   ValueInternalLink *tempBuckets = buckets_;
224
   buckets_ = other.buckets_;
225
   other.buckets_ = tempBuckets;
226
   ValueInternalLink *tempTailLink = tailLink_;
227
   tailLink_ = other.tailLink_;
228
   other.tailLink_ = tempTailLink;
229
   BucketIndex tempBucketsSize = bucketsSize_;
230
   bucketsSize_ = other.bucketsSize_;
231
   other.bucketsSize_ = tempBucketsSize;
232
   BucketIndex tempItemCount = itemCount_;
233
   itemCount_ = other.itemCount_;
234
   other.itemCount_ = tempItemCount;
235
}
236
 
237
 
238
void 
239
ValueInternalMap::clear()
240
{
241
   ValueInternalMap dummy;
242
   swap( dummy );
243
}
244
 
245
 
246
ValueInternalMap::BucketIndex 
247
ValueInternalMap::size() const
248
{
249
   return itemCount_;
250
}
251
 
252
bool 
253
ValueInternalMap::reserveDelta( BucketIndex growth )
254
{
255
   return reserve( itemCount_ + growth );
256
}
257
 
258
bool 
259
ValueInternalMap::reserve( BucketIndex newItemCount )
260
{
261
   if ( !buckets_  &&  newItemCount > 0 )
262
   {
263
      buckets_ = mapAllocator()->allocateMapBuckets( 1 );
264
      bucketsSize_ = 1;
265
      tailLink_ = &buckets_[0];
266
   }
267
//   BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
268
   return true;
269
}
270
 
271
 
272
const Value *
273
ValueInternalMap::find( const char *key ) const
274
{
275
   if ( !bucketsSize_ )
276
      return 0;
277
   HashKey hashedKey = hash( key );
278
   BucketIndex bucketIndex = hashedKey % bucketsSize_;
279
   for ( const ValueInternalLink *current = &buckets_[bucketIndex]; 
280
         current != 0; 
281
         current = current->next_ )
282
   {
283
      for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
284
      {
285
         if ( current->items_[index].isItemAvailable() )
286
            return 0;
287
         if ( strcmp( key, current->keys_[index] ) == 0 )
288
            return &current->items_[index];
289
      }
290
   }
291
   return 0;
292
}
293
 
294
 
295
Value *
296
ValueInternalMap::find( const char *key )
297
{
298
   const ValueInternalMap *constThis = this;
299
   return const_cast<Value *>( constThis->find( key ) );
300
}
301
 
302
 
303
Value &
304
ValueInternalMap::resolveReference( const char *key,
305
                                    bool isStatic )
306
{
307
   HashKey hashedKey = hash( key );
308
   if ( bucketsSize_ )
309
   {
310
      BucketIndex bucketIndex = hashedKey % bucketsSize_;
311
      ValueInternalLink **previous = 0;
312
      BucketIndex index;
313
      for ( ValueInternalLink *current = &buckets_[bucketIndex]; 
314
            current != 0; 
315
            previous = &current->next_, current = current->next_ )
316
      {
317
         for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
318
         {
319
            if ( current->items_[index].isItemAvailable() )
320
               return setNewItem( key, isStatic, current, index );
321
            if ( strcmp( key, current->keys_[index] ) == 0 )
322
               return current->items_[index];
323
         }
324
      }
325
   }
326
 
327
   reserveDelta( 1 );
328
   return unsafeAdd( key, isStatic, hashedKey );
329
}
330
 
331
 
332
void 
333
ValueInternalMap::remove( const char *key )
334
{
335
   HashKey hashedKey = hash( key );
336
   if ( !bucketsSize_ )
337
      return;
338
   BucketIndex bucketIndex = hashedKey % bucketsSize_;
339
   for ( ValueInternalLink *link = &buckets_[bucketIndex]; 
340
         link != 0; 
341
         link = link->next_ )
342
   {
343
      BucketIndex index;
344
      for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
345
      {
346
         if ( link->items_[index].isItemAvailable() )
347
            return;
348
         if ( strcmp( key, link->keys_[index] ) == 0 )
349
         {
350
            doActualRemove( link, index, bucketIndex );
351
            return;
352
         }
353
      }
354
   }
355
}
356
 
357
void 
358
ValueInternalMap::doActualRemove( ValueInternalLink *link, 
359
                                  BucketIndex index,
360
                                  BucketIndex bucketIndex )
361
{
362
   // find last item of the bucket and swap it with the 'removed' one.
363
   // set removed items flags to 'available'.
364
   // if last page only contains 'available' items, then desallocate it (it's empty)
365
   ValueInternalLink *&lastLink = getLastLinkInBucket( index );
366
   BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
367
   for ( ;   
368
         lastItemIndex < ValueInternalLink::itemPerLink; 
369
         ++lastItemIndex ) // may be optimized with dicotomic search
370
   {
371
      if ( lastLink->items_[lastItemIndex].isItemAvailable() )
372
         break;
373
   }
374
 
375
   BucketIndex lastUsedIndex = lastItemIndex - 1;
376
   Value *valueToDelete = &link->items_[index];
377
   Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
378
   if ( valueToDelete != valueToPreserve )
379
      valueToDelete->swap( *valueToPreserve );
380
   if ( lastUsedIndex == 0 )  // page is now empty
381
   {  // remove it from bucket linked list and delete it.
382
      ValueInternalLink *linkPreviousToLast = lastLink->previous_;
383
      if ( linkPreviousToLast != 0 )   // can not deleted bucket link.
384
      {
385
         mapAllocator()->releaseMapLink( lastLink );
386
         linkPreviousToLast->next_ = 0;
387
         lastLink = linkPreviousToLast;
388
      }
389
   }
390
   else
391
   {
392
      Value dummy;
393
      valueToPreserve->swap( dummy ); // restore deleted to default Value.
394
      valueToPreserve->setItemUsed( false );
395
   }
396
   --itemCount_;
397
}
398
 
399
 
400
ValueInternalLink *&
401
ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
402
{
403
   if ( bucketIndex == bucketsSize_ - 1 )
404
      return tailLink_;
405
   ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
406
   if ( !previous )
407
      previous = &buckets_[bucketIndex];
408
   return previous;
409
}
410
 
411
 
412
Value &
413
ValueInternalMap::setNewItem( const char *key, 
414
                              bool isStatic,
415
                              ValueInternalLink *link, 
416
                              BucketIndex index )
417
{
418
   char *duplicatedKey = valueAllocator()->makeMemberName( key );
419
   ++itemCount_;
420
   link->keys_[index] = duplicatedKey;
421
   link->items_[index].setItemUsed();
422
   link->items_[index].setMemberNameIsStatic( isStatic );
423
   return link->items_[index]; // items already default constructed.
424
}
425
 
426
 
427
Value &
428
ValueInternalMap::unsafeAdd( const char *key, 
429
                             bool isStatic, 
430
                             HashKey hashedKey )
431
{
432
   JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
433
   BucketIndex bucketIndex = hashedKey % bucketsSize_;
434
   ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
435
   ValueInternalLink *link = previousLink;
436
   BucketIndex index;
437
   for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
438
   {
439
      if ( link->items_[index].isItemAvailable() )
440
         break;
441
   }
442
   if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
443
   {
444
      ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
445
      index = 0;
446
      link->next_ = newLink;
447
      previousLink = newLink;
448
      link = newLink;
449
   }
450
   return setNewItem( key, isStatic, link, index );
451
}
452
 
453
 
454
ValueInternalMap::HashKey 
455
ValueInternalMap::hash( const char *key ) const
456
{
457
   HashKey hash = 0;
458
   while ( *key )
459
      hash += *key++ * 37;
460
   return hash;
461
}
462
 
463
 
464
int 
465
ValueInternalMap::compare( const ValueInternalMap &other ) const
466
{
467
   int sizeDiff( itemCount_ - other.itemCount_ );
468
   if ( sizeDiff != 0 )
469
      return sizeDiff;
470
   // Strict order guaranty is required. Compare all keys FIRST, then compare values.
471
   IteratorState it;
472
   IteratorState itEnd;
473
   makeBeginIterator( it );
474
   makeEndIterator( itEnd );
475
   for ( ; !equals(it,itEnd); increment(it) )
476
   {
477
      if ( !other.find( key( it ) ) )
478
         return 1;
479
   }
480
 
481
   // All keys are equals, let's compare values
482
   makeBeginIterator( it );
483
   for ( ; !equals(it,itEnd); increment(it) )
484
   {
485
      const Value *otherValue = other.find( key( it ) );
486
      int valueDiff = value(it).compare( *otherValue );
487
      if ( valueDiff != 0 )
488
         return valueDiff;
489
   }
490
   return 0;
491
}
492
 
493
 
494
void 
495
ValueInternalMap::makeBeginIterator( IteratorState &it ) const
496
{
497
   it.map_ = const_cast<ValueInternalMap *>( this );
498
   it.bucketIndex_ = 0;
499
   it.itemIndex_ = 0;
500
   it.link_ = buckets_;
501
}
502
 
503
 
504
void 
505
ValueInternalMap::makeEndIterator( IteratorState &it ) const
506
{
507
   it.map_ = const_cast<ValueInternalMap *>( this );
508
   it.bucketIndex_ = bucketsSize_;
509
   it.itemIndex_ = 0;
510
   it.link_ = 0;
511
}
512
 
513
 
514
bool 
515
ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
516
{
517
   return x.map_ == other.map_  
518
          &&  x.bucketIndex_ == other.bucketIndex_  
519
          &&  x.link_ == other.link_
520
          &&  x.itemIndex_ == other.itemIndex_;
521
}
522
 
523
 
524
void 
525
ValueInternalMap::incrementBucket( IteratorState &iterator )
526
{
527
   ++iterator.bucketIndex_;
528
   JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
529
      "ValueInternalMap::increment(): attempting to iterate beyond end." );
530
   if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
531
      iterator.link_ = 0;
532
   else
533
      iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
534
   iterator.itemIndex_ = 0;
535
}
536
 
537
 
538
void 
539
ValueInternalMap::increment( IteratorState &iterator )
540
{
541
   JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
542
   ++iterator.itemIndex_;
543
   if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
544
   {
545
      JSON_ASSERT_MESSAGE( iterator.link_ != 0,
546
         "ValueInternalMap::increment(): attempting to iterate beyond end." );
547
      iterator.link_ = iterator.link_->next_;
548
      if ( iterator.link_ == 0 )
549
         incrementBucket( iterator );
550
   }
551
   else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
552
   {
553
      incrementBucket( iterator );
554
   }
555
}
556
 
557
 
558
void 
559
ValueInternalMap::decrement( IteratorState &iterator )
560
{
561
   if ( iterator.itemIndex_ == 0 )
562
   {
563
      JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
564
      if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
565
      {
566
         JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
567
         --(iterator.bucketIndex_);
568
      }
569
      iterator.link_ = iterator.link_->previous_;
570
      iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
571
   }
572
}
573
 
574
 
575
const char *
576
ValueInternalMap::key( const IteratorState &iterator )
577
{
578
   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
579
   return iterator.link_->keys_[iterator.itemIndex_];
580
}
581
 
582
const char *
583
ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
584
{
585
   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
586
   isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
587
   return iterator.link_->keys_[iterator.itemIndex_];
588
}
589
 
590
 
591
Value &
592
ValueInternalMap::value( const IteratorState &iterator )
593
{
594
   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
595
   return iterator.link_->items_[iterator.itemIndex_];
596
}
597
 
598
 
599
int 
600
ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
601
{
602
   int offset = 0;
603
   IteratorState it = x;
604
   while ( !equals( it, y ) )
605
      increment( it );
606
   return offset;
607
}