Annotation of parser3/src/include/pa_array.h, revision 1.59
1.24 paf 1: /** @file
1.59 ! paf 2: Parser: Array & Array_iterator classes decls.
1.26 paf 3:
1.59 ! paf 4: Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
1.53 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1 paf 6: */
7:
1.24 paf 8: #ifndef PA_ARRAY_H
9: #define PA_ARRAY_H
1.54 paf 10:
1.59 ! paf 11: static const char* IDENT_ARRAY_Y="$Date: 2003/04/14 14:03:11 $";
1.24 paf 12:
1.59 ! paf 13: // includes
! 14:
! 15: #include "pa_memory.h"
! 16: #include "pa_exception.h"
! 17:
! 18: // forwards
! 19:
! 20: template<typename T> class Array_iterator;
! 21:
! 22: // defines
! 23:
! 24: #define ARRAY_OPTION_LIMIT_ALL ((size_t)-1)
! 25:
! 26: /// Simple Array
! 27: template<typename T> class Array: public PA_Object {
! 28:
! 29: friend class Array_iterator<T>;
! 30:
! 31: protected:
! 32:
! 33: /// elements[growing size] here
! 34: T *felements;
! 35:
! 36: // allocated size
! 37: size_t fallocated;
! 38:
! 39: // array size
! 40: size_t fused;
1.1 paf 41:
42: public:
1.59 ! paf 43: struct Action_options {
! 44: size_t offset;
! 45: size_t limit; //< ARRAY_OPTION_LIMIT_ALL means 'all'. zero limit means 'nothing'
! 46: bool reverse;
! 47: bool defined;
! 48:
! 49: Action_options(
! 50: size_t aoffset=0,
! 51: size_t alimit=ARRAY_OPTION_LIMIT_ALL,
! 52: bool areverse=false):
! 53: offset(aoffset), limit(alimit), reverse(areverse),
! 54: defined(false) {}
! 55:
! 56: bool adjust(size_t count) {
! 57: if(!count || !limit)
! 58: return false;
! 59: size_t row=offset;
! 60: if(row>=count)
! 61: return false;
! 62: // max(limit)
! 63: size_t m=reverse?
! 64: offset
! 65: :count-offset;
! 66: if(!m)
! 67: return false;
! 68: // fix limit
! 69: if(limit==ARRAY_OPTION_LIMIT_ALL || limit>m)
! 70: limit=m;
1.7 paf 71:
1.59 ! paf 72: return true;
! 73: }
1.29 paf 74:
1.59 ! paf 75:
1.1 paf 76: };
77:
1.59 ! paf 78: typedef T element_type;
! 79:
! 80: Array(size_t initial=3):
! 81: fallocated(initial>3?initial:3),
! 82: fused(0)
! 83: {
! 84: felements=static_cast<T*>(malloc(fallocated*sizeof(T)));
! 85: }
1.6 paf 86:
1.59 ! paf 87: /// how many items are in Array
! 88: size_t count() const { return fused; }
! 89: /// append to array
! 90: Array& operator += (T src) {
! 91: if(is_full())
! 92: expand(2);
1.7 paf 93:
1.59 ! paf 94: felements[fused++]=src;
1.24 paf 95:
1.59 ! paf 96: return *this;
! 97: }
1.24 paf 98:
99: /// append other Array portion to this one. starting from offset
1.59 ! paf 100: Array& append(const Array& src,
! 101: size_t offset=0,
! 102: size_t limit=ARRAY_OPTION_LIMIT_ALL, //< negative limit means 'all'. zero limit means 'nothing'
! 103: bool reverse=false) {
! 104:
! 105: size_t src_count=src.count();
! 106: // skip tivials
! 107: if(!src_count || !limit || offset>=src_count)
! 108: return *this;
! 109: // max(limit)
! 110: size_t m=reverse?
! 111: 1+offset
! 112: :src_count-offset;
! 113: if(!m)
! 114: return *this;
! 115: // fix limit
! 116: if(limit==ARRAY_OPTION_LIMIT_ALL || limit>m)
! 117: limit=m;
! 118:
! 119: ssize_t delta=reverse?
! 120: (ssize_t)limit
! 121: :limit-(fallocated-fused);
! 122: if(delta>0)
! 123: expand(delta);
! 124:
! 125: T* from=&src.felements[offset];
! 126: T* to=&felements[fused];
! 127: if(reverse) { // reverse
! 128: for(T* from_end=from-limit; from>from_end; --from)
! 129: *to++=*from;
! 130:
! 131: } else { // forward
! 132: for(T* from_end=from+limit; from<from_end; from++)
! 133: *to++=*from;
! 134: }
! 135:
! 136: fused+=limit;
! 137: return *this;
! 138: }
! 139:
! 140: /// get index-element
! 141: T get(size_t index) const {
! 142: assert(index>=0 && index<count());
! 143: return felements[index];
! 144: }
! 145:
! 146: /// ref version of get
! 147: T& get_ref(size_t index) const {
! 148: assert(index>=0 && index<count());
! 149: return felements[index];
! 150: }
! 151:
! 152: /// put index-element
! 153: void put(size_t index, T element) {
! 154: assert(index>=0 && index<count());
! 155: felements[index]=element;
! 156: }
! 157:
! 158: T operator [](size_t index) const { return get(index); }
1.29 paf 159:
160: /// iterate over all elements
1.59 ! paf 161: template<typename I> void for_each(void (*callback)(T, I), I info) const {
! 162: T *last=felements+fused;
! 163: for(T *current=felements; current<last; current++)
! 164: callback(*current, info);
! 165: }
1.49 paf 166:
1.59 ! paf 167: /// iterate over all elements until condition becomes true, return that element
! 168: template<typename I> T first_that(bool (*callback)(T, I), I info) const {
! 169: T *last=felements+fused;
! 170: for(T *current=felements; current<last; current++)
! 171: if(callback(*current, info))
! 172: return *current;
1.1 paf 173:
1.59 ! paf 174: return T(0);
! 175: }
1.1 paf 176:
1.59 ! paf 177: protected:
1.1 paf 178:
1.59 ! paf 179: bool is_full() {
! 180: return fused == fallocated;
! 181: }
! 182: void expand(size_t delta) {
! 183: size_t new_allocated=fallocated+delta;
! 184: felements = (T *)realloc(felements, new_allocated*sizeof(T));
! 185: memset(&felements[fallocated], 0, delta*sizeof(T));
! 186: fallocated=new_allocated;
1.1 paf 187: }
1.2 paf 188:
1.1 paf 189: private: //disabled
190:
1.59 ! paf 191: Array(const Array&) {}
1.12 paf 192: Array& operator = (const Array&) { return *this; }
1.42 parser 193: };
194:
195:
1.59 ! paf 196: /** Array iterator, usage:
! 197: @code
! 198: // Array<T> a;
! 199: for(Array_iterator<T> i(a); i.has_next(); ) {
! 200: T& element=i.next();
! 201: ...
! 202: }
! 203: @endcode
! 204: */
! 205: template<typename T> class Array_iterator {
! 206:
! 207: const Array<T>& farray;
! 208: T *fcurrent;
! 209: T *flast;
! 210:
1.42 parser 211: public:
212:
1.59 ! paf 213: Array_iterator(const Array<T>& aarray): farray(aarray) {
! 214: fcurrent=farray.felements;
! 215: flast=farray.felements+farray.count();
1.42 parser 216: }
217:
218: /// there are still elements
219: bool has_next() {
1.59 ! paf 220: return fcurrent<flast;
1.42 parser 221: }
222:
1.59 ! paf 223: /// quickly extracts next Array element
! 224: const T next() {
! 225: return *(fcurrent++);
! 226: }
! 227:
! 228: };
! 229: /*
! 230: /** Nonconst array iterator, usage:
! 231: @code
! 232: // Array<T> a;
! 233: for(Array_iterator<T> i(a); i.has_next(); ) {
! 234: T& element=i.next();
! 235: ...
! 236: }
! 237: @endcode
! 238: * /
! 239: template<typename T> class Array_modifing_iterator {
! 240:
! 241: Array<T>& farray;
! 242: T *fcurrent;
! 243: T *flast;
! 244:
! 245: public:
! 246:
! 247: Array_modifing_iterator(Array<T>& aarray): farray(aarray) {
! 248: fcurrent=farray.felements;
! 249: flast=farray.felements+farray.count();
1.42 parser 250: }
251:
1.59 ! paf 252: /// there are still elements
! 253: bool has_next() {
! 254: return fcurrent<flast;
1.42 parser 255: }
256:
1.59 ! paf 257: /// quickly extracts next Array element
! 258: T& next() {
! 259: return *(fcurrent++);
! 260: }
1.42 parser 261:
1.1 paf 262: };
1.59 ! paf 263: */
1.1 paf 264: #endif
E-mail: