|
|
| version 1.57.2.27.2.9, 2003/03/27 10:53:01 | version 1.60, 2003/11/07 13:59:21 |
|---|---|
| Line 8 | Line 8 |
| #ifndef PA_ARRAY_H | #ifndef PA_ARRAY_H |
| #define PA_ARRAY_H | #define PA_ARRAY_H |
| static const char* IDENT_ARRAY_H="$Date$"; | static const char* IDENT_ARRAY_Y="$Date$"; |
| // includes | // includes |
| Line 19 static const char* IDENT_ARRAY_H="$Date$ | Line 19 static const char* IDENT_ARRAY_H="$Date$ |
| template<typename T> class Array_iterator; | template<typename T> class Array_iterator; |
| // defines | |
| #define ARRAY_OPTION_LIMIT_ALL ((size_t)-1) | |
| /// Simple Array | /// Simple Array |
| template<typename T> class Array: public PA_Object { | template<typename T> class Array: public PA_Object { |
| Line 36 protected: | Line 40 protected: |
| size_t fused; | size_t fused; |
| public: | 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; | |
| } | |
| }; | |
| typedef T element_type; | typedef T element_type; |
| Array(int initial=3): | Array(size_t initial=3): |
| fallocated(initial>3?initial:3), | fallocated(initial>3?initial:3), |
| fused(0) | fused(0) |
| { | { |
| Line 58 public: | Line 97 public: |
| } | } |
| /// append other Array portion to this one. starting from offset | /// append other Array portion to this one. starting from offset |
| Array& append(const Array& src, int offset=0, int limit=0) { | Array& append(const Array& src, |
| if(offset<0) { | size_t offset=0, |
| throw Exception(0, | size_t limit=ARRAY_OPTION_LIMIT_ALL, //< negative limit means 'all'. zero limit means 'nothing' |
| 0, | bool reverse=false) { |
| "Array::append(offset=%d) out <0", offset); | |
| //return Nothing; // never | 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 | // fix limit |
| { | if(limit==ARRAY_OPTION_LIMIT_ALL || limit>m) |
| int m=src.count()-offset; | limit=m; |
| if(!m || limit<0) | |
| return *this; | |
| if(!limit || limit>m) | |
| limit=m; | |
| } | |
| int delta=limit-(fallocated-fused); | ssize_t delta=reverse? |
| (ssize_t)limit | |
| :limit-(fallocated-fused); | |
| if(delta>0) | if(delta>0) |
| expand(delta); | expand(delta); |
| T* from=&src.felements[offset]; | T* from=&src.felements[offset]; |
| T* to=&felements[fused]; | T* to=&felements[fused]; |
| T* from_end=from+limit; | if(reverse) { // reverse |
| while(from<from_end) | for(T* from_end=from-limit; from>from_end; --from) |
| *to++=*from++; | *to++=*from; |
| } else { // forward | |
| for(T* from_end=from+limit; from<from_end; from++) | |
| *to++=*from; | |
| } | |
| fused+=limit; | fused+=limit; |
| return *this; | return *this; |
| } | } |
| /// quick version of get index-element [use in tight places when sure] | /// get index-element |
| T unchecked_get(size_t index) const { | T get(size_t index) const { |
| assert(index>=0 && index<count()); | |
| return felements[index]; | return felements[index]; |
| } | } |
| /// ref version of quick version of get index-element [use in tight places when sure] | /// ref version of get |
| T& unchecked_get_ref(size_t index) const { | T& get_ref(size_t index) const { |
| assert(index>=0 && index<count()); | |
| return felements[index]; | return felements[index]; |
| } | } |
| size_t check(const char* name, size_t index) const { | |
| size_t lcount=count(); | |
| if(!(index>=0 && index<lcount)) { | |
| throw Exception(0, | |
| 0, | |
| "Array::%s(%d) out of range [0..%d]", name, index, lcount-1); | |
| return 0; // never | |
| } | |
| return index; | |
| } | |
| /// get index-element | |
| T get(size_t index) const { | |
| return unchecked_get(check("get", index)); | |
| } | |
| T operator [](size_t index) const { return get(index); } | |
| /* | |
| /// get the reference to index-element | |
| T& get_ref(size_t index) { | |
| return felements[check("get_ref", index)]; | |
| }*/ | |
| /// put index-element | /// put index-element |
| void put(size_t index, T element) { | void put(size_t index, T element) { |
| felements[check("put", index)]=element; | assert(index>=0 && index<count()); |
| felements[index]=element; | |
| } | } |
| T operator [](size_t index) const { return get(index); } | |
| /// iterate over all elements | /// iterate over all elements |
| template<typename I> void for_each(void (*callback)(T, I), I info) const { | template<typename I> void for_each(void (*callback)(T, I), I info) const { |
| T *last=felements+fused; | T *last=felements+fused; |
| for(T *current=felements; current<last; current++) | for(T *current=felements; current<last; current++) |
| callback(*current, info); | callback(*current, info); |
| } | |
| /// iterate over all elements | |
| template<typename I> void for_each_ref(void (*callback)(T&, I), I info) { | |
| T *last=felements+fused; | |
| for(T *current=felements; current<last; current++) | |
| callback(*current, info); | |
| } | } |
| /// iterate over all elements until condition becomes true, return that element | /// iterate over all elements until condition becomes true, return that element |