source: cpp/gdk/collectionobj.cpp @ 104

Last change on this file since 104 was 104, checked in by sz, 11 years ago

introducing object de/serialization - see serialtest.cpp
the core GDK classes can be now used in multiple threads (ifdef MULTITHREADED)

  • Property svn:eol-style set to native
File size: 8.4 KB
Line 
1// This file is a part of the Framsticks GDK library.
2// Copyright (C) 2002-2011  Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include "collectionobj.h"
6#include "nonstd_math.h" //sqrt in borland
7#include "stderrors.h"
8#include "nonstd_stl.h"
9#include "sstringutils.h"
10
11#define FIELDSTRUCT VectorObject
12ParamEntry vector_paramtab[]=
13{
14{"Vector",1,11,"Vector","Vector is 1-dimensional array, indexed by integer value (starting from 0). "
15 "Multidimensional arrays can be simulated by putting other Vector objects into the Vector.\n"
16 "Example:\nvar v=Vector.new();\nv.add(123); v.add(\"string\");",},
17{"clear",0,PARAM_NOSTATIC,"clear data","p()",PROCEDURE(p_clear),},
18{"size",0,PARAM_READONLY+PARAM_NOSTATIC,"element count","d",GETONLY(size),},
19{"remove",0,PARAM_NOSTATIC,"remove at position","p(d position)",PROCEDURE(p_remove),},
20{"get",0,PARAM_NOSTATIC,"get value at position","p x(d position)",PROCEDURE(p_get),},
21{"set",0,PARAM_NOSTATIC,"set value at position","p(d position,x value)",PROCEDURE(p_set),},
22{"add",0,PARAM_NOSTATIC,"append at the end","p(x value)",PROCEDURE(p_add),},
23{"find",0,PARAM_NOSTATIC,"find","p d(x value)",PROCEDURE(p_find),"returns the element index or -1 if not found"},
24{"avg",0,PARAM_READONLY+PARAM_NOSTATIC,"average","f",GETONLY(avg)},
25{"stdev",0,PARAM_READONLY+PARAM_NOSTATIC,"standard deviation","f",GETONLY(stdev),"=sqrt(sum((element[i]-avg)^2)/(size-1)) which is estimated population std.dev. from sample std.dev."},
26{"toString",0,PARAM_READONLY+PARAM_NOSTATIC,"textual form","s",GETONLY(toString),},
27{"new",0,0,"create new Vector","p oVector()",STATICPROCEDURE(p_new),},
28{0,0,0,},
29};
30#undef FIELDSTRUCT
31
32#define FIELDSTRUCT DictionaryObject
33ParamEntry dictionary_paramtab[]=
34{
35{"Dictionary",1,9,"Dictionary","Dictionary associates stored values with string keys "
36 "(\"key\" is the first argument in get/set/remove functions). Integer \"key\" can be "
37 "used to enumerate all elements (the sequence of elements is not preserved).\n"
38 "Example:\nvar d=Dictionary.new(); d.set(\"name\",\"John\"); d.set(\"age\",44);\n"
39 "var i;\nfor(i=0;i<d.size;i++) Simulator.print(d.getKey(i)+\" is \"+d.get(i));",},
40{"clear",0,PARAM_NOSTATIC,"clear data","p()",PROCEDURE(p_clear),},
41{"size",0,PARAM_NOSTATIC,"element count","d",GETONLY(size),},
42{"remove",0,PARAM_NOSTATIC,"remove named or indexed element","p(x key)",PROCEDURE(p_remove),},
43{"get",0,PARAM_NOSTATIC,"get named or indexed element","p x(x key)",PROCEDURE(p_get),},
44{"getKey",0,PARAM_NOSTATIC,"get a key of the indexed element","p s(d index)",PROCEDURE(p_getKey),},
45{"set",0,PARAM_NOSTATIC,"set named or indexed element","p(x key,x value)",PROCEDURE(p_set),},
46{"find",0,PARAM_NOSTATIC,"find","p s(x value)",PROCEDURE(p_find),"returns the element key or null if not found"},
47{"new",0,0,"create new Dictionary","p oDictionary()",STATICPROCEDURE(p_new),},
48{"toString",0,PARAM_READONLY+PARAM_NOSTATIC,"textual form","s",GETONLY(toString),},
49{0,0,0,},
50};
51#undef FIELDSTRUCT
52
53Param VectorObject::par(vector_paramtab);
54Param DictionaryObject::par(dictionary_paramtab);
55
56/////////////////////////////////////////
57
58VectorObject::VectorObject(Pt3D &pt)
59        :readonly(0),owndata(1)
60{
61set(0,ExtValue(pt.x));
62set(1,ExtValue(pt.y));
63set(2,ExtValue(pt.z));
64}
65
66void VectorObject::clear()
67{
68if (owndata)
69for(int i=data.size()-1;i>=0;i--)
70        {
71        ExtValue *v=(ExtValue*)data.get(i);
72        if (v) delete v;
73        }
74//nie tak spektakularny jak rasowe bugi roku ale tez idiotyczny :>
75//wszystko przez to ze poczatkowo bylo tylko uzywane w destruktorze...
76data.clear();
77}
78
79void VectorObject::p_remove(PARAMPROCARGS)
80{
81if (readonly) return;
82int i=args->getInt();
83if ((i<0)||(i>=data.size())) return;
84ExtValue *v=(ExtValue*)data.get(i);
85if (v) delete v;
86data-=i;
87}
88
89void VectorObject::set(int i,const ExtValue& val)
90{
91int oldsize=data.size();
92if (i<0) return;
93ExtValue *v=(ExtValue*)data.get(i);
94if (v) delete v;
95data.set(i,new ExtValue(val));
96i--;
97while(i>=oldsize)
98        {
99        data.set(i,0);
100        i--;
101        }
102}
103
104void VectorObject::p_get(PARAMPROCARGS)
105{
106int i=args->getInt();
107if (listIndexCheck(&data,i,"VectorObject","get"))
108        {
109        ExtValue *v=get(i);
110        if (v)
111                {
112                *ret=*v;
113                return;
114                }
115        }
116*ret=ExtValue();
117}
118
119void VectorObject::get_avg(ExtValue* ret)
120{
121if (!data.size()) {ret->setEmpty(); return;}
122double s=0.0;
123for(int i=data.size()-1;i>=0;i--)
124        s+=((ExtValue*)data.get(i))->getDouble();
125s/=data.size();
126ret->setDouble(s);
127}
128
129SString VectorObject::serialize() const
130{
131SString out="[";
132        {
133        for(int i=0;i<data.size();i++)
134                {
135                ExtValue* v=(ExtValue*)data.get(i);
136                if (i) out+=",";
137                if (v)
138                        out+=v->serialize();
139                else
140                        out+="null";
141                }
142        }
143out+="]";
144//sprintf(out.directAppend(20),"<Vector@%p>",this);out.endAppend();
145return out;
146}
147
148static ThreadSingleton<SList> tostring_trace;
149
150void VectorObject::get_toString(ExtValue* ret)
151{
152SString out="[";
153//static SListTempl<VectorObject*> trace;
154if (tostring_trace.getref().find(this)>=0)
155        out+="...";
156else
157        {
158        tostring_trace.getref()+=this;
159        for(int i=0;i<data.size();i++)
160                {
161                ExtValue* v=(ExtValue*)data.get(i);
162                if (i) out+=",";
163                if (v)
164                        out+=v->getString();
165                else
166                        out+="null";
167                }
168        tostring_trace.getref()-=this;
169        }
170out+="]";
171ret->setString(out);
172}
173
174void VectorObject::get_stdev(ExtValue* ret)
175{
176if (!data.size()) {ret->setEmpty(); return;}
177get_avg(ret);
178double a=ret->getDouble();
179double s=0.0;
180for(int i=data.size()-1;i>=0;i--)
181        {
182        double d=a-((ExtValue*)data.get(i))->getDouble();
183        s+=d*d;
184        }
185ret->setDouble(sqrt(s/max(1,data.size()-1)));
186}
187
188void VectorObject::p_find(PARAMPROCARGS)
189{
190short i;
191for(i=0;i<data.size();i++)
192        {
193        if ((*args)==(*get(i)))
194                {ret->setInt(i);return;}
195        }
196ret->setInt(-1);
197}
198
199VectorObject* VectorObject::fromObject(const ExtObject& o)
200{
201return (VectorObject*)o.getTarget(par.getName());
202}
203
204/////////////////////////////
205
206void DictionaryObject::clear()
207{
208for(HashEntryIterator it(hash);it.isValid();)
209        {
210        ExtValue *v=(ExtValue*)hash.remove(it);
211        if (v) delete v;
212        }
213hash.clear();
214hash.init();
215}
216
217void DictionaryObject::p_find(PARAMPROCARGS)
218{
219for(HashEntryIterator it(hash);it.isValid();it++)
220        {
221        if ((*args)==(*((ExtValue*)it->value)))
222                {
223                ret->setString(it->key);
224                return;
225                }
226        }
227ret->setEmpty();
228}
229
230HashEntryIterator* DictionaryObject::getIndexIterator(int i)
231{
232if (i<0) return 0;
233if (i>=hash.getSize()) return 0;
234
235if ((!it.isValid())||(it_index>i))
236        {
237        it=HashEntryIterator(hash);
238        it_index=0;
239        }
240while(it.isValid())
241        {
242        if (it_index==i)
243                return &it;
244        it_index++;
245        it++;
246        }
247return 0;
248}
249
250void DictionaryObject::p_remove(PARAMPROCARGS)
251{
252if ((args->type==TInt)||(args->type==TDouble))
253        {
254        HashEntryIterator* iter=getIndexIterator(args->getInt());
255        if (iter)
256                {
257                ExtValue *oldval=(ExtValue*)hash.remove(*iter);
258                if (oldval) {*ret=*oldval; delete oldval;} else *ret=ExtValue();
259                }
260        }
261else
262        {
263        ExtValue *oldval=(ExtValue*)hash.remove(args[0].getString());
264        if (oldval) {*ret=*oldval; delete oldval;} else *ret=ExtValue();
265        }
266}
267
268void DictionaryObject::p_get(PARAMPROCARGS)
269{
270if ((args->type==TInt)||(args->type==TDouble))
271        {
272        HashEntryIterator* iter=getIndexIterator(args->getInt());
273        if (iter && (*iter)->value)
274                {
275                *ret=*((ExtValue*)(*iter)->value);
276                return;
277                }
278        }
279else
280        {
281        ExtValue *val=(ExtValue*)hash.get(args[0].getString());
282        if (val)
283                {
284                *ret=*val;
285                return;
286                }
287        }
288*ret=ExtValue();
289}
290
291void DictionaryObject::p_getKey(PARAMPROCARGS)
292{
293HashEntryIterator* iter=getIndexIterator(args->getInt());
294if (iter)
295        {
296        *ret=(*iter)->key;
297        return;
298        }
299*ret=ExtValue();
300}
301
302void DictionaryObject::p_set(PARAMPROCARGS)
303{
304ExtValue *newval=(args[0].getType()==TUnknown)?0:new ExtValue(args[0]);
305ExtValue *oldval=(ExtValue*)hash.put(args[1].getString(),newval);
306if (oldval) {*ret=*oldval; delete oldval;} else *ret=ExtValue();
307}
308
309SString DictionaryObject::serialize() const
310{
311SString out="{";
312        {
313        for(HashEntryIterator it(hash);it.isValid();)
314                {
315                out+="\"";
316                SString q=it->key; sstringQuote(q);
317                out+=q;
318                out+="\":";
319                out+=((ExtValue*)it->value)->serialize();
320                it++;
321                if (it.isValid()) out+=",";
322                }
323        }
324out+="}";
325return out;
326}
327
328void DictionaryObject::get_toString(ExtValue* ret)
329{
330SString out="{";
331//static SListTempl<DictionaryObject*> trace;
332if (tostring_trace.getref().find(this)>=0)
333        out+="...";
334else
335        {
336        tostring_trace.getref()+=this;
337        for(HashEntryIterator it(hash);it.isValid();)
338                {
339                out+=it->key;
340                out+=":";
341                out+=((ExtValue*)it->value)->getString();
342                it++;
343                if (it.isValid()) out+=",";
344                }
345        tostring_trace.getref()-=this;
346        }
347out+="}";
348ret->setString(out);
349}
350
351DictionaryObject* DictionaryObject::fromObject(const ExtObject& o)
352{
353return (DictionaryObject*)o.getTarget(par.getName());
354}
Note: See TracBrowser for help on using the repository browser.