--- parser3/src/include/pa_array.h 2003/04/14 14:03:11 1.57.2.27.2.17 +++ parser3/src/include/pa_array.h 2003/04/11 15:00:05 1.58 @@ -1,264 +1,198 @@ /** @file - Parser: Array & Array_iterator classes decls. + Parser: Array & Array_iter classes decls. - Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) + Copyright (c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ #ifndef PA_ARRAY_H #define PA_ARRAY_H -static const char* IDENT_ARRAY_Y="$Date: 2003/04/14 14:03:11 $"; +static const char* IDENT_ARRAY_Y="$Date: 2003/04/11 15:00:05 $"; -// includes - -#include "pa_memory.h" -#include "pa_exception.h" - -// forwards - -template class Array_iterator; - -// defines - -#define ARRAY_OPTION_LIMIT_ALL ((size_t)-1) - -/// Simple Array -template class Array: public PA_Object { - - friend class Array_iterator; - -protected: - - /// elements[growing size] here - T *felements; - - // allocated size - size_t fallocated; - - // array size - size_t fused; +#include "pa_pool.h" +#include "pa_types.h" +#include "pa_string.h" + +class Array_iter; + +/** + Pooled Array. + + Internal structure: + @verbatim + Array Chunk0 + ====== ======== + head--------------->[ptr] + append_here-------->[ptr] + link_row ........ + . . + . [ptr] + ...........>[link to the next chunk] + @endverbatim +*/ +class Array : public Pooled { + friend class Array_iter; public: - struct Action_options { - size_t offset; - size_t limit; //< ARRAY_OPTION_LIMIT_ALL means 'all'. zero limit means 'nothing' - bool reverse; - bool defined; - - Action_options( - size_t aoffset=0, - size_t alimit=ARRAY_OPTION_LIMIT_ALL, - bool areverse=false): - offset(aoffset), limit(alimit), reverse(areverse), - defined(false) {} - - bool adjust(size_t count) { - if(!count || !limit) - return false; - size_t row=offset; - if(row>=count) - return false; - // max(limit) - size_t m=reverse? - offset - :count-offset; - if(!m) - return false; - // fix limit - if(limit==ARRAY_OPTION_LIMIT_ALL || limit>m) - limit=m; - return true; - } + /// Array item type + typedef void Item; - + /*/// for_each iterator function type, const info + typedef void (*For_each_func_const)(Item *value, const void *info); + */ + + /// for_each iterator function type + typedef void (*For_each_func)(Item *value, void *info); + /* + /// for_each iterator function type, passing item storage address + typedef void (*For_each_func_storage)(Item ** value, void *info); + */ + + /// first_that iterator function type, const info + typedef void *(*Item_that_func_const)(Item *value, const void *info); + + /// first_that iterator function type + typedef void *(*Item_that_func)(Item *value, void *info); + + enum { + CR_INITIAL_ROWS_DEFAULT=3, ///< default preallocated row count + CR_GROW_COUNT=3 ///< each time the Array chunk_is_full() array expanded() }; - typedef T element_type; - - Array(size_t initial=3): - fallocated(initial>3?initial:3), - fused(0) - { - felements=static_cast(malloc(fallocated*sizeof(T))); - } +public: - /// how many items are in Array - size_t count() const { return fused; } - /// append to array - Array& operator += (T src) { - if(is_full()) - expand(2); + Array(Pool& apool, int initial_rows=CR_INITIAL_ROWS_DEFAULT); - felements[fused++]=src; + /// size Array. how many items are in it + int size() const { return fused_rows; } + /// append Item to array + Array& operator += (Item *src); + /// append int value to array + Array& operator += (int value) { return *this+=reinterpret_cast(value); } - return *this; - } + /// dirty hack to allow constant items storage. I long for Array + Array& operator += (const Item *src) { return *this+=const_cast(src); } /// append other Array portion to this one. starting from offset - Array& append(const Array& src, - size_t offset=0, - size_t limit=ARRAY_OPTION_LIMIT_ALL, //< negative limit means 'all'. zero limit means 'nothing' - bool reverse=false) { - - size_t src_count=src.count(); - // skip tivials - if(!src_count || !limit || offset>=src_count) - return *this; - // max(limit) - size_t m=reverse? - 1+offset - :src_count-offset; - if(!m) - return *this; - // fix limit - if(limit==ARRAY_OPTION_LIMIT_ALL || limit>m) - limit=m; - - ssize_t delta=reverse? - (ssize_t)limit - :limit-(fallocated-fused); - if(delta>0) - expand(delta); - - T* from=&src.felements[offset]; - T* to=&felements[fused]; - if(reverse) { // reverse - for(T* from_end=from-limit; from>from_end; --from) - *to++=*from; - - } else { // forward - for(T* from_end=from+limit; from=0 && index=0 && index=0 && index(get(index)); } + + void put(int index, Item *item); + void put_int(int index, int value) { put(index, reinterpret_cast(value)); } + /// convinient way to get strings from Array. I long for Array + const String *get_string(int index) const { + return const_cast(static_cast(get(index))); + } + + /*/// iterate over all elements, const info + void for_each(For_each_func_const func, const void *info=0) const; + */ /// iterate over all elements - template void for_each(void (*callback)(T, I), I info) const { - T *last=felements+fused; - for(T *current=felements; current T first_that(bool (*callback)(T, I), I info) const { - T *last=felements+fused; - for(T *current=felements; current a; - for(Array_iterator i(a); i.has_next(); ) { - T& element=i.next(); - ... - } - @endcode -*/ -template class Array_iterator { - - const Array& farray; - T *fcurrent; - T *flast; - +/// handy array iterator +class Array_iter { public: - Array_iterator(const Array& aarray): farray(aarray) { - fcurrent=farray.felements; - flast=farray.felements+farray.count(); + Array_iter(const Array& aarray) : array(aarray), + chunk(aarray.head), + row(chunk->rows), + countdown(chunk->count) { } /// there are still elements bool has_next() { - return fcurrent a; - for(Array_iterator i(a); i.has_next(); ) { - T& element=i.next(); - ... - } - @endcode -* / -template class Array_modifing_iterator { - - Array& farray; - T *fcurrent; - T *flast; - -public: - - Array_modifing_iterator(Array& aarray): farray(aarray) { - fcurrent=farray.felements; - flast=farray.felements+farray.count(); + /// quickly extracts next Array::Item + Array::Item *next() { + // assuming: never called after has_next()! + if(countdown==0) { // end of chunk? + chunk=row->link; + row=chunk->rows; + countdown=chunk->count; + } + Array::Item *result=row->item; + row++; countdown--; + return result; } - /// there are still elements - bool has_next() { - return fcurrent(static_cast(next())); } - /// quickly extracts next Array element - T& next() { - return *(fcurrent++); - } +private: + const Array& array; + const Array::Chunk *chunk; + const Array::Chunk::Row *row; + int countdown; }; -*/ + #endif