Diff for /parser3/src/include/pa_array.h between versions 1.17 and 1.57.2.5

version 1.17, 2001/02/21 17:36:29 version 1.57.2.5, 2003/01/23 17:05:33
Line 1 Line 1
 /*  /** @file
   $Id$          Parser: Array & Array_iterator classes decls.
 */  
   
 /*  
   
         Array               Chunk0  
         ======              ========  
         head--------------->[ptr]  
         append_here-------->[ptr]  
         link_row            ........  
                         .                       .  
                         .                       [ptr]  
                         ...........>[link to the next chunk]  
   
           Copyright (c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com)
           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
   
 #include <stddef.h>  static const char* IDENT_ARRAY_Y="$Date$";
   
 #include "pa_pool.h"  #include "pa_pool.h"
 #include "pa_types.h"  #include "pa_exception.h"
 #include "pa_string.h"  
   
 class Array : public Pooled {  template<typename T> class Array_iterator;
 public:  
   /**     
           Simple Array.
   
         typedef void Item;  */
   template<typename T> class Array: public PA_Object {
   
         enum {          friend class Array_iterator;
                 CR_INITIAL_ROWS_DEFAULT=10,  
                 CR_GROW_PERCENT=60          // allocated size
         };          int fallocated;
   
 public:  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);
   
                   felements=new T[fallocated];
           }
           override ~Array() {
                   T *last=felements+fused;
                   for(T *current=felements; current<last; current++)
                           delete current;
   
                   delete 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;
   
         Array(Pool& apool, int initial_rows=CR_INITIAL_ROWS_DEFAULT);                  return *this;
           }
   
         int size() const { return fused_rows; }          /// append other Array portion to this one. starting from offset
         Array& operator += (Item *src);          Array& append(const Array& src, int offset=0, int limit=0) {
         Array& append_array(const Array& src);                  if(!(offset>=0 && offset<src.count())) {
         Item *quick_get(int index) const {                          throw Exception(0, 
                 // considering these true:                                  Exception::undefined_source,
                 //   index increments from 0 to size()-1                                  "Array::append(offset=%d) out of range [0..%d]", offset, src.count()-1);
                 //   index>=0 && index<size()                          //return 0; // never
                 //   index>=cache_chunk_base                  }
                   // fix limit
                 // next chunk will be with "index" row                  {
                 if(!(index<cache_chunk_base+cache_chunk->count)) {                          int m=src.count()-offset;
                         int count=cache_chunk->count;                          if(!m || limit<0)
                         cache_chunk_base+=count;                                  return *this;
                         cache_chunk=cache_chunk->rows[count].link;                          if(!limit || limit>m)
                                   limit=m;
                 }                  }
                   
                 return cache_chunk->rows[index-cache_chunk_base].item;                  int needed=limit-(fallocated-fused);
                   if(needed>0)
                           expand(needed);
   
                   memcpy(&felements[fused+=limit], &src.felements[offset], limit*sizeof(T));
                   return *this;
           }
   
           /// get index-element
           T get(int index) const {
                   if(!(index>=0 && index<count())) {
                           throw Exception(0, 
                                   Exception::undefined_source,
                                   "Array::get(%d) out of range [0..%d]", index, count()-1);
                           return 0; // never
                   }
   
                   return felements[index];
         }          }
   
         Item *get(int index) const;          /// put index-element
         void put(int index, Item *item);          void put(int index, T element) {
         const char *get_cstr(int index) const {                   if(!(index>=0 && index<size())) {
                 return static_cast<const char *>(get(index));                           throw Exception(0, 
                                   Exception::undefined_source, 
                                   "Array::put(%d) out of range [0..%d]", index, size()-1);
                           return; // never
                   }
                   felements[index]=element;
         }          }
         const String *get_string(int index) const {   
                 return static_cast<const String *>(get(index));   
           /// iterate over all elements
           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);
         }          }
   
 private:          /// 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;
   
         struct Chunk {                  return 0;
                 // the number of rows in chunk  
                 int count;  
                 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  protected:
         // helps appending Arrays  
         Chunk *tail;  
   
         // next append would write to this record          // default expand delta size
         Chunk::Row *append_here;          int fdelta;
           
         // the address of place where lies address   
         // of the link to the next chunk to allocate  
         Chunk::Row *link_row;  
   
 private:          /// elements[growing size] here
           T *felements;
   
         // array size          // array size
         int fused_rows;          int fused;
   
         mutable int cache_chunk_base;          bool is_full() {
         mutable Chunk *cache_chunk;                  return fused == fallocated;
                   }
 private:          void expand(int delta) {
                   fallocated+=delta;
         bool chunk_is_full() {                  felements = (T *)pa_realloc(felements, fallocated*sizeof(T));
                 return append_here == link_row;  
         }          }
         void expand(int chunk_rows);  
   
 private: //disabled  private: //disabled
   
         //Array(Array&) { }  
         Array& operator = (const Array&) { return *this; }          Array& operator = (const Array&) { return *this; }
 };  };
   
   typedef smart_ptr<char> CharPtr;
   
   class Pool: public Array<CharPtr> {
   public:
           char *malloc(size_t size) {
                   CharPtr result=CharPtr(new char[size]);
                   *this += result;
                   return result.get();
           }
   };
   
   /// handy array iterator
   template<typename T> class Array_iterator {
   
           const Array<T>& farray;
           T *fcurrent;
           T *flast;
   
   public:
   
           Array_iterator(const Array<T>& aarray) : farray(aarray) {
                   fcurrent(farray.felements);
                   flast=farray+farray.count();
           }
   
           /// there are still elements
           bool has_next() {
                   return fcurrent<flast;
           }
   
           /// quickly extracts next Array element
           T next() {
                   return *(furrent++);
           }
   
   };
   
 #endif  #endif

Removed from v.1.17  
changed lines
  Added in v.1.57.2.5


E-mail: