Diff for /parser3/src/include/pa_array.h between versions 1.82 and 1.106

version 1.82, 2015/07/28 14:41:32 version 1.106, 2026/01/06 13:07:58
Line 1 Line 1
 /** @file  /** @file
         Parser: Array & Array_iterator classes decls.          Parser: Array & Array_iterator classes decls.
   
         Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com)          Copyright (c) 2001-2024 Art. Lebedev Studio (http://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
Line 13 Line 13
 // includes  // includes
   
 #include "pa_memory.h"  #include "pa_memory.h"
   #include "pa_types.h"
   #include "pa_int.h"
 #include "pa_exception.h"  #include "pa_exception.h"
   
 // forwards  // 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  // defines
   
Line 27  template<typename T> class Array_iterato Line 31  template<typename T> class Array_iterato
 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:
   
Line 37  protected: Line 43  protected:
         size_t fallocated;          size_t fallocated;
   
         // array size          // array size
         size_t 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 {          struct Action_options {
                 size_t offset;                  size_t offset;
                 size_t limit; //< ARRAY_OPTION_LIMIT_ALL means 'all'. zero limit means 'nothing'                  size_t limit; //< ARRAY_OPTION_LIMIT_ALL means 'all'. zero limit means 'nothing'
Line 47  public: Line 57  public:
                 bool defined;                  bool defined;
                                   
                 Action_options(                  Action_options(
                         size_t aoffset=0,                           size_t aoffset=0,
                         size_t alimit=ARRAY_OPTION_LIMIT_ALL,                           size_t alimit=ARRAY_OPTION_LIMIT_ALL,
                         bool areverse=false):                           bool areverse=false):
                         offset(aoffset), limit(alimit), reverse(areverse),                           offset(aoffset), limit(alimit), reverse(areverse), 
                         defined(false) {}                          defined(false) {}
   
Line 65  public: Line 75  public:
                         if(!m)                          if(!m)
                                 return false;                                  return false;
                         // fix limit                          // fix limit
                         if(limit==ARRAY_OPTION_LIMIT_ALL || limit>m)                          if(limit>m)
                                 limit=m;                                  limit=m;
   
                         return true;                          return true;
                 }                  }
   
                   
         };          };
   
         typedef T element_type;          typedef T element_type;
   
         inline Array(size_t initial=0):          inline Array(size_t initial=0):
                 fallocated(initial),                  fallocated(initial),
                 fused(0)                  fsize(0)
         {          {
                 felements=fallocated?(T *)pa_malloc(fallocated*sizeof(T)):0;                  felements=fallocated?(T *)pa_malloc(fallocated*sizeof(T)):0;
         }          }
   
 #ifdef USE_DESTRUCTORS   #ifdef USE_DESTRUCTORS
         inline ~Array(){          inline ~Array(){
                 if(felements)                  if(felements)
                         pa_free(felements);                          pa_free(felements);
Line 91  public: Line 99  public:
 #endif  #endif
   
         /// how many items are in Array          /// how many items are in Array
         inline size_t count() const { return fused; }          inline size_t count() const { return fsize; }
   
         /// append to array          /// append to array
         inline Array& operator+=(T src) {          inline Array& operator+=(T src) {
                 if(is_full())                  if(is_full())
                         expand(fallocated>0? 2+fallocated/32 : 3); // 3 is PAF default, confirmed by tests                          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,           void append(const Array& src, size_t offset=0, size_t limit=ARRAY_OPTION_LIMIT_ALL) { //< zero limit means 'nothing'
                 size_t offset=0,   
                 size_t limit=ARRAY_OPTION_LIMIT_ALL) { //< negative limit means 'all'. zero limit means 'nothing'  
   
                 size_t src_count=src.count();                  size_t src_count=src.count();
                 // skip tivials                  // skip tivials
                 if(!src_count || !limit || offset>=src_count)                  if(!src_count || !limit || offset>=src_count)
                         return *this;                          return;
                 // max(limit)                  // max(limit)
                 size_t m=src_count-offset;                  size_t m=src_count-offset;
                 // fix limit                  // fix limit
                 if(limit==ARRAY_OPTION_LIMIT_ALL || limit>m)                  if(limit>m)
                         limit=m;                          limit=m;
   
                 ssize_t delta=limit-(fallocated-fused);                  fit(fsize-1+limit);
                 if(delta>0)                  memcpy(felements+fsize, src.felements+offset, limit * sizeof(T));
                         expand(delta);                  fsize+=limit;
   
                 T* from=&src.felements[offset];  
                 T* to=&felements[fused];  
                 for(T* from_end=from+limit; from<from_end; from++)  
                         *to++=*from;  
                 fused+=limit;  
                 return *this;  
         }          }
   
         /// get index-element          /// get index-element
Line 152  public: Line 151  public:
                 assert(index<=count());                  assert(index<=count());
   
                 if(is_full())                  if(is_full())
                         expand(fallocated>0? 2+fallocated/32 : 3); // 3 is PAF default, confirmed by tests                          expand();
   
                 memmove(felements+index+1, felements+index, (fused-index) * sizeof(T));                  memmove(felements+index+1, felements+index, (fsize-index) * sizeof(T));
   
                 felements[index]=element;                  felements[index]=element;
                 fused++;                  fsize++;
         }          }
   
         /// remove index-element          /// remove index-element
         inline void remove(size_t index) {          inline void remove(size_t index) {
                 assert(index<count());                  assert(index<count());
                 if (index<--fused)                  if (index<--fsize)
                         memmove(felements+index, felements+index+1, (fused-index) * sizeof(T));                          memmove(felements+index, felements+index+1, (fsize-index) * sizeof(T));
         }          }
   
         inline T operator [](size_t index) const { return get(index); }          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++)                  for(T *current=felements; current<last; current++)
                         callback(*current, info);                          callback(*current, info);
         }          }
   
         /// iterate over all elements          /// iterate over all elements
         template<typename I> void for_each(bool (*callback)(T, I), I info) const {          template<typename I> void for_each(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;                                  return;
Line 186  public: Line 191  public:
   
         /// iterate over all elements          /// iterate over all elements
         template<typename I> void for_each_ref(void (*callback)(T&, I), I info) {          template<typename I> void for_each_ref(void (*callback)(T&, I), I info) {
                 T *last=felements+fused;                  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 207  public: Line 212  public:
   
 protected:  protected:
   
         bool is_full() {          inline bool is_full() {
                 return fused == fallocated;                  return fsize == fallocated;
           }
   
           inline void expand() {
                   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 expand(size_t delta) {  
           void resize(size_t asize) {
                 if(fallocated){                  if(fallocated){
                         size_t new_allocated=fallocated+delta;                          felements=(T *)pa_realloc(felements, asize*sizeof(T));
                         felements=(T *)pa_realloc(felements, new_allocated*sizeof(T));  #ifdef PA_DEBUG_DISABLE_GC
                         fallocated=new_allocated;                          // 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 {                  } else {
                         fallocated=delta;                          fallocated=asize;
                         felements=(T *)pa_malloc(fallocated*sizeof(T));                          felements=(T *)pa_malloc(asize*sizeof(T));
                 }                  }
         }          }
   
Line 231  private: //disabled Line 250  private: //disabled
 /** Array iterator, usage:  /** Array iterator, usage:
         @code          @code
         // Array<T> a;          // Array<T> a;
         for(Array_iterator<T> i(a); i.has_next(); ) {          for(Array_iterator<T> i(a); i; ) {
                 T& element=i.next();                  T& element=i.next();
                 ...                  ...
         }                 }       
Line 244  template<typename T> class Array_iterato Line 263  template<typename T> class Array_iterato
         T *flast;          T *flast;
   
 public:  public:
   
         Array_iterator(const Array<T>& aarray): farray(aarray) {          Array_iterator(const Array<T>& aarray): farray(aarray) {
                 fcurrent=farray.felements;                  fcurrent=farray.felements;
                 flast=farray.felements+farray.count();                  flast=farray.felements + farray.fsize;
         }          }
   
         /// there are still elements          /// there are still elements
         bool has_next() {          inline operator bool () {
                 return fcurrent<flast;                  return fcurrent < flast;
         }          }
   
         /// quickly extracts next Array element          /// returns the current element and advances the iterator
         T next() {          inline T next() {
                 return *(fcurrent++);                  return *(fcurrent++);
         }          }
   
           /// returns the current element
           inline T value() {
                   return *(fcurrent);
           }
   
           // returns the current index of the iterator
           inline size_t index() {
                   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:
           Array_robust_iterator(const Array<T>& aarray) : farray(aarray), findex(0) {}
   
           inline operator bool() {
                   return findex < farray.fsize;
           }
   
           inline void next() {
                   findex++;
           }
   
           inline T value() {
                   return farray.felements[findex];
           }
   
           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.82  
changed lines
  Added in v.1.106


E-mail: