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

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

source reorganization (see README)
new feature added: part/joint shapes (see frams/_demos/part_shapes.cpp)

  • Property svn:eol-style set to native
File size: 19.5 KB
RevLine 
[109]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 <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 SString* altname,bool force)
203{
204const char *p;
205SString ws;
206int err=0,i;
207bool withname=false;
208if ((!altname)||(altname->len()))
209        {
210        err|=(fputs(altname?((const char*)(*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
333void ParamInterface::load(VirtFILE* f)
334{
335SString buf;
336int i;
337const char *p,*p0;
338int p_len;
339bool loaded;
340while(loadSStringLine(f,buf))
341        {
342        const char* t=(const char*)buf;
343        p0=t; while ((*p0==' ')||(*p0=='\t')) p0++;
344        if (!*p0) break;
345        p=strchr(p0,':'); if (!p) continue;
346        p_len=p-p0;
347        loaded=false;
348        if (p_len&&((i=findIdn(p0,p_len))>=0)&&(!(flags(i)&PARAM_DONTLOAD)))
349                {
350                if (p0[p_len+1]=='~')
351                        {
352                        SString s;
353                        czytdotyldy(f,s);
354                        removeCR(s);
355                        int ch; while((ch=fgetc(f))!=EOF) if (ch=='\n') break;
356                        unquoteTilde(s);
357                        set(i,(const char*)s);
358                        }
359                else
360                        {
361                        set(i,p0+p_len+1);
362                        }
363                loaded=true;
364                }
365        if ((!loaded) && (p0[p_len+1]=='~'))
366                { // eat unrecognized multiline field
367                SString s;
368                czytdotyldy(f,s);
369                int ch; while((ch=fgetc(f))!=EOF) if (ch=='\n') break;
370                }
371        }
372}
373
374
375/*
376SString SimpleAbstractParam::getString(int i)
377{
378char *t;
379switch (*(t=type(i)))
380        {
381        case 'd':
382        {
383        for (i=atol(get(i));i>=0;i--) if (t) t=strchr(t+1,'~');
384        if (t)
385                {
386                t++;
387                char *t2=strchr(t,'~');
388                if (!t2) t2=t+strlen(t);
389                SString str;
390                strncpy(str.directWrite(t2-t),t,t2-t);
391                str.endWrite(t2-t);
392                return str;
393                }
394        }
395        }
396return get(i);
397}
398*/
399
400int ParamInterface::findId(const char* n)
401{
402int i; const char *p;
403        for (i=0;p=id(i);i++) if (!strcmp(n,p)) return i;
404return -1;
405}
406
407int ParamInterface::findIdn(const char* naz,int n)
408{
409int i; const char *p;
410        for (i=0;p=id(i);i++) if ((!strncmp(naz,p,n))&&(!p[n])) return i;
411return -1;
412}
413
414void ParamInterface::get(int i,ExtValue &ret)
415{
416switch(type(i)[0])
417        {
418        case 'd':       ret.setInt(getInt(i)); break;
419        case 'f':       ret.setDouble(getDouble(i)); break;
420        case 's':       ret.setString(getString(i)); break;
421        case 'o':       ret.setObject(getObject(i)); break;
422        case 'x':       ret=getExtValue(i); break;
423        default: FMprintf("ParamInterface","get",FMLV_ERROR,"'%s.%s' is not a field",getName(),id(i));
424        }
425}
426
427static bool stringIsNumeric(const char* str)
428{//   /-?.?[0-9]+/
429if (!str) return false;
430if (*str=='-') str++;
431if (*str=='.') str++;
432return isdigit(*str)!=0;
433}
434
435int ParamInterface::setInt(int i,const char* str)
436{
437if (!stringIsNumeric(str))
438        {
439        long a,b,c;
440        if (getMinMax(i,a,b,c)>=3)
441                return setInt(i,c);
442        else
443                return setInt(i,(long)0);
444        }
445else
446        return setInt(i,atol(str));
447}
448
449int ParamInterface::setDouble(int i,const char* str)
450{
451if (!stringIsNumeric(str))
452        {
453        double a,b,c;
454        if (getMinMax(i,a,b,c)>=3)
455                return setDouble(i,c);
456        else
457                return setDouble(i,(double)0);
458        }
459else
460        return setDouble(i,atof(str));
461}
462
463int ParamInterface::set(int i,const ExtValue &v)
464{
465switch(type(i)[0])
466        {
467        case 'd': if ((v.type==TInt)||(v.type==TDouble)) return setInt(i,v.getInt()); else return setInt(i,(const char*)v.getString());
468        case 'f': if ((v.type==TInt)||(v.type==TDouble)) return setDouble(i,v.getDouble()); else return setDouble(i,(const char*)v.getString());
469        case 's': { SString t=v.getString(); return setString(i,t); }
470        case 'o': return setObject(i,v.getObject());
471        case 'x': return setExtValue(i,v);
472        default: FMprintf("ParamInterface","get",FMLV_ERROR,"'%s.%s' is not a field",getName(),id(i));
473        }
474return 0;
475}
476
477int ParamInterface::set(int i,const char *v)
478{
479switch(type(i)[0])
480        {
481        case 'd': return setInt(i,v);
482        case 'f': return setDouble(i,v);
483        case 's': { SString t(v); return setString(i,t); }
484        case 'x':
485        {
486        ExtValue e;
487        const char* after;
488        if (!strncmp(v,SERIALIZATION_PREFIX,strlen(SERIALIZATION_PREFIX)))
489                {
490                after=e.deserialize(v+strlen(SERIALIZATION_PREFIX));
491                if ((after==NULL)||(*after))
492                        FMprintf("ParamInterface","set",FMLV_WARN,"serialization format mismatch in %s.%s",(getName()?getName():"<Unknown>"),id(i));
493                }
494        else if ((after=e.parseNumber(v))&&(*after==0)) //consumed the whole string
495                {
496                //OK!
497                }
498        else
499                {
500                e.setString(SString(v));
501                }
502        return setExtValue(i,e);
503        }
504        }
505return 0;
506}
507
508SString ParamInterface::getText(int i)
509{
510const char *t;
511if ((*(t=type(i)))=='d')
512        {
513        for (int j=getInt(i);j>=0;j--) if (t) t=strchr(t+1,'~');
514        if (t)
515                {
516                t++;
517                const char *t2=strchr(t,'~');
518                if (!t2) t2=t+strlen(t);
519                return SString(t,t2-t);
520                }
521        }
522return get(i);
523}
524
525SString ParamInterface::get(int i)
526{
527switch(type(i)[0])
528        {
529        case 'd': return SString::valueOf(getInt(i));
530        case 'f': return SString::valueOf(getDouble(i));
531        case 's': return getString(i);
532        }
533ExtValue v;
534get(i,v);
535return v.getString();
536}
537
538
539//////////////////////////////// PARAM ////////////////////////////////////
540
541void *SimpleAbstractParam::getTarget(int i)
542{
543return (void*)(((char*)object)+entry(i)->offset);
544//return &(object->*(entry(i)->fldptr));
545}
546
547///////// get
548
549long SimpleAbstractParam::getInt(int i)
550{
551ExtValue v;
552ParamEntry *pe=entry(i);
553if (pe->fun1)
554        {
555        (*(void(*)(void*,ExtValue*))pe->fun1)(object,&v);
556        return v.getInt();
557        }
558else
559        {
560        void *target=getTarget(i);
561        return *((long*)target);
562        }
563}
564
565double SimpleAbstractParam::getDouble(int i)
566{
567ExtValue v;
568ParamEntry *pe=entry(i);
569if (pe->fun1)
570        {
571        (*(void(*)(void*,ExtValue*))pe->fun1)(object,&v);
572        return v.getDouble();
573        }
574else
575        {
576        void *target=getTarget(i);
577        return *((double*)target);
578        }
579}
580
581SString SimpleAbstractParam::getString(int i)
582{
583ExtValue v;
584ParamEntry *pe=entry(i);
585if (pe->fun1)
586        {
587        (*(void(*)(void*,ExtValue*))pe->fun1)(object,&v);
588        return v.getString();
589        }
590else
591        {
592        void *target=getTarget(i);
593        return *((SString*)target);
594        }
595}
596
597ExtObject SimpleAbstractParam::getObject(int i)
598{
599ExtValue v;
600ParamEntry *pe=entry(i);
601if (pe->fun1)
602        {
603        (*(void(*)(void*,ExtValue*))pe->fun1)(object,&v);
604        return v.getObject();
605        }
606else
607        {
608        void *target=getTarget(i);
609        return *((ExtObject*)target);
610        }
611}
612
613ExtValue SimpleAbstractParam::getExtValue(int i)
614{
615ExtValue v;
616ParamEntry *pe=entry(i);
617if (pe->fun1)
618        {
619        (*(void(*)(void*,ExtValue*))pe->fun1)(object,&v);
620        return v;
621        }
622else
623        {
624        void *target=getTarget(i);
625        return *((ExtValue*)target);
626        }
627}
628
629
630//////// set
631
632int SimpleAbstractParam::setInt(int i,long x)
633{
634ExtValue v;
635ParamEntry *pe=entry(i);
636if (pe->flags&PARAM_READONLY) return PSET_RONLY;
637long xcopy=x; //only needed for messageOnExceedRange(): retain original, requested value of x because it may be changed below
638long a=0,b=0;
639int result=0;
640const char* t=pe->type+1;
641while(*t) if (*t==' ') break; else t++;
642if (sscanf(t,"%ld %ld",&a,&b)==2)
643        if (a<=b) // jezeli max<min to znaczy ze min/max nie obowiazuje
644                {
645                if (x<a) {x=a; result=PSET_HITMIN;}
646                else if (x>b) {x=b; result=PSET_HITMAX;}
647                }
648
649if (pe->fun2)
650        {
651        v.setInt(x);
652        result |= (*(int(*)(void*,const ExtValue*))pe->fun2)(object,&v);
653        }
654else
655        {
656        void *target=getTarget(i);
657        if (dontcheckchanges || (*((long*)target)!=x))
658                        {
659                        result |= PSET_CHANGED;
660                        *((long*)target)=x;
661                        }
662        }
663    messageOnExceedRange(i,result,xcopy);
664        return result;
665}
666
667int SimpleAbstractParam::setDouble(int i,double x)
668{
669ExtValue v;
670ParamEntry *pe=entry(i);
671if (pe->flags&PARAM_READONLY) return PSET_RONLY;
672double xcopy=x; //only needed for messageOnExceedRange(): retain original, requested value of x because it may be changed below
673double a=0,b=0;
674int result=0;
675const char* t=pe->type+1;
676while(*t) if (*t==' ') break; else t++;
677if (sscanf(t,"%lg %lg",&a,&b)==2)
678        if (a<=b) // jezeli max<min to znaczy ze min/max nie obowiazuje
679                {
680                if (x<a) {x=a; result=PSET_HITMIN;}
681                else if (x>b) {x=b; result=PSET_HITMAX;}
682                }
683
684if (pe->fun2)
685        {
686        v.setDouble(x);
687        result |= (*(int(*)(void*,const ExtValue*))pe->fun2)(object,&v);
688        }
689else
690        {
691        void *target=getTarget(i);
692        if (dontcheckchanges || (*((double*)target)!=x))
693                {
694                result|=PSET_CHANGED;
695                *((double*)target)=x;
696                }
697        }
698    messageOnExceedRange(i,result,xcopy);
699        return result;
700}
701
702int SimpleAbstractParam::setString(int i,const SString& x)
703{
704ExtValue v;
705SString vs;
706const SString *xx=&x;
707ParamEntry *pe=entry(i);
708if (pe->flags&PARAM_READONLY) return PSET_RONLY;
709SString xcopy=x; //only needed for messageOnExceedRange(): retain original, requested value of x because it may be changed below
710const char* t=pe->type+1;
711while(*t) if (*t==' ') break; else t++;
712long a=0,b=0;
713int result=0;
714if (sscanf(t,"%ld %ld",&a,&b)==2)
715        {
716        if ((x.len()>b)&&(b>0))
717                {
718                vs=x.substr(0,b);
719                xx=&vs;
720                result|=PSET_HITMAX;
721                }
722        }
723
724if (pe->fun2)
725        {
726        v.setString(*xx);
727        result |= (*(int(*)(void*,const ExtValue*))pe->fun2)(object,&v);
728        }
729else
730        {
731        void *target=getTarget(i);
732        if (dontcheckchanges || (!(*((SString*)target) == *xx)))
733                {
734                result|=PSET_CHANGED;
735                *((SString*)target)=x;
736                }
737        }
738    messageOnExceedRange(i,result,xcopy);
739        return result;
740}
741
742int SimpleAbstractParam::setObject(int i,const ExtObject& x)
743{
744ExtValue v;
745ParamEntry *pe=entry(i);
746if (pe->flags&PARAM_READONLY) return PSET_RONLY;
747ExtObject xcopy=x; //only needed for messageOnExceedRange(): retain original, requested value of x because it may be changed below
748if (pe->fun2)
749        {
750        v.setObject(x);
751        int result=(*(int(*)(void*,const ExtValue*))pe->fun2)(object,&v);
752    messageOnExceedRange(i,result,xcopy);
753    return result;
754        }
755else
756        {
757        void *target=getTarget(i);
758        *((ExtObject*)target)=x;
759        return PSET_CHANGED;
760        }
761}
762
763int SimpleAbstractParam::setExtValue(int i,const ExtValue& x)
764{
765ParamEntry *pe=entry(i);
766if (pe->flags&PARAM_READONLY) return PSET_RONLY;
767ExtValue xcopy=x; //only needed for messageOnExceedRange(): retain original, requested value of x because it may be changed below
768if (pe->fun2)
769        {
770        int result=(*(int(*)(void*,const ExtValue*))pe->fun2)(object,&x);
771    messageOnExceedRange(i,result,xcopy);
772    return result;
773        }
774else
775        {
776        void *target=getTarget(i);
777        *((ExtValue*)target)=x;
778        return PSET_CHANGED;
779        }
780}
781
782void SimpleAbstractParam::call(int i,ExtValue *args,ExtValue *ret)
783{
784ParamEntry *pe=entry(i);
785if (!pe) return;
786if (pe->fun1 && (pe->type[0]=='p'))
787        (*(void(*)(void*,ExtValue*,ExtValue*))pe->fun1)(object,args,ret);
788else
789        {
790        FMprintf("SimpleAbstractParam","call",FMLV_ERROR,
791                 (*pe->type!='p')?"'%s.%s' is not a function":"Internal error - undefined function pointer for '%s.%s'",getName(),pe->id);
792        }
793}
794
795void SimpleAbstractParam::setDefault(bool numericonly)
796{
797bool save=dontcheckchanges;
798dontcheckchanges=1;
799ParamInterface::setDefault(numericonly);
800dontcheckchanges=save;
801}
802
803void SimpleAbstractParam::setDefault(int i,bool numericonly)
804{
805bool save=dontcheckchanges;
806dontcheckchanges=1;
807ParamInterface::setDefault(i,numericonly);
808dontcheckchanges=save;
809}
810
811// zwraca adres poczatku linii
812// len = dlugosc linii (bez \n)
813// 0 moze oznaczac linie dlugosci 0 lub koniec SStringa
814// poz jest przesuwane na poczatek nastepnej linii
815// typowa petla: for(poz=0;poz<s.d;) {line=getline(s,poz,len);...
816static const char *getline(const SString &s,int &poz,int &len)
817{
818const char *beg=(const char*)s+poz;
819if (poz>=s.len()) {poz=s.len(); len=0; return (const char*)s+s.len();}
820const char *lf=strchr(beg,'\n');
821if (!lf) { lf=(const char*)s+s.len()-1; poz=s.len(); }
822else {poz=(lf-(const char*)s)+1; if (poz>s.len()) poz=s.len();}
823while (lf>=beg) if ((*lf=='\n')||(*lf=='\r')) lf--; else break;
824len=lf-beg+1;
825return beg;
826}
827
828void ParamInterface::load2(const SString &s,int &poz)
829{
830int i; // numer akt. parametru
831int tmpi;
832int len;
833int ret;
834const char *t,*lin,*end;
835const char *rownasie,*przecinek;
836char remember;
837const char *quote,*quote2;
838const char *value,*valstop;
839SString tmpvalue;
840if (poz>=s.len()) return;
841t=(const char*)s+poz;
842
843// na razie wszystko musi byc w jednej linii...
844lin=getline(s,poz,len);
845if (!len) return; // pusta linia = koniec
846i=0;
847end=lin+len;
848while(t<end)
849{
850// przetwarzanie jednego par
851while (strchr(" \n\r\t",*t)) if (t<end) t++; else return;
852
853przecinek=strchrlimit(t,',',end); if (!przecinek) przecinek=end;
854quote=strchrlimit(t,'\"',przecinek);
855if (quote)
856        {
857        quote2=skipQuoteString(quote+1,end);
858        if (quote2>przecinek)
859                {
860                przecinek=strchrlimit(quote2+1,',',end);
861                if (!przecinek) przecinek=end;
862                }
863        rownasie=strchrlimit(t,'=',quote);
864        }
865else
866        {
867        rownasie=strchrlimit(t,'=',przecinek);
868        quote2=0;
869        }
870if (rownasie==t) { t++; rownasie=0; }
871if (przecinek==t)       // skip empty value
872        {
873        t++; i++;
874        continue;
875        }
876if (rownasie) // have parameter name
877        {
878        tmpi=findIdn(t,rownasie-t);
879        i=tmpi;
880        if (tmpi<0)
881                FMprintf("Param","load2",FMLV_WARN,"Unknown property name for '%s' (ignored)",getName());
882        t=rownasie+1; // t=value
883        }
884#ifdef WARN_MISSING_NAME
885else
886#ifdef SAVE_SELECTED_NAMES
887if (!(flags(i)&PARAM_CANOMITNAME))
888#endif
889        {
890        FMprintf("Param","load2",FMLV_WARN,"Missing property name in '%s' (assuming '%s')",
891                 getName(),id(i)?id(i):"unknown property?");
892        }
893#endif
894if ((i>=0)&&id(i))
895        {
896        value=t;
897        if (quote)
898                {
899                tmpvalue.copyFrom(quote+1,quote2-quote-1);
900                sstringUnquote(tmpvalue);
901                value=tmpvalue;
902                valstop=quote2;
903                }
904        else
905                if (przecinek<end) valstop=przecinek; else valstop=end;
906
907        remember=*valstop;
908        *(char*)valstop=0;
909        ret=set(i,value);
910        if (ret&(PSET_HITMAX|PSET_HITMIN))
911                FMprintf("Param","load2",FMLV_WARN,"Adjusted '%s' in '%s' (was too %s)",
912                        id(i),getName(),(ret&PSET_HITMAX)?"big":"small");
913        *(char*)valstop=remember;
914        }
915
916if (i>=0) i++;
917#ifdef __CODEGUARD__
918if (przecinek<end-1) t=przecinek+1; else return;
919#else
920t=przecinek+1;
921#endif
922}
923return;
924}
925
926int Param::grmember(int g,int a)
927{
928if ((getGroupCount()<2)&&(!g))
929        return (a<getPropCount())?a:-9999;
930
931ParamEntry *e=entry(0);
932int x=0,i=0;
933for (;e->id;i++,e++)
934        {
935        if (e->group==g)
936                if (a==x) return i; else x++;
937        }
938return -9999;
939}
940
Note: See TracBrowser for help on using the repository browser.