JsonCpp project page JsonCpp home page

json_internalarray.inl

Go to the documentation of this file.
00001 // Copyright 2007-2010 Baptiste Lepilleur
00002 // Distributed under MIT license, or public domain if desired and
00003 // recognized in your jurisdiction.
00004 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
00005 
00006 // included by json_value.cpp
00007 
00008 namespace Json {
00009 
00010 // //////////////////////////////////////////////////////////////////
00011 // //////////////////////////////////////////////////////////////////
00012 // //////////////////////////////////////////////////////////////////
00013 // class ValueInternalArray
00014 // //////////////////////////////////////////////////////////////////
00015 // //////////////////////////////////////////////////////////////////
00016 // //////////////////////////////////////////////////////////////////
00017 
00018 ValueArrayAllocator::~ValueArrayAllocator()
00019 {
00020 }
00021 
00022 // //////////////////////////////////////////////////////////////////
00023 // class DefaultValueArrayAllocator
00024 // //////////////////////////////////////////////////////////////////
00025 #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00026 class DefaultValueArrayAllocator : public ValueArrayAllocator
00027 {
00028 public: // overridden from ValueArrayAllocator
00029    virtual ~DefaultValueArrayAllocator()
00030    {
00031    }
00032 
00033    virtual ValueInternalArray *newArray()
00034    {
00035       return new ValueInternalArray();
00036    }
00037 
00038    virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
00039    {
00040       return new ValueInternalArray( other );
00041    }
00042 
00043    virtual void destructArray( ValueInternalArray *array )
00044    {
00045       delete array;
00046    }
00047 
00048    virtual void reallocateArrayPageIndex( Value **&indexes, 
00049                                           ValueInternalArray::PageIndex &indexCount,
00050                                           ValueInternalArray::PageIndex minNewIndexCount )
00051    {
00052       ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
00053       if ( minNewIndexCount > newIndexCount )
00054          newIndexCount = minNewIndexCount;
00055       void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
00056       if ( !newIndexes )
00057          throw std::bad_alloc();
00058       indexCount = newIndexCount;
00059       indexes = static_cast<Value **>( newIndexes );
00060    }
00061    virtual void releaseArrayPageIndex( Value **indexes, 
00062                                        ValueInternalArray::PageIndex indexCount )
00063    {
00064       if ( indexes )
00065          free( indexes );
00066    }
00067 
00068    virtual Value *allocateArrayPage()
00069    {
00070       return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
00071    }
00072 
00073    virtual void releaseArrayPage( Value *value )
00074    {
00075       if ( value )
00076          free( value );
00077    }
00078 };
00079 
00080 #else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00082 class DefaultValueArrayAllocator : public ValueArrayAllocator
00083 {
00084 public: // overridden from ValueArrayAllocator
00085    virtual ~DefaultValueArrayAllocator()
00086    {
00087    }
00088 
00089    virtual ValueInternalArray *newArray()
00090    {
00091       ValueInternalArray *array = arraysAllocator_.allocate();
00092       new (array) ValueInternalArray(); // placement new
00093       return array;
00094    }
00095 
00096    virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
00097    {
00098       ValueInternalArray *array = arraysAllocator_.allocate();
00099       new (array) ValueInternalArray( other ); // placement new
00100       return array;
00101    }
00102 
00103    virtual void destructArray( ValueInternalArray *array )
00104    {
00105       if ( array )
00106       {
00107          array->~ValueInternalArray();
00108          arraysAllocator_.release( array );
00109       }
00110    }
00111 
00112    virtual void reallocateArrayPageIndex( Value **&indexes, 
00113                                           ValueInternalArray::PageIndex &indexCount,
00114                                           ValueInternalArray::PageIndex minNewIndexCount )
00115    {
00116       ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
00117       if ( minNewIndexCount > newIndexCount )
00118          newIndexCount = minNewIndexCount;
00119       void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
00120       if ( !newIndexes )
00121          throw std::bad_alloc();
00122       indexCount = newIndexCount;
00123       indexes = static_cast<Value **>( newIndexes );
00124    }
00125    virtual void releaseArrayPageIndex( Value **indexes, 
00126                                        ValueInternalArray::PageIndex indexCount )
00127    {
00128       if ( indexes )
00129          free( indexes );
00130    }
00131 
00132    virtual Value *allocateArrayPage()
00133    {
00134       return static_cast<Value *>( pagesAllocator_.allocate() );
00135    }
00136 
00137    virtual void releaseArrayPage( Value *value )
00138    {
00139       if ( value )
00140          pagesAllocator_.release( value );
00141    }
00142 private:
00143    BatchAllocator<ValueInternalArray,1> arraysAllocator_;
00144    BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
00145 };
00146 #endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00147 
00148 static ValueArrayAllocator *&arrayAllocator()
00149 {
00150    static DefaultValueArrayAllocator defaultAllocator;
00151    static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
00152    return arrayAllocator;
00153 }
00154 
00155 static struct DummyArrayAllocatorInitializer {
00156    DummyArrayAllocatorInitializer() 
00157    {
00158       arrayAllocator();      // ensure arrayAllocator() statics are initialized before main().
00159    }
00160 } dummyArrayAllocatorInitializer;
00161 
00162 // //////////////////////////////////////////////////////////////////
00163 // class ValueInternalArray
00164 // //////////////////////////////////////////////////////////////////
00165 bool 
00166 ValueInternalArray::equals( const IteratorState &x, 
00167                             const IteratorState &other )
00168 {
00169    return x.array_ == other.array_  
00170           &&  x.currentItemIndex_ == other.currentItemIndex_  
00171           &&  x.currentPageIndex_ == other.currentPageIndex_;
00172 }
00173 
00174 
00175 void 
00176 ValueInternalArray::increment( IteratorState &it )
00177 {
00178    JSON_ASSERT_MESSAGE( it.array_  &&
00179       (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
00180       != it.array_->size_,
00181       "ValueInternalArray::increment(): moving iterator beyond end" );
00182    ++(it.currentItemIndex_);
00183    if ( it.currentItemIndex_ == itemsPerPage )
00184    {
00185       it.currentItemIndex_ = 0;
00186       ++(it.currentPageIndex_);
00187    }
00188 }
00189 
00190 
00191 void 
00192 ValueInternalArray::decrement( IteratorState &it )
00193 {
00194    JSON_ASSERT_MESSAGE( it.array_  &&  it.currentPageIndex_ == it.array_->pages_ 
00195                         &&  it.currentItemIndex_ == 0,
00196       "ValueInternalArray::decrement(): moving iterator beyond end" );
00197    if ( it.currentItemIndex_ == 0 )
00198    {
00199       it.currentItemIndex_ = itemsPerPage-1;
00200       --(it.currentPageIndex_);
00201    }
00202    else
00203    {
00204       --(it.currentItemIndex_);
00205    }
00206 }
00207 
00208 
00209 Value &
00210 ValueInternalArray::unsafeDereference( const IteratorState &it )
00211 {
00212    return (*(it.currentPageIndex_))[it.currentItemIndex_];
00213 }
00214 
00215 
00216 Value &
00217 ValueInternalArray::dereference( const IteratorState &it )
00218 {
00219    JSON_ASSERT_MESSAGE( it.array_  &&
00220       (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
00221       < it.array_->size_,
00222       "ValueInternalArray::dereference(): dereferencing invalid iterator" );
00223    return unsafeDereference( it );
00224 }
00225 
00226 void 
00227 ValueInternalArray::makeBeginIterator( IteratorState &it ) const
00228 {
00229    it.array_ = const_cast<ValueInternalArray *>( this );
00230    it.currentItemIndex_ = 0;
00231    it.currentPageIndex_ = pages_;
00232 }
00233 
00234 
00235 void 
00236 ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
00237 {
00238    it.array_ = const_cast<ValueInternalArray *>( this );
00239    it.currentItemIndex_ = index % itemsPerPage;
00240    it.currentPageIndex_ = pages_ + index / itemsPerPage;
00241 }
00242 
00243 
00244 void 
00245 ValueInternalArray::makeEndIterator( IteratorState &it ) const
00246 {
00247    makeIterator( it, size_ );
00248 }
00249 
00250 
00251 ValueInternalArray::ValueInternalArray()
00252    : pages_( 0 )
00253    , size_( 0 )
00254    , pageCount_( 0 )
00255 {
00256 }
00257 
00258 
00259 ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
00260    : pages_( 0 )
00261    , pageCount_( 0 )
00262    , size_( other.size_ )
00263 {
00264    PageIndex minNewPages = other.size_ / itemsPerPage;
00265    arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
00266    JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, 
00267                         "ValueInternalArray::reserve(): bad reallocation" );
00268    IteratorState itOther;
00269    other.makeBeginIterator( itOther );
00270    Value *value;
00271    for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
00272    {
00273       if ( index % itemsPerPage == 0 )
00274       {
00275          PageIndex pageIndex = index / itemsPerPage;
00276          value = arrayAllocator()->allocateArrayPage();
00277          pages_[pageIndex] = value;
00278       }
00279       new (value) Value( dereference( itOther ) );
00280    }
00281 }
00282 
00283 
00284 ValueInternalArray &
00285 ValueInternalArray::operator =( const ValueInternalArray &other )
00286 {
00287    ValueInternalArray temp( other );
00288    swap( temp );
00289    return *this;
00290 }
00291 
00292 
00293 ValueInternalArray::~ValueInternalArray()
00294 {
00295    // destroy all constructed items
00296    IteratorState it;
00297    IteratorState itEnd;
00298    makeBeginIterator( it);
00299    makeEndIterator( itEnd );
00300    for ( ; !equals(it,itEnd); increment(it) )
00301    {
00302       Value *value = &dereference(it);
00303       value->~Value();
00304    }
00305    // release all pages
00306    PageIndex lastPageIndex = size_ / itemsPerPage;
00307    for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
00308       arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
00309    // release pages index
00310    arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
00311 }
00312 
00313 
00314 void 
00315 ValueInternalArray::swap( ValueInternalArray &other )
00316 {
00317    Value **tempPages = pages_;
00318    pages_ = other.pages_;
00319    other.pages_ = tempPages;
00320    ArrayIndex tempSize = size_;
00321    size_ = other.size_;
00322    other.size_ = tempSize;
00323    PageIndex tempPageCount = pageCount_;
00324    pageCount_ = other.pageCount_;
00325    other.pageCount_ = tempPageCount;
00326 }
00327 
00328 void 
00329 ValueInternalArray::clear()
00330 {
00331    ValueInternalArray dummy;
00332    swap( dummy );
00333 }
00334 
00335 
00336 void 
00337 ValueInternalArray::resize( ArrayIndex newSize )
00338 {
00339    if ( newSize == 0 )
00340       clear();
00341    else if ( newSize < size_ )
00342    {
00343       IteratorState it;
00344       IteratorState itEnd;
00345       makeIterator( it, newSize );
00346       makeIterator( itEnd, size_ );
00347       for ( ; !equals(it,itEnd); increment(it) )
00348       {
00349          Value *value = &dereference(it);
00350          value->~Value();
00351       }
00352       PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
00353       PageIndex lastPageIndex = size_ / itemsPerPage;
00354       for ( ; pageIndex < lastPageIndex; ++pageIndex )
00355          arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
00356       size_ = newSize;
00357    }
00358    else if ( newSize > size_ )
00359       resolveReference( newSize );
00360 }
00361 
00362 
00363 void 
00364 ValueInternalArray::makeIndexValid( ArrayIndex index )
00365 {
00366    // Need to enlarge page index ?
00367    if ( index >= pageCount_ * itemsPerPage )
00368    {
00369       PageIndex minNewPages = (index + 1) / itemsPerPage;
00370       arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
00371       JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
00372    }
00373 
00374    // Need to allocate new pages ?
00375    ArrayIndex nextPageIndex = 
00376       (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
00377                                   : size_;
00378    if ( nextPageIndex <= index )
00379    {
00380       PageIndex pageIndex = nextPageIndex / itemsPerPage;
00381       PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
00382       for ( ; pageToAllocate-- > 0; ++pageIndex )
00383          pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
00384    }
00385 
00386    // Initialize all new entries
00387    IteratorState it;
00388    IteratorState itEnd;
00389    makeIterator( it, size_ );
00390    size_ = index + 1;
00391    makeIterator( itEnd, size_ );
00392    for ( ; !equals(it,itEnd); increment(it) )
00393    {
00394       Value *value = &dereference(it);
00395       new (value) Value(); // Construct a default value using placement new
00396    }
00397 }
00398 
00399 Value &
00400 ValueInternalArray::resolveReference( ArrayIndex index )
00401 {
00402    if ( index >= size_ )
00403       makeIndexValid( index );
00404    return pages_[index/itemsPerPage][index%itemsPerPage];
00405 }
00406 
00407 Value *
00408 ValueInternalArray::find( ArrayIndex index ) const
00409 {
00410    if ( index >= size_ )
00411       return 0;
00412    return &(pages_[index/itemsPerPage][index%itemsPerPage]);
00413 }
00414 
00415 ValueInternalArray::ArrayIndex 
00416 ValueInternalArray::size() const
00417 {
00418    return size_;
00419 }
00420 
00421 int 
00422 ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
00423 {
00424    return indexOf(y) - indexOf(x);
00425 }
00426 
00427 
00428 ValueInternalArray::ArrayIndex 
00429 ValueInternalArray::indexOf( const IteratorState &iterator )
00430 {
00431    if ( !iterator.array_ )
00432       return ArrayIndex(-1);
00433    return ArrayIndex(
00434       (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage 
00435       + iterator.currentItemIndex_ );
00436 }
00437 
00438 
00439 int 
00440 ValueInternalArray::compare( const ValueInternalArray &other ) const
00441 {
00442    int sizeDiff( size_ - other.size_ );
00443    if ( sizeDiff != 0 )
00444       return sizeDiff;
00445    
00446    for ( ArrayIndex index =0; index < size_; ++index )
00447    {
00448       int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare( 
00449          other.pages_[index/itemsPerPage][index%itemsPerPage] );
00450       if ( diff != 0 )
00451          return diff;
00452    }
00453    return 0;
00454 }
00455 
00456 } // namespace Json

SourceForge Logo hosts this site. Send comments to:
Json-cpp Developers