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

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.23    ! moko       11: #define IDENT_PA_VARRAY_H "$Id: pa_varray.h,v 1.22 2024/10/28 13:05:14 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) {
1.16      moko       37:                memcpy(this->felements, elements, size * sizeof(T));
1.6       moko       38:                this->fsize=size;
                     39:        }
                     40: 
1.23    ! moko       41:        void copy(SparseArray<T> &src) {
        !            42:                size_t size=src.fsize;
        !            43:                if(size){
        !            44:                        fit(size-1);
        !            45:                        memcpy(this->felements, src.felements, size * sizeof(T));
        !            46:                        this->fsize=size;
        !            47:                        fused=src.fused;
        !            48:                }
        !            49:        }
        !            50: 
        !            51:        // note: 'operator+=' is used directly from Array
1.17      moko       52: 
                     53:        void fit(size_t index);
                     54: 
1.4       moko       55:        inline T get(size_t index) const {
1.18      moko       56:                return index < this->fsize ? this->felements[index] : NULL;
1.4       moko       57:        }
                     58: 
1.5       moko       59:        inline void put(size_t index, T element){
                     60:                this->fit(index);
1.2       moko       61:                this->felements[index]=element;
1.5       moko       62:                if(index >= this->fsize){
                     63:                        this->fsize=index+1;
                     64:                }
                     65:        }
                     66: 
1.10      moko       67:        inline bool put_dont_replace(size_t index, T element){
                     68:                this->fit(index);
                     69:                if(this->felements[index])
                     70:                        return true;
                     71:                this->felements[index]=element;
                     72:                if(index >= this->fsize){
                     73:                        this->fsize=index+1;
                     74:                }
                     75:                return false;
                     76:        }
                     77: 
1.5       moko       78:        inline void insert(size_t index, T element) {
                     79:                if(index >= this->fsize){
                     80:                        this->fit(index);
                     81:                        this->felements[index]=element;
                     82:                        this->fsize=index+1;
                     83:                } else {
                     84:                        Array<T>::insert(index, element);
                     85:                }
                     86:        }
                     87: 
                     88:        size_t used() const{
1.15      moko       89: #ifndef DEBUG_ARRAY_USED
                     90:                if(!fused)
                     91: #endif
                     92:                {
                     93:                        size_t used=0;
1.5       moko       94:                        for(Array_iterator<T> i(*this); i;) {
                     95:                                if(i.next())
1.15      moko       96:                                        used++;
1.5       moko       97:                        }
1.15      moko       98: #ifdef DEBUG_ARRAY_USED
                     99:                        if(fused && fused!=used)
                    100:                                throw Exception(PARSER_RUNTIME, 0, "cached elements count %d differs from actual %d", fused, used);
1.22      moko      101:                        printf(fused ? "cached used %d\n" : "counted used %d\n", used);
1.15      moko      102: #endif
                    103:                        fused=used;
1.5       moko      104:                }
                    105:                return fused;
                    106:        }
                    107: 
                    108:        inline void clear(size_t index) {
1.18      moko      109:                if(index < this->fsize){
1.5       moko      110:                        this->felements[index]=NULL;
1.18      moko      111:                        if(index == this->fsize-1){
1.7       moko      112:                                this->fsize--;
1.18      moko      113:                                locate_last_used();
1.14      moko      114:                        }
1.2       moko      115:                }
                    116:        }
1.5       moko      117: 
                    118:        inline void clear() { Array<T>::clear(); }
                    119: 
1.8       moko      120:        inline void remove(size_t index) {
1.18      moko      121:                if(index < this->fsize){
1.8       moko      122:                        Array<T>::remove(index);
1.18      moko      123:                        if(index==this->fsize)
                    124:                                locate_last_used();
1.8       moko      125:                }
                    126:        }
                    127: 
1.18      moko      128:        inline T pop() {
                    129:                if(this->fsize){
                    130:                        T result=this->felements[this->fsize-1];
                    131:                        this->fsize--;
                    132:                        locate_last_used();
                    133:                        return result;
                    134:                }
                    135:                return NULL;
                    136:        }
                    137: 
1.5       moko      138:        inline void invalidate(){
                    139:                fused=0;
                    140:        }
                    141: 
1.18      moko      142:        inline void locate_last_used(){
                    143:                for(;this->fsize>0 && !this->felements[this->fsize-1];this->fsize--);
                    144:        }
                    145: 
1.11      moko      146:        inline void confirm_all_used(){
1.18      moko      147:                fused=this->fsize;
1.11      moko      148:        }
                    149: 
1.19      moko      150:        inline void change_used(int delta){
                    151:                if(fused){
                    152:                        fused+=delta;
                    153:                }
                    154:        }
                    155: 
1.15      moko      156:        void compact(bool compact_undef){
1.13      moko      157:                T* dst=this->felements;
                    158:                T* elements_end=dst + this->fsize;
                    159: 
1.15      moko      160:                if(compact_undef){
                    161:                        for(T* src=this->felements; src < elements_end; src++)
                    162:                                if(*src && (*src)->is_defined())
                    163:                                        *dst++=*src;
                    164:                } else {
                    165:                        for(T* src=this->felements; src < elements_end; src++)
                    166:                                if(*src)
                    167:                                        *dst++=*src;
                    168:                }
                    169: 
                    170:                this->fsize=dst-this->felements;
1.13      moko      171:        }
                    172: 
1.2       moko      173: };
                    174: 
                    175: 
1.1       moko      176: class VArray: public VHashBase {
                    177: public: // value
                    178: 
                    179:        override const char* type() const { return VARRAY_TYPE; }
                    180:        override VStateless_class *get_class() { return array_class; }
                    181: 
1.5       moko      182:        /// VArray: used elements count
                    183:        override int as_int() const { return farray.used(); }
                    184:        override double as_double() const { return farray.used(); }
1.22      moko      185:        override bool is_defined() const { return farray.count()!=0; }
                    186:        override bool as_bool() const { return farray.count()!=0; }
1.5       moko      187:        override Value& as_expr_result() { return *new VInt(farray.used()); }
1.1       moko      188: 
                    189:        /// VArray: virtual hash
                    190:        override HashStringValue *get_hash() { return &hash(); }
                    191:        override HashStringValue* get_fields() { return &hash(); }
                    192:        override HashStringValue* get_fields_reference() { return &hash(); }
                    193: 
                    194:        /// VArray: json-string
                    195:        override const String* get_json_string(Json_options& options);
                    196: 
                    197:        /// VArray: (key)=value
                    198:        override Value* get_element(const String& aname) {
                    199: #if !defined(FEATURE_GET_ELEMENT4CALL) || !defined(OPTIMIZE_BYTECODE_GET_ELEMENT__SPECIAL)
                    200:                // $method, CLASS, CLASS_NAME
                    201:                if(Value* result=VStateless_object::get_element(aname))
                    202:                        return result;
                    203: #endif
1.20      moko      204:                // $element, here as index() allows only numbers
                    205:                if(Value* result=farray.get(index(aname)))
                    206:                        return result;
                    207: 
1.1       moko      208:                return NULL;
                    209:        }
                    210: 
                    211: #ifdef FEATURE_GET_ELEMENT4CALL
                    212:        override Value* get_element4call(const String& aname) {
                    213:                // $method first
                    214:                if(Value* result=VStateless_object::get_element(aname))
                    215:                        return result;
                    216: 
                    217:                // $element
1.12      moko      218:                if(is_index(aname))
                    219:                        if(Value* result=farray.get(index(aname)))
                    220:                                return result;
1.1       moko      221: 
                    222:                return bark("%s method not found", &aname);
                    223:        }
                    224: #endif
                    225: 
                    226:        /// VArray: (key)=value
                    227:        override const VJunction* put_element(const String& aname, Value* avalue) {
1.5       moko      228:                farray.put(index(aname), avalue);
1.14      moko      229:                farray.invalidate();
1.1       moko      230:                return 0;
                    231:        }
                    232: 
                    233: public: // VHashBase
                    234: 
                    235:        override HashStringValue& hash();
                    236:        override void set_default(Value*) { }
                    237:        override Value* get_default() { return 0; }
1.5       moko      238:        override void add(Value* avalue) { farray+=avalue; /* only json uses it, thus no need to invalidate()*/ }
1.1       moko      239: 
                    240: public: // usage
                    241: 
1.14      moko      242:        VArray(size_t initial=0): farray(initial) {}
                    243:        VArray(size_t size, Value** elements): farray(size, elements) {}
1.1       moko      244: 
                    245:        ArrayValue &array() { return farray; }
                    246: 
                    247:        static size_t index(int aindex){
                    248:                if(aindex<0)
1.21      moko      249:                        throw Exception("number.format", 0, "index is out of range (negative)");
1.1       moko      250:                return aindex;
                    251:        }
                    252: 
1.7       moko      253:        static size_t index(const String::Body& aindex){ return pa_atoui(aindex.cstr()); }
                    254:        static size_t index(const String& aindex){ return pa_atoui(aindex.cstr(), 10, &aindex); }
1.1       moko      255: 
1.12      moko      256:        static bool is_index(const String& aindex){
1.20      moko      257:                for(const char *pos=aindex.cstr(); *pos ;pos++){
1.12      moko      258:                        if ((*pos < '0') || (*pos > '9'))
                    259:                                return false;
                    260:                }
                    261:                return true;
                    262:        }
                    263: 
1.5       moko      264:        bool contains(size_t index){
                    265:                return farray.get(index) != NULL;
1.1       moko      266:        }
                    267: 
                    268: private:
                    269: 
                    270:        ArrayValue farray;
                    271: 
                    272: };
                    273: 
                    274: #endif

E-mail: