Drizzled Public API Documentation

json_internalarray.inl
00001 /*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00002  * 
00003  *  JSON Library, originally from http://jsoncpp.sourceforge.net/
00004  *
00005  *  Copyright (C) 2011 Stewart Smith
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions are
00010  *  met:
00011  *
00012  *      * Redistributions of source code must retain the above copyright
00013  *  notice, this list of conditions and the following disclaimer.
00014  *
00015  *      * Redistributions in binary form must reproduce the above
00016  *  copyright notice, this list of conditions and the following disclaimer
00017  *  in the documentation and/or other materials provided with the
00018  *  distribution.
00019  *
00020  *      * The names of its contributors may not be used to endorse or
00021  *  promote products derived from this software without specific prior
00022  *  written permission.
00023  *
00024  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00027  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 
00038 #pragma once
00039 // included by json_value.cpp
00040 // everything is within Json namespace
00041 
00042 // //////////////////////////////////////////////////////////////////
00043 // //////////////////////////////////////////////////////////////////
00044 // //////////////////////////////////////////////////////////////////
00045 // class ValueInternalArray
00046 // //////////////////////////////////////////////////////////////////
00047 // //////////////////////////////////////////////////////////////////
00048 // //////////////////////////////////////////////////////////////////
00049 
00050 ValueArrayAllocator::~ValueArrayAllocator()
00051 {
00052 }
00053 
00054 // //////////////////////////////////////////////////////////////////
00055 // class DefaultValueArrayAllocator
00056 // //////////////////////////////////////////////////////////////////
00057 #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00058 class DefaultValueArrayAllocator : public ValueArrayAllocator
00059 {
00060 public: // overridden from ValueArrayAllocator
00061    virtual ~DefaultValueArrayAllocator()
00062    {
00063    }
00064 
00065    virtual ValueInternalArray *newArray()
00066    {
00067       return new ValueInternalArray();
00068    }
00069 
00070    virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
00071    {
00072       return new ValueInternalArray( other );
00073    }
00074 
00075    virtual void destructArray( ValueInternalArray *array )
00076    {
00077       delete array;
00078    }
00079 
00080    virtual void reallocateArrayPageIndex( Value **&indexes, 
00081                                           ValueInternalArray::PageIndex &indexCount,
00082                                           ValueInternalArray::PageIndex minNewIndexCount )
00083    {
00084       ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
00085       if ( minNewIndexCount > newIndexCount )
00086          newIndexCount = minNewIndexCount;
00087       void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
00088       if ( !newIndexes )
00089          throw std::bad_alloc();
00090       indexCount = newIndexCount;
00091       indexes = static_cast<Value **>( newIndexes );
00092    }
00093    virtual void releaseArrayPageIndex( Value **indexes, 
00094                                        ValueInternalArray::PageIndex indexCount )
00095    {
00096       free( indexes );
00097    }
00098 
00099    virtual Value *allocateArrayPage()
00100    {
00101       return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
00102    }
00103 
00104    virtual void releaseArrayPage( Value *value )
00105    {
00106       free( value );
00107    }
00108 };
00109 
00110 #else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00111 
00112 class DefaultValueArrayAllocator : public ValueArrayAllocator
00113 {
00114 public: // overridden from ValueArrayAllocator
00115    virtual ~DefaultValueArrayAllocator()
00116    {
00117    }
00118 
00119    virtual ValueInternalArray *newArray()
00120    {
00121       ValueInternalArray *array = arraysAllocator_.allocate();
00122       new (array) ValueInternalArray(); // placement new
00123       return array;
00124    }
00125 
00126    virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
00127    {
00128       ValueInternalArray *array = arraysAllocator_.allocate();
00129       new (array) ValueInternalArray( other ); // placement new
00130       return array;
00131    }
00132 
00133    virtual void destructArray( ValueInternalArray *array )
00134    {
00135       if ( array )
00136       {
00137          array->~ValueInternalArray();
00138          arraysAllocator_.release( array );
00139       }
00140    }
00141 
00142    virtual void reallocateArrayPageIndex( Value **&indexes, 
00143                                           ValueInternalArray::PageIndex &indexCount,
00144                                           ValueInternalArray::PageIndex minNewIndexCount )
00145    {
00146       ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
00147       if ( minNewIndexCount > newIndexCount )
00148          newIndexCount = minNewIndexCount;
00149       void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
00150       if ( !newIndexes )
00151          throw std::bad_alloc();
00152       indexCount = newIndexCount;
00153       indexes = static_cast<Value **>( newIndexes );
00154    }
00155    virtual void releaseArrayPageIndex( Value **indexes, 
00156                                        ValueInternalArray::PageIndex indexCount )
00157    {
00158       free( indexes );
00159    }
00160 
00161    virtual Value *allocateArrayPage()
00162    {
00163       return static_cast<Value *>( pagesAllocator_.allocate() );
00164    }
00165 
00166    virtual void releaseArrayPage( Value *value )
00167    {
00168       if ( value )
00169          pagesAllocator_.release( value );
00170    }
00171 private:
00172    BatchAllocator<ValueInternalArray,1> arraysAllocator_;
00173    BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
00174 };
00175 #endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00176 
00177 static ValueArrayAllocator *&arrayAllocator()
00178 {
00179    static DefaultValueArrayAllocator defaultAllocator;
00180    static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
00181    return arrayAllocator;
00182 }
00183 
00184 static struct DummyArrayAllocatorInitializer {
00185    DummyArrayAllocatorInitializer() 
00186    {
00187       arrayAllocator();      // ensure arrayAllocator() statics are initialized before main().
00188    }
00189 } dummyArrayAllocatorInitializer;
00190 
00191 // //////////////////////////////////////////////////////////////////
00192 // class ValueInternalArray
00193 // //////////////////////////////////////////////////////////////////
00194 bool 
00195 ValueInternalArray::equals( const IteratorState &x, 
00196                             const IteratorState &other )
00197 {
00198    return x.array_ == other.array_  
00199           &&  x.currentItemIndex_ == other.currentItemIndex_  
00200           &&  x.currentPageIndex_ == other.currentPageIndex_;
00201 }
00202 
00203 
00204 void 
00205 ValueInternalArray::increment( IteratorState &it )
00206 {
00207    JSON_ASSERT_MESSAGE( it.array_  &&
00208       (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
00209       != it.array_->size_,
00210       "ValueInternalArray::increment(): moving iterator beyond end" );
00211    ++(it.currentItemIndex_);
00212    if ( it.currentItemIndex_ == itemsPerPage )
00213    {
00214       it.currentItemIndex_ = 0;
00215       ++(it.currentPageIndex_);
00216    }
00217 }
00218 
00219 
00220 void 
00221 ValueInternalArray::decrement( IteratorState &it )
00222 {
00223    JSON_ASSERT_MESSAGE( it.array_  &&  it.currentPageIndex_ == it.array_->pages_ 
00224                         &&  it.currentItemIndex_ == 0,
00225       "ValueInternalArray::decrement(): moving iterator beyond end" );
00226    if ( it.currentItemIndex_ == 0 )
00227    {
00228       it.currentItemIndex_ = itemsPerPage-1;
00229       --(it.currentPageIndex_);
00230    }
00231    else
00232    {
00233       --(it.currentItemIndex_);
00234    }
00235 }
00236 
00237 
00238 Value &
00239 ValueInternalArray::unsafeDereference( const IteratorState &it )
00240 {
00241    return (*(it.currentPageIndex_))[it.currentItemIndex_];
00242 }
00243 
00244 
00245 Value &
00246 ValueInternalArray::dereference( const IteratorState &it )
00247 {
00248    JSON_ASSERT_MESSAGE( it.array_  &&
00249       (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
00250       < it.array_->size_,
00251       "ValueInternalArray::dereference(): dereferencing invalid iterator" );
00252    return unsafeDereference( it );
00253 }
00254 
00255 void 
00256 ValueInternalArray::makeBeginIterator( IteratorState &it ) const
00257 {
00258    it.array_ = const_cast<ValueInternalArray *>( this );
00259    it.currentItemIndex_ = 0;
00260    it.currentPageIndex_ = pages_;
00261 }
00262 
00263 
00264 void 
00265 ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
00266 {
00267    it.array_ = const_cast<ValueInternalArray *>( this );
00268    it.currentItemIndex_ = index % itemsPerPage;
00269    it.currentPageIndex_ = pages_ + index / itemsPerPage;
00270 }
00271 
00272 
00273 void 
00274 ValueInternalArray::makeEndIterator( IteratorState &it ) const
00275 {
00276    makeIterator( it, size_ );
00277 }
00278 
00279 
00280 ValueInternalArray::ValueInternalArray()
00281    : pages_( 0 )
00282    , size_( 0 )
00283    , pageCount_( 0 )
00284 {
00285 }
00286 
00287 
00288 ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
00289    : pages_( 0 )
00290    , pageCount_( 0 )
00291    , size_( other.size_ )
00292 {
00293    PageIndex minNewPages = other.size_ / itemsPerPage;
00294    arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
00295    JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, 
00296                         "ValueInternalArray::reserve(): bad reallocation" );
00297    IteratorState itOther;
00298    other.makeBeginIterator( itOther );
00299    Value *value;
00300    for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
00301    {
00302       if ( index % itemsPerPage == 0 )
00303       {
00304          PageIndex pageIndex = index / itemsPerPage;
00305          value = arrayAllocator()->allocateArrayPage();
00306          pages_[pageIndex] = value;
00307       }
00308       new (value) Value( dereference( itOther ) );
00309    }
00310 }
00311 
00312 
00313 ValueInternalArray &
00314 ValueInternalArray::operator =( const ValueInternalArray &other )
00315 {
00316    ValueInternalArray temp( other );
00317    swap( temp );
00318    return *this;
00319 }
00320 
00321 
00322 ValueInternalArray::~ValueInternalArray()
00323 {
00324    // destroy all constructed items
00325    IteratorState it;
00326    IteratorState itEnd;
00327    makeBeginIterator( it);
00328    makeEndIterator( itEnd );
00329    for ( ; !equals(it,itEnd); increment(it) )
00330    {
00331       Value *value = &dereference(it);
00332       value->~Value();
00333    }
00334    // release all pages
00335    PageIndex lastPageIndex = size_ / itemsPerPage;
00336    for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
00337       arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
00338    // release pages index
00339    arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
00340 }
00341 
00342 
00343 void 
00344 ValueInternalArray::swap( ValueInternalArray &other )
00345 {
00346    Value **tempPages = pages_;
00347    pages_ = other.pages_;
00348    other.pages_ = tempPages;
00349    ArrayIndex tempSize = size_;
00350    size_ = other.size_;
00351    other.size_ = tempSize;
00352    PageIndex tempPageCount = pageCount_;
00353    pageCount_ = other.pageCount_;
00354    other.pageCount_ = tempPageCount;
00355 }
00356 
00357 void 
00358 ValueInternalArray::clear()
00359 {
00360    ValueInternalArray dummy;
00361    swap( dummy );
00362 }
00363 
00364 
00365 void 
00366 ValueInternalArray::resize( ArrayIndex newSize )
00367 {
00368    if ( newSize == 0 )
00369       clear();
00370    else if ( newSize < size_ )
00371    {
00372       IteratorState it;
00373       IteratorState itEnd;
00374       makeIterator( it, newSize );
00375       makeIterator( itEnd, size_ );
00376       for ( ; !equals(it,itEnd); increment(it) )
00377       {
00378          Value *value = &dereference(it);
00379          value->~Value();
00380       }
00381       PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
00382       PageIndex lastPageIndex = size_ / itemsPerPage;
00383       for ( ; pageIndex < lastPageIndex; ++pageIndex )
00384          arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
00385       size_ = newSize;
00386    }
00387    else if ( newSize > size_ )
00388       resolveReference( newSize );
00389 }
00390 
00391 
00392 void 
00393 ValueInternalArray::makeIndexValid( ArrayIndex index )
00394 {
00395    // Need to enlarge page index ?
00396    if ( index >= pageCount_ * itemsPerPage )
00397    {
00398       PageIndex minNewPages = (index + 1) / itemsPerPage;
00399       arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
00400       JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
00401    }
00402 
00403    // Need to allocate new pages ?
00404    ArrayIndex nextPageIndex = 
00405       (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
00406                                   : size_;
00407    if ( nextPageIndex <= index )
00408    {
00409       PageIndex pageIndex = nextPageIndex / itemsPerPage;
00410       PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
00411       for ( ; pageToAllocate-- > 0; ++pageIndex )
00412          pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
00413    }
00414 
00415    // Initialize all new entries
00416    IteratorState it;
00417    IteratorState itEnd;
00418    makeIterator( it, size_ );
00419    size_ = index + 1;
00420    makeIterator( itEnd, size_ );
00421    for ( ; !equals(it,itEnd); increment(it) )
00422    {
00423       Value *value = &dereference(it);
00424       new (value) Value(); // Construct a default value using placement new
00425    }
00426 }
00427 
00428 Value &
00429 ValueInternalArray::resolveReference( ArrayIndex index )
00430 {
00431    if ( index >= size_ )
00432       makeIndexValid( index );
00433    return pages_[index/itemsPerPage][index%itemsPerPage];
00434 }
00435 
00436 Value *
00437 ValueInternalArray::find( ArrayIndex index ) const
00438 {
00439    if ( index >= size_ )
00440       return 0;
00441    return &(pages_[index/itemsPerPage][index%itemsPerPage]);
00442 }
00443 
00444 ValueInternalArray::ArrayIndex 
00445 ValueInternalArray::size() const
00446 {
00447    return size_;
00448 }
00449 
00450 int 
00451 ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
00452 {
00453    return indexOf(y) - indexOf(x);
00454 }
00455 
00456 
00457 ValueInternalArray::ArrayIndex 
00458 ValueInternalArray::indexOf( const IteratorState &iterator )
00459 {
00460    if ( !iterator.array_ )
00461       return ArrayIndex(-1);
00462    return ArrayIndex(
00463       (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage 
00464       + iterator.currentItemIndex_ );
00465 }
00466 
00467 
00468 int 
00469 ValueInternalArray::compare( const ValueInternalArray &other ) const
00470 {
00471    int sizeDiff( size_ - other.size_ );
00472    if ( sizeDiff != 0 )
00473       return sizeDiff;
00474    
00475    for ( ArrayIndex index =0; index < size_; ++index )
00476    {
00477       int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare( 
00478          other.pages_[index/itemsPerPage][index%itemsPerPage] );
00479       if ( diff != 0 )
00480          return diff;
00481    }
00482    return 0;
00483 }