Annotation of parser3/src/main/pa_array.C, revision 1.35
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.24 paf 5:
1.22 paf 6: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
1.21 paf 7:
1.35 ! parser 8: $Id: pa_array.C,v 1.34 2001/05/16 16:54:00 parser Exp $
1.1 paf 9: */
10:
11: #include "pa_pool.h"
1.8 paf 12: #include "pa_array.h"
1.13 paf 13: #include "pa_exception.h"
1.30 paf 14: #include "pa_common.h"
1.1 paf 15:
1.10 paf 16: Array::Array(Pool& apool, int initial_rows) :
1.34 parser 17: Pooled(apool) {
1.33 parser 18: initial_rows=max(initial_rows, CR_INITIAL_ROWS_DEFAULT);
1.30 paf 19:
1.6 paf 20: head=tail=static_cast<Chunk *>(
1.17 paf 21: malloc(sizeof(int)+sizeof(Chunk::Row)*initial_rows+sizeof(Chunk *)));
1.6 paf 22: head->count=initial_rows;
1.1 paf 23: append_here=head->rows;
1.6 paf 24: link_row=&head->rows[initial_rows];
1.1 paf 25: link_row->link=0;
26: fused_rows=0;
1.2 paf 27:
1.3 paf 28: cache_chunk_base=0;
29: cache_chunk=head;
1.1 paf 30: }
31:
1.9 paf 32: void Array::expand(int chunk_rows) {
1.6 paf 33: Chunk *chunk=tail=static_cast<Chunk *>(
1.17 paf 34: malloc(sizeof(int)+sizeof(Chunk::Row)*chunk_rows+sizeof(Chunk *)));
1.6 paf 35: chunk->count=chunk_rows;
1.1 paf 36: link_row->link=chunk;
37: append_here=chunk->rows;
1.6 paf 38: link_row=&chunk->rows[chunk_rows];
1.1 paf 39: link_row->link=0;
40: }
41:
42:
1.15 paf 43: Array& Array::operator += (Item *src) {
1.1 paf 44: if(chunk_is_full())
1.32 parser 45: expand(tail->count+CR_GROW_COUNT);
1.1 paf 46:
47: append_here->item=src;
48: append_here++; fused_rows++;
49:
50: return *this;
51: }
52:
1.15 paf 53: Array::Item *Array::get(int index) const {
1.3 paf 54: if(!(index>=0 && index<size())) {
1.17 paf 55: THROW(0, 0, 0,
1.12 paf 56: "Array::get(%d) out of range [0..%d]", index, size()-1);
1.33 parser 57: return 0; // never
1.2 paf 58: }
59:
1.3 paf 60: // if they ask index to the left of cached position, forget cache
61: if(index<cache_chunk_base) {
62: cache_chunk_base=0;
63: cache_chunk=head;
64: }
65:
66: // navigate to chunk with "index" row
67: while(!(index>=cache_chunk_base && index<cache_chunk_base+cache_chunk->count)) {
68: int count=cache_chunk->count;
69: cache_chunk_base+=count;
70: cache_chunk=cache_chunk->rows[count].link;
71: }
72:
73: return cache_chunk->rows[index-cache_chunk_base].item;
1.16 paf 74: }
75:
76: void Array::put(int index, Item *item) {
77: if(!(index>=0 && index<size())) {
1.17 paf 78: THROW(0, 0, 0,
1.16 paf 79: "Array::put(%d) out of range [0..%d]", index, size()-1);
1.33 parser 80: return; // never
1.16 paf 81: }
82:
83: // if they ask index to the left of cached position, forget cache
84: if(index<cache_chunk_base) {
85: cache_chunk_base=0;
86: cache_chunk=head;
87: }
88:
89: // navigate to chunk with "index" row
90: while(!(index>=cache_chunk_base && index<cache_chunk_base+cache_chunk->count)) {
91: int count=cache_chunk->count;
92: cache_chunk_base+=count;
93: cache_chunk=cache_chunk->rows[count].link;
94: }
95:
96: cache_chunk->rows[index-cache_chunk_base].item=item;
1.4 paf 97: }
98:
1.18 paf 99: Array& Array::append_array(const Array& src, int offset) {
100: int src_rows_to_copy=src.fused_rows-offset;
1.4 paf 101: int last_chunk_rows_left=link_row-append_here;
102:
1.5 paf 103: // our last chunk too small for src to fit?
1.18 paf 104: if(src_rows_to_copy>last_chunk_rows_left) {
1.5 paf 105: // shrink last chunk to used rows
106: tail->count-=last_chunk_rows_left;
107: link_row=append_here;
108:
1.6 paf 109: // append new src_used_rows-ed chunk
1.18 paf 110: expand(src_rows_to_copy);
1.5 paf 111: }
112:
1.18 paf 113: Chunk *src_chunk=src.head;
1.6 paf 114: Chunk::Row *dest_rows=append_here;
1.18 paf 115: int rows_left_to_copy=src.fused_rows;
116: int rows_left_to_skip=offset;
1.6 paf 117: while(true) {
118: int src_count=src_chunk->count;
119: Chunk *next_chunk=src_chunk->rows[src_count].link;
120: if(next_chunk) {
121: // not last source chunk
122: // taking it all
1.18 paf 123: int rows_to_copy_now=src_count-rows_left_to_skip;
124: if(rows_to_copy_now>0)
125: memcpy(dest_rows, src_chunk->rows+rows_left_to_skip,
126: sizeof(Chunk::Row)*rows_to_copy_now);
1.19 paf 127: else
128: rows_left_to_skip-=src_count;
129:
1.18 paf 130: dest_rows+=rows_to_copy_now;
1.6 paf 131: rows_left_to_copy-=src_count;
132: src_chunk=next_chunk;
133: } else {
134: // the last source chunk
135: // taking only those rows of chunk that _left_to_copy
1.18 paf 136: int rows_to_copy_now=rows_left_to_copy-rows_left_to_skip;
137: if(rows_to_copy_now>0)
138: memcpy(dest_rows, src_chunk->rows+rows_left_to_skip,
139: sizeof(Chunk::Row)*rows_to_copy_now);
1.6 paf 140: break;
1.4 paf 141: }
142: }
1.18 paf 143: append_here+=src_rows_to_copy;
144: fused_rows+=src_rows_to_copy;
1.4 paf 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: }
164:
1.31 paf 165: /*void Array::for_each(For_each_func_const func, const void *info) const {
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.29 paf 181: Array::Item* Array::first_that(First_that_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: if((*func)(row->item, info))
187: return row->item;
188: break;
189: } else {
190: int count=chunk->count;
191: for(int i=0; i<count; i++) {
192: Item* item=chunk->rows[i].item;
193: if((*func)(item, info))
194: return item;
195: }
196: chunk=chunk->rows[count].link;
197: }
198: }
199: return 0;
200: }
201:
202: Array::Item* Array::first_that(First_that_func func, void *info) const {
1.26 paf 203: Chunk *chunk=head;
204: while(true) {
205: if(chunk==tail) { // last chunk?
206: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.27 paf 207: if((*func)(row->item, info))
208: return row->item;
1.26 paf 209: break;
210: } else {
211: int count=chunk->count;
1.27 paf 212: for(int i=0; i<count; i++) {
213: Item* item=chunk->rows[i].item;
214: if((*func)(item, info))
215: return item;
216: }
1.26 paf 217: chunk=chunk->rows[count].link;
218: }
219: }
220: return 0;
1.4 paf 221: }
E-mail: