|
|
| version 1.16, 2001/02/21 17:36:58 | version 1.30, 2001/03/29 17:11:41 |
|---|---|
| Line 1 | Line 1 |
| /* | /** @file |
| $Id$ | Parser: array class. |
| Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) | |
| Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) | |
| $Id$ | |
| */ | */ |
| #include <string.h> | #include "pa_config_includes.h" |
| #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" | |
| Array::Array(Pool& apool, int initial_rows) : | Array::Array(Pool& apool, int initial_rows) : |
| Pooled(apool) { | Pooled(apool) { |
| initial_rows=min(3, initial_rows); | |
| head=tail=static_cast<Chunk *>( | head=tail=static_cast<Chunk *>( |
| pool().malloc(sizeof(int)+sizeof(Chunk::Row)*initial_rows+sizeof(Chunk *))); | malloc(sizeof(int)+sizeof(Chunk::Row)*initial_rows+sizeof(Chunk *))); |
| 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]; |
| Line 23 Array::Array(Pool& apool, int initial_ro | Line 32 Array::Array(Pool& apool, int initial_ro |
| } | } |
| void Array::expand(int chunk_rows) { | void Array::expand(int chunk_rows) { |
| if(chunk_rows<CR_INITIAL_ROWS_DEFAULT) | |
| chunk_rows=CR_INITIAL_ROWS_DEFAULT; | |
| Chunk *chunk=tail=static_cast<Chunk *>( | Chunk *chunk=tail=static_cast<Chunk *>( |
| pool().malloc(sizeof(int)+sizeof(Chunk::Row)*chunk_rows+sizeof(Chunk *))); | malloc(sizeof(int)+sizeof(Chunk::Row)*chunk_rows+sizeof(Chunk *))); |
| 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 45 Array& Array::operator += (Item *src) { | Line 57 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())) { |
| pool().exception().raise(0, 0, 0, | THROW(0, 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; | return 0; |
| } | } |
| Line 68 Array::Item *Array::get(int index) const | Line 80 Array::Item *Array::get(int index) const |
| void Array::put(int index, Item *item) { | void Array::put(int index, Item *item) { |
| if(!(index>=0 && index<size())) { | if(!(index>=0 && index<size())) { |
| pool().exception().raise(0, 0, 0, | THROW(0, 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; | return; |
| } | } |
| Line 89 void Array::put(int index, Item *item) { | Line 101 void Array::put(int index, Item *item) { |
| cache_chunk->rows[index-cache_chunk_base].item=item; | cache_chunk->rows[index-cache_chunk_base].item=item; |
| } | } |
| Array& Array::append_array(const Array& src) { | Array& Array::append_array(const Array& src, int offset) { |
| int src_used_rows=src.fused_rows; | int src_rows_to_copy=src.fused_rows-offset; |
| int last_chunk_rows_left=link_row-append_here; | int last_chunk_rows_left=link_row-append_here; |
| // our last chunk too small for src to fit? | // our last chunk too small for src to fit? |
| if(src_used_rows>last_chunk_rows_left) { | if(src_rows_to_copy>last_chunk_rows_left) { |
| // shrink last chunk to used rows | // shrink last chunk to used rows |
| tail->count-=last_chunk_rows_left; | tail->count-=last_chunk_rows_left; |
| link_row=append_here; | link_row=append_here; |
| // append new src_used_rows-ed chunk | // append new src_used_rows-ed chunk |
| expand(src_used_rows); | expand(src_rows_to_copy); |
| } | } |
| Chunk *src_chunk=src.head; | Chunk *src_chunk=src.head; |
| Chunk::Row *dest_rows=append_here; | Chunk::Row *dest_rows=append_here; |
| int rows_left_to_copy=src_used_rows; | int rows_left_to_copy=src.fused_rows; |
| int rows_left_to_skip=offset; | |
| while(true) { | while(true) { |
| int src_count=src_chunk->count; | int src_count=src_chunk->count; |
| Chunk *next_chunk=src_chunk->rows[src_count].link; | Chunk *next_chunk=src_chunk->rows[src_count].link; |
| if(next_chunk) { | if(next_chunk) { |
| // not last source chunk | // not last source chunk |
| // taking it all | // taking it all |
| memcpy(dest_rows, src_chunk->rows, sizeof(Chunk::Row)*src_count); | int rows_to_copy_now=src_count-rows_left_to_skip; |
| dest_rows+=src_count; | if(rows_to_copy_now>0) |
| memcpy(dest_rows, src_chunk->rows+rows_left_to_skip, | |
| sizeof(Chunk::Row)*rows_to_copy_now); | |
| else | |
| rows_left_to_skip-=src_count; | |
| dest_rows+=rows_to_copy_now; | |
| rows_left_to_copy-=src_count; | rows_left_to_copy-=src_count; |
| src_chunk=next_chunk; | src_chunk=next_chunk; |
| } else { | } else { |
| // the last source chunk | // the last source chunk |
| // taking only those rows of chunk that _left_to_copy | // taking only those rows of chunk that _left_to_copy |
| memcpy(dest_rows, src_chunk->rows, sizeof(Chunk::Row)*rows_left_to_copy); | int rows_to_copy_now=rows_left_to_copy-rows_left_to_skip; |
| if(rows_to_copy_now>0) | |
| memcpy(dest_rows, src_chunk->rows+rows_left_to_skip, | |
| sizeof(Chunk::Row)*rows_to_copy_now); | |
| break; | break; |
| } | } |
| } | } |
| append_here+=src_used_rows; | append_here+=src_rows_to_copy; |
| fused_rows+=src_used_rows; | fused_rows+=src_rows_to_copy; |
| return *this; | 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; i<count; i++) | |
| (*func)(chunk->rows[i].item, info); | |
| chunk=chunk->rows[count].link; | |
| } | |
| } | |
| } | |
| Array::Item* Array::first_that(First_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((*func)(row->item, info)) | |
| return row->item; | |
| break; | |
| } else { | |
| int count=chunk->count; | |
| for(int i=0; i<count; i++) { | |
| Item* item=chunk->rows[i].item; | |
| if((*func)(item, info)) | |
| return item; | |
| } | |
| chunk=chunk->rows[count].link; | |
| } | |
| } | |
| return 0; | |
| } | |
| Array::Item* Array::first_that(First_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((*func)(row->item, info)) | |
| return row->item; | |
| break; | |
| } else { | |
| int count=chunk->count; | |
| for(int i=0; i<count; i++) { | |
| Item* item=chunk->rows[i].item; | |
| if((*func)(item, info)) | |
| return item; | |
| } | |
| chunk=chunk->rows[count].link; | |
| } | |
| } | |
| return 0; | |
| } |