source: cpp/frams/param/param.cpp @ 144

Last change on this file since 144 was 144, checked in by sz, 7 years ago

Param and ExtValue? improvements (better control on conversions, "load" returns the number of loaded fields)

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