Annotation of parser3/src/include/pa_array.h, revision 1.57.2.27.2.17
1.24 paf 1: /** @file
1.57.2.2 paf 2: Parser: Array & Array_iterator classes decls.
1.26 paf 3:
1.57.2.16 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.57.2.27.2.1 (paf 11:): static const char* IDENT_ARRAY_Y="$Date: 2003/04/14 11:23:41 $";
1.24 paf 12:
1.57.2.25 paf 13: // includes
14:
15: #include "pa_memory.h"
1.57.2.3 paf 16: #include "pa_exception.h"
1.24 paf 17:
1.57.2.25 paf 18: // forwards
1.42 parser 19:
1.57.2.25 paf 20: template<typename T> class Array_iterator;
1.24 paf 21:
1.57.2.27.2.1 (paf 22:): // defines
23:):
24:): #define ARRAY_OPTION_LIMIT_ALL ((size_t)-1)
25:):
1.57.2.25 paf 26: /// Simple Array
1.57.2.2 paf 27: template<typename T> class Array: public PA_Object {
1.1 paf 28:
1.57.2.9 paf 29: friend class Array_iterator<T>;
1.57.2.2 paf 30:
1.57.2.13 paf 31: protected:
32:
33: /// elements[growing size] here
34: T *felements;
35:
1.57.2.2 paf 36: // allocated size
1.57.2.27.2.7 (paf 37:: size_t fallocated;
1.1 paf 38:
1.57.2.13 paf 39: // array size
1.57.2.27.2.7 (paf 40:: size_t fused;
1.57.2.13 paf 41:
1.57.2.2 paf 42: public:
1.57.2.27.2.1 (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;
71:):
72:): return true;
73:): }
74:):
75:):
76:): };
77:):
1.57.2.2 paf 78: typedef T element_type;
1.7 paf 79:
1.57.2.27.2.1 (paf 80:): Array(size_t initial=3):
1.57.2.27 paf 81: fallocated(initial>3?initial:3),
1.57.2.2 paf 82: fused(0)
83: {
1.57.2.27.2.2 (paf 84:: felements=static_cast<T*>(malloc(fallocated*sizeof(T)));
1.57.2.2 paf 85: }
1.24 paf 86:
1.57.2.2 paf 87: /// how many items are in Array
1.57.2.27.2.7 (paf 88:: size_t count() const { return fused; }
1.57.2.2 paf 89: /// append to array
90: Array& operator += (T src) {
91: if(is_full())
1.57.2.27.2.4 (paf 92:: expand(2);
1.24 paf 93:
1.57.2.2 paf 94: felements[fused++]=src;
1.37 paf 95:
1.57.2.2 paf 96: return *this;
1.34 paf 97: }
1.35 paf 98:
1.57.2.2 paf 99: /// append other Array portion to this one. starting from offset
1.57.2.27.2.1 (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;
1.57.2.2 paf 115: // fix limit
1.57.2.27.2.1 (paf 116:): if(limit==ARRAY_OPTION_LIMIT_ALL || limit>m)
117:): limit=m;
1.29 paf 118:
1.57.2.27.2.1 (paf 119:): ssize_t delta=reverse?
120:): (ssize_t)limit
121:): :limit-(fallocated-fused);
1.57.2.23 paf 122: if(delta>0)
123: expand(delta);
124:
125: T* from=&src.felements[offset];
126: T* to=&felements[fused];
1.57.2.27.2.1 (paf 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:): }
1.57.2.23 paf 135:
136: fused+=limit;
1.57.2.4 paf 137: return *this;
1.57.2.2 paf 138: }
1.49 paf 139:
1.57.2.27.2.1 (paf 140:): /// get index-element
141:): T get(size_t index) const {
142:): assert(index>=0 && index<count());
1.57.2.27.2.7 (paf 143:: return felements[index];
144:: }
145::
1.57.2.27.2.1 (paf 146:): /// ref version of get
147:): T& get_ref(size_t index) const {
148:): assert(index>=0 && index<count());
1.57.2.27.2.9 (paf 149:: return felements[index];
150:: }
151::
1.57.2.2 paf 152: /// put index-element
1.57.2.27.2.8 (paf 153:: void put(size_t index, T element) {
1.57.2.27.2.1 (paf 154:): assert(index>=0 && index<count());
155:): felements[index]=element;
1.57.2.2 paf 156: }
1.1 paf 157:
1.57.2.27.2.1 (paf 158:): T operator [](size_t index) const { return get(index); }
1.7 paf 159:
1.57.2.2 paf 160: /// iterate over all elements
1.57.2.6 paf 161: template<typename I> void for_each(void (*callback)(T, I), I info) const {
1.57.2.2 paf 162: T *last=felements+fused;
163: for(T *current=felements; current<last; current++)
164: callback(*current, info);
165: }
1.1 paf 166:
1.57.2.2 paf 167: /// iterate over all elements until condition becomes true, return that element
1.57.2.6 paf 168: template<typename I> T first_that(bool (*callback)(T, I), I info) const {
1.57.2.2 paf 169: T *last=felements+fused;
170: for(T *current=felements; current<last; current++)
171: if(callback(*current, info))
172: return *current;
1.7 paf 173:
1.57.2.20 paf 174: return T(0);
1.57.2.2 paf 175: }
1.1 paf 176:
1.57.2.3 paf 177: protected:
1.1 paf 178:
1.57.2.2 paf 179: bool is_full() {
180: return fused == fallocated;
181: }
1.57.2.27.2.5 (paf 182:: void expand(size_t delta) {
183:: size_t new_allocated=fallocated+delta;
184:: felements = (T *)realloc(felements, new_allocated*sizeof(T));
1.57.2.22 paf 185: memset(&felements[fallocated], 0, delta*sizeof(T));
1.57.2.27.2.5 (paf 186:: fallocated=new_allocated;
1.1 paf 187: }
1.2 paf 188:
1.1 paf 189: private: //disabled
190:
1.57.2.27.2.6 (paf 191:: Array(const Array&) {}
1.12 paf 192: Array& operator = (const Array&) { return *this; }
1.57.2.5 paf 193: };
194:
1.42 parser 195:
1.57.2.27.2.1 (paf 196:: /** Array iterator, usage:
197:: @code
198:: // Array<T> a;
1.57.2.27.2.9 (paf 199:: for(Array_iterator<T> i(a); i.has_next(); ) {
1.57.2.27.2.1 (paf 200:: T& element=i.next();
201:: ...
202:: }
203:: @endcode
204:: */
1.57.2.2 paf 205: template<typename T> class Array_iterator {
206:
1.57.2.27.2.1 (paf 207:: const Array<T>& farray;
208:: T *fcurrent;
209:: T *flast;
210::
211:: public:
212::
213:: Array_iterator(const Array<T>& aarray): farray(aarray) {
214:: fcurrent=farray.felements;
215:: flast=farray.felements+farray.count();
216:: }
217::
218:: /// there are still elements
219:: bool has_next() {
220:: return fcurrent<flast;
221:: }
222::
223:: /// quickly extracts next Array element
1.57.2.27.2.8 (paf 224:: const T next() {
1.57.2.27.2.1 (paf 225:: return *(fcurrent++);
226:: }
227::
228:: };
1.57.2.27.2.9 (paf 229:: /*
1.57.2.27.2.1 (paf 230:: /** Nonconst array iterator, usage:
231:: @code
232:: // Array<T> a;
1.57.2.27.2.9 (paf 233:: for(Array_iterator<T> i(a); i.has_next(); ) {
1.57.2.27.2.1 (paf 234:: T& element=i.next();
235:: ...
236:: }
237:: @endcode
1.57.2.27.2.9 (paf 238:: * /
1.57.2.27.2.1 (paf 239:: template<typename T> class Array_modifing_iterator {
240::
1.57.2.9 paf 241: Array<T>& farray;
1.57.2.2 paf 242: T *fcurrent;
243: T *flast;
244:
1.42 parser 245: public:
246:
1.57.2.27.2.1 (paf 247:: Array_modifing_iterator(Array<T>& aarray): farray(aarray) {
1.57.2.9 paf 248: fcurrent=farray.felements;
249: flast=farray.felements+farray.count();
1.42 parser 250: }
251:
252: /// there are still elements
253: bool has_next() {
1.57.2.2 paf 254: return fcurrent<flast;
1.42 parser 255: }
256:
1.57.2.2 paf 257: /// quickly extracts next Array element
1.57.2.27.2.9 (paf 258:: T& next() {
1.57.2.9 paf 259: return *(fcurrent++);
1.42 parser 260: }
261:
1.1 paf 262: };
1.57.2.27.2.9 (paf 263:: */
1.1 paf 264: #endif
E-mail: