Annotation of parser3/src/main/pa_array.C, revision 1.56
1.23 paf 1: /** @file
1.24 paf 2: Parser: array class.
3:
1.54 paf 4: Copyright (c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com)
1.47 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.49 paf 6: */
1.24 paf 7:
1.56 ! paf 8: static const char* IDENT_ARRAY_C="$Date: 2003/04/11 15:00:05 $";
1.1 paf 9:
10: #include "pa_pool.h"
1.8 paf 11: #include "pa_array.h"
1.13 paf 12: #include "pa_exception.h"
1.30 paf 13: #include "pa_common.h"
1.1 paf 14:
1.51 paf 15: Array::Array(Pool& apool, int initial_rows) : Pooled(apool) {
16: initial_rows=max(initial_rows, CR_INITIAL_ROWS_DEFAULT);
17:
1.6 paf 18: head=tail=static_cast<Chunk *>(
1.41 paf 19: malloc(sizeof(int)+sizeof(Chunk::Row)*initial_rows+sizeof(Chunk *), 19));
1.6 paf 20: head->count=initial_rows;
1.1 paf 21: append_here=head->rows;
1.6 paf 22: link_row=&head->rows[initial_rows];
1.1 paf 23: link_row->link=0;
24: fused_rows=0;
1.45 paf 25: }
26:
1.9 paf 27: void Array::expand(int chunk_rows) {
1.6 paf 28: Chunk *chunk=tail=static_cast<Chunk *>(
1.41 paf 29: malloc(sizeof(int)+sizeof(Chunk::Row)*chunk_rows+sizeof(Chunk *), 2));
1.6 paf 30: chunk->count=chunk_rows;
1.1 paf 31: link_row->link=chunk;
32: append_here=chunk->rows;
1.6 paf 33: link_row=&chunk->rows[chunk_rows];
1.1 paf 34: link_row->link=0;
35: }
36:
37:
1.15 paf 38: Array& Array::operator += (Item *src) {
1.1 paf 39: if(chunk_is_full())
1.32 parser 40: expand(tail->count+CR_GROW_COUNT);
1.1 paf 41:
42: append_here->item=src;
43: append_here++; fused_rows++;
44:
45: return *this;
46: }
47:
1.15 paf 48: Array::Item *Array::get(int index) const {
1.3 paf 49: if(!(index>=0 && index<size())) {
1.48 paf 50: throw Exception(0, 0,
1.12 paf 51: "Array::get(%d) out of range [0..%d]", index, size()-1);
1.33 parser 52: return 0; // never
1.2 paf 53: }
54:
1.42 paf 55: int base=0;
56: Chunk *chunk=head;
1.3 paf 57:
58: // navigate to chunk with "index" row
1.42 paf 59: while(!(index>=base && index<base+chunk->count)) {
60: int count=chunk->count;
61: base+=count;
62: chunk=chunk->rows[count].link;
1.3 paf 63: }
64:
1.42 paf 65: return chunk->rows[index-base].item;
1.16 paf 66: }
67:
68: void Array::put(int index, Item *item) {
69: if(!(index>=0 && index<size())) {
1.48 paf 70: throw Exception(0, 0,
1.16 paf 71: "Array::put(%d) out of range [0..%d]", index, size()-1);
1.33 parser 72: return; // never
1.16 paf 73: }
74:
1.42 paf 75: int base=0;
76: Chunk *chunk=head;
1.16 paf 77:
78: // navigate to chunk with "index" row
1.42 paf 79: while(!(index>=base && index<base+chunk->count)) {
80: int count=chunk->count;
81: base+=count;
82: chunk=chunk->rows[count].link;
1.16 paf 83: }
84:
1.42 paf 85: chunk->rows[index-base].item=item;
1.4 paf 86: }
87:
1.55 paf 88: Array& Array::append_array(const Array& src, int offset, int limit, bool reverse) {
89: if(reverse)
90: throw Exception(0,
91: 0,
92: "not implemented in this version, please upgrade");
1.51 paf 93: // fix limit
94: {
1.56 ! paf 95: if(offset<0 || offset>=src.fused_rows)
1.55 paf 96: return *this;
97:
1.51 paf 98: int m=src.fused_rows-offset;
1.55 paf 99: if(!m || !limit)
1.51 paf 100: return *this;
1.55 paf 101: if(limit<0 || limit>m)
1.51 paf 102: limit=m;
103: }
104:
1.4 paf 105: int last_chunk_rows_left=link_row-append_here;
106:
1.5 paf 107: // our last chunk too small for src to fit?
1.51 paf 108: if(limit>last_chunk_rows_left) {
1.5 paf 109: // shrink last chunk to used rows
110: tail->count-=last_chunk_rows_left;
111: link_row=append_here;
112:
1.6 paf 113: // append new src_used_rows-ed chunk
1.51 paf 114: expand(limit);
1.5 paf 115: }
116:
1.51 paf 117: // prepare...
1.18 paf 118: Chunk *src_chunk=src.head;
1.6 paf 119: Chunk::Row *dest_rows=append_here;
1.51 paf 120:
121: // a little ahead of time, no harm done ['limit' destroyed later]
122: append_here+=limit;
123: fused_rows+=limit;
124:
125: // ...do it
1.6 paf 126: while(true) {
127: int src_count=src_chunk->count;
1.51 paf 128: int rows_to_copy_now=min(src_count-offset, limit);
1.6 paf 129: Chunk *next_chunk=src_chunk->rows[src_count].link;
130: if(next_chunk) {
131: // not last source chunk
1.51 paf 132: if(rows_to_copy_now>0) {
133: memcpy(dest_rows, src_chunk->rows+offset,
1.18 paf 134: sizeof(Chunk::Row)*rows_to_copy_now);
1.53 paf 135: offset=0;
1.51 paf 136: if(!(limit-=rows_to_copy_now))
137: break;
138: } else
139: offset-=src_count;
1.19 paf 140:
1.18 paf 141: dest_rows+=rows_to_copy_now;
1.6 paf 142: src_chunk=next_chunk;
143: } else {
144: // the last source chunk
1.18 paf 145: if(rows_to_copy_now>0)
1.51 paf 146: memcpy(dest_rows, src_chunk->rows+offset,
1.18 paf 147: sizeof(Chunk::Row)*rows_to_copy_now);
1.6 paf 148: break;
1.4 paf 149: }
150: }
151:
152: return *this;
1.26 paf 153: }
154:
1.28 paf 155: void Array::for_each(For_each_func func, void *info) const {
1.26 paf 156: Chunk *chunk=head;
157: while(true) {
158: if(chunk==tail) { // last chunk?
159: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
160: (*func)(row->item, info);
161: break;
162: } else {
163: int count=chunk->count;
164: for(int i=0; i<count; i++)
165: (*func)(chunk->rows[i].item, info);
166: chunk=chunk->rows[count].link;
167: }
168: }
169: }
1.44 paf 170:
171: /*void Array::for_each(For_each_func_storage func, void *info) {
172: Chunk *chunk=head;
173: while(true) {
174: if(chunk==tail) { // last chunk?
175: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
176: (*func)(&row->item, info);
177: break;
178: } else {
179: int count=chunk->count;
180: for(int i=0; i<count; i++)
181: (*func)(&chunk->rows[i].item, info);
182: chunk=chunk->rows[count].link;
183: }
184: }
185: }
186: */
1.26 paf 187:
1.31 paf 188: /*void Array::for_each(For_each_func_const func, const void *info) const {
189: Chunk *chunk=head;
190: while(true) {
191: if(chunk==tail) { // last chunk?
192: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
193: (*func)(row->item, info);
194: break;
195: } else {
196: int count=chunk->count;
197: for(int i=0; i<count; i++)
198: (*func)(chunk->rows[i].item, info);
199: chunk=chunk->rows[count].link;
200: }
201: }
202: }
203: */
1.38 parser 204: void* Array::first_that(Item_that_func_const func, const void *info) const {
1.29 paf 205: Chunk *chunk=head;
206: while(true) {
207: if(chunk==tail) { // last chunk?
208: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.38 parser 209: if(void *result=(*func)(row->item, info))
210: return result;
1.29 paf 211: break;
212: } else {
213: int count=chunk->count;
214: for(int i=0; i<count; i++) {
215: Item* item=chunk->rows[i].item;
1.38 parser 216: if(void *result=(*func)(item, info))
217: return result;
1.29 paf 218: }
219: chunk=chunk->rows[count].link;
220: }
221: }
222: return 0;
223: }
224:
1.38 parser 225: void* Array::first_that(Item_that_func func, void *info) const {
1.26 paf 226: Chunk *chunk=head;
227: while(true) {
228: if(chunk==tail) { // last chunk?
229: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.38 parser 230: if(void *result=(*func)(row->item, info))
231: return result;
1.26 paf 232: break;
233: } else {
234: int count=chunk->count;
1.27 paf 235: for(int i=0; i<count; i++) {
236: Item* item=chunk->rows[i].item;
1.38 parser 237: if(void *result=(*func)(item, info))
238: return result;
1.27 paf 239: }
1.26 paf 240: chunk=chunk->rows[count].link;
241: }
242: }
243: return 0;
1.4 paf 244: }
E-mail: