Diff for /parser3/src/include/pa_array.h between versions 1.36 and 1.57.2.26

version 1.36, 2001/04/26 14:55:25 version 1.57.2.26, 2003/02/26 10:17:30
Line 1 Line 1
 /** @file  /** @file
         Parser: array class decl.          Parser: Array & Array_iterator classes decls.
   
         Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)          Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
           Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
         Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)  
   
         $Id$  
 */  */
   
 #ifndef PA_ARRAY_H  #ifndef PA_ARRAY_H
 #define PA_ARRAY_H  #define PA_ARRAY_H
   
 #include <stddef.h>  static const char* IDENT_ARRAY_H="$Date$";
   
 #include "pa_pool.h"  // includes
 #include "pa_types.h"  
 #include "pa_string.h"  
   
 /**       
         Pooled Array.  
   
         Internal structure:  
         @verbatim  
                 Array               Chunk0  
                 ======              ========  
                 head--------------->[ptr]  
                 append_here-------->[ptr]  
                 link_row            ........  
                                 .                       .  
                                 .                       [ptr]  
                                 ...........>[link to the next chunk]  
         @endverbatim  
 */  
   
 class Array : public Pooled {  #include "pa_memory.h"
 public:  #include "pa_exception.h"
   
         /// Array item type  // forwards
         typedef void Item;  
   
         /*/// for_each iterator function type, const info  template<typename T> class Array_iterator;
         typedef void (*For_each_func_const)(Item *value, const void *info);  
         */  
   
         /// for_each iterator function type  
         typedef void (*For_each_func)(Item *value, void *info);  
   
         /// first_that iterator function type, const info  
         typedef bool (*First_that_func_const)(Item *value, const void *info);  
   
         /// first_that iterator function type  
         typedef bool (*First_that_func)(Item *value, void *info);  
   
         enum {  
                 CR_INITIAL_ROWS_DEFAULT=10, ///< default preallocated row count  
                 CR_GROW_PERCENT=60 ///< each time the Array chunk_is_full() array expanded()  
         };  
   
 public:  /// Simple Array
   template<typename T> class Array: public PA_Object {
   
         Array(Pool& apool, int initial_rows=CR_INITIAL_ROWS_DEFAULT);          friend class Array_iterator<T>;
   
         /**  protected:
                 size Array. how many items are in it.   
                 must be used with quick_get like this:  
                 @code  
                         int size=src.quick_size();  
                         for(int i=0; i<size; i++) {  
                                 z=src.quick_get(i);  
                         }  
                 @endcode  
         */  
         int quick_size() const {   
                 // for quick_get  
                 cache_chunk_base=0;  
                 cache_chunk=head;  
                 return size();   
         }  
         /// size Array. how many items are in it  
         int size() const { return fused_rows; }  
         /// append Item to array  
         Array& operator += (Item *src);  
   
         /// dirty hack to allow constant items storage. I long for Array<const Item*>          // default expand delta size
         Array& operator += (const Item *src) { return *this+=const_cast<Item*>(src); }          int fdelta;
   
         /// append other Array portion to this one. starting from offset          /// elements[growing size] here
         Array& append_array(const Array& src, int offset=0);          T *felements;
   
           // allocated size
           int fallocated;
   
           // array size
           int fused;
   
   public:
           typedef T element_type;
   
           Array(int initial=3, int delta=1):
                   fallocated(initial?initial:3),
                   fdelta(delta),
                   fused(0)
           {
                   if(fallocated<=0 || fdelta<1)
                           throw Exception(0, 
                                   Exception::undefined_source,
                                   "Array::Array(%d, %d) too small", initial, delta);
   
                   // we can't use new(0) here[like we did in Hash] because we need to use realloc
                   // on MSVC new returns NOT pointer learned from pa_malloc, so we can't do new+realloc
                   felements=static_cast<T*>(calloc(fallocated*sizeof(T)));
           }
           override ~Array() {
                   // see comment in ctor
                   T *last=felements+fused;
                   for(T *current=felements; current<last; current++)
                           current->~T(); // manually invoking destructors
   
                   free(felements);
           }
   
           /// how many items are in Array
           int count() const { return fused; }
           /// append to array
           Array& operator += (T src) {
                   if(is_full())
                           expand(fdelta);
   
         /**                   felements[fused++]=src;
                 quickly gets some item considering...  
   
                 these true:                  return *this;
                         - index increments from 0 to size()-1          }
                         - index>=0 && index<size()  
                         - index>=cache_chunk_base          /// append other Array portion to this one. starting from offset
         */          Array& append(const Array& src, int offset=0, int limit=0) {
         Item *quick_get(int index) const {                  if(offset<0) {
                 // next chunk will be with "index" row                          throw Exception(0, 
                 if(!(index<cache_chunk_base+cache_chunk->count)) {                                  Exception::undefined_source,
                         int count=cache_chunk->count;                                  "Array::append(offset=%d) out <0", offset);
                         cache_chunk_base+=count;                          //return Nothing; // never
                         cache_chunk=cache_chunk->rows[count].link;  
                 }                  }
                   // fix limit
                   {
                           int m=src.count()-offset;
                           if(!m || limit<0)
                                   return *this;
                           if(!limit || limit>m)
                                   limit=m;
                   }
   
                   int delta=limit-(fallocated-fused);
                   if(delta>0)
                           expand(delta);
   
                   T* from=&src.felements[offset];
                   T* to=&felements[fused];
                   T* from_end=from+limit;
                   while(from<from_end)
                           *to++=*from++;
                                   
                 return cache_chunk->rows[index-cache_chunk_base].item;                  fused+=limit;
                   return *this;
         }          }
   
         Item *get(int index) const;          /// get index-element
         void put(int index, Item *item);          T& get(int index) const {
         /// convinient way to get strings from Array. I long for Array<const String *>                  if(!(index>=0 && index<count())) {
         const String *get_string(int index) const {                           throw Exception(0, 
                 return const_cast<const String *>(static_cast<String *>(get(index)));                                   Exception::undefined_source,
                                   "Array::get(%d) out of range [0..%d]", index, count()-1);
                           return felements[0]; // never
                   }
   
                   return felements[index];
         }          }
         const String *quick_get_string(int index) const {   
                 return const_cast<const String *>(static_cast<String *>(quick_get(index)));           T& operator [](int index) const { return get(index); }
   
           /// put index-element
           void put(int index, T& element) {
                   if(!(index>=0 && index<count())) {
                           throw Exception(0, 
                                   Exception::undefined_source, 
                                   "Array::put(%d) out of range [0..%d]", index, count()-1);
                           return; // never
                   }
                   felements[index]=element;
         }          }
   
         /*/// iterate over all elements, const info  
         void for_each(For_each_func_const func, const void *info=0) const;  
         /*/  
   
         /// iterate over all elements          /// iterate over all elements
         void for_each(For_each_func func, void *info=0) const;          template<typename I> void for_each(void (*callback)(T, I), I info) const {
                   T *last=felements+fused;
                   for(T *current=felements; current<last; current++)
                           callback(*current, info);
           }
   
         /// iterate over all elements until condition, const info          /// iterate over all elements until condition becomes true, return that element
         void* first_that(First_that_func_const func, const void *info=0) const;          template<typename I> T first_that(bool (*callback)(T, I), I info) const {
                   T *last=felements+fused;
                   for(T *current=felements; current<last; current++)
                           if(callback(*current, info))
                                   return *current;
   
                   return T(0);
           }
   
         /// iterate over all elements until condition  protected:
         void* first_that(First_that_func func, void *info=0) const;  
   
 private:          bool is_full() {
                   return fused == fallocated;
         /// several record elements          }
         struct Chunk {          void expand(int delta) {
                 int count;  ///< the number of rows in chunk                  felements = (T *)realloc(felements, (fallocated+delta)*sizeof(T));
                 /// item or a link to next chunk union                  memset(&felements[fallocated], 0, delta*sizeof(T));
                 union Row {                  fallocated+=delta;
                         Item *item;          }
                         Chunk *link;  ///< link to the next chunk in chain  
                 } rows[1];  
                 // next rows are here  
         }  
                 *head;  ///< the head chunk of the chunk chain  
   
         /** last allocated chunk  
                 helps appending Arrays  
         */  
         Chunk *tail;  
   
         /// next append would write to this record  
         Chunk::Row *append_here;  
           
         /**     the address of place where lies address   
                 of the link to the next chunk to allocate  
         */  
         Chunk::Row *link_row;  
   
 private:  private: //disabled
   
         // array size          Array& operator = (const Array&) { return *this; }
         int fused_rows;  };
   
   
   /// handy array iterator
   template<typename T> class Array_iterator {
   
           Array<T>& farray;
           T *fcurrent;
           T *flast;
   
   public:
   
         mutable int cache_chunk_base;          Array_iterator(Array<T>& aarray): farray(aarray) {
         mutable Chunk *cache_chunk;                  fcurrent=farray.felements;
                           flast=farray.felements+farray.count();
 private:          }
   
         bool chunk_is_full() {          /// there are still elements
                 return append_here == link_row;          bool has_next() {
                   return fcurrent<flast;
         }          }
         void expand(int chunk_rows);  
   
 private: //disabled          /// quickly extracts next Array element
           T& next() {
                   return *(fcurrent++);
           }
   
         //Array(Array&) { }  
         Array& operator = (const Array&) { return *this; }  
 };  };
   
 #endif  #endif

Removed from v.1.36  
changed lines
  Added in v.1.57.2.26


E-mail: