Annotation of parser3/src/main/pa_array.C, revision 1.43
1.23 paf 1: /** @file
1.24 paf 2: Parser: array class.
3:
1.21 paf 4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
1.43 ! paf 5: Author: Alexander Petrosyan <paf@design.ru> (http://paf.design.ru)
1.24 paf 6:
1.43 ! paf 7: $Id: pa_array.C,v 1.42 2001/10/29 15:27:02 paf Exp $
1.1 paf 8: */
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.10 paf 15: Array::Array(Pool& apool, int initial_rows) :
1.34 parser 16: Pooled(apool) {
1.33 parser 17: initial_rows=max(initial_rows, CR_INITIAL_ROWS_DEFAULT);
1.30 paf 18:
1.6 paf 19: head=tail=static_cast<Chunk *>(
1.41 paf 20: malloc(sizeof(int)+sizeof(Chunk::Row)*initial_rows+sizeof(Chunk *), 19));
1.6 paf 21: head->count=initial_rows;
1.1 paf 22: append_here=head->rows;
1.6 paf 23: link_row=&head->rows[initial_rows];
1.1 paf 24: link_row->link=0;
25: fused_rows=0;
26: }
27:
1.9 paf 28: void Array::expand(int chunk_rows) {
1.6 paf 29: Chunk *chunk=tail=static_cast<Chunk *>(
1.41 paf 30: malloc(sizeof(int)+sizeof(Chunk::Row)*chunk_rows+sizeof(Chunk *), 2));
1.6 paf 31: chunk->count=chunk_rows;
1.1 paf 32: link_row->link=chunk;
33: append_here=chunk->rows;
1.6 paf 34: link_row=&chunk->rows[chunk_rows];
1.1 paf 35: link_row->link=0;
36: }
37:
38:
1.15 paf 39: Array& Array::operator += (Item *src) {
1.1 paf 40: if(chunk_is_full())
1.32 parser 41: expand(tail->count+CR_GROW_COUNT);
1.1 paf 42:
43: append_here->item=src;
44: append_here++; fused_rows++;
45:
46: return *this;
47: }
48:
1.15 paf 49: Array::Item *Array::get(int index) const {
1.3 paf 50: if(!(index>=0 && index<size())) {
1.40 parser 51: throw Exception(0, 0, 0,
1.12 paf 52: "Array::get(%d) out of range [0..%d]", index, size()-1);
1.33 parser 53: return 0; // never
1.2 paf 54: }
55:
1.42 paf 56: int base=0;
57: Chunk *chunk=head;
1.3 paf 58:
59: // navigate to chunk with "index" row
1.42 paf 60: while(!(index>=base && index<base+chunk->count)) {
61: int count=chunk->count;
62: base+=count;
63: chunk=chunk->rows[count].link;
1.3 paf 64: }
65:
1.42 paf 66: return chunk->rows[index-base].item;
1.16 paf 67: }
68:
69: void Array::put(int index, Item *item) {
70: if(!(index>=0 && index<size())) {
1.40 parser 71: throw Exception(0, 0, 0,
1.16 paf 72: "Array::put(%d) out of range [0..%d]", index, size()-1);
1.33 parser 73: return; // never
1.16 paf 74: }
75:
1.42 paf 76: int base=0;
77: Chunk *chunk=head;
1.16 paf 78:
79: // navigate to chunk with "index" row
1.42 paf 80: while(!(index>=base && index<base+chunk->count)) {
81: int count=chunk->count;
82: base+=count;
83: chunk=chunk->rows[count].link;
1.16 paf 84: }
85:
1.42 paf 86: chunk->rows[index-base].item=item;
1.4 paf 87: }
88:
1.18 paf 89: Array& Array::append_array(const Array& src, int offset) {
90: int src_rows_to_copy=src.fused_rows-offset;
1.4 paf 91: int last_chunk_rows_left=link_row-append_here;
92:
1.5 paf 93: // our last chunk too small for src to fit?
1.18 paf 94: if(src_rows_to_copy>last_chunk_rows_left) {
1.5 paf 95: // shrink last chunk to used rows
96: tail->count-=last_chunk_rows_left;
97: link_row=append_here;
98:
1.6 paf 99: // append new src_used_rows-ed chunk
1.18 paf 100: expand(src_rows_to_copy);
1.5 paf 101: }
102:
1.18 paf 103: Chunk *src_chunk=src.head;
1.6 paf 104: Chunk::Row *dest_rows=append_here;
1.18 paf 105: int rows_left_to_copy=src.fused_rows;
106: int rows_left_to_skip=offset;
1.6 paf 107: while(true) {
108: int src_count=src_chunk->count;
109: Chunk *next_chunk=src_chunk->rows[src_count].link;
110: if(next_chunk) {
111: // not last source chunk
112: // taking it all
1.18 paf 113: int rows_to_copy_now=src_count-rows_left_to_skip;
114: if(rows_to_copy_now>0)
115: memcpy(dest_rows, src_chunk->rows+rows_left_to_skip,
116: sizeof(Chunk::Row)*rows_to_copy_now);
1.19 paf 117: else
118: rows_left_to_skip-=src_count;
119:
1.18 paf 120: dest_rows+=rows_to_copy_now;
1.6 paf 121: rows_left_to_copy-=src_count;
122: src_chunk=next_chunk;
123: } else {
124: // the last source chunk
125: // taking only those rows of chunk that _left_to_copy
1.18 paf 126: int rows_to_copy_now=rows_left_to_copy-rows_left_to_skip;
127: if(rows_to_copy_now>0)
128: memcpy(dest_rows, src_chunk->rows+rows_left_to_skip,
129: sizeof(Chunk::Row)*rows_to_copy_now);
1.6 paf 130: break;
1.4 paf 131: }
132: }
1.18 paf 133: append_here+=src_rows_to_copy;
134: fused_rows+=src_rows_to_copy;
1.4 paf 135:
136: return *this;
1.26 paf 137: }
138:
1.28 paf 139: void Array::for_each(For_each_func func, void *info) const {
1.26 paf 140: Chunk *chunk=head;
141: while(true) {
142: if(chunk==tail) { // last chunk?
143: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
144: (*func)(row->item, info);
145: break;
146: } else {
147: int count=chunk->count;
148: for(int i=0; i<count; i++)
149: (*func)(chunk->rows[i].item, info);
150: chunk=chunk->rows[count].link;
151: }
152: }
153: }
154:
1.31 paf 155: /*void Array::for_each(For_each_func_const func, const void *info) const {
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: }
170: */
1.38 parser 171: void* Array::first_that(Item_that_func_const func, const void *info) const {
1.29 paf 172: Chunk *chunk=head;
173: while(true) {
174: if(chunk==tail) { // last chunk?
175: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.38 parser 176: if(void *result=(*func)(row->item, info))
177: return result;
1.29 paf 178: break;
179: } else {
180: int count=chunk->count;
181: for(int i=0; i<count; i++) {
182: Item* item=chunk->rows[i].item;
1.38 parser 183: if(void *result=(*func)(item, info))
184: return result;
1.29 paf 185: }
186: chunk=chunk->rows[count].link;
187: }
188: }
189: return 0;
190: }
191:
1.38 parser 192: void* Array::first_that(Item_that_func func, void *info) const {
1.26 paf 193: Chunk *chunk=head;
194: while(true) {
195: if(chunk==tail) { // last chunk?
196: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.38 parser 197: if(void *result=(*func)(row->item, info))
198: return result;
1.26 paf 199: break;
200: } else {
201: int count=chunk->count;
1.27 paf 202: for(int i=0; i<count; i++) {
203: Item* item=chunk->rows[i].item;
1.38 parser 204: if(void *result=(*func)(item, info))
205: return result;
1.27 paf 206: }
1.26 paf 207: chunk=chunk->rows[count].link;
208: }
209: }
210: return 0;
1.4 paf 211: }
E-mail: