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

1.23      paf         1: /** @file
1.24      paf         2:        Parser: array class.
                      3: 
1.54      paf         4:        Copyright (c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com)
1.47      paf         5:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.49      paf         6: */
1.24      paf         7: 
1.55    ! paf         8: static const char* IDENT_ARRAY_C="$Date: 2003/01/21 15:51:13 $";
1.1       paf         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.51      paf        15: Array::Array(Pool& apool, int initial_rows) : Pooled(apool) {
                     16:        initial_rows=max(initial_rows, CR_INITIAL_ROWS_DEFAULT);
                     17: 
1.6       paf        18:        head=tail=static_cast<Chunk *>(
1.41      paf        19:                malloc(sizeof(int)+sizeof(Chunk::Row)*initial_rows+sizeof(Chunk *), 19));
1.6       paf        20:        head->count=initial_rows;
1.1       paf        21:        append_here=head->rows;
1.6       paf        22:        link_row=&head->rows[initial_rows];
1.1       paf        23:        link_row->link=0;
                     24:        fused_rows=0;
1.45      paf        25: }
                     26: 
1.9       paf        27: void Array::expand(int chunk_rows) {
1.6       paf        28:        Chunk *chunk=tail=static_cast<Chunk *>(
1.41      paf        29:                malloc(sizeof(int)+sizeof(Chunk::Row)*chunk_rows+sizeof(Chunk *), 2));
1.6       paf        30:        chunk->count=chunk_rows;
1.1       paf        31:        link_row->link=chunk;
                     32:        append_here=chunk->rows;
1.6       paf        33:        link_row=&chunk->rows[chunk_rows];
1.1       paf        34:        link_row->link=0;
                     35: }
                     36: 
                     37: 
1.15      paf        38: Array& Array::operator += (Item *src) {
1.1       paf        39:        if(chunk_is_full())
1.32      parser     40:                expand(tail->count+CR_GROW_COUNT);
1.1       paf        41: 
                     42:        append_here->item=src;
                     43:        append_here++; fused_rows++;
                     44: 
                     45:        return *this;
                     46: }
                     47: 
1.15      paf        48: Array::Item *Array::get(int index) const {
1.3       paf        49:        if(!(index>=0 && index<size())) {
1.48      paf        50:                throw Exception(0, 0,
1.12      paf        51:                        "Array::get(%d) out of range [0..%d]", index, size()-1);
1.33      parser     52:                return 0; // never
1.2       paf        53:        }
                     54: 
1.42      paf        55:        int base=0;
                     56:        Chunk *chunk=head;
1.3       paf        57: 
                     58:        // navigate to chunk with "index" row
1.42      paf        59:        while(!(index>=base && index<base+chunk->count)) {
                     60:                int count=chunk->count;
                     61:                base+=count;
                     62:                chunk=chunk->rows[count].link;
1.3       paf        63:        }
                     64: 
1.42      paf        65:        return chunk->rows[index-base].item;
1.16      paf        66: }
                     67: 
                     68: void Array::put(int index, Item *item) {
                     69:        if(!(index>=0 && index<size())) {
1.48      paf        70:                throw Exception(0, 0, 
1.16      paf        71:                        "Array::put(%d) out of range [0..%d]", index, size()-1);
1.33      parser     72:                return; // never
1.16      paf        73:        }
                     74: 
1.42      paf        75:        int base=0;
                     76:        Chunk *chunk=head;
1.16      paf        77: 
                     78:        // navigate to chunk with "index" row
1.42      paf        79:        while(!(index>=base && index<base+chunk->count)) {
                     80:                int count=chunk->count;
                     81:                base+=count;
                     82:                chunk=chunk->rows[count].link;
1.16      paf        83:        }
                     84: 
1.42      paf        85:        chunk->rows[index-base].item=item;
1.4       paf        86: }
                     87: 
1.55    ! paf        88: Array& Array::append_array(const Array& src, int offset, int limit, bool reverse) {
        !            89:        if(reverse)
        !            90:                throw Exception(0,
        !            91:                        0,
        !            92:                        "not implemented in this version, please upgrade");
1.51      paf        93:        // fix limit
                     94:        {
1.55    ! paf        95:                if(offset<0 || offset>src.fused_rows)
        !            96:                        return *this;
        !            97: 
1.51      paf        98:                int m=src.fused_rows-offset;
1.55    ! paf        99:                if(!m || !limit)
1.51      paf       100:                        return *this;
1.55    ! paf       101:                if(limit<0 || limit>m)
1.51      paf       102:                        limit=m;
                    103:        }
                    104: 
1.4       paf       105:        int last_chunk_rows_left=link_row-append_here;
                    106:        
1.5       paf       107:        // our last chunk too small for src to fit?
1.51      paf       108:        if(limit>last_chunk_rows_left) {
1.5       paf       109:                // shrink last chunk to used rows
                    110:                tail->count-=last_chunk_rows_left;
                    111:                link_row=append_here;
                    112: 
1.6       paf       113:                // append new src_used_rows-ed chunk 
1.51      paf       114:                expand(limit);
1.5       paf       115:        }
                    116: 
1.51      paf       117:        // prepare...
1.18      paf       118:        Chunk *src_chunk=src.head;
1.6       paf       119:        Chunk::Row *dest_rows=append_here;
1.51      paf       120: 
                    121:        // a little ahead of time, no harm done ['limit' destroyed later]
                    122:        append_here+=limit;
                    123:        fused_rows+=limit;
                    124: 
                    125:        // ...do it
1.6       paf       126:        while(true) {
                    127:                int src_count=src_chunk->count;
1.51      paf       128:                int rows_to_copy_now=min(src_count-offset, limit);
1.6       paf       129:                Chunk *next_chunk=src_chunk->rows[src_count].link;
                    130:                if(next_chunk) {
                    131:                        // not last source chunk
1.51      paf       132:                        if(rows_to_copy_now>0) {
                    133:                                memcpy(dest_rows, src_chunk->rows+offset, 
1.18      paf       134:                                        sizeof(Chunk::Row)*rows_to_copy_now);
1.53      paf       135:                                offset=0;
1.51      paf       136:                                if(!(limit-=rows_to_copy_now))
                    137:                                        break;
                    138:                        } else
                    139:                                offset-=src_count;
1.19      paf       140: 
1.18      paf       141:                        dest_rows+=rows_to_copy_now;
1.6       paf       142:                        src_chunk=next_chunk;
                    143:                } else {
                    144:                        // the last source chunk
1.18      paf       145:                        if(rows_to_copy_now>0)
1.51      paf       146:                                memcpy(dest_rows, src_chunk->rows+offset, 
1.18      paf       147:                                        sizeof(Chunk::Row)*rows_to_copy_now);
1.6       paf       148:                        break;
1.4       paf       149:                }
                    150:        }
                    151: 
                    152:        return *this;
1.26      paf       153: }
                    154: 
1.28      paf       155: void Array::for_each(For_each_func func, void *info) const {
1.26      paf       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: }
1.44      paf       170: 
                    171: /*void Array::for_each(For_each_func_storage func, void *info) {
                    172:        Chunk *chunk=head;
                    173:        while(true) {
                    174:                if(chunk==tail) { // last chunk?
                    175:                        for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
                    176:                                (*func)(&row->item, info);
                    177:                        break;
                    178:                } else {
                    179:                        int count=chunk->count;
                    180:                        for(int i=0; i<count; i++)
                    181:                                (*func)(&chunk->rows[i].item, info);
                    182:                        chunk=chunk->rows[count].link;
                    183:                }
                    184:        }
                    185: }
                    186: */
1.26      paf       187: 
1.31      paf       188: /*void Array::for_each(For_each_func_const func, const void *info) const {
                    189:        Chunk *chunk=head;
                    190:        while(true) {
                    191:                if(chunk==tail) { // last chunk?
                    192:                        for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
                    193:                                (*func)(row->item, info);
                    194:                        break;
                    195:                } else {
                    196:                        int count=chunk->count;
                    197:                        for(int i=0; i<count; i++)
                    198:                                (*func)(chunk->rows[i].item, info);
                    199:                        chunk=chunk->rows[count].link;
                    200:                }
                    201:        }
                    202: }
                    203: */
1.38      parser    204: void* Array::first_that(Item_that_func_const func, const void *info) const {
1.29      paf       205:        Chunk *chunk=head;
                    206:        while(true) {
                    207:                if(chunk==tail) { // last chunk?
                    208:                        for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.38      parser    209:                                if(void *result=(*func)(row->item, info))
                    210:                                        return result;
1.29      paf       211:                        break;
                    212:                } else {
                    213:                        int count=chunk->count;
                    214:                        for(int i=0; i<count; i++) {
                    215:                                Item* item=chunk->rows[i].item;
1.38      parser    216:                                if(void *result=(*func)(item, info))
                    217:                                        return result;
1.29      paf       218:                        }
                    219:                        chunk=chunk->rows[count].link;
                    220:                }
                    221:        }
                    222:        return 0;
                    223: }
                    224: 
1.38      parser    225: void* Array::first_that(Item_that_func func, void *info) const {
1.26      paf       226:        Chunk *chunk=head;
                    227:        while(true) {
                    228:                if(chunk==tail) { // last chunk?
                    229:                        for(Chunk::Row *row=chunk->rows; row!=append_here; row++)
1.38      parser    230:                                if(void *result=(*func)(row->item, info))
                    231:                                        return result;
1.26      paf       232:                        break;
                    233:                } else {
                    234:                        int count=chunk->count;
1.27      paf       235:                        for(int i=0; i<count; i++) {
                    236:                                Item* item=chunk->rows[i].item;
1.38      parser    237:                                if(void *result=(*func)(item, info))
                    238:                                        return result;
1.27      paf       239:                        }
1.26      paf       240:                        chunk=chunk->rows[count].link;
                    241:                }
                    242:        }
                    243:        return 0;
1.4       paf       244: }

E-mail: