Diff for /parser3/src/include/pa_array.h between versions 1.57.2.21 and 1.108

version 1.57.2.21, 2003/02/17 07:18:58 version 1.108, 2026/04/25 13:38:46
Line 1 Line 1
 /** @file  /** @file
         Parser: Array & Array_iterator classes decls.          Parser: Array & Array_iterator classes decls.
   
         Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)          Copyright (c) 2001-2026 Art. Lebedev Studio (https://www.artlebedev.com)
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <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$";  #define IDENT_PA_ARRAY_H "$Id$"
   
 #include "pa_pool.h"  // includes
   
   #include "pa_memory.h"
   #include "pa_types.h"
 #include "pa_exception.h"  #include "pa_exception.h"
   
   // forwards
   
 template<typename T> class Array_iterator;  template<typename T> class Array_iterator;
   template<typename T> class Array_robust_iterator;
   template<typename T> class Array_reverse_iterator;
   
 /**       // defines
         Simple Array.  
   
 */  #define ARRAY_OPTION_LIMIT_ALL ((size_t)-1)
   
   /// Simple Array
 template<typename T> class Array: public PA_Object {  template<typename T> class Array: public PA_Object {
   
         friend class Array_iterator<T>;          friend class Array_iterator<T>;
           friend class Array_robust_iterator<T>;
           friend class Array_reverse_iterator<T>;
   
 protected:  protected:
   
         // default expand delta size  
         int fdelta;  
   
         /// elements[growing size] here          /// elements[growing size] here
         T *felements;          T *felements;
   
         // allocated size          // allocated size
         int fallocated;          size_t fallocated;
   
         // array size          // array size
         int fused;          size_t fsize;
   
 public:  public:
           typedef Array_iterator<T> Iterator;
           typedef Array_robust_iterator<T> RobustIterator;
           typedef Array_reverse_iterator<T> ReverseIterator;
   
           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;
                           if(offset>=count)
                                   return false;
                           // max(limit)
                           size_t m=reverse?
                                   offset+1
                                   :count-offset;
                           if(!m)
                                   return false;
                           // fix limit
                           if(limit>m)
                                   limit=m;
   
                           return true;
                   }
           };
   
         typedef T element_type;          typedef T element_type;
   
         Array(int initial=3, int delta=1):          inline Array(size_t initial=0):
                 fallocated(initial?initial:3),                  fallocated(initial),
                 fdelta(delta),                  fsize(0)
                 fused(0)  
         {          {
                 if(fallocated<=0 || fdelta<1)                  felements=fallocated?(T *)pa_malloc(fallocated*sizeof(T)):0;
                         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;  #ifdef USE_DESTRUCTORS
           inline ~Array(){
                   if(felements)
                           pa_free(felements);
         }          }
   #endif
   
         /// how many items are in Array          /// how many items are in Array
         int count() const { return fused; }          inline size_t count() const { return fsize; }
   
         /// append to array          /// append to array
         Array& operator += (T src) {          inline Array& operator+=(T src) {
                 if(is_full())                  if(is_full())
                         expand(fdelta);                          expand();
   
                 felements[fused++]=src;                  felements[fsize++]=src;
   
                 return *this;                  return *this;
         }          }
   
         /// append other Array portion to this one. starting from offset          /// append other Array portion to this one. starting from offset
         Array& append(const Array& src, int offset=0, int limit=0) {          void append(const Array& src, size_t offset=0, size_t limit=ARRAY_OPTION_LIMIT_ALL) { //< zero limit means 'nothing'
                 if(!(offset>=0 && offset<src.count())) {                  size_t src_count=src.count();
                         throw Exception(0,                   // skip tivials
                                 Exception::undefined_source,                  if(!src_count || !limit || offset>=src_count)
                                 "Array::append(offset=%d) out of range [0..%d]", offset, src.count()-1);                          return;
                         //return 0; // never                  // max(limit)
                 }                  size_t m=src_count-offset;
                 // fix limit                  // fix limit
                 {                  if(limit>m)
                         int m=src.count()-offset;                          limit=m;
                         if(!m || limit<0)  
                                 return *this;  
                         if(!limit || limit>m)  
                                 limit=m;  
                 }  
   
                 int needed=limit-(fallocated-fused);  
                 if(needed>0)  
                         expand(needed);  
   
                 memcpy(&felements[fused+=limit], &src.felements[offset], limit*sizeof(T));                  fit(fsize-1+limit);
                 return *this;                  memcpy(felements+fsize, src.felements+offset, limit * sizeof(T));
                   fsize+=limit;
         }          }
   
         /// get index-element          /// get index-element
         T& get(int index) const {          inline T get(size_t index) const {
                 if(!(index>=0 && index<count())) {                  assert(index<count());
                         throw Exception(0,   
                                 Exception::undefined_source,  
                                 "Array::get(%d) out of range [0..%d]", index, count()-1);  
                         return felements[0]; // never  
                 }  
   
                 return felements[index];                  return felements[index];
         }          }
   
         T& operator [](int index) const { return get(index); }          /// ref version of get
           inline T& get_ref(size_t index) const {
                   assert(index<count());
                   return felements[index];
           }
   
         /// put index-element          /// put index-element
         void put(int index, T& element) {          inline void put(size_t index, T element) {
                 if(!(index>=0 && index<count())) {                  assert(index<count());
                         throw Exception(0,   
                                 Exception::undefined_source,   
                                 "Array::put(%d) out of range [0..%d]", index, count()-1);  
                         return; // never  
                 }  
                 felements[index]=element;                  felements[index]=element;
         }          }
   
           /// insert index-element
           inline void insert(size_t index, T element) {
                   assert(index<=count());
   
                   if(is_full())
                           expand();
   
                   memmove(felements+index+1, felements+index, (fsize-index) * sizeof(T));
   
                   felements[index]=element;
                   fsize++;
           }
   
           /// remove index-element
           inline void remove(size_t index) {
                   assert(index<count());
                   if (index<--fsize)
                           memmove(felements+index, felements+index+1, (fsize-index) * sizeof(T));
           }
   
           inline T operator [](size_t index) const { return get(index); }
   
           inline void clear() {
                   if(fsize)
                           memset((void *)felements, 0, fsize * sizeof(T));
                   fsize=0;
           }
   
         /// iterate over all elements          /// iterate over all elements
         template<typename I> void for_each(void (*callback)(T, I), I info) const {          template<typename I> void for_each(void (*callback)(T, I), I info) const {
                 T *last=felements+fused;                  T *last=felements+fsize;
                   for(T *current=felements; current<last; current++)
                           callback(*current, info);
           }
   
           /// iterate over all elements
           template<typename I> void for_each(bool (*callback)(T, I), I info) const {
                   T *last=felements+fsize;
                   for(T *current=felements; current<last; current++)
                           if(callback(*current, info))
                                   return;
           }
   
           /// iterate over all elements
           template<typename I> void for_each_ref(void (*callback)(T&, I), I info) {
                   T *last=felements+fsize;
                 for(T *current=felements; current<last; current++)                  for(T *current=felements; current<last; current++)
                         callback(*current, info);                          callback(*current, info);
         }          }
   
         /// iterate over all elements until condition becomes true, return that element          /// iterate over all elements until condition becomes true, return that element
         template<typename I> T first_that(bool (*callback)(T, I), I info) const {          template<typename I> T first_that(bool (*callback)(T, I), I info) const {
                 T *last=felements+fused;                  T *last=felements+fsize;
                 for(T *current=felements; current<last; current++)                  for(T *current=felements; current<last; current++)
                         if(callback(*current, info))                          if(callback(*current, info))
                                 return *current;                                  return *current;
Line 140  public: Line 205  public:
                 return T(0);                  return T(0);
         }          }
   
           inline T* ptr(size_t index){
                   return felements + index;
           }
   
 protected:  protected:
   
         bool is_full() {          inline bool is_full() {
                 return fused == fallocated;                  return fsize == fallocated;
         }          }
         void expand(int delta) {  
                 fallocated+=delta;          inline void expand() {
                 felements = (T *)realloc(felements, fallocated*sizeof(T));                  resize(fallocated>0 ? fallocated+fallocated/2+2 : 3); // 3 is PAF default, confirmed by tests
           }
   
           inline void fit(size_t index){
                   if(index >= fallocated)
                           resize(max(fallocated+fallocated/4, index+1));
           }
   
           void resize(size_t asize) {
                   if(fallocated){
                           felements=(T *)pa_realloc(felements, asize*sizeof(T));
   #ifdef PA_DEBUG_DISABLE_GC
                           // non-gc realloc doesn't zero; manually zero expanded region
                           if(asize > fallocated)
                                   memset((void *)(felements+fallocated), 0, (asize-fallocated) * sizeof(T));
   #endif
                           fallocated=asize;
                   } else {
                           fallocated=asize;
                           felements=(T *)pa_malloc(asize*sizeof(T));
                   }
         }          }
   
 private: //disabled  private: //disabled
   
           Array(const Array&) {}
         Array& operator = (const Array&) { return *this; }          Array& operator = (const Array&) { return *this; }
 };  };
   
 typedef smart_ptr<char> CharPtr;  
   
 class Pool: public Array<CharPtr> {  /** Array iterator, usage:
           @code
           // Array<T> a;
           for(Array_iterator<T> i(a); i; ) {
                   T& element=i.next();
                   ...
           }       
           @endcode
   */
   template<typename T> class Array_iterator {
   
           const Array<T>& farray;
           T *fcurrent;
           T *flast;
   
 public:  public:
         char *malloc(size_t size) {          Array_iterator(const Array<T>& aarray): farray(aarray) {
                 CharPtr result=CharPtr((char *)Array<CharPtr>::malloc(size));                  fcurrent=farray.felements;
                 *this += result;                  flast=farray.felements + farray.fsize;
                 return result.get();  
         }          }
   
         char *copy(const char* buf, size_t size=0) {          /// there are still elements
                 if(!size)          inline operator bool () {
                         size=strlen(buf)+1;                  return fcurrent < flast;
   
                 char *result=malloc(size);  
                 memcpy(result, buf, size);  
                 return result;  
         }          }
 };  
   
 inline void *operator new[] (size_t size, Pool& pool) {          /// returns the current element and advances the iterator
         return pool.malloc(size);          inline T next() {
 }                  return *(fcurrent++);
           }
   
 /// handy array iterator          /// returns the current element
 template<typename T> class Array_iterator {          inline T value() {
                   return *(fcurrent);
           }
   
         Array<T>& farray;          // returns the current index of the iterator
         T *fcurrent;          inline size_t index() {
         T *flast;                  return fcurrent - farray.felements;
           }
   };
   
   // Slower array iterator for arrays that can be modified during iteration
   template<typename T> class Array_robust_iterator {
   
           const Array<T>& farray;
           size_t findex;
   
 public:  public:
           Array_robust_iterator(const Array<T>& aarray) : farray(aarray), findex(0) {}
   
         Array_iterator(Array<T>& aarray): farray(aarray) {          inline operator bool() {
                 fcurrent=farray.felements;                  return findex < farray.fsize;
                 flast=farray.felements+farray.count();  
         }          }
   
         /// there are still elements          inline void next() {
         bool has_next() {                  findex++;
                 return fcurrent<flast;  
         }          }
   
         /// quickly extracts next Array element          inline T value() {
         T& next() {                  return farray.felements[findex];
                 return *(fcurrent++);  
         }          }
   
           inline size_t index() {
                   return findex;
           }
 };  };
   
   // Robust as used for arrays that can be modified during iteration
   template<typename T> class Array_reverse_iterator {
   
           const Array<T>& farray;
           size_t findex;
   
   public:
           Array_reverse_iterator(const Array<T>& aarray): farray(aarray), findex(aarray.fsize) {}
   
           inline operator bool () {
                   return (findex > 0) && (findex <= farray.fsize);
           }
   
           inline T prev() {
                   return farray.felements[--findex];
           }
   
           inline size_t index() {
                   return findex;
           }
   };
 #endif  #endif

Removed from v.1.57.2.21  
changed lines
  Added in v.1.108


E-mail: