--- parser3/src/main/Attic/pa_array.C 2001/01/29 15:56:04 1.7 +++ parser3/src/main/Attic/pa_array.C 2003/01/21 15:51:13 1.54 @@ -1,32 +1,32 @@ -/* - $Id: pa_array.C,v 1.7 2001/01/29 15:56:04 paf Exp $ +/** @file + Parser: array class. + + Copyright (c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com) + Author: Alexandr Petrosian (http://paf.design.ru) */ -#include +static const char* IDENT_ARRAY_C="$Date: 2003/01/21 15:51:13 $"; #include "pa_pool.h" +#include "pa_array.h" +#include "pa_exception.h" +#include "pa_common.h" -void *Array::operator new(size_t size, Pool *apool) { - return apool->malloc(size); -} +Array::Array(Pool& apool, int initial_rows) : Pooled(apool) { + initial_rows=max(initial_rows, CR_INITIAL_ROWS_DEFAULT); -Array::Array(Pool *apool, int initial_rows) : - pool(apool) { head=tail=static_cast( - pool->malloc(sizeof(int)+sizeof(Chunk::Row)*initial_rows+sizeof(Chunk *))); + malloc(sizeof(int)+sizeof(Chunk::Row)*initial_rows+sizeof(Chunk *), 19)); head->count=initial_rows; append_here=head->rows; link_row=&head->rows[initial_rows]; link_row->link=0; fused_rows=0; - - cache_chunk_base=0; - cache_chunk=head; } void Array::expand(int chunk_rows) { Chunk *chunk=tail=static_cast( - pool->malloc(sizeof(int)+sizeof(Chunk::Row)*chunk_rows+sizeof(Chunk *))); + malloc(sizeof(int)+sizeof(Chunk::Row)*chunk_rows+sizeof(Chunk *), 2)); chunk->count=chunk_rows; link_row->link=chunk; append_here=chunk->rows; @@ -35,9 +35,9 @@ void Array::expand(int chunk_rows) { } -Array& Array::operator += (Item src) { +Array& Array::operator += (Item *src) { if(chunk_is_full()) - expand(tail->count*CR_GROW_PERCENT/100); + expand(tail->count+CR_GROW_COUNT); append_here->item=src; append_here++; fused_rows++; @@ -45,66 +45,194 @@ Array& Array::operator += (Item src) { return *this; } -Array::Item& Array::operator [] (int index) { +Array::Item *Array::get(int index) const { if(!(index>=0 && index=base && indexcount)) { + int count=chunk->count; + base+=count; + chunk=chunk->rows[count].link; } + return chunk->rows[index-base].item; +} + +void Array::put(int index, Item *item) { + if(!(index>=0 && index=cache_chunk_base && indexcount)) { - int count=cache_chunk->count; - cache_chunk_base+=count; - cache_chunk=cache_chunk->rows[count].link; + while(!(index>=base && indexcount)) { + int count=chunk->count; + base+=count; + chunk=chunk->rows[count].link; } - return cache_chunk->rows[index-cache_chunk_base].item; + chunk->rows[index-base].item=item; } -Array& Array::operator += (Array& src) { - int src_used_rows=src.fused_rows; +Array& Array::append_array(const Array& src, int offset, int limit) { + //if(((void*)&src)==(void*)0x6cf520) _asm int 3; + // fix limit + { + int m=src.fused_rows-offset; + if(!m || limit<0) + return *this; + if(!limit || limit>m) + limit=m; + } + int last_chunk_rows_left=link_row-append_here; // our last chunk too small for src to fit? - if(src_used_rows>last_chunk_rows_left) { + if(limit>last_chunk_rows_left) { // shrink last chunk to used rows tail->count-=last_chunk_rows_left; link_row=append_here; // append new src_used_rows-ed chunk - expand(src_used_rows); + expand(limit); } - Chunk *src_chunk=src.head; + // prepare... + Chunk *src_chunk=src.head; Chunk::Row *dest_rows=append_here; - int rows_left_to_copy=src_used_rows; + + // a little ahead of time, no harm done ['limit' destroyed later] + append_here+=limit; + fused_rows+=limit; + + // ...do it while(true) { int src_count=src_chunk->count; + int rows_to_copy_now=min(src_count-offset, limit); Chunk *next_chunk=src_chunk->rows[src_count].link; if(next_chunk) { // not last source chunk - // taking it all - memcpy(dest_rows, src_chunk->rows, sizeof(Chunk::Row)*src_count); - dest_rows+=src_count; - rows_left_to_copy-=src_count; - + if(rows_to_copy_now>0) { + memcpy(dest_rows, src_chunk->rows+offset, + sizeof(Chunk::Row)*rows_to_copy_now); + offset=0; + if(!(limit-=rows_to_copy_now)) + break; + } else + offset-=src_count; + + dest_rows+=rows_to_copy_now; src_chunk=next_chunk; } else { // the last source chunk - // taking only those rows of chunk that _left_to_copy - memcpy(dest_rows, src_chunk->rows, sizeof(Chunk::Row)*rows_left_to_copy); + if(rows_to_copy_now>0) + memcpy(dest_rows, src_chunk->rows+offset, + sizeof(Chunk::Row)*rows_to_copy_now); break; } } - append_here+=src_used_rows; - fused_rows+=src_used_rows; return *this; } + +void Array::for_each(For_each_func func, void *info) const { + Chunk *chunk=head; + while(true) { + if(chunk==tail) { // last chunk? + for(Chunk::Row *row=chunk->rows; row!=append_here; row++) + (*func)(row->item, info); + break; + } else { + int count=chunk->count; + for(int i=0; irows[i].item, info); + chunk=chunk->rows[count].link; + } + } +} + +/*void Array::for_each(For_each_func_storage func, void *info) { + Chunk *chunk=head; + while(true) { + if(chunk==tail) { // last chunk? + for(Chunk::Row *row=chunk->rows; row!=append_here; row++) + (*func)(&row->item, info); + break; + } else { + int count=chunk->count; + for(int i=0; irows[i].item, info); + chunk=chunk->rows[count].link; + } + } +} +*/ + +/*void Array::for_each(For_each_func_const func, const void *info) const { + Chunk *chunk=head; + while(true) { + if(chunk==tail) { // last chunk? + for(Chunk::Row *row=chunk->rows; row!=append_here; row++) + (*func)(row->item, info); + break; + } else { + int count=chunk->count; + for(int i=0; irows[i].item, info); + chunk=chunk->rows[count].link; + } + } +} +*/ +void* Array::first_that(Item_that_func_const func, const void *info) const { + Chunk *chunk=head; + while(true) { + if(chunk==tail) { // last chunk? + for(Chunk::Row *row=chunk->rows; row!=append_here; row++) + if(void *result=(*func)(row->item, info)) + return result; + break; + } else { + int count=chunk->count; + for(int i=0; irows[i].item; + if(void *result=(*func)(item, info)) + return result; + } + chunk=chunk->rows[count].link; + } + } + return 0; +} + +void* Array::first_that(Item_that_func func, void *info) const { + Chunk *chunk=head; + while(true) { + if(chunk==tail) { // last chunk? + for(Chunk::Row *row=chunk->rows; row!=append_here; row++) + if(void *result=(*func)(row->item, info)) + return result; + break; + } else { + int count=chunk->count; + for(int i=0; irows[i].item; + if(void *result=(*func)(item, info)) + return result; + } + chunk=chunk->rows[count].link; + } + } + return 0; +}