Annotation of parser3/src/main/pa_array.C, revision 1.36

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

E-mail: