|
|
| version 1.37, 2001/06/28 07:44:17 | version 1.48, 2002/03/27 15:30:36 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: array class. | Parser: array class. |
| Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | |
| Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) | $Id$ |
| */ | */ |
| static const char *RCSId="$Id$"; | |
| #include "pa_pool.h" | #include "pa_pool.h" |
| #include "pa_array.h" | #include "pa_array.h" |
| #include "pa_exception.h" | #include "pa_exception.h" |
| #include "pa_common.h" | #include "pa_common.h" |
| Array::Array(Pool& apool, int initial_rows) : | void Array::construct_new(int initial_rows) { |
| Pooled(apool) { | |
| initial_rows=max(initial_rows, CR_INITIAL_ROWS_DEFAULT); | |
| head=tail=static_cast<Chunk *>( | head=tail=static_cast<Chunk *>( |
| 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; | head->count=initial_rows; |
| append_here=head->rows; | append_here=head->rows; |
| link_row=&head->rows[initial_rows]; | link_row=&head->rows[initial_rows]; |
| link_row->link=0; | link_row->link=0; |
| fused_rows=0; | fused_rows=0; |
| } | |
| Array::Array(Pool& apool, int initial_rows) : Pooled(apool) { | |
| construct_new(max(initial_rows, CR_INITIAL_ROWS_DEFAULT)); | |
| } | |
| cache_chunk_base=0; | Array::Array(const Array& source, int offset) : Pooled(source.pool()) { |
| cache_chunk=head; | construct_new(source.size()); |
| append_array(source, offset); | |
| } | } |
| void Array::expand(int chunk_rows) { | void Array::expand(int chunk_rows) { |
| Chunk *chunk=tail=static_cast<Chunk *>( | Chunk *chunk=tail=static_cast<Chunk *>( |
| 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; | chunk->count=chunk_rows; |
| link_row->link=chunk; | link_row->link=chunk; |
| append_here=chunk->rows; | append_here=chunk->rows; |
| Line 51 Array& Array::operator += (Item *src) { | Line 54 Array& Array::operator += (Item *src) { |
| Array::Item *Array::get(int index) const { | Array::Item *Array::get(int index) const { |
| if(!(index>=0 && index<size())) { | if(!(index>=0 && index<size())) { |
| THROW(0, 0, 0, | throw Exception(0, 0, |
| "Array::get(%d) out of range [0..%d]", index, size()-1); | "Array::get(%d) out of range [0..%d]", index, size()-1); |
| return 0; // never | return 0; // never |
| } | } |
| // if they ask index to the left of cached position, forget cache | int base=0; |
| if(index<cache_chunk_base) { | Chunk *chunk=head; |
| cache_chunk_base=0; | |
| cache_chunk=head; | |
| } | |
| // navigate to chunk with "index" row | // navigate to chunk with "index" row |
| while(!(index>=cache_chunk_base && index<cache_chunk_base+cache_chunk->count)) { | while(!(index>=base && index<base+chunk->count)) { |
| int count=cache_chunk->count; | int count=chunk->count; |
| cache_chunk_base+=count; | base+=count; |
| cache_chunk=cache_chunk->rows[count].link; | chunk=chunk->rows[count].link; |
| } | } |
| return cache_chunk->rows[index-cache_chunk_base].item; | return chunk->rows[index-base].item; |
| } | } |
| void Array::put(int index, Item *item) { | void Array::put(int index, Item *item) { |
| if(!(index>=0 && index<size())) { | if(!(index>=0 && index<size())) { |
| THROW(0, 0, 0, | throw Exception(0, 0, |
| "Array::put(%d) out of range [0..%d]", index, size()-1); | "Array::put(%d) out of range [0..%d]", index, size()-1); |
| return; // never | return; // never |
| } | } |
| // if they ask index to the left of cached position, forget cache | int base=0; |
| if(index<cache_chunk_base) { | Chunk *chunk=head; |
| cache_chunk_base=0; | |
| cache_chunk=head; | |
| } | |
| // navigate to chunk with "index" row | // navigate to chunk with "index" row |
| while(!(index>=cache_chunk_base && index<cache_chunk_base+cache_chunk->count)) { | while(!(index>=base && index<base+chunk->count)) { |
| int count=cache_chunk->count; | int count=chunk->count; |
| cache_chunk_base+=count; | base+=count; |
| cache_chunk=cache_chunk->rows[count].link; | chunk=chunk->rows[count].link; |
| } | } |
| cache_chunk->rows[index-cache_chunk_base].item=item; | chunk->rows[index-base].item=item; |
| } | } |
| Array& Array::append_array(const Array& src, int offset) { | Array& Array::append_array(const Array& src, int offset) { |
| Line 161 void Array::for_each(For_each_func func, | Line 158 void Array::for_each(For_each_func func, |
| } | } |
| } | } |
| /*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; i<count; i++) | |
| (*func)(&chunk->rows[i].item, info); | |
| chunk=chunk->rows[count].link; | |
| } | |
| } | |
| } | |
| */ | |
| /*void Array::for_each(For_each_func_const func, const void *info) const { | /*void Array::for_each(For_each_func_const func, const void *info) const { |
| Chunk *chunk=head; | Chunk *chunk=head; |
| while(true) { | while(true) { |
| Line 177 void Array::for_each(For_each_func func, | Line 191 void Array::for_each(For_each_func func, |
| } | } |
| } | } |
| */ | */ |
| Array::Item* Array::first_that(First_that_func_const func, const void *info) const { | void* Array::first_that(Item_that_func_const func, const void *info) const { |
| Chunk *chunk=head; | Chunk *chunk=head; |
| while(true) { | while(true) { |
| if(chunk==tail) { // last chunk? | if(chunk==tail) { // last chunk? |
| for(Chunk::Row *row=chunk->rows; row!=append_here; row++) | for(Chunk::Row *row=chunk->rows; row!=append_here; row++) |
| if((*func)(row->item, info)) | if(void *result=(*func)(row->item, info)) |
| return row->item; | return result; |
| break; | break; |
| } else { | } else { |
| int count=chunk->count; | int count=chunk->count; |
| for(int i=0; i<count; i++) { | for(int i=0; i<count; i++) { |
| Item* item=chunk->rows[i].item; | Item* item=chunk->rows[i].item; |
| if((*func)(item, info)) | if(void *result=(*func)(item, info)) |
| return item; | return result; |
| } | } |
| chunk=chunk->rows[count].link; | chunk=chunk->rows[count].link; |
| } | } |
| Line 198 Array::Item* Array::first_that(First_tha | Line 212 Array::Item* Array::first_that(First_tha |
| return 0; | return 0; |
| } | } |
| Array::Item* Array::first_that(First_that_func func, void *info) const { | void* Array::first_that(Item_that_func func, void *info) const { |
| Chunk *chunk=head; | Chunk *chunk=head; |
| while(true) { | while(true) { |
| if(chunk==tail) { // last chunk? | if(chunk==tail) { // last chunk? |
| for(Chunk::Row *row=chunk->rows; row!=append_here; row++) | for(Chunk::Row *row=chunk->rows; row!=append_here; row++) |
| if((*func)(row->item, info)) | if(void *result=(*func)(row->item, info)) |
| return row->item; | return result; |
| break; | break; |
| } else { | } else { |
| int count=chunk->count; | int count=chunk->count; |
| for(int i=0; i<count; i++) { | for(int i=0; i<count; i++) { |
| Item* item=chunk->rows[i].item; | Item* item=chunk->rows[i].item; |
| if((*func)(item, info)) | if(void *result=(*func)(item, info)) |
| return item; | return result; |
| } | } |
| chunk=chunk->rows[count].link; | chunk=chunk->rows[count].link; |
| } | } |