Annotation of parser3/src/main/pa_array.C, revision 1.51
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.51 ! paf 8: static const char* IDENT_ARRAY_C="$Date: 2002/08/01 11:41:18 $";
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;
! 93: if(!m)
! 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.51 ! paf 129: if(!(limit-=rows_to_copy_now))
! 130: break;
! 131: } else
! 132: offset-=src_count;
1.19 paf 133:
1.18 paf 134: dest_rows+=rows_to_copy_now;
1.6 paf 135: src_chunk=next_chunk;
136: } else {
137: // the last source chunk
1.18 paf 138: if(rows_to_copy_now>0)
1.51 ! paf 139: memcpy(dest_rows, src_chunk->rows+offset,
1.18 paf 140: sizeof(Chunk::Row)*rows_to_copy_now);
1.6 paf 141: break;
1.4 paf 142: }
143: }
144:
145: return *this;
1.26 paf 146: }
147:
1.28 paf 148: void Array::for_each(For_each_func func, void *info) const {
1.26 paf 149: Chunk *chunk=head;
150: while(true) {
151: if(chunk==tail) { // last chunk?
152: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
153: (*func)(row->item, info);
154: break;
155: } else {
156: int count=chunk->count;
157: for(int i=0; i<count; i++)
158: (*func)(chunk->rows[i].item, info);
159: chunk=chunk->rows[count].link;
160: }
161: }
162: }
1.44 paf 163:
164: /*void Array::for_each(For_each_func_storage func, void *info) {
165: Chunk *chunk=head;
166: while(true) {
167: if(chunk==tail) { // last chunk?
168: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
169: (*func)(&row->item, info);
170: break;
171: } else {
172: int count=chunk->count;
173: for(int i=0; i<count; i++)
174: (*func)(&chunk->rows[i].item, info);
175: chunk=chunk->rows[count].link;
176: }
177: }
178: }
179: */
1.26 paf 180:
1.31 paf 181: /*void Array::for_each(For_each_func_const func, const void *info) const {
182: Chunk *chunk=head;
183: while(true) {
184: if(chunk==tail) { // last chunk?
185: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
186: (*func)(row->item, info);
187: break;
188: } else {
189: int count=chunk->count;
190: for(int i=0; i<count; i++)
191: (*func)(chunk->rows[i].item, info);
192: chunk=chunk->rows[count].link;
193: }
194: }
195: }
196: */
1.38 parser 197: void* Array::first_that(Item_that_func_const func, const void *info) const {
1.29 paf 198: Chunk *chunk=head;
199: while(true) {
200: if(chunk==tail) { // last chunk?
201: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.38 parser 202: if(void *result=(*func)(row->item, info))
203: return result;
1.29 paf 204: break;
205: } else {
206: int count=chunk->count;
207: for(int i=0; i<count; i++) {
208: Item* item=chunk->rows[i].item;
1.38 parser 209: if(void *result=(*func)(item, info))
210: return result;
1.29 paf 211: }
212: chunk=chunk->rows[count].link;
213: }
214: }
215: return 0;
216: }
217:
1.38 parser 218: void* Array::first_that(Item_that_func func, void *info) const {
1.26 paf 219: Chunk *chunk=head;
220: while(true) {
221: if(chunk==tail) { // last chunk?
222: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.38 parser 223: if(void *result=(*func)(row->item, info))
224: return result;
1.26 paf 225: break;
226: } else {
227: int count=chunk->count;
1.27 paf 228: for(int i=0; i<count; i++) {
229: Item* item=chunk->rows[i].item;
1.38 parser 230: if(void *result=(*func)(item, info))
231: return result;
1.27 paf 232: }
1.26 paf 233: chunk=chunk->rows[count].link;
234: }
235: }
236: return 0;
1.4 paf 237: }
E-mail: