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

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

E-mail: