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