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

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

E-mail: