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

Last change on this file since 144 was 144, checked in by sz, 10 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.