Annotation of parser3/src/types/pa_varray.h, revision 1.15

1.1       moko        1: /** @file
                      2:        Parser: @b array parser type decl.
                      3: 
                      4:        Copyright (c) 2001-2023 Art. Lebedev Studio (http://www.artlebedev.com)
                      5:        Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
                      6: */
                      7: 
                      8: #ifndef PA_VARRAY_H
                      9: #define PA_VARRAY_H
                     10: 
1.15    ! moko       11: #define IDENT_PA_VARRAY_H "$Id: pa_varray.h,v 1.14 2024/10/23 23:53:06 moko Exp $"
1.1       moko       12: 
                     13: #include "classes.h"
                     14: #include "pa_value.h"
                     15: #include "pa_array.h"
                     16: #include "pa_vhash.h"
                     17: #include "pa_vint.h"
                     18: #include "pa_globals.h"
                     19: #include "pa_symbols.h"
                     20: 
                     21: // defines
                     22: 
1.2       moko       23: #define VARRAY_TYPE "array"
1.15    ! moko       24: //#define DEBUG_ARRAY_USED
1.1       moko       25: 
                     26: extern Methoded* array_class;
                     27: 
1.2       moko       28: /// Sparse Array
                     29: template<typename T> class SparseArray: public Array<T> {
1.5       moko       30: 
                     31:        mutable size_t fused;
                     32: 
1.2       moko       33: public:
1.5       moko       34:        inline SparseArray(size_t initial=0) : Array<T>(initial), fused(0) {}
1.2       moko       35: 
1.6       moko       36:        inline SparseArray(size_t size, T* elements) : Array<T>(size), fused(size) {
                     37:                T* elements_end=elements + size;
                     38:                for(T* dst=this->felements; elements < elements_end;)
                     39:                        *dst++=*elements++;
                     40:                this->fsize=size;
                     41:        }
                     42: 
1.4       moko       43:        inline T get(size_t index) const {
                     44:                return index < this->count() ? this->felements[index] : NULL;
                     45:        }
                     46: 
1.9       moko       47:        void fit(size_t index);
                     48: 
1.5       moko       49:        inline void put(size_t index, T element){
                     50:                this->fit(index);
1.2       moko       51:                this->felements[index]=element;
1.5       moko       52:                if(index >= this->fsize){
                     53:                        this->fsize=index+1;
                     54:                }
                     55:        }
                     56: 
1.10      moko       57:        inline bool put_dont_replace(size_t index, T element){
                     58:                this->fit(index);
                     59:                if(this->felements[index])
                     60:                        return true;
                     61:                this->felements[index]=element;
                     62:                if(index >= this->fsize){
                     63:                        this->fsize=index+1;
                     64:                }
                     65:                return false;
                     66:        }
                     67: 
1.5       moko       68:        inline void insert(size_t index, T element) {
                     69:                if(index >= this->fsize){
                     70:                        this->fit(index);
                     71:                        this->felements[index]=element;
                     72:                        this->fsize=index+1;
                     73:                } else {
                     74:                        Array<T>::insert(index, element);
                     75:                }
                     76:        }
                     77: 
                     78:        size_t used() const{
1.15    ! moko       79: #ifndef DEBUG_ARRAY_USED
        !            80:                if(!fused)
        !            81: #endif
        !            82:                {
        !            83:                        size_t used=0;
1.5       moko       84:                        for(Array_iterator<T> i(*this); i;) {
                     85:                                if(i.next())
1.15    ! moko       86:                                        used++;
1.5       moko       87:                        }
1.15    ! moko       88: #ifdef DEBUG_ARRAY_USED
        !            89:                        if(fused && fused!=used)
        !            90:                                throw Exception(PARSER_RUNTIME, 0, "cached elements count %d differs from actual %d", fused, used);
        !            91: #endif
        !            92:                        fused=used;
1.5       moko       93:                }
                     94:                return fused;
                     95:        }
                     96: 
                     97:        inline void clear(size_t index) {
1.7       moko       98:                if(index < this->count()){
1.5       moko       99:                        this->felements[index]=NULL;
1.14      moko      100:                        if(index+1 == this->fsize){
1.7       moko      101:                                this->fsize--;
1.14      moko      102:                        }
1.2       moko      103:                }
                    104:        }
1.5       moko      105: 
                    106:        inline void clear() { Array<T>::clear(); }
                    107: 
1.8       moko      108:        inline void remove(size_t index) {
                    109:                if(index < this->count()){
                    110:                        Array<T>::remove(index);
                    111:                }
                    112:        }
                    113: 
1.5       moko      114:        inline void invalidate(){
                    115:                fused=0;
                    116:        }
                    117: 
1.11      moko      118:        inline void confirm_all_used(){
                    119:                fused=this->count();
                    120:        }
                    121: 
1.15    ! moko      122:        void compact(bool compact_undef){
1.13      moko      123:                T* dst=this->felements;
                    124:                T* elements_end=dst + this->fsize;
                    125: 
1.15    ! moko      126:                if(compact_undef){
        !           127:                        for(T* src=this->felements; src < elements_end; src++)
        !           128:                                if(*src && (*src)->is_defined())
        !           129:                                        *dst++=*src;
        !           130:                } else {
        !           131:                        for(T* src=this->felements; src < elements_end; src++)
        !           132:                                if(*src)
        !           133:                                        *dst++=*src;
        !           134:                }
        !           135: 
        !           136:                this->fsize=dst-this->felements;
1.13      moko      137:                this->fused=this->fsize;
                    138:        }
                    139: 
1.2       moko      140: };
                    141: 
                    142: 
1.1       moko      143: class VArray: public VHashBase {
                    144: public: // value
                    145: 
                    146:        override const char* type() const { return VARRAY_TYPE; }
                    147:        override VStateless_class *get_class() { return array_class; }
                    148: 
1.5       moko      149:        /// VArray: used elements count
                    150:        override int as_int() const { return farray.used(); }
                    151:        override double as_double() const { return farray.used(); }
                    152:        override bool is_defined() const { return farray.used()!=0; }
                    153:        override bool as_bool() const { return farray.used()!=0; }
                    154:        override Value& as_expr_result() { return *new VInt(farray.used()); }
1.1       moko      155: 
                    156:        /// VArray: virtual hash
                    157:        override HashStringValue *get_hash() { return &hash(); }
                    158:        override HashStringValue* get_fields() { return &hash(); }
                    159:        override HashStringValue* get_fields_reference() { return &hash(); }
                    160: 
                    161:        /// VArray: json-string
                    162:        override const String* get_json_string(Json_options& options);
                    163: 
                    164:        /// VArray: (key)=value
                    165:        override Value* get_element(const String& aname) {
                    166:                // $element first
1.4       moko      167:                if(Value* result=farray.get(index(aname)))
1.1       moko      168:                        return result;
                    169: 
                    170:                // $fields -- pseudo field to make 'hash' and 'array' more like 'table'
                    171:                if(SYMBOLS_EQ(aname,FIELDS_SYMBOL))
                    172:                        return this;
                    173: 
                    174: #if !defined(FEATURE_GET_ELEMENT4CALL) || !defined(OPTIMIZE_BYTECODE_GET_ELEMENT__SPECIAL)
                    175:                // $method, CLASS, CLASS_NAME
                    176:                if(Value* result=VStateless_object::get_element(aname))
                    177:                        return result;
                    178: #endif
                    179:                return NULL;
                    180:        }
                    181: 
                    182: #ifdef FEATURE_GET_ELEMENT4CALL
                    183:        override Value* get_element4call(const String& aname) {
                    184:                // $method first
                    185:                if(Value* result=VStateless_object::get_element(aname))
                    186:                        return result;
                    187: 
                    188:                // $element
1.12      moko      189:                if(is_index(aname))
                    190:                        if(Value* result=farray.get(index(aname)))
                    191:                                return result;
1.1       moko      192: 
                    193:                return bark("%s method not found", &aname);
                    194:        }
                    195: #endif
                    196: 
                    197:        /// VArray: (key)=value
                    198:        override const VJunction* put_element(const String& aname, Value* avalue) {
1.5       moko      199:                farray.put(index(aname), avalue);
1.14      moko      200:                farray.invalidate();
1.1       moko      201:                return 0;
                    202:        }
                    203: 
                    204: public: // VHashBase
                    205: 
                    206:        override HashStringValue& hash();
                    207:        override void set_default(Value*) { }
                    208:        override Value* get_default() { return 0; }
1.5       moko      209:        override void add(Value* avalue) { farray+=avalue; /* only json uses it, thus no need to invalidate()*/ }
1.1       moko      210: 
                    211: public: // usage
                    212: 
1.14      moko      213:        VArray(size_t initial=0): farray(initial) {}
                    214:        VArray(size_t size, Value** elements): farray(size, elements) {}
1.1       moko      215: 
                    216:        ArrayValue &array() { return farray; }
                    217: 
                    218:        static size_t index(int aindex){
                    219:                if(aindex<0)
1.9       moko      220:                        throw Exception("number.format", 0, "index out of range (negative)");
1.1       moko      221:                return aindex;
                    222:        }
                    223: 
1.7       moko      224:        static size_t index(const String::Body& aindex){ return pa_atoui(aindex.cstr()); }
                    225:        static size_t index(const String& aindex){ return pa_atoui(aindex.cstr(), 10, &aindex); }
1.1       moko      226: 
1.12      moko      227:        static bool is_index(const String& aindex){
                    228:                for(const char *pos=aindex.cstr();*pos;pos++){
                    229:                        if ((*pos < '0') || (*pos > '9'))
                    230:                                return false;
                    231:                }
                    232:                return true;
                    233:        }
                    234: 
1.5       moko      235:        bool contains(size_t index){
                    236:                return farray.get(index) != NULL;
1.1       moko      237:        }
                    238: 
                    239: private:
                    240: 
                    241:        ArrayValue farray;
                    242: 
                    243: };
                    244: 
                    245: #endif

E-mail: