Diff for /parser3/src/include/pa_array.h between versions 1.22 and 1.64

version 1.22, 2001/03/11 08:16:32 version 1.64, 2004/02/11 15:33:13
Line 1 Line 1
 /*  /** @file
         Parser          Parser: Array & Array_iterator classes decls.
         Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)  
         Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)  
   
         $Id$          Copyright (c) 2001-2004 ArtLebedev Group (http://www.artlebedev.com)
           Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
 */  */
   
 /*  #ifndef PA_ARRAY_H
   #define PA_ARRAY_H
   
         Array               Chunk0  static const char * const IDENT_ARRAY_Y="$Date$";
         ======              ========  
         head--------------->[ptr]  
         append_here-------->[ptr]  
         link_row            ........  
                         .                       .  
                         .                       [ptr]  
                         ...........>[link to the next chunk]  
   
 */  // includes
   
 #ifndef PA_ARRAY_H  #include "pa_memory.h"
 #define PA_ARRAY_H  #include "pa_exception.h"
   
 #include <stddef.h>  // forwards
   
 #include "pa_pool.h"  template<typename T> class Array_iterator;
 #include "pa_types.h"  
 #include "pa_string.h"  
   
 class Array : public Pooled {  // defines
 public:  
   
         typedef void Item;  #define ARRAY_OPTION_LIMIT_ALL ((size_t)-1)
   
         enum {  /// Simple Array
                 CR_INITIAL_ROWS_DEFAULT=10,  template<typename T> class Array: public PA_Object {
                 CR_GROW_PERCENT=60  
         };          friend class Array_iterator<T>;
   
   protected:
   
           /// elements[growing size] here
           T *felements;
   
           // allocated size
           size_t fallocated;
   
           // array size
           size_t fused;
   
 public:  public:
           struct Action_options {
                   size_t offset;
                   size_t limit; //< ARRAY_OPTION_LIMIT_ALL means 'all'. zero limit means 'nothing'
                   bool reverse;
                   bool defined;
                   
                   Action_options(
                           size_t aoffset=0, 
                           size_t alimit=ARRAY_OPTION_LIMIT_ALL, 
                           bool areverse=false): 
                           offset(aoffset), limit(alimit), reverse(areverse), 
                           defined(false) {}
   
                   bool adjust(size_t count) {
                           if(!count || !limit)
                                   return false;
                           size_t row=offset;
                           if(row>=count)
                                   return false;
                           // max(limit)
                           size_t m=reverse?
                                   offset
                                   :count-offset;
                           if(!m)
                                   return false;
                           // fix limit
                           if(limit==ARRAY_OPTION_LIMIT_ALL || limit>m)
                                   limit=m;
   
                           return true;
                   }
   
         Array(Pool& apool, int initial_rows=CR_INITIAL_ROWS_DEFAULT);                  
           };
   
         int size() const {           typedef T element_type;
                 // for get and quick_get  
                 cache_chunk_base=0;          Array(size_t initial=3):
                 cache_chunk=head;                  fallocated(initial>3?initial:3),
                 return fused_rows;                   fused(0)
         }          {
         Array& operator += (Item *src);                  felements=static_cast<T*>(malloc(fallocated*sizeof(T)));
         // Array<const Item*> replacement          }
         Array& operator += (const Item *src) { return *this+=const_cast<Item*>(src); }  
         Array& append_array(const Array& src, int offset=0);          /// how many items are in Array
         Item *quick_get(int index) const {          size_t count() const { return fused; }
                 // considering these true:          /// append to array
                 //   index increments from 0 to size()-1          Array& operator += (T src) {
                 //   index>=0 && index<size()                  if(is_full())
                 //   index>=cache_chunk_base                          expand(2);
   
                 // next chunk will be with "index" row                  felements[fused++]=src;
                 if(!(index<cache_chunk_base+cache_chunk->count)) {  
                         int count=cache_chunk->count;                  return *this;
                         cache_chunk_base+=count;          }
                         cache_chunk=cache_chunk->rows[count].link;  
           /// append other Array portion to this one. starting from offset
           Array& append(const Array& src, 
                   size_t offset=0, 
                   size_t limit=ARRAY_OPTION_LIMIT_ALL, //< negative limit means 'all'. zero limit means 'nothing'
                   bool reverse=false) {
   
                   size_t src_count=src.count();
                   // skip tivials
                   if(!src_count || !limit || offset>=src_count)
                           return *this;
                   // max(limit)
                   size_t m=reverse?
                           1+offset
                           :src_count-offset;
                   if(!m)
                           return *this;
                   // fix limit
                   if(limit==ARRAY_OPTION_LIMIT_ALL || limit>m)
                           limit=m;
   
                   ssize_t delta=reverse?
                           (ssize_t)limit
                           :limit-(fallocated-fused);
                   if(delta>0)
                           expand(delta);
   
                   T* from=&src.felements[offset];
                   T* to=&felements[fused];
                   if(reverse) { // reverse
                           for(T* from_end=from-limit; from>from_end; --from)
                                   *to++=*from;
   
                   } else { // forward
                           for(T* from_end=from+limit; from<from_end; from++)
                                   *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(size_t index) const {
         const char *get_cstr(int index) const {                   assert(index<count());
                 return static_cast<const char *>(get(index));                   return felements[index];
         }  
         const String *get_string(int index) const {   
                 return static_cast<const String *>(get(index));   
         }          }
   
 private:          /// ref version of get
           T& get_ref(size_t index) const {
                   assert(index<count());
                   return felements[index];
           }
   
         struct Chunk {          /// put index-element
                 // the number of rows in chunk          void put(size_t index, T element) {
                 int count;                  assert(index<count());
                 union Row {                  felements[index]=element;
                         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          T operator [](size_t index) const { return get(index); }
         // helps appending Arrays  
         Chunk *tail;  
   
         // next append would write to this record          /// iterate over all elements
         Chunk::Row *append_here;          template<typename I> void for_each(void (*callback)(T, I), I info) const {
                           T *last=felements+fused;
         // the address of place where lies address                   for(T *current=felements; current<last; current++)
         // of the link to the next chunk to allocate                          callback(*current, info);
         Chunk::Row *link_row;          }
   
 private:          /// iterate over all elements
           template<typename I> void for_each_ref(void (*callback)(T&, I), I info) {
                   T *last=felements+fused;
                   for(T *current=felements; current<last; current++)
                           callback(*current, info);
           }
   
         // array size          /// iterate over all elements until condition becomes true, return that element
         int fused_rows;          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);
           }
   
         mutable int cache_chunk_base;  protected:
         mutable Chunk *cache_chunk;  
           
 private:  
   
         bool chunk_is_full() {          bool is_full() {
                 return append_here == link_row;                  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; }
 };  };
   
   
   /** Array iterator, usage:
           @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:
   
           Array_iterator(const Array<T>& aarray): farray(aarray) {
                   fcurrent=farray.felements;
                   flast=farray.felements+farray.count();
           }
   
           /// there are still elements
           bool has_next() {
                   return fcurrent<flast;
           }
   
           /// quickly extracts next Array element
           const T next() {
                   return *(fcurrent++);
           }
   
   };
 #endif  #endif

Removed from v.1.22  
changed lines
  Added in v.1.64


E-mail: