source: cpp/frams/vm/classes/collectionobj.cpp @ 171

Last change on this file since 171 was 171, checked in by sz, 10 years ago

getObjectTarget is now the recommended way to retrieve object from ExtValue?, can post the standard warning message about missing object

  • Property svn:eol-style set to native
File size: 11.2 KB
RevLine 
[121]1// This file is a part of the Framsticks GDK.
2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
[109]3// Refer to http://www.framsticks.com/ for further information.
4
5#include "collectionobj.h"
6#include <common/nonstd_math.h> //sqrt in borland
7#include <frams/errmgr/stderrors.h>
8#include <common/nonstd_stl.h>
9#include <frams/util/sstringutils.h>
10#ifndef NO_VMACHINE
11#include <frams/vm/vmachine.h>
12#endif
13
14#define FIELDSTRUCT VectorObject
15ParamEntry vector_paramtab[]=
16{
17{"Vector",1,13,"Vector","Vector is 1-dimensional array, indexed by integer value (starting from 0). "
18 "Multidimensional arrays can be simulated by putting other Vector objects into the Vector.\n"
19 "Example:\nvar v=Vector.new();\nv.add(123); v.add(\"string\");",},
20{"clear",0,PARAM_NOSTATIC,"clear data","p()",PROCEDURE(p_clear),},
21{"size",0,PARAM_READONLY+PARAM_NOSTATIC,"element count","d",GETONLY(size),},
22{"remove",0,PARAM_NOSTATIC,"remove at position","p(d position)",PROCEDURE(p_remove),},
23{"get",0,PARAM_NOSTATIC,"get value at position","p x(d position)",PROCEDURE(p_get),},
24{"set",0,PARAM_NOSTATIC,"set value at position","p(d position,x value)",PROCEDURE(p_set),},
25{"add",0,PARAM_NOSTATIC,"append at the end","p(x value)",PROCEDURE(p_add),},
26{"find",0,PARAM_NOSTATIC,"find","p d(x value)",PROCEDURE(p_find),"returns the element index or -1 if not found"},
27{"avg",0,PARAM_READONLY+PARAM_NOSTATIC,"average","f",GETONLY(avg)},
28{"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."},
29{"toString",0,PARAM_READONLY+PARAM_NOSTATIC,"textual form","s",GETONLY(toString),},
30{"new",0,0,"create new Vector","p oVector()",STATICPROCEDURE(p_new),},
31{"sort",0,PARAM_NOSTATIC,"sort elements (in place)","p(o comparator)",PROCEDURE(p_sort),"comparator can be null, giving the \"natural\" sorting order (depending on element type), otherwise it must be a function reference obtained by the \"function FUNCTIONNAME\" operator.\n\nExample:\nfunction compareLastDigit(a,b) {return (a%10)<(b%10);}\nvar v=[16,23,35,42,54,61];\nv.sort(function compareLastDigit);"},
[127]32{"iterator",0,PARAM_NOSTATIC+PARAM_READONLY,"iterator","o",GETONLY(iterator),},
[109]33{0,0,0,},
34};
35#undef FIELDSTRUCT
36
37#define FIELDSTRUCT DictionaryObject
38ParamEntry dictionary_paramtab[]=
39{
40{"Dictionary",1,9,"Dictionary","Dictionary associates stored values with string keys "
41 "(\"key\" is the first argument in get/set/remove functions). Integer \"key\" can be "
42 "used to enumerate all elements (the sequence of elements is not preserved).\n"
43 "Example:\nvar d=Dictionary.new(); d.set(\"name\",\"John\"); d.set(\"age\",44);\n"
44 "var i;\nfor(i=0;i<d.size;i++) Simulator.print(d.getKey(i)+\" is \"+d.get(i));",},
45{"clear",0,PARAM_NOSTATIC,"clear data","p()",PROCEDURE(p_clear),},
[127]46{"size",0,PARAM_NOSTATIC+PARAM_READONLY,"element count","d",GETONLY(size),},
[109]47{"remove",0,PARAM_NOSTATIC,"remove named or indexed element","p(x key)",PROCEDURE(p_remove),},
48{"get",0,PARAM_NOSTATIC,"get named or indexed element","p x(x key)",PROCEDURE(p_get),},
49{"getKey",0,PARAM_NOSTATIC,"get a key of the indexed element","p s(d index)",PROCEDURE(p_getKey),},
50{"set",0,PARAM_NOSTATIC,"set named or indexed element","p(x key,x value)",PROCEDURE(p_set),},
51{"find",0,PARAM_NOSTATIC,"find","p s(x value)",PROCEDURE(p_find),"returns the element key or null if not found"},
52{"new",0,0,"create new Dictionary","p oDictionary()",STATICPROCEDURE(p_new),},
53{"toString",0,PARAM_READONLY+PARAM_NOSTATIC,"textual form","s",GETONLY(toString),},
54{0,0,0,},
55};
56#undef FIELDSTRUCT
57
58Param VectorObject::par(vector_paramtab);
59Param DictionaryObject::par(dictionary_paramtab);
60
61/////////////////////////////////////////
62
63VectorObject::VectorObject(Pt3D &pt)
64        :readonly(0),owndata(1)
65{
66set(0,ExtValue(pt.x));
67set(1,ExtValue(pt.y));
68set(2,ExtValue(pt.z));
69}
70
71void VectorObject::clear()
72{
73if (owndata)
74for(int i=data.size()-1;i>=0;i--)
75        {
76        ExtValue *v=(ExtValue*)data.get(i);
77        if (v) delete v;
78        }
79data.clear();
80}
81
82void VectorObject::p_remove(PARAMPROCARGS)
83{
84if (readonly) return;
85int i=args->getInt();
86if ((i<0)||(i>=data.size())) return;
87ExtValue *v=(ExtValue*)data.get(i);
88if (v) delete v;
89data-=i;
90}
91
92void VectorObject::set(int i,const ExtValue& val)
93{
94int oldsize=data.size();
95if (i<0) return;
96ExtValue *v=(ExtValue*)data.get(i);
97if (v) delete v;
98data.set(i,new ExtValue(val));
99i--;
100while(i>=oldsize)
101        {
102        data.set(i,0);
103        i--;
104        }
105}
106
107void VectorObject::p_get(PARAMPROCARGS)
108{
109int i=args->getInt();
110if (listIndexCheck(&data,i,"VectorObject","get"))
111        {
112        ExtValue *v=get(i);
113        if (v)
114                {
115                *ret=*v;
116                return;
117                }
118        }
119*ret=ExtValue();
120}
121
122void VectorObject::get_avg(ExtValue* ret)
123{
124if (!data.size()) {ret->setEmpty(); return;}
125double s=0.0;
126for(int i=data.size()-1;i>=0;i--)
127        s+=((ExtValue*)data.get(i))->getDouble();
128s/=data.size();
129ret->setDouble(s);
130}
131
132SString VectorObject::serialize() const
133{
134SString out="[";
135        {
136        for(int i=0;i<data.size();i++)
137                {
138                ExtValue* v=(ExtValue*)data.get(i);
139                if (i) out+=",";
140                if (v)
141                        out+=v->serialize();
142                else
143                        out+="null";
144                }
145        }
146out+="]";
147//sprintf(out.directAppend(20),"<Vector@%p>",this);out.endAppend();
148return out;
149}
150
151static THREAD_LOCAL_DEF(SList,tostring_trace);
152
153void VectorObject::get_toString(ExtValue* ret)
154{
155SString out="[";
156//static SListTempl<VectorObject*> trace;
157if (tlsGetRef(tostring_trace).find(this)>=0)
158        out+="...";
159else
160        {
161        tlsGetRef(tostring_trace)+=this;
162        for(int i=0;i<data.size();i++)
163                {
164                ExtValue* v=(ExtValue*)data.get(i);
165                if (i) out+=",";
166                if (v)
167                        out+=v->getString();
168                else
169                        out+="null";
170                }
171        tlsGetRef(tostring_trace)-=this;
172        }
173out+="]";
174ret->setString(out);
175}
176
177void VectorObject::get_stdev(ExtValue* ret)
178{
179if (!data.size()) {ret->setEmpty(); return;}
180get_avg(ret);
181double a=ret->getDouble();
182double s=0.0;
183for(int i=data.size()-1;i>=0;i--)
184        {
185        double d=a-((ExtValue*)data.get(i))->getDouble();
186        s+=d*d;
187        }
188ret->setDouble(sqrt(s/max(1,data.size()-1)));
189}
190
191void VectorObject::p_find(PARAMPROCARGS)
192{
193short i;
194for(i=0;i<data.size();i++)
195        {
196        if ((*args)==(*get(i)))
197                {ret->setInt(i);return;}
198        }
199ret->setInt(-1);
200}
201
202class VEComparator
203{
204public:
205bool operator()(const ExtValue *a,const ExtValue *b) {return a->compare(*b)<0;}
206};
207
208#ifndef NO_VMACHINE
209class VMVEComparator
210{
211public:
212VMachine::JumpTargetObject *jto;
213VMachine *vm;
214VMVEComparator(VMachine::JumpTargetObject *_jto):jto(_jto),vm(jto->vm) {}
215bool operator()(const ExtValue *a,const ExtValue *b);
216};
217
218bool VMVEComparator::operator()(const ExtValue *a,const ExtValue *b)
219{
220if (!VMCode::prepareDynamicJumpTarget(jto->pc,jto->code))
221        return false;
222
223vm->push(*a);
224vm->push(*b);
225vm->pushNewCallState();
226vm->jumpDynamicJumpTarget(jto->pc);
227vm->run();
228vm->popCallState();
229bool ret;
230ExtValue& retval=vm->getValue();
231if (retval.type==TInvalid)
232        {
233        ret=false;
234        FMprintf("VectorElementComparator","",FMLV_ERROR,"Comparison function returned no value");
235        }
236else
237        ret=(retval.getInt()!=0);
238vm->drop(2);
239return ret;
240}
241#endif
242
243void VectorObject::p_sort(PARAMPROCARGS)
244{
245#ifndef NO_VMACHINE
246VMachine::JumpTargetObject *jto=VMachine::JumpTargetObject::fromObject(args->getObject());
247if (jto)
248        {
249        VMVEComparator cmp(jto);
[153]250        ExtValue **first=(ExtValue**)&data.getref(0);
[109]251        std::sort(first,first+data.size(),cmp);
252        }
253else
254#endif
255        {
256        VEComparator cmp;
[153]257        ExtValue **first=(ExtValue**)&data.getref(0);
[109]258        std::sort(first,first+data.size(),cmp);
259        }
260ret->setEmpty();
261}
262
263void VectorObject::get_iterator(ExtValue* ret)
264{
265ret->setObject(VectorIterator::makeFrom(this));
266}
267
[171]268VectorObject* VectorObject::fromObject(const ExtObject& o, bool warn)
[109]269{
[171]270return (VectorObject*)o.getTarget(par.getName(),true,warn);
[109]271}
272
273/////////////////////////////
274
275void DictionaryObject::clear()
276{
277for(HashEntryIterator it(hash);it.isValid();)
278        {
279        ExtValue *v=(ExtValue*)hash.remove(it);
280        if (v) delete v;
281        }
282hash.clear();
283hash.init();
284}
285
286void DictionaryObject::p_find(PARAMPROCARGS)
287{
288for(HashEntryIterator it(hash);it.isValid();it++)
289        {
290        if ((*args)==(*((ExtValue*)it->value)))
291                {
292                ret->setString(it->key);
293                return;
294                }
295        }
296ret->setEmpty();
297}
298
299HashEntryIterator* DictionaryObject::getIndexIterator(int i)
300{
301if (i<0) return 0;
302if (i>=hash.getSize()) return 0;
303
304if ((!it.isValid())||(it_index>i))
305        {
306        it=HashEntryIterator(hash);
307        it_index=0;
308        }
309while(it.isValid())
310        {
311        if (it_index==i)
312                return &it;
313        it_index++;
314        it++;
315        }
316return 0;
317}
318
319void DictionaryObject::p_remove(PARAMPROCARGS)
320{
321if ((args->type==TInt)||(args->type==TDouble))
322        {
323        HashEntryIterator* iter=getIndexIterator(args->getInt());
324        if (iter)
325                {
326                ExtValue *oldval=(ExtValue*)hash.remove(*iter);
327                if (oldval) {*ret=*oldval; delete oldval;} else *ret=ExtValue();
328                }
329        }
330else
331        {
332        ExtValue *oldval=(ExtValue*)hash.remove(args[0].getString());
333        if (oldval) {*ret=*oldval; delete oldval;} else *ret=ExtValue();
334        }
335}
336
337void DictionaryObject::p_get(PARAMPROCARGS)
338{
339if ((args->type==TInt)||(args->type==TDouble))
340        {
341        HashEntryIterator* iter=getIndexIterator(args->getInt());
342        if (iter && (*iter)->value)
343                {
344                *ret=*((ExtValue*)(*iter)->value);
345                return;
346                }
347        }
348else
349        {
350        ExtValue *val=(ExtValue*)hash.get(args[0].getString());
351        if (val)
352                {
353                *ret=*val;
354                return;
355                }
356        }
357*ret=ExtValue();
358}
359
360void DictionaryObject::p_getKey(PARAMPROCARGS)
361{
362HashEntryIterator* iter=getIndexIterator(args->getInt());
363if (iter)
364        {
365        *ret=(*iter)->key;
366        return;
367        }
368*ret=ExtValue();
369}
370
371void DictionaryObject::p_set(PARAMPROCARGS)
372{
373ExtValue *newval=(args[0].getType()==TUnknown)?0:new ExtValue(args[0]);
374ExtValue *oldval=(ExtValue*)hash.put(args[1].getString(),newval);
375if (oldval) {*ret=*oldval; delete oldval;} else *ret=ExtValue();
376}
377
378SString DictionaryObject::serialize() const
379{
380SString out="{";
381        {
382        for(HashEntryIterator it(hash);it.isValid();)
383                {
384                out+="\"";
385                SString q=it->key; sstringQuote(q);
386                out+=q;
387                out+="\":";
[164]388                if (it->value!=NULL)
389                        out+=((ExtValue*)it->value)->serialize();
390                else
391                        out+="null";
[109]392                it++;
393                if (it.isValid()) out+=",";
394                }
395        }
396out+="}";
397return out;
398}
399
400void DictionaryObject::get_toString(ExtValue* ret)
401{
402SString out="{";
403//static SListTempl<DictionaryObject*> trace;
404if (tlsGetRef(tostring_trace).find(this)>=0)
405        out+="...";
406else
407        {
408        tlsGetRef(tostring_trace)+=this;
409        for(HashEntryIterator it(hash);it.isValid();)
410                {
411                out+=it->key;
412                out+=":";
[164]413                if (it->value!=NULL)
414                        out+=((ExtValue*)it->value)->getString();
415                else
416                        out+="null";
[109]417                it++;
418                if (it.isValid()) out+=",";
419                }
420        tlsGetRef(tostring_trace)-=this;
421        }
422out+="}";
423ret->setString(out);
424}
425
[171]426DictionaryObject* DictionaryObject::fromObject(const ExtObject& o, bool warn)
[109]427{
[171]428return (DictionaryObject*)o.getTarget(par.getName(), true, warn);
[109]429}
430
431////////////////
432
433VectorIterator::VectorIterator(VectorObject* v)
434{
435vec=v;
436vec->incref();
437pos=-1;
438}
439
440#define FIELDSTRUCT VectorIterator
441ParamEntry vectoriterator_paramtab[]=
442{
443 {"VectorIterator",1,2,"VectorIterator","VectorIterator"},
444{"next",0,PARAM_READONLY+PARAM_NOSTATIC,"next","d 0 1",GETONLY(next),},
445{"value",0,PARAM_READONLY+PARAM_NOSTATIC,"value","x",GETONLY(value),},
446{0,0,0,},
447};
448#undef FIELDSTRUCT
449
450ExtObject VectorIterator::makeFrom(VectorObject *v)
451{
452static Param par(vectoriterator_paramtab);
453return ExtObject(&par,new VectorIterator(v));
454}
455
456VectorIterator::~VectorIterator()
457{
458vec->decref();
459}
460
461void VectorIterator::get_next(ExtValue* ret)
462{
463pos++;
464ret->setInt((pos < vec->data.size()) ? 1 : 0);
465}
466
467void VectorIterator::get_value(ExtValue* ret)
468{
469ExtValue *v=(ExtValue*) (((pos>=0)&&(pos<vec->data.size())) ? vec->data(pos) : NULL );
470if (v)
471        *ret=*v;
472else
473        ret->setEmpty();
474}
Note: See TracBrowser for help on using the repository browser.