source: cpp/gdk/param.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: 19.9 KB
Line 
1// This file is a part of the Framsticks GDK library.
2// Copyright (C) 2002-2013  Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include <stdio.h>
6#include <ctype.h>
7
8#include "param.h"
9#include "extvalue.h"
10#include "framsg.h"
11#include "sstringutils.h"
12
13//#define SAVE_ALL_NAMES
14#define SAVE_SELECTED_NAMES
15#define WARN_MISSING_NAME
16
17char MakeCodeGuardHappy;
18
19ParamEntry empty_paramtab[]=
20{ {"Empty",1,0,"Empty",}, {0,0,0,}, };
21
22static void czytdotyldy(VirtFILE *f,SString &s)
23{
24SString temp;
25int z;
26char last_char=0;
27while((z=fgetc(f))!=EOF)
28        {
29        if (z=='~')
30                if (last_char!='\\') break;
31        last_char=(char)z;
32        temp+=last_char;
33        }
34s=temp;
35}
36
37static const char *strchrlimit(const char *t,int ch,const char *limit)
38{
39int n=limit-t;
40for (;(n>0)&&*t;t++,n--)
41        if (*t==ch) return t;
42return 0;
43}
44
45static char* fgets0(char*t,int d,VirtFILE *f, bool& eolfound)
46{
47char *r=fgets(t,d,f);
48eolfound=false;
49if (r)
50        {
51        int d=strlen(r);
52        while (d-- > 0) if ((r[d]=='\r')||(r[d]=='\n')) {r[d]=0; eolfound=true;} else break;
53        }
54return r;
55}
56
57void ParamInterface::copyFrom(ParamInterface *src)
58{
59int n=getPropCount();
60ExtValue v;
61int j;
62for(int i=0;i<n;i++)
63  if ((!(flags(i)&PARAM_READONLY))
64          && (*type(i)!='p'))
65        {
66        j=src->findId(id(i));
67        if (j<0) continue;
68        src->get(j,v);
69        set(i,v);
70        }
71}
72
73void ParamInterface::quickCopyFrom(ParamInterface *src)
74{
75int n=getPropCount();
76ExtValue v;
77for(int i=0;i<n;i++)
78  if ((!(flags(i)&PARAM_READONLY))
79          && (*type(i)!='p'))
80          {
81          src->get(i,v);
82          set(i,v);
83          }
84}
85
86int ParamInterface::getMinMax(int prop,long& minumum,long& maximum,long &def)
87{
88const char* t=type(prop)+1;
89while(*t) if (*t==' ') break; else t++;
90return sscanf(t,"%ld %ld %ld",&minumum,&maximum,&def);
91}
92
93int ParamInterface::getMinMax(int prop,double& minumum,double& maximum,double& def)
94{
95const char* t=type(prop)+1;
96while(*t) if (*t==' ') break; else t++;
97return sscanf(t,"%lg %lg %lg",&minumum,&maximum,&def);
98}
99
100void ParamInterface::setDefault(bool numericonly)
101{
102int n=getPropCount();
103for(int i=0;i<n;i++)
104        setDefault(i,numericonly);
105}
106
107void ParamInterface::setMin()
108{
109int n=getPropCount();
110for(int i=0;i<n;i++)
111        setMin(i);
112}
113
114void ParamInterface::setMax()
115{
116int n=getPropCount();
117for(int i=0;i<n;i++)
118        setMax(i);
119}
120
121void ParamInterface::setDefault(int i,bool numericonly)
122{
123const char *t=type(i);
124switch(*t)
125        {
126        case 'f':
127        {
128        double a=0,b=0,c=0;
129        getMinMax(i,a,b,c);
130        setDouble(i,c);
131        }
132        break;
133        case 'd':
134        {
135        long a=0,b=0,c=0;
136        getMinMax(i,a,b,c);
137        setInt(i,c);
138        }
139        break;
140        default: if (!numericonly) set(i,"");
141        }
142}
143
144void ParamInterface::setMin(int i)
145{
146const char *t=type(i);
147switch(*t)
148        {
149        case 'f':
150        {
151        double a=0,b=0,c=0;
152        getMinMax(i,a,b,c);
153        setDouble(i,a);
154        }
155        break;
156        case 'd':
157        {
158        long a=0,b=0,c=0;
159        getMinMax(i,a,b,c);
160        setInt(i,a);
161        }
162        break;
163        default: set(i,"");
164        }
165}
166
167void ParamInterface::setMax(int i)
168{
169const char *t=type(i);
170switch(*t)
171        {
172        case 'f':
173        {
174        double a=0,b=0,c=0;
175        getMinMax(i,a,b,c);
176        setDouble(i,b);
177        }
178        break;
179        case 'd':
180        {
181        long a=0,b=0,c=0;
182        getMinMax(i,a,b,c);
183        setInt(i,b);
184        }
185        break;
186        default: set(i,"");
187        }
188}
189
190SString ParamInterface::getStringById(const char*prop)
191{int i=findId(prop); if (i>=0) return getString(i); else return SString();}
192long ParamInterface::getIntById(const char*prop)
193{int i=findId(prop); if (i>=0) return getInt(i); else return 0;}
194double ParamInterface::getDoubleById(const char*prop)
195{int i=findId(prop); if (i>=0) return getDouble(i); else return 0;}
196ExtObject ParamInterface::getObjectById(const char*prop)
197{int i=findId(prop); if (i>=0) return getObject(i); else return ExtObject();}
198ExtValue ParamInterface::getExtValueById(const char*prop)
199{int i=findId(prop); if (i>=0) return getExtValue(i); else return ExtValue();}
200
201int ParamInterface::setIntById(const char* prop,long v)
202{int i=findId(prop); if (i>=0) return setInt(i,v); else return PSET_NOPROPERTY;}
203int ParamInterface::setDoubleById(const char* prop,double v)
204{int i=findId(prop); if (i>=0) return setDouble(i,v); else return PSET_NOPROPERTY;}
205int ParamInterface::setStringById(const char* prop,const SString &v)
206{int i=findId(prop); if (i>=0) return setString(i,v); else return PSET_NOPROPERTY;}
207int ParamInterface::setObjectById(const char* prop,const ExtObject &v)
208{int i=findId(prop); if (i>=0) return setObject(i,v); else return PSET_NOPROPERTY;}
209int ParamInterface::setExtValueById(const char* prop,const ExtValue &v)
210{int i=findId(prop); if (i>=0) return setExtValue(i,v); else return PSET_NOPROPERTY;}
211int ParamInterface::setById(const char* prop,const ExtValue &v)
212{int i=findId(prop); if (i>=0) return set(i,v); else return PSET_NOPROPERTY;}
213
214int ParamInterface::save(VirtFILE* f,const SString* altname,bool force)
215{
216const char *p;
217SString ws;
218int err=0,i;
219bool withname=false;
220if ((!altname)||(altname->len()))
221        {
222        err|=(fputs(altname?((const char*)(*altname)):getName(),f)==EOF);
223        err|=(fputs(":\n",f)==EOF);
224        withname=true;
225        }
226for (i=0;p=id(i);i++)
227        err|=saveprop(f,i,p,force);
228if (withname)
229        err|=(fputs("\n",f)==EOF);
230return err;
231}
232
233const char* ParamInterface::SERIALIZATION_PREFIX="@Serialized:";
234
235int ParamInterface::saveprop(VirtFILE* f,int i,const char* p,bool force)
236{
237if ((flags(i)&PARAM_DONTSAVE)&&(!force)) return 0;
238const char *typ=type(i);
239if ((*typ=='p')||(*typ=='o')) return 0;
240
241const char *t,*w;
242SString ws;
243int err=0,cr;
244
245err|=(fputs(p,f)==EOF); fputc(':',f);
246cr=0;
247if (*typ=='x')
248        {
249        ExtValue ex;
250        get(i,ex);
251        ws=SString(SERIALIZATION_PREFIX)+ex.serialize();
252        }
253else
254        ws=get(i);
255quoteTilde(ws);
256w=ws;
257if (ws.len()>50) cr=1;
258else for (t=w;*t;t++) if ((*t==10)||(*t==13)) {cr=1; break;}
259if (cr) fputs("~\n",f);
260err|=(fputs(w,f)==EOF);
261err|=(fputs(cr ? "~\n" : "\n",f)==EOF);
262return err;
263}
264
265
266int SimpleAbstractParam::isequal(int i,void* defdata)
267{ // defdata->member == object->member ?
268void *backup=object;
269switch(type(i)[0])
270        {
271        case 'd':
272                {
273                select(defdata);
274                long x=getInt(i);
275                select(backup);
276                return x==getInt(i);
277                }
278        case 'f':
279                {
280                select(defdata);
281                double x=getDouble(i);
282                select(backup);
283                return x==getDouble(i);
284                }
285        case 's':
286                {
287                select(defdata);
288                SString x=getString(i);
289                select(backup);
290                return x==getString(i);
291                }
292        }
293return 1;
294}
295
296void SimpleAbstractParam::save2(SString& f,void *defdata,bool addcr,bool all_names)
297{ // defdata!=NULL -> nie zapisuje wartosci domyslnych
298const char *p;
299int i;
300int needlabel=0;
301int first=1;
302SString val;
303SString t;
304int fl;
305// t+=SString(getName()); t+=':';
306for (i=0;p=id(i);i++)
307        if (!((fl=flags(i))&PARAM_DONTSAVE))
308        {
309        if (defdata && isequal(i,defdata))
310                needlabel=1;
311        else
312                {
313                if (!first) t+=", ";
314#ifndef SAVE_ALL_NAMES
315#ifdef SAVE_SELECTED_NAMES
316                if (needlabel || all_names || !(fl & PARAM_CANOMITNAME))
317#else
318                if (needlabel)
319#endif
320#endif
321                        { t+=p; t+="="; needlabel=0; }
322                if (type(i)[0]=='s')
323                        { // string - special case
324                        SString str=getString(i);
325                        if (strContainsOneOf(str,", \\\n\r\t\""))
326                                {
327                                t+="\"";
328                                sstringQuote(str);
329                                t+=str;
330                                t+="\"";
331                                }
332                        else
333                                t+=str;
334                        }
335                else
336                        t+=get(i);
337                first=0;
338                }
339        }
340if (addcr)
341        t+="\n";
342f+=t;
343}
344
345void ParamInterface::load(VirtFILE* f)
346{
347char t[100];
348int i;
349const char *p,*p0;
350int p_len;
351bool eol,loaded;
352while(fgets0(t,100,f,eol))
353        {
354        p0=t; while ((*p0==' ')||(*p0=='\t')) p0++;
355        if (!*p0) break;
356        p=strchr(p0,':'); if (!p) continue;
357        p_len=p-p0;
358        loaded=false;
359        if (p_len&&((i=findIdn(p0,p_len))>=0)&&(!(flags(i)&PARAM_DONTLOAD)))
360                {
361                if (p0[p_len+1]=='~')
362                        {
363                        SString s;
364                        czytdotyldy(f,s);
365                        int ch; while((ch=fgetc(f))!=EOF) if (ch=='\n') break;
366                        unquoteTilde(s);
367                        set(i,(const char*)s);
368                        }
369                else
370                        {
371                        if (eol)
372                                set(i,p0+p_len+1);
373                        else
374                                {
375                                SString tmp=p0+p_len+1;
376                                while(!eol)
377                                        {
378                                        if (!fgets0(t,100,f,eol)) break;
379                                        tmp+=t;
380                                        }
381                                set(i,(const char*)tmp);
382                                }
383                        }
384                loaded=true;
385                }
386        if ((!loaded) && (p0[p_len+1]=='~'))
387                { // eat unrecognized multiline field
388                SString s;
389                czytdotyldy(f,s);
390                int ch; while((ch=fgetc(f))!=EOF) if (ch=='\n') break;
391                }
392        }
393}
394
395
396/*
397SString SimpleAbstractParam::getString(int i)
398{
399char *t;
400switch (*(t=type(i)))
401        {
402        case 'd':
403        {
404        for (i=atol(get(i));i>=0;i--) if (t) t=strchr(t+1,'~');
405        if (t)
406                {
407                t++;
408                char *t2=strchr(t,'~');
409                if (!t2) t2=t+strlen(t);
410                SString str;
411                strncpy(str.directWrite(t2-t),t,t2-t);
412                str.endWrite(t2-t);
413                return str;
414                }
415        }
416        }
417return get(i);
418}
419*/
420
421int ParamInterface::findId(const char* n)
422{
423int i; const char *p;
424        for (i=0;p=id(i);i++) if (!strcmp(n,p)) return i;
425return -1;
426}
427
428int ParamInterface::findIdn(const char* naz,int n)
429{
430int i; const char *p;
431        for (i=0;p=id(i);i++) if ((!strncmp(naz,p,n))&&(!p[n])) return i;
432return -1;
433}
434
435void ParamInterface::get(int i,ExtValue &ret)
436{
437switch(type(i)[0])
438        {
439        case 'd':       ret.setInt(getInt(i)); break;
440        case 'f':       ret.setDouble(getDouble(i)); break;
441        case 's':       ret.setString(getString(i)); break;
442        case 'o':       ret.setObject(getObject(i)); break;
443        case 'x':       ret=getExtValue(i); break;
444        default: FMprintf("ParamInterface","get",FMLV_ERROR,"'%s.%s' is not a field",getName(),id(i));
445        }
446}
447
448static bool stringIsNumeric(const char* str)
449{//   /-?.?[0-9]+/
450if (!str) return false;
451if (*str=='-') str++;
452if (*str=='.') str++;
453return isdigit(*str);
454}
455
456int ParamInterface::setInt(int i,const char* str)
457{
458if (!stringIsNumeric(str))
459        {
460        long a,b,c;
461        if (getMinMax(i,a,b,c)>=3)
462                return setInt(i,c);
463        else
464                return setInt(i,(long)0);
465        }
466else
467        return setInt(i,atol(str));
468}
469
470int ParamInterface::setDouble(int i,const char* str)
471{
472if (!stringIsNumeric(str))
473        {
474        double a,b,c;
475        if (getMinMax(i,a,b,c)>=3)
476                return setDouble(i,c);
477        else
478                return setDouble(i,(double)0);
479        }
480else
481        return setDouble(i,atof(str));
482}
483
484int ParamInterface::set(int i,const ExtValue &v)
485{
486switch(type(i)[0])
487        {
488        case 'd': if ((v.type==TInt)||(v.type==TDouble)) return setInt(i,v.getInt()); else return setInt(i,(const char*)v.getString());
489        case 'f': if ((v.type==TInt)||(v.type==TDouble)) return setDouble(i,v.getDouble()); else return setDouble(i,(const char*)v.getString());
490        case 's': { SString t=v.getString(); return setString(i,t); }
491        case 'o': return setObject(i,v.getObject());
492        case 'x': return setExtValue(i,v);
493        default: FMprintf("ParamInterface","get",FMLV_ERROR,"'%s.%s' is not a field",getName(),id(i));
494        }
495return 0;
496}
497
498int ParamInterface::set(int i,const char *v)
499{
500switch(type(i)[0])
501        {
502        case 'd': return setInt(i,v);
503        case 'f': return setDouble(i,v);
504        case 's': { SString t(v); return setString(i,t); }
505        case 'x':
506        {
507        ExtValue e;
508        const char* after;
509        if (!strncmp(v,SERIALIZATION_PREFIX,strlen(SERIALIZATION_PREFIX)))
510                {
511                after=e.deserialize(v+strlen(SERIALIZATION_PREFIX));
512                if ((after==NULL)||(*after))
513                        FMprintf("ParamInterface","set",FMLV_WARN,"serialization format mismatch in %s.%s",(getName()?getName():"<Unknown>"),id(i));
514                }
515        else if ((after=e.parseNumber(v))&&(*after==0)) //consumed the whole string
516                {
517                //OK!
518                }
519        else
520                {
521                e.setString(SString(v));
522                }
523        return setExtValue(i,e);
524        }
525        }
526return 0;
527}
528
529SString ParamInterface::getText(int i)
530{
531const char *t;
532if ((*(t=type(i)))=='d')
533        {
534        for (int j=getInt(i);j>=0;j--) if (t) t=strchr(t+1,'~');
535        if (t)
536                {
537                t++;
538                const char *t2=strchr(t,'~');
539                if (!t2) t2=t+strlen(t);
540                return SString(t,t2-t);
541                }
542        }
543return get(i);
544}
545
546SString ParamInterface::get(int i)
547{
548switch(type(i)[0])
549        {
550        case 'd':
551                {
552                SString tmp;
553                sprintf(tmp.directWrite(20),"%ld",getInt(i)); tmp.endWrite();
554                return tmp;
555                }
556        case 'f':
557                {
558                SString tmp;
559                sprintf(tmp.directWrite(20),"%lg",getDouble(i)); tmp.endWrite();
560                return tmp;
561                }
562        case 's':
563                return getString(i);
564        }
565ExtValue v;
566get(i,v);
567return v.getString();
568}
569
570
571//////////////////////////////// PARAM ////////////////////////////////////
572
573void *SimpleAbstractParam::getTarget(int i)
574{
575return (void*)(((char*)object)+entry(i)->offset);
576//return &(object->*(entry(i)->fldptr));
577}
578
579///////// get
580
581long SimpleAbstractParam::getInt(int i)
582{
583ExtValue v;
584ParamEntry *pe=entry(i);
585if (pe->fun1)
586        {
587        (*(void(*)(void*,ExtValue*))pe->fun1)(object,&v);
588        return v.getInt();
589        }
590else
591        {
592        void *target=getTarget(i);
593        return *((long*)target);
594        }
595}
596
597double SimpleAbstractParam::getDouble(int i)
598{
599ExtValue v;
600ParamEntry *pe=entry(i);
601if (pe->fun1)
602        {
603        (*(void(*)(void*,ExtValue*))pe->fun1)(object,&v);
604        return v.getDouble();
605        }
606else
607        {
608        void *target=getTarget(i);
609        return *((double*)target);
610        }
611}
612
613SString SimpleAbstractParam::getString(int i)
614{
615ExtValue v;
616ParamEntry *pe=entry(i);
617if (pe->fun1)
618        {
619        (*(void(*)(void*,ExtValue*))pe->fun1)(object,&v);
620        return v.getString();
621        }
622else
623        {
624        void *target=getTarget(i);
625        return *((SString*)target);
626        }
627}
628
629ExtObject SimpleAbstractParam::getObject(int i)
630{
631ExtValue v;
632ParamEntry *pe=entry(i);
633if (pe->fun1)
634        {
635        (*(void(*)(void*,ExtValue*))pe->fun1)(object,&v);
636        return v.getObject();
637        }
638else
639        {
640        void *target=getTarget(i);
641        return *((ExtObject*)target);
642        }
643}
644
645ExtValue SimpleAbstractParam::getExtValue(int i)
646{
647ExtValue v;
648ParamEntry *pe=entry(i);
649if (pe->fun1)
650        {
651        (*(void(*)(void*,ExtValue*))pe->fun1)(object,&v);
652        return v;
653        }
654else
655        {
656        void *target=getTarget(i);
657        return *((ExtValue*)target);
658        }
659}
660
661
662//////// set
663
664int SimpleAbstractParam::setInt(int i,long x)
665{
666ExtValue v;
667ParamEntry *pe=entry(i);
668if (pe->flags&PARAM_READONLY) return PSET_RONLY;
669long xcopy=x; //only needed for messageOnExceedRange(): retain original, requested value of x because it may be changed below
670long a=0,b=0;
671int result=0;
672const char* t=pe->type+1;
673while(*t) if (*t==' ') break; else t++;
674if (sscanf(t,"%ld %ld",&a,&b)==2)
675        if (a<=b) // jezeli max<min to znaczy ze min/max nie obowiazuje
676                {
677                if (x<a) {x=a; result=PSET_HITMIN;}
678                else if (x>b) {x=b; result=PSET_HITMAX;}
679                }
680
681if (pe->fun2)
682        {
683        v.setInt(x);
684        result |= (*(int(*)(void*,const ExtValue*))pe->fun2)(object,&v);
685        }
686else
687        {
688        void *target=getTarget(i);
689        if (dontcheckchanges || (*((long*)target)!=x))
690                        {
691                        result |= PSET_CHANGED;
692                        *((long*)target)=x;
693                        }
694        }
695    messageOnExceedRange(i,result,xcopy);
696        return result;
697}
698
699int SimpleAbstractParam::setDouble(int i,double x)
700{
701ExtValue v;
702ParamEntry *pe=entry(i);
703if (pe->flags&PARAM_READONLY) return PSET_RONLY;
704double xcopy=x; //only needed for messageOnExceedRange(): retain original, requested value of x because it may be changed below
705double a=0,b=0;
706int result=0;
707const char* t=pe->type+1;
708while(*t) if (*t==' ') break; else t++;
709if (sscanf(t,"%lg %lg",&a,&b)==2)
710        if (a<=b) // jezeli max<min to znaczy ze min/max nie obowiazuje
711                {
712                if (x<a) {x=a; result=PSET_HITMIN;}
713                else if (x>b) {x=b; result=PSET_HITMAX;}
714                }
715
716if (pe->fun2)
717        {
718        v.setDouble(x);
719        result |= (*(int(*)(void*,const ExtValue*))pe->fun2)(object,&v);
720        }
721else
722        {
723        void *target=getTarget(i);
724        if (dontcheckchanges || (*((double*)target)!=x))
725                {
726                result|=PSET_CHANGED;
727                *((double*)target)=x;
728                }
729        }
730    messageOnExceedRange(i,result,xcopy);
731        return result;
732}
733
734int SimpleAbstractParam::setString(int i,const SString& x)
735{
736ExtValue v;
737SString vs;
738const SString *xx=&x;
739ParamEntry *pe=entry(i);
740if (pe->flags&PARAM_READONLY) return PSET_RONLY;
741SString xcopy=x; //only needed for messageOnExceedRange(): retain original, requested value of x because it may be changed below
742const char* t=pe->type+1;
743while(*t) if (*t==' ') break; else t++;
744long a=0,b=0;
745int result=0;
746if (sscanf(t,"%ld %ld",&a,&b)==2)
747        {
748        if ((x.len()>b)&&(b>0))
749                {
750                vs=x.substr(0,b);
751                xx=&vs;
752                result|=PSET_HITMAX;
753                }
754        }
755
756if (pe->fun2)
757        {
758        v.setString(*xx);
759        result |= (*(int(*)(void*,const ExtValue*))pe->fun2)(object,&v);
760        }
761else
762        {
763        void *target=getTarget(i);
764        if (dontcheckchanges || (!(*((SString*)target) == *xx)))
765                {
766                result|=PSET_CHANGED;
767                *((SString*)target)=x;
768                }
769        }
770    messageOnExceedRange(i,result,xcopy);
771        return result;
772}
773
774int SimpleAbstractParam::setObject(int i,const ExtObject& x)
775{
776ExtValue v;
777ParamEntry *pe=entry(i);
778if (pe->flags&PARAM_READONLY) return PSET_RONLY;
779ExtObject xcopy=x; //only needed for messageOnExceedRange(): retain original, requested value of x because it may be changed below
780if (pe->fun2)
781        {
782        v.setObject(x);
783        int result=(*(int(*)(void*,const ExtValue*))pe->fun2)(object,&v);
784    messageOnExceedRange(i,result,xcopy);
785    return result;
786        }
787else
788        {
789        void *target=getTarget(i);
790        *((ExtObject*)target)=x;
791        return PSET_CHANGED;
792        }
793}
794
795int SimpleAbstractParam::setExtValue(int i,const ExtValue& x)
796{
797ParamEntry *pe=entry(i);
798if (pe->flags&PARAM_READONLY) return PSET_RONLY;
799ExtValue xcopy=x; //only needed for messageOnExceedRange(): retain original, requested value of x because it may be changed below
800if (pe->fun2)
801        {
802        int result=(*(int(*)(void*,const ExtValue*))pe->fun2)(object,&x);
803    messageOnExceedRange(i,result,xcopy);
804    return result;
805        }
806else
807        {
808        void *target=getTarget(i);
809        *((ExtValue*)target)=x;
810        return PSET_CHANGED;
811        }
812}
813
814void SimpleAbstractParam::call(int i,ExtValue *args,ExtValue *ret)
815{
816ParamEntry *pe=entry(i);
817if (!pe) return;
818if (pe->fun1 && (pe->type[0]=='p'))
819        (*(void(*)(void*,ExtValue*,ExtValue*))pe->fun1)(object,args,ret);
820else
821        {
822        FMprintf("SimpleAbstractParam","call",FMLV_ERROR,
823                 (*pe->type!='p')?"'%s.%s' is not a function":"Internal error - undefined function pointer for '%s.%s'",getName(),pe->id);
824        }
825}
826
827void SimpleAbstractParam::setDefault(bool numericonly)
828{
829bool save=dontcheckchanges;
830dontcheckchanges=1;
831ParamInterface::setDefault(numericonly);
832dontcheckchanges=save;
833}
834
835void SimpleAbstractParam::setDefault(int i,bool numericonly)
836{
837bool save=dontcheckchanges;
838dontcheckchanges=1;
839ParamInterface::setDefault(i,numericonly);
840dontcheckchanges=save;
841}
842
843// zwraca adres poczatku linii
844// len = dlugosc linii (bez \n)
845// 0 moze oznaczac linie dlugosci 0 lub koniec SStringa
846// poz jest przesuwane na poczatek nastepnej linii
847// typowa petla: for(poz=0;poz<s.d;) {line=getline(s,poz,len);...
848static const char *getline(const SString &s,int &poz,int &len)
849{
850const char *beg=(const char*)s+poz;
851if (poz>=s.len()) {poz=s.len(); len=0; return (const char*)s+s.len();}
852const char *lf=strchr(beg,'\n');
853if (!lf) { lf=(const char*)s+s.len()-1; poz=s.len(); }
854else {poz=(lf-(const char*)s)+1; if (poz>s.len()) poz=s.len();}
855while (lf>=beg) if ((*lf=='\n')||(*lf=='\r')) lf--; else break;
856len=lf-beg+1;
857return beg;
858}
859
860void ParamInterface::load2(const SString &s,int &poz)
861{
862int i; // numer akt. parametru
863int tmpi;
864int len;
865int ret;
866const char *t,*lin,*end;
867const char *rownasie,*przecinek;
868char remember;
869const char *quote,*quote2;
870const char *value,*valstop;
871SString tmpvalue;
872if (poz>=s.len()) return;
873t=(const char*)s+poz;
874
875// na razie wszystko musi byc w jednej linii...
876lin=getline(s,poz,len);
877if (!len) return; // pusta linia = koniec
878i=0;
879end=lin+len;
880while(t<end)
881{
882// przetwarzanie jednego par
883while (strchr(" \n\r\t",*t)) if (t<end) t++; else return;
884
885przecinek=strchrlimit(t,',',end); if (!przecinek) przecinek=end;
886quote=strchrlimit(t,'\"',przecinek);
887if (quote)
888        {
889        quote2=skipQuoteString(quote+1,end);
890        if (quote2>przecinek)
891                {
892                przecinek=strchrlimit(quote2+1,',',end);
893                if (!przecinek) przecinek=end;
894                }
895        rownasie=strchrlimit(t,'=',quote);
896        }
897else
898        {
899        rownasie=strchrlimit(t,'=',przecinek);
900        quote2=0;
901        }
902if (rownasie==t) { t++; rownasie=0; }
903if (przecinek==t)       // skip empty value
904        {
905        t++; i++;
906        continue;
907        }
908if (rownasie) // have parameter name
909        {
910        tmpi=findIdn(t,rownasie-t);
911        i=tmpi;
912        if (tmpi<0)
913                FMprintf("Param","load2",FMLV_WARN,"Unknown property name for '%s' (ignored)",getName());
914        t=rownasie+1; // t=value
915        }
916#ifdef WARN_MISSING_NAME
917else
918#ifdef SAVE_SELECTED_NAMES
919if (!(flags(i)&PARAM_CANOMITNAME))
920#endif
921        {
922        FMprintf("Param","load2",FMLV_WARN,"Missing property name in '%s' (assuming '%s')",
923                 getName(),id(i)?id(i):"unknown property?");
924        }
925#endif
926if ((i>=0)&&id(i))
927        {
928        value=t;
929        if (quote)
930                {
931                tmpvalue.copyFrom(quote+1,quote2-quote-1);
932                sstringUnquote(tmpvalue);
933                value=tmpvalue;
934                valstop=quote2;
935                }
936        else
937                if (przecinek<end) valstop=przecinek; else valstop=end;
938
939        remember=*valstop;
940        *(char*)valstop=0;
941        ret=set(i,value);
942        if (ret&(PSET_HITMAX|PSET_HITMIN))
943                FMprintf("Param","load2",FMLV_WARN,"Adjusted '%s' in '%s' (was too %s)",
944                        id(i),getName(),(ret&PSET_HITMAX)?"big":"small");
945        *(char*)valstop=remember;
946        }
947
948if (i>=0) i++;
949#ifdef __CODEGUARD__
950if (przecinek<end-1) t=przecinek+1; else return;
951#else
952t=przecinek+1;
953#endif
954}
955return;
956}
957
958int Param::grmember(int g,int a)
959{
960if ((getGroupCount()<2)&&(!g))
961        return (a<getPropCount())?a:-9999;
962
963ParamEntry *e=entry(0);
964int x=0,i=0;
965for (;e->id;i++,e++)
966        {
967        if (e->group==g)
968                if (a==x) return i; else x++;
969        }
970return -9999;
971}
972
Note: See TracBrowser for help on using the repository browser.