Diff for /parser3/src/include/pa_array.h between versions 1.55 and 1.57.2.27.2.14

version 1.55, 2002/08/01 11:41:14 version 1.57.2.27.2.14, 2003/04/02 11:35:20
Line 1 Line 1
 /** @file  /** @file
         Parser: Array & Array_iter classes decls.          Parser: Array & Array_iterator classes decls.
   
         Copyright (c) 2001, 2002 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: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
 */  */
   
 #ifndef PA_ARRAY_H  #ifndef PA_ARRAY_H
 #define PA_ARRAY_H  #define PA_ARRAY_H
   
 static const char* IDENT_ARRAY_Y="$Date$";  static const char* IDENT_ARRAY_H="$Date$";
   
 #include "pa_pool.h"  // includes
 #include "pa_types.h"  
 #include "pa_string.h"  
   
 class Array_iter;  
   
 /**       
         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"
         friend class Array_iter;  #include "pa_exception.h"
 public:  
   // externals
   
   // forwards
   
   template<typename T> class Array_iterator;
   
   /// Simple Array
   template<typename T> class Array: public PA_Object {
   
         /// Array item type          friend class Array_iterator<T>;
         typedef void Item;  
   
         /*/// for_each iterator function type, const info  protected:
         typedef void (*For_each_func_const)(Item *value, const void *info);  
         */          /// elements[growing size] here
           T *felements;
         /// for_each iterator function type  
         typedef void (*For_each_func)(Item *value, void *info);          // allocated size
         /*          size_t fallocated;
         /// for_each iterator function type, passing item storage address  
         typedef void (*For_each_func_storage)(Item ** value, void *info);          // array size
         */          size_t fused;
   
         /// first_that iterator function type, const info  
         typedef void *(*Item_that_func_const)(Item *value, const void *info);  
   
         /// first_that iterator function type  
         typedef void *(*Item_that_func)(Item *value, void *info);  
   
         enum {  
                 CR_INITIAL_ROWS_DEFAULT=3, ///< default preallocated row count  
                 CR_GROW_COUNT=3 ///< each time the Array chunk_is_full() array expanded()  
         };  
   
 public:  public:
           typedef T element_type;
   
         Array(Pool& apool, int initial_rows=CR_INITIAL_ROWS_DEFAULT);          Array(int initial=3):
         Array(const Array& source, int offset=0);                  fallocated(initial>3?initial:3),
                   fused(0)
           {
                   felements=static_cast<T*>(malloc(fallocated*sizeof(T)));
           }
   
         /// size Array. how many items are in it          /// how many items are in Array
         int size() const { return fused_rows; }          size_t count() const { return fused; }
         /// append Item to array          /// append to array
         Array& operator += (Item *src);          Array& operator += (T src) {
         /// append int value to array                  if(is_full())
         Array& operator += (int value) { return *this+=reinterpret_cast<Item *>(value); }                          expand(2);
   
         /// dirty hack to allow constant items storage. I long for Array<const Item*>                  felements[fused++]=src;
         Array& operator += (const Item *src) { return *this+=const_cast<Item *>(src); }  
                   return *this;
           }
   
         /// append other Array portion to this one. starting from offset          /// append other Array portion to this one. starting from offset
         Array& append_array(const Array& src, int offset=0);          Array& append(const Array& src, int offset=0, int limit=0) {
                   if(offset<0) {
                           throw Exception(0, 
                                   0,
                                   "Array::append(offset=%d) out <0", offset);
                           //return Nothing; // never
                   }
                   // fix limit
                   {
                           int m=src.count()-offset;
                           if(!m || limit<0)
                                   return *this;
                           if(!limit || limit>m)
                                   limit=m;
                   }
   
         Item *get(int index) const;                  ssize_t delta=limit-(fallocated-fused);
         int get_int(int index) const { return reinterpret_cast<int>(get(index)); }                  if(delta>0)
                           expand(delta);
   
         void put(int index, Item *item);                  T* from=&src.felements[offset];
         void put_int(int index, int value) { put(index, reinterpret_cast<Item *>(value)); }                  T* to=&felements[fused];
         /// convinient way to get strings from Array. I long for Array<const String *>                  T* from_end=from+limit;
         const String *get_string(int index) const {                   while(from<from_end)
                 return const_cast<const String *>(static_cast<String *>(get(index)));                           *to++=*from++;
                   
                   fused+=limit;
                   return *this;
         }          }
   
         /*/// iterate over all elements, const info          /// get index-element
         void for_each(For_each_func_const func, const void *info=0) const;          T get(size_t index) const {
         */                  assert(index>=0 && index<count());
                   return felements[index];
           }
   
         /// iterate over all elements          /// ref version of get
         void for_each(For_each_func func, void *info=0) const;          T& get_ref(size_t index) const {
                   assert(index>=0 && index<count());
                   return felements[index];
           }
   
         /*/// iterate over all elements, passing address of item storage          /// put index-element
         void for_each(For_each_func_storage func, void *info=0);          void put(size_t index, T element) {
         */                  assert(index>=0 && index<count());
                   felements[index]=element;
         /// iterate over all elements until condition, const info          }
         void* first_that(Item_that_func_const func, const void *info=0) const;  
   
         /// iterate over all elements until condition  
         void* first_that(Item_that_func func, void *info=0) const;  
   
 private:  
   
         /// constructor helper  
         void construct_new(int initial_rows);  
   
 private:  
   
         /// several record elements  
         struct Chunk {  
                 int count;  ///< the number of rows in chunk  
                 /// item or a link to next chunk union  
                 union Row {  
                         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:          T operator [](size_t index) const { return get(index); }
   
         // array size          /// iterate over all elements
         int fused_rows;          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 becomes true, return that element
           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;
   
 private:                  return T(0);
           }
   
         bool chunk_is_full() {  protected:
                 return append_here == link_row;  
           bool is_full() {
                   return fused == fallocated;
           }
           void expand(size_t delta) {
                   size_t new_allocated=fallocated+delta;
                   felements = (T *)realloc(felements, new_allocated*sizeof(T));
                   memset(&felements[fallocated], 0, delta*sizeof(T));
                   fallocated=new_allocated;
         }          }
         void expand(int chunk_rows);  
   
 private: //disabled  private: //disabled
   
         //Array(Array&) { }          Array(const Array&) {}
         Array& operator = (const Array&) { return *this; }          Array& operator = (const Array&) { return *this; }
 };  };
   
   
 /// handy array iterator  /** Array iterator, usage:
 class Array_iter {          @code
           // Array<T> a;
           for(Array_iterator<T> i(a); i.has_next(); ) {
                   T& element=i.next();
                   ...
           }       
           @endcode
   */
   template<typename T> class Array_iterator {
   
           const Array<T>& farray;
           T *fcurrent;
           T *flast;
   
 public:  public:
   
         Array_iter(const Array& aarray) : array(aarray),          Array_iterator(const Array<T>& aarray): farray(aarray) {
                 chunk(aarray.head),                  fcurrent=farray.felements;
                 row(chunk->rows),                  flast=farray.felements+farray.count();
                 countdown(chunk->count) {  
         }          }
   
         /// there are still elements          /// there are still elements
         bool has_next() {          bool has_next() {
                 return !(chunk==array.tail && row==array.append_here);                  return fcurrent<flast;
         }          }
   
         /// quickly extracts next Array::Item          /// quickly extracts next Array element
         Array::Item *next() {          const T next() {
                 // assuming: never called after has_next()!                  return *(fcurrent++);
                 if(countdown==0) { // end of chunk?          }
                         chunk=row->link;  
                         row=chunk->rows;  };
                         countdown=chunk->count;  /*
                 }  /** Nonconst array iterator, usage:
                 Array::Item *result=row->item;          @code
                 row++;  countdown--;          // Array<T> a;
                 return result;          for(Array_iterator<T> i(a); i.has_next(); ) {
                   T& element=i.next();
                   ...
           }       
           @endcode
   * /
   template<typename T> class Array_modifing_iterator {
   
           Array<T>& farray;
           T *fcurrent;
           T *flast;
   
   public:
   
           Array_modifing_iterator(Array<T>& aarray): farray(aarray) {
                   fcurrent=farray.felements;
                   flast=farray.felements+farray.count();
         }          }
   
         /// quickly extracts next Array::Item as const String          /// there are still elements
         const String *next_string() {           bool has_next() {
                 return const_cast<const String *>(static_cast<String *>(next()));                   return fcurrent<flast;
         }          }
   
 private:          /// quickly extracts next Array element
         const Array& array;          T& next() {
         const Array::Chunk *chunk;                  return *(fcurrent++);
         const Array::Chunk::Row *row;          }
         int countdown;    
   
 };  };
   */
 #endif  #endif

Removed from v.1.55  
changed lines
  Added in v.1.57.2.27.2.14


E-mail: