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: