Annotation of parser3/src/main/pa_array.C, revision 1.33
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.33 ! parser 8: $Id: pa_array.C,v 1.32 2001/05/15 15:51:05 parser Exp $
1.1 paf 9: */
10:
1.25 paf 11: #include "pa_config_includes.h"
1.1 paf 12:
13: #include "pa_pool.h"
1.8 paf 14: #include "pa_array.h"
1.13 paf 15: #include "pa_exception.h"
1.30 paf 16: #include "pa_common.h"
1.1 paf 17:
1.33 ! parser 18: #include "pa_sapi.h"
! 19: #define ARRAY_STAT_MAX_PIECES 1000
! 20: int array_stat_pieces[ARRAY_STAT_MAX_PIECES];
! 21: void log_array_stats(Pool& pool) {
! 22: for(int i=0; i<ARRAY_STAT_MAX_PIECES; i++)
! 23: if(int v=array_stat_pieces[i])
! 24: SAPI::log(pool, "%i: %10d",
! 25: i, v);
! 26: }
! 27:
! 28: #define ARRAY_STAT_MAX_LEN 1000
! 29: int array_stat_lens[ARRAY_STAT_MAX_LEN];
! 30: void log_array_lens(Pool& pool) {
! 31: for(int i=0; i<ARRAY_STAT_MAX_LEN; i++)
! 32: if(int v=array_stat_lens[i])
! 33: SAPI::log(pool, "%i: %10d",
! 34: i, v);
! 35: }
! 36:
1.10 paf 37: Array::Array(Pool& apool, int initial_rows) :
1.33 ! parser 38: Pooled(apool),expand_times(0) {
! 39: array_stat_pieces[0]++;
! 40: array_stat_lens[0]++;
! 41: initial_rows=max(initial_rows, CR_INITIAL_ROWS_DEFAULT);
1.30 paf 42:
1.6 paf 43: head=tail=static_cast<Chunk *>(
1.17 paf 44: malloc(sizeof(int)+sizeof(Chunk::Row)*initial_rows+sizeof(Chunk *)));
1.6 paf 45: head->count=initial_rows;
1.1 paf 46: append_here=head->rows;
1.6 paf 47: link_row=&head->rows[initial_rows];
1.1 paf 48: link_row->link=0;
49: fused_rows=0;
1.2 paf 50:
1.3 paf 51: cache_chunk_base=0;
52: cache_chunk=head;
1.1 paf 53: }
54:
1.9 paf 55: void Array::expand(int chunk_rows) {
1.33 ! parser 56: {
! 57: int index=min(++expand_times, ARRAY_STAT_MAX_PIECES-1);
! 58: if(index)
! 59: array_stat_pieces[index-1]++;
! 60: array_stat_pieces[index]++;
! 61: }
1.20 paf 62:
1.6 paf 63: Chunk *chunk=tail=static_cast<Chunk *>(
1.17 paf 64: malloc(sizeof(int)+sizeof(Chunk::Row)*chunk_rows+sizeof(Chunk *)));
1.6 paf 65: chunk->count=chunk_rows;
1.1 paf 66: link_row->link=chunk;
67: append_here=chunk->rows;
1.6 paf 68: link_row=&chunk->rows[chunk_rows];
1.1 paf 69: link_row->link=0;
70: }
71:
72:
1.15 paf 73: Array& Array::operator += (Item *src) {
1.1 paf 74: if(chunk_is_full())
1.32 parser 75: expand(tail->count+CR_GROW_COUNT);
1.1 paf 76:
77: append_here->item=src;
78: append_here++; fused_rows++;
1.33 ! parser 79: {
! 80: int index=min(fused_rows, ARRAY_STAT_MAX_LEN-1);
! 81: if(index)
! 82: array_stat_lens[index-1]++;
! 83: array_stat_lens[index]++;
! 84: }
! 85:
1.1 paf 86:
87: return *this;
88: }
89:
1.15 paf 90: Array::Item *Array::get(int index) const {
1.3 paf 91: if(!(index>=0 && index<size())) {
1.17 paf 92: THROW(0, 0, 0,
1.12 paf 93: "Array::get(%d) out of range [0..%d]", index, size()-1);
1.33 ! parser 94: return 0; // never
1.2 paf 95: }
96:
1.3 paf 97: // if they ask index to the left of cached position, forget cache
98: if(index<cache_chunk_base) {
99: cache_chunk_base=0;
100: cache_chunk=head;
101: }
102:
103: // navigate to chunk with "index" row
104: while(!(index>=cache_chunk_base && index<cache_chunk_base+cache_chunk->count)) {
105: int count=cache_chunk->count;
106: cache_chunk_base+=count;
107: cache_chunk=cache_chunk->rows[count].link;
108: }
109:
110: return cache_chunk->rows[index-cache_chunk_base].item;
1.16 paf 111: }
112:
113: void Array::put(int index, Item *item) {
114: if(!(index>=0 && index<size())) {
1.17 paf 115: THROW(0, 0, 0,
1.16 paf 116: "Array::put(%d) out of range [0..%d]", index, size()-1);
1.33 ! parser 117: return; // never
1.16 paf 118: }
119:
120: // if they ask index to the left of cached position, forget cache
121: if(index<cache_chunk_base) {
122: cache_chunk_base=0;
123: cache_chunk=head;
124: }
125:
126: // navigate to chunk with "index" row
127: while(!(index>=cache_chunk_base && index<cache_chunk_base+cache_chunk->count)) {
128: int count=cache_chunk->count;
129: cache_chunk_base+=count;
130: cache_chunk=cache_chunk->rows[count].link;
131: }
132:
133: cache_chunk->rows[index-cache_chunk_base].item=item;
1.4 paf 134: }
135:
1.18 paf 136: Array& Array::append_array(const Array& src, int offset) {
137: int src_rows_to_copy=src.fused_rows-offset;
1.4 paf 138: int last_chunk_rows_left=link_row-append_here;
139:
1.5 paf 140: // our last chunk too small for src to fit?
1.18 paf 141: if(src_rows_to_copy>last_chunk_rows_left) {
1.5 paf 142: // shrink last chunk to used rows
143: tail->count-=last_chunk_rows_left;
144: link_row=append_here;
145:
1.6 paf 146: // append new src_used_rows-ed chunk
1.18 paf 147: expand(src_rows_to_copy);
1.5 paf 148: }
149:
1.18 paf 150: Chunk *src_chunk=src.head;
1.6 paf 151: Chunk::Row *dest_rows=append_here;
1.18 paf 152: int rows_left_to_copy=src.fused_rows;
153: int rows_left_to_skip=offset;
1.6 paf 154: while(true) {
155: int src_count=src_chunk->count;
156: Chunk *next_chunk=src_chunk->rows[src_count].link;
157: if(next_chunk) {
158: // not last source chunk
159: // taking it all
1.18 paf 160: int rows_to_copy_now=src_count-rows_left_to_skip;
161: if(rows_to_copy_now>0)
162: memcpy(dest_rows, src_chunk->rows+rows_left_to_skip,
163: sizeof(Chunk::Row)*rows_to_copy_now);
1.19 paf 164: else
165: rows_left_to_skip-=src_count;
166:
1.18 paf 167: dest_rows+=rows_to_copy_now;
1.6 paf 168: rows_left_to_copy-=src_count;
169: src_chunk=next_chunk;
170: } else {
171: // the last source chunk
172: // taking only those rows of chunk that _left_to_copy
1.18 paf 173: int rows_to_copy_now=rows_left_to_copy-rows_left_to_skip;
174: if(rows_to_copy_now>0)
175: memcpy(dest_rows, src_chunk->rows+rows_left_to_skip,
176: sizeof(Chunk::Row)*rows_to_copy_now);
1.6 paf 177: break;
1.4 paf 178: }
179: }
1.18 paf 180: append_here+=src_rows_to_copy;
181: fused_rows+=src_rows_to_copy;
1.4 paf 182:
183: return *this;
1.26 paf 184: }
185:
1.28 paf 186: void Array::for_each(For_each_func func, void *info) const {
1.26 paf 187: Chunk *chunk=head;
188: while(true) {
189: if(chunk==tail) { // last chunk?
190: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
191: (*func)(row->item, info);
192: break;
193: } else {
194: int count=chunk->count;
195: for(int i=0; i<count; i++)
196: (*func)(chunk->rows[i].item, info);
197: chunk=chunk->rows[count].link;
198: }
199: }
200: }
201:
1.31 paf 202: /*void Array::for_each(For_each_func_const func, const void *info) const {
203: Chunk *chunk=head;
204: while(true) {
205: if(chunk==tail) { // last chunk?
206: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
207: (*func)(row->item, info);
208: break;
209: } else {
210: int count=chunk->count;
211: for(int i=0; i<count; i++)
212: (*func)(chunk->rows[i].item, info);
213: chunk=chunk->rows[count].link;
214: }
215: }
216: }
217: */
1.29 paf 218: Array::Item* Array::first_that(First_that_func_const func, const void *info) const {
219: Chunk *chunk=head;
220: while(true) {
221: if(chunk==tail) { // last chunk?
222: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
223: if((*func)(row->item, info))
224: return row->item;
225: break;
226: } else {
227: int count=chunk->count;
228: for(int i=0; i<count; i++) {
229: Item* item=chunk->rows[i].item;
230: if((*func)(item, info))
231: return item;
232: }
233: chunk=chunk->rows[count].link;
234: }
235: }
236: return 0;
237: }
238:
239: Array::Item* Array::first_that(First_that_func func, void *info) const {
1.26 paf 240: Chunk *chunk=head;
241: while(true) {
242: if(chunk==tail) { // last chunk?
243: for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.27 paf 244: if((*func)(row->item, info))
245: return row->item;
1.26 paf 246: break;
247: } else {
248: int count=chunk->count;
1.27 paf 249: for(int i=0; i<count; i++) {
250: Item* item=chunk->rows[i].item;
251: if((*func)(item, info))
252: return item;
253: }
1.26 paf 254: chunk=chunk->rows[count].link;
255: }
256: }
257: return 0;
1.4 paf 258: }
E-mail: