Annotation of parser3/src/main/pa_array.C, revision 1.53
1.23 paf 1: /** @file
1.24 paf 2: Parser: array class.
3:
1.46 paf 4: Copyright (c) 2001, 2002 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.53 ! paf 8: static const char* IDENT_ARRAY_C="$Date: 2002/08/07 10:25:56 $";
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.51 paf 88: Array& Array::append_array(const Array& src, int offset, int limit) {
89: //if(((void*)&src)==(void*)0x6cf520) _asm int 3;
90: // fix limit
91: {
92: int m=src.fused_rows-offset;
1.52 paf 93: if(!m || limit<0)
1.51 paf 94: return *this;
95: if(!limit || limit>m)
96: limit=m;
97: }
98:
1.4 paf 99: int last_chunk_rows_left=link_row-append_here;
100:
1.5 paf 101: // our last chunk too small for src to fit?
1.51 paf 102: if(limit>last_chunk_rows_left) {
1.5 paf 103: // shrink last chunk to used rows
104: tail->count-=last_chunk_rows_left;
105: link_row=append_here;
106:
1.6 paf 107: // append new src_used_rows-ed chunk
1.51 paf 108: expand(limit);
1.5 paf 109: }
110:
1.51 paf 111: // prepare...
1.18 paf 112: Chunk *src_chunk=src.head;
1.6 paf 113: Chunk::Row *dest_rows=append_here;
1.51 paf 114:
115: // a little ahead of time, no harm done ['limit' destroyed later]
116: append_here+=limit;
117: fused_rows+=limit;
118:
119: // ...do it
1.6 paf 120: while(true) {
121: int src_count=src_chunk->count;
1.51 paf 122: int rows_to_copy_now=min(src_count-offset, limit);
1.6 paf 123: Chunk *next_chunk=src_chunk->rows[src_count].link;
124: if(next_chunk) {
125: // not last source chunk
1.51 paf 126: if(rows_to_copy_now>0) {
127: memcpy(dest_rows, src_chunk->rows+offset,
1.18 paf 128: sizeof(Chunk::Row)*rows_to_copy_now);
1.53 ! paf 129: offset=0;
1.51 paf 130: if(!(limit-=rows_to_copy_now))
131: break;
132: } else
133: offset-=src_count;
1.19 paf 134:
1.18 paf 135: dest_rows+=rows_to_copy_now;
1.6 paf 136: src_chunk=next_chunk;
137: } else {
138: // the last source chunk
1.18 paf 139: if(rows_to_copy_now>0)
1.51 paf 140: memcpy(dest_rows, src_chunk->rows+offset,
1.18 paf 141: sizeof(Chunk::Row)*rows_to_copy_now);
1.6 paf 142: break;
1.4 paf 143: }
144: }
145:
146: return *this;
1.26 paf 147: }
148:
1.28 paf 149: void Array::for_each(For_each_func func, void *info) const {
1.26 paf 150: Chunk *chunk=head;
151: while(true) {
152: if(chunk==tail) { // last chunk?
153: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
154: (*func)(row->item, info);
155: break;
156: } else {
157: int count=chunk->count;
158: for(int i=0; i<count; i++)
159: (*func)(chunk->rows[i].item, info);
160: chunk=chunk->rows[count].link;
161: }
162: }
163: }
1.44 paf 164:
165: /*void Array::for_each(For_each_func_storage func, void *info) {
166: Chunk *chunk=head;
167: while(true) {
168: if(chunk==tail) { // last chunk?
169: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
170: (*func)(&row->item, info);
171: break;
172: } else {
173: int count=chunk->count;
174: for(int i=0; i<count; i++)
175: (*func)(&chunk->rows[i].item, info);
176: chunk=chunk->rows[count].link;
177: }
178: }
179: }
180: */
1.26 paf 181:
1.31 paf 182: /*void Array::for_each(For_each_func_const func, const void *info) const {
183: Chunk *chunk=head;
184: while(true) {
185: if(chunk==tail) { // last chunk?
186: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
187: (*func)(row->item, info);
188: break;
189: } else {
190: int count=chunk->count;
191: for(int i=0; i<count; i++)
192: (*func)(chunk->rows[i].item, info);
193: chunk=chunk->rows[count].link;
194: }
195: }
196: }
197: */
1.38 parser 198: void* Array::first_that(Item_that_func_const func, const void *info) const {
1.29 paf 199: Chunk *chunk=head;
200: while(true) {
201: if(chunk==tail) { // last chunk?
202: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.38 parser 203: if(void *result=(*func)(row->item, info))
204: return result;
1.29 paf 205: break;
206: } else {
207: int count=chunk->count;
208: for(int i=0; i<count; i++) {
209: Item* item=chunk->rows[i].item;
1.38 parser 210: if(void *result=(*func)(item, info))
211: return result;
1.29 paf 212: }
213: chunk=chunk->rows[count].link;
214: }
215: }
216: return 0;
217: }
218:
1.38 parser 219: void* Array::first_that(Item_that_func func, void *info) const {
1.26 paf 220: Chunk *chunk=head;
221: while(true) {
222: if(chunk==tail) { // last chunk?
223: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.38 parser 224: if(void *result=(*func)(row->item, info))
225: return result;
1.26 paf 226: break;
227: } else {
228: int count=chunk->count;
1.27 paf 229: for(int i=0; i<count; i++) {
230: Item* item=chunk->rows[i].item;
1.38 parser 231: if(void *result=(*func)(item, info))
232: return result;
1.27 paf 233: }
1.26 paf 234: chunk=chunk->rows[count].link;
235: }
236: }
237: return 0;
1.4 paf 238: }
E-mail: