Changeset 720 for cpp/frams


Ignore:
Timestamp:
01/14/18 11:24:22 (7 years ago)
Author:
Maciej Komosinski
Message:

Param::save2() renamed to saveSingleLine(); unified Param::load() so that it gets a single-line/multi-line format selector

Location:
cpp/frams
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/_demos/f0_variants_test.cpp

    r534 r720  
    3030modelparam.select(&m);
    3131gen+="m:";
    32 modelparam.save2(gen,omit_default_values ? &defaultmodel : NULL);
     32modelparam.saveSingleLine(gen,omit_default_values ? &defaultmodel : NULL);
    3333
    3434Part *p;
     
    4040        partparam.select(p);
    4141        gen+="p:";
    42         partparam.save2(gen,omit_default_values ? &defaultpart : NULL);
     42        partparam.saveSingleLine(gen,omit_default_values ? &defaultpart : NULL);
    4343        }
    4444for (int i=0;j=(Joint*)m.getJoint(i);i++)
     
    4747        jointparam.setParamTab(j->usedelta?f0_joint_paramtab:f0_nodeltajoint_paramtab);
    4848        gen+="j:";
    49         jointparam.save2(gen,omit_default_values ? &defaultjoint : NULL);
     49        jointparam.saveSingleLine(gen,omit_default_values ? &defaultjoint : NULL);
    5050        }
    5151for (int i=0;n=(Neuro*)m.getNeuro(i);i++)
     
    5353        neuroparam.select(n);
    5454        gen+="n:";
    55         neuroparam.save2(gen,omit_default_values ? &defaultneuro : NULL);
     55        neuroparam.saveSingleLine(gen,omit_default_values ? &defaultneuro : NULL);
    5656        }
    5757for (int a=0;n=(Neuro*)m.getNeuro(a);a++)
     
    6767                connparam.select(&nc);
    6868                gen+="c:";
    69                 connparam.save2(gen,omit_default_values ? &defaultconn : NULL);
     69                connparam.saveSingleLine(gen,omit_default_values ? &defaultconn : NULL);
    7070                }
    7171        }
     
    106106        }
    107107
    108 printf("\nthis example shows how to save a f0 genotype using low-level ParamInterface::save2() calls\n");
     108printf("\nthis example shows how to save a f0 genotype using low-level ParamInterface::saveSingleLine() calls\n");
    109109
    110110SString f0_skipping_defaults;
     
    125125                  ( format 1 )
    126126
    127 this example shows how to save a f0 genotype using low-level ParamInterface::save2() calls
     127this example shows how to save a f0 genotype using low-level ParamInterface::saveSingleLine() calls
    128128
    129129==== with defdata (skips default values) ======
  • cpp/frams/genetics/fF/fF_genotype.h

    r667 r720  
    3636        {
    3737                SString s = serialized;
    38                 int p = 0; //position in string
    39                 return ((param.load2(s, p) == param.getPropCount()) && (p == s.len()));
     38                ParamInterface::LoadOptions opts;
     39                return ((param.load(ParamInterface::FormatSingleLine, s, &opts) == param.getPropCount()) && (opts.offset == s.len()));
    4040        }
    4141
     
    4343        {
    4444                SString tmp;
    45                 param.save2(tmp, NULL/*object containing default values for comparison*/, false/*add CR*/, false/*force field names*/);
     45                param.saveSingleLine(tmp, NULL/*object containing default values for comparison*/, false/*add CR*/, false/*force field names*/);
    4646                return string(tmp.c_str());
    4747        }
  • cpp/frams/model/model.cpp

    r660 r720  
    407407        SString mod_props;
    408408        modelparam.select(this);
    409         modelparam.save2(mod_props, handle_defaults ? &defaultmodel : NULL, true, !handle_defaults);
     409        modelparam.saveSingleLine(mod_props, handle_defaults ? &defaultmodel : NULL, true, !handle_defaults);
    410410        if (mod_props.len() > 1) //are there any non-default values? ("\n" is empty)
    411411        {
     
    419419                len = gen.len();
    420420                gen += "p:";
    421                 partparam.save2(gen, handle_defaults ? &defaultpart : NULL, true, !handle_defaults);
     421                partparam.saveSingleLine(gen, handle_defaults ? &defaultpart : NULL, true, !handle_defaults);
    422422                if (map)
    423423                        map->add(len, gen.len() - 1, partToMap(i));
     
    429429                jointparam.setParamTab(j->usedelta ? f0_joint_paramtab : f0_nodeltajoint_paramtab);
    430430                gen += "j:";
    431                 jointparam.save2(gen, handle_defaults ? &defaultjoint : NULL, true, !handle_defaults);
     431                jointparam.saveSingleLine(gen, handle_defaults ? &defaultjoint : NULL, true, !handle_defaults);
    432432                if (map)
    433433                        map->add(len, gen.len() - 1, jointToMap(i));
     
    438438                len = gen.len();
    439439                gen += "n:";
    440                 neuroparam.save2(gen, handle_defaults ? &defaultneuro : NULL, true, !handle_defaults);
     440                neuroparam.saveSingleLine(gen, handle_defaults ? &defaultneuro : NULL, true, !handle_defaults);
    441441                if (map)
    442442                        map->add(len, gen.len() - 1, neuroToMap(i));
     
    469469                        len = gen.len();
    470470                        gen += "c:";
    471                         connparam.save2(gen, handle_defaults ? &defaultconn : NULL, true, !handle_defaults);
     471                        connparam.saveSingleLine(gen, handle_defaults ? &defaultconn : NULL, true, !handle_defaults);
    472472                        if (map)
    473473                                map->add(len, gen.len() - 1, neuroToMap(n->refno));
     
    582582{
    583583        error_message = SString::empty();
    584         int pos = 0; const char*t = line.c_str();
    585         for (; *t; t++, pos++)
     584        const char*t = line.c_str();
     585        ParamInterface::LoadOptions opts;
     586        for (; *t; t++, opts.offset++)
    586587                if (!strchr(" \r\t", *t)) break;
    587588        if (*t == '#') return 0;
     
    592593                Part *p = new Part();
    593594                partparam.select(p);
    594                 pos += 2;
    595                 if (partparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { delete p; error_message = "Invalid 'p:'"; return -1; }
     595                opts.offset += 2;
     596                partparam.load(ParamInterface::FormatSingleLine, line, &opts);
     597                if (opts.parse_failed) { delete p; error_message = "Invalid 'p:'"; return -1; }
    596598                p->o.rotate(p->rot);
    597599                parts += p;
     
    604606                Param modelparam(f0_model_paramtab);
    605607                modelparam.select(this);
    606                 pos += 2;
    607                 if (modelparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { error_message = "Invalid 'm:'"; return -1; }
     608                opts.offset += 2;
     609                modelparam.load(ParamInterface::FormatSingleLine, line, &opts);
     610                if (opts.parse_failed) { error_message = "Invalid 'm:'"; return -1; }
    608611                return 0;
    609612        }
     
    613616                Joint *j = new Joint();
    614617                jointparam.select(j);
    615                 pos += 2;
     618                opts.offset += 2;
    616619                j->owner = this;
    617                 if (jointparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { delete j; error_message = "Invalid 'j:'"; return -1; }
     620                jointparam.load(ParamInterface::FormatSingleLine, line, &opts);
     621                if (opts.parse_failed) { delete j; error_message = "Invalid 'j:'"; return -1; }
    618622                bool p1_ok = false, p2_ok = false;
    619623                if ((p1_ok = ((j->p1_refno >= 0) && (j->p1_refno < getPartCount()))) &&
     
    642646                Neuro *nu = new Neuro();
    643647                neuroparam.select(nu);
    644                 pos += 2;
    645                 if (neuroparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { delete nu; error_message = "Invalid 'n:'"; return -1; }
     648                opts.offset += 2;
     649                neuroparam.load(ParamInterface::FormatSingleLine, line, &opts);
     650                if (opts.parse_failed) { delete nu; error_message = "Invalid 'n:'"; return -1; }
    646651#ifdef MODEL_V1_COMPATIBLE
    647652                if (nu->neuro_refno>=0) // parent specified...
     
    718723                NeuroConn c;
    719724                ncparam.select(&c);
    720                 pos += 2;
    721                 if (ncparam.load2(line, pos) & ParamInterface::LOAD2_PARSE_FAILED) { error_message = "Invalid 'c:'"; return -1; }
     725                opts.offset += 2;
     726                ncparam.load(ParamInterface::FormatSingleLine, line, &opts);
     727                if (opts.parse_failed) { error_message = "Invalid 'c:'"; return -1; }
    722728                bool n1_ok = false, n2_ok = false;
    723729                if ((n1_ok = ((c.n1_refno >= 0) && (c.n1_refno < getNeuroCount())))
     
    741747                Neuro *nu=new Neuro();
    742748                neuroitemparam.select(nu);
    743                 pos+=3;
    744                 if (neuroitemparam.load2(line,pos) & ParamInterface::LOAD2_PARSE_FAILED) {delete nu; return -1;}
     749                opts.offset+=3;
     750                neuroitemparam.loadSingleLine(line,opts);
     751                if (opts.parse_failed) {delete nu; return -1;}
    745752                // illegal parent?
    746753                if ((nu->neuro_refno<0)||(nu->neuro_refno>=old_getNeuroCount()))
  • cpp/frams/neuro/neuroimpl.cpp

    r492 r720  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    1414#endif
    1515
    16 const int NeuroImpl::ENDDRAWING=-9999;
    17 const int NeuroImpl::MAXDRAWINGXY=0xffff;
    18 
    19 int NeuroNetImpl::mytags_id=0;
     16const int NeuroImpl::ENDDRAWING = -9999;
     17const int NeuroImpl::MAXDRAWINGXY = 0xffff;
     18
     19int NeuroNetImpl::mytags_id = 0;
    2020
    2121/////////////////////////////////////////////////////////
    2222
    2323#define FIELDSTRUCT NeuroNetConfig
    24 static ParamEntry nncfg_paramtab[]=
    25 {
    26 {"Creature: Neurons",1,3,"nnsim",},
    27 {"randinit",1,0,"Random initialization","f 0 10 0.01",FIELD(randominit),"Allowed range for initializing all neuron states with uniform distribution random numbers and zero mean. Set to 0 for deterministic initialization."},
    28 {"nnoise",1,0,"Noise","f 0 1 0",FIELD(nnoise),"Gaussian neural noise: a random value is added to each neural output in each simulation step. Set standard deviation here to add random noise, or 0 for deterministic simulation."},
    29 {"touchrange",1,0,"T receptor range","f 0 100 1",FIELD(touchrange),},
    30 {0,0,0,},
    31 }; 
     24static ParamEntry nncfg_paramtab[] =
     25{
     26        { "Creature: Neurons", 1, 3, "nnsim", },
     27        { "randinit", 1, 0, "Random initialization", "f 0 10 0.01", FIELD(randominit), "Allowed range for initializing all neuron states with uniform distribution random numbers and zero mean. Set to 0 for deterministic initialization." },
     28        { "nnoise", 1, 0, "Noise", "f 0 1 0", FIELD(nnoise), "Gaussian neural noise: a random value is added to each neural output in each simulation step. Set standard deviation here to add random noise, or 0 for deterministic simulation." },
     29        { "touchrange", 1, 0, "T receptor range", "f 0 100 1", FIELD(touchrange), },
     30        { 0, 0, 0, },
     31};
    3232#undef FIELDSTRUCT
    3333
    3434NeuroNetConfig::NeuroNetConfig(NeuroFactory *fac)
    35         :par(nncfg_paramtab,this),
    36          randominit(0.01),
    37          nnoise(0),
    38          touchrange(1),
    39          factory(fac)
     35        :par(nncfg_paramtab, this),
     36        randominit(0.01),
     37        nnoise(0),
     38        touchrange(1),
     39        factory(fac)
    4040{}
    4141
     
    4444NeuroNetImpl::NeuroNetImpl(Model& model, NeuroNetConfig& conf
    4545#ifdef NEURO_SIGNALS
    46 , ChannelSpace *ch
    47 #endif
    48 )
    49         :mod(model),config(conf),
    50          isbuilt(1),errorcount(0)
     46        , ChannelSpace *ch
     47#endif
     48        )
     49        :mod(model), config(conf),
     50        isbuilt(1), errorcount(0)
    5151#ifdef NEURO_SIGNALS
    52 ,channels(ch)
    53 #endif
    54 {
    55 if (!mytags_id) mytags_id=mod.userdata.newID();
    56 
    57 Neuro *n;
    58 NeuroImpl *ni;
    59 Joint *j;
    60 int i;
    61 DB(printf("makeNeuroNet(%p)\n",&mod));
    62 
    63 minorder=3; maxorder=0;
    64 errorcount=0;
    65 
    66 for (i=0;j=mod.getJoint(i);i++)
    67         j->flags&=~(4+8); // todo: !!!neuroitems shouldn't use model fields!!!
    68 
    69 for (i=0;n=mod.getNeuro(i);i++)
    70         {
    71         ni=conf.factory->createNeuroImpl(n);
    72         n->userdata[mytags_id]=ni;
    73         if (!ni) { errorcount++;
    74                 logPrintf("NeuroNetImpl","create",LOG_WARN,"neuron #%d (%s) implementation not available",
    75                          i,n->getClassName().c_str());
    76                 continue; } // implementation not available?!
    77         ni->owner=this;
    78         ni->neuro=n;
    79         ni->readParam();
    80         }
    81 
    82 for (i=0;n=mod.getNeuro(i);i++)
    83         {
    84         n->state+=(rnd01-0.5)*config.randominit;
    85         ni=(NeuroImpl*)n->userdata[mytags_id];
    86         if (!ni) continue;
    87         if (!ni->lateinit())
    88                 { ni->status=NeuroImpl::InitError; errorcount++;
    89                 logPrintf("NeuroNetImpl","create",LOG_WARN,"neuron #%d (%s) initialization failed",
    90                          i,n->getClassName().c_str());
    91                 continue; }
    92         ni->status=NeuroImpl::InitOk;
    93         int order=ni->getSimOrder();
    94         if (order<0) order=0; else if (order>2) order=2;
    95         if (order<minorder) minorder=order;
    96         if (order>maxorder) maxorder=order;
    97         neurons[order]+=ni;
    98         if (ni->getNeedPhysics())
    99                 neurons[3]+=ni;
    100         }
    101 cnode=mod.delmodel_list.add(STATRICKCALLBACK(this,&NeuroNetImpl::destroyNN,0));
     52        , channels(ch)
     53#endif
     54{
     55        if (!mytags_id) mytags_id = mod.userdata.newID();
     56
     57        Neuro *n;
     58        NeuroImpl *ni;
     59        Joint *j;
     60        int i;
     61        DB(printf("makeNeuroNet(%p)\n", &mod));
     62
     63        minorder = 3; maxorder = 0;
     64        errorcount = 0;
     65
     66        for (i = 0; j = mod.getJoint(i); i++)
     67                j->flags &= ~(4 + 8); // todo: !!!neuroitems shouldn't use model fields!!!
     68
     69        for (i = 0; n = mod.getNeuro(i); i++)
     70        {
     71                ni = conf.factory->createNeuroImpl(n);
     72                n->userdata[mytags_id] = ni;
     73                if (!ni)
     74                {
     75                        errorcount++;
     76                        logPrintf("NeuroNetImpl", "create", LOG_WARN, "neuron #%d (%s) implementation not available",
     77                                i, n->getClassName().c_str());
     78                        continue;
     79                } // implementation not available?!
     80                ni->owner = this;
     81                ni->neuro = n;
     82                ni->readParam();
     83        }
     84
     85        for (i = 0; n = mod.getNeuro(i); i++)
     86        {
     87                n->state += (rnd01 - 0.5)*config.randominit;
     88                ni = (NeuroImpl*)n->userdata[mytags_id];
     89                if (!ni) continue;
     90                if (!ni->lateinit())
     91                {
     92                        ni->status = NeuroImpl::InitError;
     93                        errorcount++;
     94                        logPrintf("NeuroNetImpl", "create", LOG_WARN, "neuron #%d (%s) initialization failed",
     95                                i, n->getClassName().c_str());
     96                        continue;
     97                }
     98                ni->status = NeuroImpl::InitOk;
     99                int order = ni->getSimOrder();
     100                if (order < 0) order = 0; else if (order>2) order = 2;
     101                if (order < minorder) minorder = order;
     102                if (order > maxorder) maxorder = order;
     103                neurons[order] += ni;
     104                if (ni->getNeedPhysics())
     105                        neurons[3] += ni;
     106        }
     107        cnode = mod.delmodel_list.add(STATRICKCALLBACK(this, &NeuroNetImpl::destroyNN, 0));
    102108}
    103109
    104110void NeuroNetImpl::destroyNN(CALLBACKARGS)
    105111{
    106 if (!isbuilt) return;
    107 DB(printf("destroyNeuroNet(%p)\n",&mod));
    108 NeuroImpl *ni;
    109 Neuro *n;
    110 for (int i=0;n=mod.getNeuro(i);i++)
    111         {
    112         ni=(NeuroImpl*)n->userdata[mytags_id];
    113         delete ni;
    114         n->userdata[mytags_id]=0;
    115         }
    116 mod.delmodel_list.remove(cnode);
    117 isbuilt=0; errorcount=0;
    118 delete this;
     112        if (!isbuilt) return;
     113        DB(printf("destroyNeuroNet(%p)\n", &mod));
     114        NeuroImpl *ni;
     115        Neuro *n;
     116        for (int i = 0; n = mod.getNeuro(i); i++)
     117        {
     118                ni = (NeuroImpl*)n->userdata[mytags_id];
     119                delete ni;
     120                n->userdata[mytags_id] = 0;
     121        }
     122        mod.delmodel_list.remove(cnode);
     123        isbuilt = 0; errorcount = 0;
     124        delete this;
    119125}
    120126
    121127NeuroNetImpl::~NeuroNetImpl()
    122128{
    123 destroyNN(0,0);
     129        destroyNN(0, 0);
    124130}
    125131
    126132void NeuroNetImpl::simulateNeuroNet()
    127133{
    128 NeuroImpl *ni;
    129 for (int order=minorder;order<=maxorder;order++)
    130         {
     134        NeuroImpl *ni;
     135        for (int order = minorder; order <= maxorder; order++)
     136        {
     137                int i;
     138                SList &nlist = neurons[order];
     139                for (i = 0; ni = (NeuroImpl*)nlist(i); i++)
     140                        ni->go();
     141                for (i = 0; ni = (NeuroImpl*)nlist(i); i++)
     142                        ni->commit();
     143        }
     144}
     145
     146void NeuroNetImpl::simulateNeuroPhysics()
     147{
     148        NeuroImpl *ni;
    131149        int i;
    132         SList &nlist=neurons[order];
    133         for (i=0;ni=(NeuroImpl*)nlist(i);i++)
    134                 ni->go();
    135         for (i=0;ni=(NeuroImpl*)nlist(i);i++)
    136                 ni->commit();
    137         }
    138 }
    139 
    140 void NeuroNetImpl::simulateNeuroPhysics()
    141 {
    142 NeuroImpl *ni;
    143 int i;
    144 SList &nlist=neurons[3];
    145 for (i=0;ni=(NeuroImpl*)nlist(i);i++)
    146         ni->goPhysics();
     150        SList &nlist = neurons[3];
     151        for (i = 0; ni = (NeuroImpl*)nlist(i); i++)
     152                ni->goPhysics();
    147153}
    148154
     
    151157void NeuroImpl::setChannelCount(int c)
    152158{
    153 if (c<1) c=1;
    154 if (c==channels) return;
    155 if (c<channels) {channels=c; chstate.trim(c-1); chnewstate.trim(c-1); return;}
    156 double s=getState(channels-1);
    157 chnewstate.setSize(c-1);
    158 chstate.setSize(c-1);
    159 for(int i=channels;i<c;i++)
    160         {chstate(i-1)=s; chnewstate(i-1)=s;}
    161 channels=c;
    162 }
    163 
    164 void NeuroImpl::setState(double st,int channel)
    165 {
    166 validateNeuroState(st);
    167 if (channel>=channels) channel=channels-1;
    168 if (channel<=0) {newstate=st;return;}
    169 chnewstate(channel-1)=st;
    170 }
    171 
    172 void NeuroImpl::setCurrentState(double st,int channel)
    173 {
    174 validateNeuroState(st);
    175 if (channel>=channels) channel=channels-1;
    176 if (channel<=0) {neuro->state=st; return;}
    177 chstate(channel-1)=st;
     159        if (c < 1) c = 1;
     160        if (c == channels) return;
     161        if (c < channels) { channels = c; chstate.trim(c - 1); chnewstate.trim(c - 1); return; }
     162        double s = getState(channels - 1);
     163        chnewstate.setSize(c - 1);
     164        chstate.setSize(c - 1);
     165        for (int i = channels; i < c; i++)
     166        {
     167                chstate(i - 1) = s;
     168                chnewstate(i - 1) = s;
     169        }
     170        channels = c;
     171}
     172
     173void NeuroImpl::setState(double st, int channel)
     174{
     175        validateNeuroState(st);
     176        if (channel >= channels) channel = channels - 1;
     177        if (channel <= 0) { newstate = st; return; }
     178        chnewstate(channel - 1) = st;
     179}
     180
     181void NeuroImpl::setCurrentState(double st, int channel)
     182{
     183        validateNeuroState(st);
     184        if (channel >= channels) channel = channels - 1;
     185        if (channel <= 0) { neuro->state = st; return; }
     186        chstate(channel - 1) = st;
    178187}
    179188
    180189double NeuroImpl::getNewState(int channel)
    181190{
    182 if (neuro->flags&Neuro::HoldState) return getState(channel);
    183 if (channel>=channels) channel=channels-1;
    184 if (channel<=0) {return newstate;}
    185 return chnewstate(channel-1);
     191        if (neuro->flags&Neuro::HoldState) return getState(channel);
     192        if (channel >= channels) channel = channels - 1;
     193        if (channel <= 0) { return newstate; }
     194        return chnewstate(channel - 1);
    186195}
    187196
    188197double NeuroImpl::getState(int channel)
    189198{
    190 if (channel>=channels) channel=channels-1;
    191 if (channel<=0) return neuro->state;
    192 return chstate(channel-1);
     199        if (channel >= channels) channel = channels - 1;
     200        if (channel <= 0) return neuro->state;
     201        return chstate(channel - 1);
    193202}
    194203
    195204void NeuroImpl::commit()
    196205{
    197 if (!(neuro->flags&Neuro::HoldState))
    198         {
    199         if (channels>1)
    200                 chstate=chnewstate;
    201         neuro->state=newstate;
    202         if (owner->getConfig().nnoise>0.0)
     206        if (!(neuro->flags&Neuro::HoldState))
     207        {
     208                if (channels > 1)
     209                        chstate = chnewstate;
     210                neuro->state = newstate;
     211                if (owner->getConfig().nnoise > 0.0)
    203212                {
    204                 neuro->state+=RndGen.GaussStd()*owner->getConfig().nnoise;
    205                 if (channels>1)
    206                         for(int i=0;i<chstate.size();i++)
    207                                 chstate(0)+=RndGen.GaussStd()*owner->getConfig().nnoise;
     213                        neuro->state += RndGen.GaussStd()*owner->getConfig().nnoise;
     214                        if (channels > 1)
     215                                for (int i = 0; i < chstate.size(); i++)
     216                                        chstate(0) += RndGen.GaussStd()*owner->getConfig().nnoise;
    208217                }
    209218        }
     
    212221int NeuroImpl::getInputChannelCount(int i)
    213222{
    214 if ((i<0)||(i >= neuro->getInputCount())) return 1;
    215 Neuro *nu=neuro->getInput(i);
    216 NeuroImpl *ni=NeuroNetImpl::getImpl(nu);
    217 if (!ni) return 1;
    218 return ni->channels;
    219 }
    220 
    221 double NeuroImpl::getInputState(int i,int channel)
    222 {
    223 if ((i<0)||(i >= neuro->getInputCount())) return 0;
    224 Neuro *nu=neuro->getInput(i);
    225 if (channel<=0) return nu->state;
    226 NeuroImpl *ni=NeuroNetImpl::getImpl(nu);
    227 if (!ni) return nu->state;
    228 if (channel>=ni->channels) channel=ni->channels-1;
    229 if (!channel) return nu->state;
    230 return ni->chstate(channel-1);
     223        if ((i < 0) || (i >= neuro->getInputCount())) return 1;
     224        Neuro *nu = neuro->getInput(i);
     225        NeuroImpl *ni = NeuroNetImpl::getImpl(nu);
     226        if (!ni) return 1;
     227        return ni->channels;
     228}
     229
     230double NeuroImpl::getInputState(int i, int channel)
     231{
     232        if ((i < 0) || (i >= neuro->getInputCount())) return 0;
     233        Neuro *nu = neuro->getInput(i);
     234        if (channel <= 0) return nu->state;
     235        NeuroImpl *ni = NeuroNetImpl::getImpl(nu);
     236        if (!ni) return nu->state;
     237        if (channel >= ni->channels) channel = ni->channels - 1;
     238        if (!channel) return nu->state;
     239        return ni->chstate(channel - 1);
    231240}
    232241
    233242double NeuroImpl::getWeightedInputState(int i, int channel)
    234243{
    235 if ((i<0)||(i >= neuro->getInputCount())) return 0;
    236 double w;
    237 Neuro *nu=neuro->getInput(i,w);
    238 if (channel<=0) return nu->state * w;
    239 NeuroImpl *ni=NeuroNetImpl::getImpl(nu);
    240 if (!ni) return nu->state * w;
    241 if (channel>=ni->channels) channel=ni->channels-1;
    242 if (!channel) return w * nu->state;
    243 return w * ni->chstate(channel-1);
     244        if ((i < 0) || (i >= neuro->getInputCount())) return 0;
     245        double w;
     246        Neuro *nu = neuro->getInput(i, w);
     247        if (channel <= 0) return nu->state * w;
     248        NeuroImpl *ni = NeuroNetImpl::getImpl(nu);
     249        if (!ni) return nu->state * w;
     250        if (channel >= ni->channels) channel = ni->channels - 1;
     251        if (!channel) return w * nu->state;
     252        return w * ni->chstate(channel - 1);
    244253}
    245254
    246255double NeuroImpl::getInputSum(int startwith)
    247256{
    248 if (startwith<0) return 0;
    249 Neuro *inp;
    250 double sum=0.0;
    251 while(inp=neuro->getInput(startwith++))
    252         sum+=inp->state;
    253 return sum;
     257        if (startwith < 0) return 0;
     258        Neuro *inp;
     259        double sum = 0.0;
     260        while (inp = neuro->getInput(startwith++))
     261                sum += inp->state;
     262        return sum;
    254263}
    255264
    256265double NeuroImpl::getWeightedInputSum(int startwith)
    257266{
    258 if (startwith<0) return 0;
    259 Neuro *inp;
    260 double sum=0.0;
    261 double w;
    262 while(inp=neuro->getInput(startwith++,w))
    263         sum+=inp->state*w;
    264 return sum;
     267        if (startwith < 0) return 0;
     268        Neuro *inp;
     269        double sum = 0.0;
     270        double w;
     271        while (inp = neuro->getInput(startwith++, w))
     272                sum += inp->state*w;
     273        return sum;
    265274}
    266275
    267276void NeuroImpl::readParam()
    268277{
    269 Param par;
    270 if (!paramentries) return;
    271 par.setParamTab(paramentries);
    272 par.select(this);
    273 par.setDefault();
    274 int zero=0;
    275 par.load2(neuro->getClassParams(),zero);
     278        Param par;
     279        if (!paramentries) return;
     280        par.setParamTab(paramentries);
     281        par.select(this);
     282        par.setDefault();
     283        par.load(ParamInterface::FormatSingleLine, neuro->getClassParams());
    276284}
    277285
    278286Param& NeuroImpl::getStaticParam()
    279287{
    280 static Param p(neuroimpl_tab,0,"Neuro");
    281 return p;
     288        static Param p(neuroimpl_tab, 0, "Neuro");
     289        return p;
    282290}
    283291
     
    291299
    292300#define FIELDSTRUCT NeuroImpl
    293 ParamEntry neuroimpl_tab[]=
    294 {
    295 {"Neuro",1,27+NEUROIMPL_SIGNAL_PROPS,"Neuro","Live Neuron object."},
    296 
    297 {"getInputState",0,0,"Get input signal","p f(d input)",PROCEDURE(p_get),},
    298 {"getInputWeight",0,0,"Get input weight","p f(d input)",PROCEDURE(p_getweight),},
    299 {"getWeightedInputState",0,0,"Get weighted input signal","p f(d input)",PROCEDURE(p_getw),},
    300 {"getInputSum",0,0,"Get signal sum","p f(d input)",PROCEDURE(p_getsum),},
    301 {"getWeightedInputSum",0,0,"Get weighted signal sum","p f(d input)",PROCEDURE(p_getwsum),"Uses any number of inputs starting with the specified input. getWeightedInputSum(0)=weightedInputSum"},
    302 {"getInputCount",0,PARAM_READONLY,"Get input count","d",GETONLY(count),},
    303 {"inputSum",0,PARAM_READONLY,"Full signal sum","f",GETONLY(sum),},
    304 {"weightedInputSum",0,PARAM_READONLY,"Full weighted signal sum","f",GETONLY(wsum),},
    305 {"getInputChannelCount",0,0,"Get channel count for input","p d(d input)",PROCEDURE(p_getchancount),},
    306 {"getInputStateChannel",0,0,"Get input signal from channel","p f(d input,d channel)",PROCEDURE(p_getchan),},
    307 {"getWeightedInputStateChannel",0,0,"Get weighted input signal from channel","p f(d input,d channel)",PROCEDURE(p_getwchan),},
    308 {"state",0,0,"Neuron state (channel 0)","f",GETSET(state),"When read, returns the current neuron state.\nWhen written, sets the 'internal' neuron state that will become current in the next step.\nTypically you should use this field, and not currState."},
    309 {"channelCount",0,0,"Number of output channels","d",GETSET(channels),},
    310 {"getStateChannel",0,0,"Get state for channel","p f(d channel)",PROCEDURE(p_getstate),},
    311 {"setStateChannel",0,0,"Set state for channel","p(d channel,f value)",PROCEDURE(p_setstate),},
    312 {"hold",0,0,"Hold state","d 0 1",GETSET(hold),"\"Holding\" means keeping the neuron state as is, blocking the regular neuron operation. This is useful when your script needs to inject some control signals into the NN. Without \"holding\", live neurons would be constantly overwriting your changes, and the rest of the NN could see inconsistent states, depending on the connections. Setting hold=1 ensures the neuron state will be only set by you, and not by the neuron. The enforced signal value can be set using Neuro.currState before or after setting hold=1. Set hold=0 to resume normal operation.",},
    313 {"currState",0,0,"Current neuron state (channel 0)","f",GETSET(cstate),"When read, it behaves just like the 'state' field.\nWhen written, changes the current neuron state immediately, which disturbs the regular synchronous NN operation.\nThis feature should only be used while controlling the neuron 'from outside' (like a neuro probe) and not in the neuron definition. See also: Neuro.hold",},
    314 {"setCurrStateChannel",0,0,"Set current neuron state for channel","p(d channel,f value)",PROCEDURE(p_setcstate),"Analogous to \"currState\"."},
    315 {"position_x",0,PARAM_READONLY,"Position x","f",GETONLY(position_x),},
    316 {"position_y",0,PARAM_READONLY,"Position y","f",GETONLY(position_y),},
    317 {"position_z",0,PARAM_READONLY,"Position z","f",GETONLY(position_z),},
    318 {"creature",0,PARAM_READONLY,"Gets owner creature","o Creature",GETONLY(creature),},
    319 {"part",0,PARAM_READONLY,"The Part object where this neuron is located","o MechPart",GETONLY(part),},
    320 {"joint",0,PARAM_READONLY,"The Joint object where this neuron is located","o MechJoint",GETONLY(joint),},
    321 {"neuroproperties",0,PARAM_READONLY,"Custom neuron fields","o NeuroProperties",GETONLY(fields),
    322 "Neurons can have different fields depending on their class. Script neurons have their fields defined using the \"property:\" syntax. If you develop a custom neuron script you should use the NeuroProperties object for accessing your own neuron fields. The Neuro.neuroproperties property is meant for accessing the neuron fields from the outside script.\n"
    323 "Examples:\n"
    324 "var c=Populations.createFromString(\"X[N]\");\n"
    325 "Simulator.print(\"standard neuron inertia=\"+c.getNeuro(0).neuroproperties.in);\n"
    326 "c=Populations.createFromString(\"X[Nn,e:0.1]\");\n"
    327 "Simulator.print(\"noisy neuron error rate=\"+c.getNeuro(0).neuroproperties.e);\n"
    328 "\n"
    329 "The Interface object can be used to discover which fields are available for a certain neuron object:\n"
    330 "c=Populations.createFromString(\"X[N]\");\n"
    331 "var iobj=Interface.makeFrom(c.getNeuro(0).neuroproperties);\n"
    332 "var i;\n"
    333 "for(i=0;i<iobj.size;i++)\n"
    334 " Simulator.print(iobj.getId(i)+\" (\"+iobj.getName(i)+\")\");",},
    335 {"def",0,PARAM_READONLY,"Neuron definition from which this live neuron was built","o NeuroDef",GETONLY(neurodef),},
    336 {"classObject",0,PARAM_READONLY,"Neuron class for this neuron","o NeuroClass",GETONLY(classObject),},
     301ParamEntry neuroimpl_tab[] =
     302{
     303        { "Neuro", 1, 27 + NEUROIMPL_SIGNAL_PROPS, "Neuro", "Live Neuron object." },
     304
     305        { "getInputState", 0, 0, "Get input signal", "p f(d input)", PROCEDURE(p_get), },
     306        { "getInputWeight", 0, 0, "Get input weight", "p f(d input)", PROCEDURE(p_getweight), },
     307        { "getWeightedInputState", 0, 0, "Get weighted input signal", "p f(d input)", PROCEDURE(p_getw), },
     308        { "getInputSum", 0, 0, "Get signal sum", "p f(d input)", PROCEDURE(p_getsum), },
     309        { "getWeightedInputSum", 0, 0, "Get weighted signal sum", "p f(d input)", PROCEDURE(p_getwsum), "Uses any number of inputs starting with the specified input. getWeightedInputSum(0)=weightedInputSum" },
     310        { "getInputCount", 0, PARAM_READONLY, "Get input count", "d", GETONLY(count), },
     311        { "inputSum", 0, PARAM_READONLY, "Full signal sum", "f", GETONLY(sum), },
     312        { "weightedInputSum", 0, PARAM_READONLY, "Full weighted signal sum", "f", GETONLY(wsum), },
     313        { "getInputChannelCount", 0, 0, "Get channel count for input", "p d(d input)", PROCEDURE(p_getchancount), },
     314        { "getInputStateChannel", 0, 0, "Get input signal from channel", "p f(d input,d channel)", PROCEDURE(p_getchan), },
     315        { "getWeightedInputStateChannel", 0, 0, "Get weighted input signal from channel", "p f(d input,d channel)", PROCEDURE(p_getwchan), },
     316        { "state", 0, 0, "Neuron state (channel 0)", "f", GETSET(state), "When read, returns the current neuron state.\nWhen written, sets the 'internal' neuron state that will become current in the next step.\nTypically you should use this field, and not currState." },
     317        { "channelCount", 0, 0, "Number of output channels", "d", GETSET(channels), },
     318        { "getStateChannel", 0, 0, "Get state for channel", "p f(d channel)", PROCEDURE(p_getstate), },
     319        { "setStateChannel", 0, 0, "Set state for channel", "p(d channel,f value)", PROCEDURE(p_setstate), },
     320        { "hold", 0, 0, "Hold state", "d 0 1", GETSET(hold), "\"Holding\" means keeping the neuron state as is, blocking the regular neuron operation. This is useful when your script needs to inject some control signals into the NN. Without \"holding\", live neurons would be constantly overwriting your changes, and the rest of the NN could see inconsistent states, depending on the connections. Setting hold=1 ensures the neuron state will be only set by you, and not by the neuron. The enforced signal value can be set using Neuro.currState before or after setting hold=1. Set hold=0 to resume normal operation.", },
     321        { "currState", 0, 0, "Current neuron state (channel 0)", "f", GETSET(cstate), "When read, it behaves just like the 'state' field.\nWhen written, changes the current neuron state immediately, which disturbs the regular synchronous NN operation.\nThis feature should only be used while controlling the neuron 'from outside' (like a neuro probe) and not in the neuron definition. See also: Neuro.hold", },
     322        { "setCurrStateChannel", 0, 0, "Set current neuron state for channel", "p(d channel,f value)", PROCEDURE(p_setcstate), "Analogous to \"currState\"." },
     323        { "position_x", 0, PARAM_READONLY, "Position x", "f", GETONLY(position_x), },
     324        { "position_y", 0, PARAM_READONLY, "Position y", "f", GETONLY(position_y), },
     325        { "position_z", 0, PARAM_READONLY, "Position z", "f", GETONLY(position_z), },
     326        { "creature", 0, PARAM_READONLY, "Gets owner creature", "o Creature", GETONLY(creature), },
     327        { "part", 0, PARAM_READONLY, "The Part object where this neuron is located", "o MechPart", GETONLY(part), },
     328        { "joint", 0, PARAM_READONLY, "The Joint object where this neuron is located", "o MechJoint", GETONLY(joint), },
     329        { "neuroproperties", 0, PARAM_READONLY, "Custom neuron fields", "o NeuroProperties", GETONLY(fields),
     330        "Neurons can have different fields depending on their class. Script neurons have their fields defined using the \"property:\" syntax. If you develop a custom neuron script you should use the NeuroProperties object for accessing your own neuron fields. The Neuro.neuroproperties property is meant for accessing the neuron fields from the outside script.\n"
     331        "Examples:\n"
     332        "var c=Populations.createFromString(\"X[N]\");\n"
     333        "Simulator.print(\"standard neuron inertia=\"+c.getNeuro(0).neuroproperties.in);\n"
     334        "c=Populations.createFromString(\"X[Nn,e:0.1]\");\n"
     335        "Simulator.print(\"noisy neuron error rate=\"+c.getNeuro(0).neuroproperties.e);\n"
     336        "\n"
     337        "The Interface object can be used to discover which fields are available for a certain neuron object:\n"
     338        "c=Populations.createFromString(\"X[N]\");\n"
     339        "var iobj=Interface.makeFrom(c.getNeuro(0).neuroproperties);\n"
     340        "var i;\n"
     341        "for(i=0;i<iobj.size;i++)\n"
     342        " Simulator.print(iobj.getId(i)+\" (\"+iobj.getName(i)+\")\");", },
     343        { "def", 0, PARAM_READONLY, "Neuron definition from which this live neuron was built", "o NeuroDef", GETONLY(neurodef), },
     344        { "classObject", 0, PARAM_READONLY, "Neuron class for this neuron", "o NeuroClass", GETONLY(classObject), },
    337345#ifdef NEURO_SIGNALS
    338 {"signals",0,PARAM_READONLY,"Signals","o NeuroSignals",FIELD(sigs_obj),},
    339 #endif
    340 
    341 {0,0,0,},
     346        { "signals", 0, PARAM_READONLY, "Signals", "o NeuroSignals", FIELD(sigs_obj), },
     347#endif
     348
     349        { 0, 0, 0, },
    342350};
    343351#undef FIELDSTRUCT
    344352
    345353#ifdef NEURO_SIGNALS
    346 ParamEntry neurosignals_paramtab[]=
    347  {
    348 {"NeuroSignals",1,8,"NeuroSignals","Signals attached to a neuron.\nSee also: Signal, WorldSignals, CreatureSignals.\nscripts/light.neuro and scripts/seelight.neuro are simple custom neuron examples demonstrating how to send/receive signals between creatures.",},
     354ParamEntry neurosignals_paramtab[] =
     355{
     356        { "NeuroSignals", 1, 8, "NeuroSignals", "Signals attached to a neuron.\nSee also: Signal, WorldSignals, CreatureSignals.\nscripts/light.neuro and scripts/seelight.neuro are simple custom neuron examples demonstrating how to send/receive signals between creatures.", },
    349357
    350358#define FIELDSTRUCT NeuroSignals
    351 SIGNPAR_ADD(""),
    352 SIGNPAR_RECEIVE(""),
    353 SIGNPAR_RECEIVESET(""),
    354 SIGNPAR_RECEIVEFILTER(""),
    355 SIGNPAR_RECEIVESINGLE(""),
     359        SIGNPAR_ADD(""),
     360        SIGNPAR_RECEIVE(""),
     361        SIGNPAR_RECEIVESET(""),
     362        SIGNPAR_RECEIVEFILTER(""),
     363        SIGNPAR_RECEIVESINGLE(""),
    356364#undef FIELDSTRUCT
    357365
    358366#define FIELDSTRUCT SignalSet
    359 SIGNSETPAR_GET,
    360 SIGNSETPAR_SIZE,
    361 SIGNSETPAR_CLEAR,
     367        SIGNSETPAR_GET,
     368        SIGNSETPAR_SIZE,
     369        SIGNSETPAR_CLEAR,
    362370#undef FIELDSTRUCT
    363 {0,0,0,},
    364  };
     371        { 0, 0, 0, },
     372};
    365373
    366374Param& NeuroSignals::getStaticParam()
    367375{
    368 static Param p(neurosignals_paramtab,0);
    369 return p;
     376        static Param p(neurosignals_paramtab, 0);
     377        return p;
    370378}
    371379#endif
    372380
    373381#ifdef NEURO_SIGNALS
    374 class NeuroSigSource: public SigSource
    375 {
    376   protected:
    377 NeuroImpl* owner;
    378   public:
    379 NeuroSigSource(NeuroImpl *n,Creature *c):SigSource(0,c),owner(n) {}
    380 bool update();
     382class NeuroSigSource : public SigSource
     383{
     384protected:
     385        NeuroImpl* owner;
     386public:
     387        NeuroSigSource(NeuroImpl *n, Creature *c) :SigSource(0, c), owner(n) {}
     388        bool update();
    381389};
    382390
    383391bool NeuroSigSource::update()
    384392{
    385 Pt3D p;
    386 if (owner->getPosition(p))
    387         {
    388         setLocation(p);
    389         return true;
    390         }
    391 return false;
     393        Pt3D p;
     394        if (owner->getPosition(p))
     395        {
     396                setLocation(p);
     397                return true;
     398        }
     399        return false;
    392400}
    393401
    394402Creature *NeuroSignals::getCreature()
    395403{
    396 if (!cr)
    397         {
    398         cr=owner->getCreature();
    399         }
    400 return cr;
     404        if (!cr)
     405        {
     406                cr = owner->getCreature();
     407        }
     408        return cr;
    401409}
    402410
    403411void NeuroSignals::p_add(PARAMPROCARGS)
    404412{
    405 SigSource *s=new NeuroSigSource(owner,getCreature());
    406 if (owner->owner->channels)
    407         {
    408         SigChannel *ch=owner->owner->channels->getChannel(args->getString(),true);
    409         ch->addSource(s);
    410         }
    411 else
    412         SigChannel::dummy_channel.addSource(s);
    413 sigs+=s;
    414 s->setupObject(ret);
     413        SigSource *s = new NeuroSigSource(owner, getCreature());
     414        if (owner->owner->channels)
     415        {
     416                SigChannel *ch = owner->owner->channels->getChannel(args->getString(), true);
     417                ch->addSource(s);
     418        }
     419        else
     420                SigChannel::dummy_channel.addSource(s);
     421        sigs += s;
     422        s->setupObject(ret);
    415423}
    416424
    417425void NeuroSignals::p_receive(PARAMPROCARGS)
    418426{
    419 SigChannel *ch; Pt3D p;
    420 if (owner->owner->channels && (ch=owner->owner->channels->getChannel(args->getString(),false)) && owner->getPosition(p))
    421         ret->setDouble(ch->receive(&p,getCreature()));
    422 else
    423         ret->setDouble(0);
     427        SigChannel *ch; Pt3D p;
     428        if (owner->owner->channels && (ch = owner->owner->channels->getChannel(args->getString(), false)) && owner->getPosition(p))
     429                ret->setDouble(ch->receive(&p, getCreature()));
     430        else
     431                ret->setDouble(0);
    424432}
    425433
    426434void NeuroSignals::p_receiveFilter(PARAMPROCARGS)
    427435{
    428 SigChannel *ch; Pt3D p;
    429 if (owner->owner->channels && (ch=owner->owner->channels->getChannel(args[3].getString(),false)) && owner->getPosition(p))
    430         ret->setDouble(ch->receive(&p,getCreature(),args[2].getDouble(),args[1].getDouble(),args[0].getDouble()));
    431 else
    432         ret->setDouble(0);
     436        SigChannel *ch; Pt3D p;
     437        if (owner->owner->channels && (ch = owner->owner->channels->getChannel(args[3].getString(), false)) && owner->getPosition(p))
     438                ret->setDouble(ch->receive(&p, getCreature(), args[2].getDouble(), args[1].getDouble(), args[0].getDouble()));
     439        else
     440                ret->setDouble(0);
    433441}
    434442
    435443void NeuroSignals::p_receiveSet(PARAMPROCARGS)
    436444{
    437 SigChannel *ch; Pt3D p;
    438 SigVector *vec=new SigVector();
    439 if (owner->owner->channels && (ch=owner->owner->channels->getChannel(args[1].getString(),false)) && owner->getPosition(p))
    440         ch->receiveSet(vec,&p,getCreature(),args[0].getDouble());
    441 ret->setObject(vec->makeObject());
     445        SigChannel *ch; Pt3D p;
     446        SigVector *vec = new SigVector();
     447        if (owner->owner->channels && (ch = owner->owner->channels->getChannel(args[1].getString(), false)) && owner->getPosition(p))
     448                ch->receiveSet(vec, &p, getCreature(), args[0].getDouble());
     449        ret->setObject(vec->makeObject());
    442450}
    443451
    444452void NeuroSignals::p_receiveSingle(PARAMPROCARGS)
    445453{
    446 SigChannel *ch; Pt3D p;
    447 if (owner->owner->channels && (ch=owner->owner->channels->getChannel(args[1].getString(),false)) && owner->getPosition(p))
    448         {
    449         SigSource *src=ch->receiveSingle(&p,getCreature(),args[0].getDouble(),0,1e99);
    450         if (src)
     454        SigChannel *ch; Pt3D p;
     455        if (owner->owner->channels && (ch = owner->owner->channels->getChannel(args[1].getString(), false)) && owner->getPosition(p))
     456        {
     457                SigSource *src = ch->receiveSingle(&p, getCreature(), args[0].getDouble(), 0, 1e99);
     458                if (src)
    451459                {
    452                 src->setupObject(ret);
    453                 return;
     460                        src->setupObject(ret);
     461                        return;
    454462                }
    455463        }
    456 ret->setEmpty();
     464        ret->setEmpty();
    457465}
    458466#endif
     
    460468#ifndef SDK_WITHOUT_FRAMS
    461469extern ParamEntry creature_paramtab[];
    462 static Param creature_param(creature_paramtab,0);
     470static Param creature_param(creature_paramtab, 0);
    463471#endif
    464472
     
    466474{
    467475#ifndef SDK_WITHOUT_FRAMS
    468 CreatMechObject *cmo=(CreatMechObject *)neuro->owner->userdata[CreatMechObject::modeltags_id];
    469 return cmo->creature;
     476        CreatMechObject *cmo = (CreatMechObject *)neuro->owner->userdata[CreatMechObject::modeltags_id];
     477        return cmo->creature;
    470478#else
    471 return 0;
     479        return 0;
    472480#endif
    473481}
     
    476484{
    477485#ifndef SDK_WITHOUT_FRAMS
    478 ret->setObject(ExtObject(&creature_param,getCreature()));
     486        ret->setObject(ExtObject(&creature_param, getCreature()));
    479487#endif
    480488}
     
    483491{
    484492#ifndef SDK_WITHOUT_FRAMS
    485 Part *pa;
    486 if (pa=neuro->getPart())
    487         ret->setObject(ExtObject(&MechPart::getStaticParam(),((MechPart *)pa->userdata[CreatMechObject::modeltags_id])));
    488 else
    489         ret->setEmpty();
     493        Part *pa;
     494        if (pa = neuro->getPart())
     495                ret->setObject(ExtObject(&MechPart::getStaticParam(), ((MechPart *)pa->userdata[CreatMechObject::modeltags_id])));
     496        else
     497                ret->setEmpty();
    490498#endif
    491499}
     
    494502{
    495503#ifndef SDK_WITHOUT_FRAMS
    496 Joint *jo;
    497 if (jo=neuro->getJoint())
    498         ret->setObject(ExtObject(&MechJoint::getStaticParam(),((MechJoint*)jo->userdata[CreatMechObject::modeltags_id])));
    499 else
    500         ret->setEmpty();
     504        Joint *jo;
     505        if (jo = neuro->getJoint())
     506                ret->setObject(ExtObject(&MechJoint::getStaticParam(), ((MechJoint*)jo->userdata[CreatMechObject::modeltags_id])));
     507        else
     508                ret->setEmpty();
    501509#endif
    502510}
     
    505513{
    506514#ifndef SDK_WITHOUT_FRAMS
    507 Part *pa; Joint *jo;
    508 if (pa=neuro->getPart())
    509         {pos=((MechPart *)pa->userdata[CreatMechObject::modeltags_id])->p; return true;}
    510 if (jo=neuro->getJoint())
    511         {
    512         if (neuro->getClass()->getVisualHints() & NeuroClass::AtFirstPart)
    513                 pos=((MechPart*)jo->part1->userdata[CreatMechObject::modeltags_id])->p;
    514         else if (neuro->getClass()->getVisualHints() & NeuroClass::AtSecondPart)
    515                 pos=((MechPart*)jo->part2->userdata[CreatMechObject::modeltags_id])->p;
    516         else pos=(((MechPart*)jo->part1->userdata[CreatMechObject::modeltags_id])->p
    517                    +((MechPart*)jo->part2->userdata[CreatMechObject::modeltags_id])->p)/2;
    518         return true;
    519         }
    520 #endif
    521 return false;
     515        Part *pa; Joint *jo;
     516        if (pa = neuro->getPart())
     517        {
     518                pos = ((MechPart *)pa->userdata[CreatMechObject::modeltags_id])->p;
     519                return true;
     520        }
     521        if (jo = neuro->getJoint())
     522        {
     523                if (neuro->getClass()->getVisualHints() & NeuroClass::AtFirstPart)
     524                        pos = ((MechPart*)jo->part1->userdata[CreatMechObject::modeltags_id])->p;
     525                else if (neuro->getClass()->getVisualHints() & NeuroClass::AtSecondPart)
     526                        pos = ((MechPart*)jo->part2->userdata[CreatMechObject::modeltags_id])->p;
     527                else pos = (((MechPart*)jo->part1->userdata[CreatMechObject::modeltags_id])->p
     528                        + ((MechPart*)jo->part2->userdata[CreatMechObject::modeltags_id])->p) / 2;
     529                return true;
     530        }
     531#endif
     532        return false;
    522533}
    523534
    524535void NeuroImpl::get_position_x(ExtValue *ret)
    525 {Pt3D pos; if (getPosition(pos)) ret->setDouble(pos.x); else ret->setEmpty();}
     536{
     537        Pt3D pos;
     538        if (getPosition(pos)) ret->setDouble(pos.x); else ret->setEmpty();
     539}
    526540void NeuroImpl::get_position_y(ExtValue *ret)
    527 {Pt3D pos; if (getPosition(pos)) ret->setDouble(pos.y); else ret->setEmpty();}
     541{
     542        Pt3D pos;
     543        if (getPosition(pos)) ret->setDouble(pos.y); else ret->setEmpty();
     544}
    528545void NeuroImpl::get_position_z(ExtValue *ret)
    529 {Pt3D pos; if (getPosition(pos)) ret->setDouble(pos.z); else ret->setEmpty();}
     546{
     547        Pt3D pos;
     548        if (getPosition(pos)) ret->setDouble(pos.z); else ret->setEmpty();
     549}
    530550
    531551
    532552void NeuroImpl::createFieldsObject()
    533553{
    534 fields_param=new Param(paramentries?paramentries:(ParamEntry*)&empty_paramtab,this,"NeuroProperties");
    535 fields_object=new ExtObject(fields_param);
     554        fields_param = new Param(paramentries ? paramentries : (ParamEntry*)&empty_paramtab, this, "NeuroProperties");
     555        fields_object = new ExtObject(fields_param);
    536556}
    537557
    538558void NeuroImpl::get_fields(ExtValue *ret)
    539559{
    540 if (!fields_object)
    541         createFieldsObject();
    542 ret->setObject(*fields_object);
     560        if (!fields_object)
     561                createFieldsObject();
     562        ret->setObject(*fields_object);
    543563}
    544564
    545565void NeuroImpl::get_neurodef(ExtValue *ret)
    546566{
    547 ret->setObject(ExtObject(&Neuro::getStaticParam(),neuro));
     567        ret->setObject(ExtObject(&Neuro::getStaticParam(), neuro));
    548568}
    549569
     
    551571{
    552572#ifndef SDK_WITHOUT_FRAMS
    553 NeuroClassExt::makeStaticObject(ret,neuroclass);
     573        NeuroClassExt::makeStaticObject(ret, neuroclass);
    554574#endif
    555575}
     
    557577NeuroImpl::~NeuroImpl()
    558578{
    559 if (fields_param)
    560         {
    561         delete fields_param;
    562         delete fields_object;
    563         }
    564 }
     579        if (fields_param)
     580        {
     581                delete fields_param;
     582                delete fields_object;
     583        }
     584}
  • cpp/frams/param/multiparamload.cpp

    r535 r720  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    1010void MultiParamLoader::init()
    1111{
    12 file=0; ownfile=0;
    13 status=0;
    14 reset();
     12        file = 0; ownfile = 0;
     13        status = 0;
     14        reset();
    1515}
    1616
    1717void MultiParamLoader::reset()
    1818{
    19 status=0;
    20 breakcond=OnError;
    21 aborting=false;
    22 emptyparam.setParamTab(empty_paramtab);
    23 linenum=0;
     19        status = 0;
     20        breakcond = OnError;
     21        aborting = false;
     22        emptyparam.setParamTab(empty_paramtab);
     23        linenum = 0;
    2424}
    2525
    2626int MultiParamLoader::findObject(const ExtObject &o)
    2727{
    28 for(int i=0;i<objects.size();i++)
    29         if ((*objects(i))==o)
    30                 return i;
    31 return -1;
     28        for (int i = 0; i < objects.size(); i++)
     29                if ((*objects(i)) == o)
     30                        return i;
     31        return -1;
    3232}
    3333
    3434void MultiParamLoader::removeObject(const ExtObject &o)
    3535{
    36 int i=findObject(o);
    37 if (i>=0)
    38         {
    39         delete objects(i);
    40         objects-=i;
     36        int i = findObject(o);
     37        if (i >= 0)
     38        {
     39                delete objects(i);
     40                objects -= i;
    4141        }
    4242}
     
    4444void MultiParamLoader::clearObjects()
    4545{
    46 FOREACH(ExtObject*,o,objects)
    47         delete o;
    48 objects.clear();
     46        FOREACH(ExtObject*, o, objects)
     47                delete o;
     48        objects.clear();
    4949}
    5050
    5151void MultiParamLoader::load()
    5252{
    53 clearstack();
    54 if (!file)
    55         {
    56         lasterror="can't open file";
    57         status=OnError;
    58         return;
    59         }
    60 status=Loading;
    61 aborting=false;
     53        clearstack();
     54        if (!file)
     55        {
     56                lasterror = "can't open file";
     57                status = OnError;
     58                return;
     59        }
     60        status = Loading;
     61        aborting = false;
    6262}
    6363
    6464void MultiParamLoader::abort()
    6565{
    66 if (file && ownfile)
    67         {
    68         delete file;
    69         file=0;
    70         }
    71 clearstack();
    72 status=Finished;
    73 aborting=true;
     66        if (file && ownfile)
     67        {
     68                delete file;
     69                file = 0;
     70        }
     71        clearstack();
     72        status = Finished;
     73        aborting = true;
    7474}
    7575
    7676void MultiParamLoader::load(VirtFILE *f)
    7777{
    78 abort();
    79 ownfile=0;
    80 file=f;
    81 load();
     78        abort();
     79        ownfile = 0;
     80        file = f;
     81        load();
    8282}
    8383
    8484void MultiParamLoader::load(const char* filename)
    8585{
    86 abort();
    87 ownfile=1;
    88 file=Vfopen(filename,FOPEN_READ_BINARY);
    89 load();
     86        abort();
     87        ownfile = 1;
     88        file = Vfopen(filename, FOPEN_READ_BINARY);
     89        load();
    9090}
    9191
    9292int MultiParamLoader::go()
    9393{
    94 SString buf;
    95 if (status==OnError) return status;
    96 int unexpected_line = 0;
    97 while (!finished())
    98         {
    99         if ((status==BeforeObject) || ((status==BeforeUnknown) && !lastobject.isEmpty()))
    100                 {
    101                 Param tmp_param;
    102                 ParamInterface *pi=lastobject.getParamInterface(tmp_param);
    103                 pi->load(file,true,&aborting,&linenum);
    104                 if ((status!=Finished) && maybeBreak(AfterObject))
    105                         break;
    106                 unexpected_line = 0;
    107                 continue;
    108                 }
    109         else if (status==BeforeUnknown)
    110                 {
    111                 logPrintf("MultiParamLoader","go",LOG_WARN,"Skipping object '%s'",lastunknown.c_str());
    112                 loadObjectNow(&emptyparam,false);
    113                 continue;
    114                 }
    115         if (!loadSStringLine(file,buf))
    116                 {
    117                 unexpected_line = 0;
    118                 if (!returnFromIncluded())
    119                         {
    120                         abort();
    121                         break;
    122                         }
    123                 else
     94        SString buf;
     95        if (status == OnError) return status;
     96        int unexpected_line = 0;
     97        while (!finished())
     98        {
     99                if ((status == BeforeObject) || ((status == BeforeUnknown) && !lastobject.isEmpty()))
     100                {
     101                        Param tmp_param;
     102                        ParamInterface *pi = lastobject.getParamInterface(tmp_param);
     103                        ParamInterface::LoadOptions opts;
     104                        opts.abortable = &aborting;
     105                        opts.warn_unknown_fields = true;
     106                        opts.linenum = &linenum;
     107                        pi->load(ParamInterface::FormatMultiLine, file, &opts);
     108                        if ((status != Finished) && maybeBreak(AfterObject))
     109                                break;
     110                        unexpected_line = 0;
    124111                        continue;
    125112                }
    126         linenum++;
    127         if (buf[0]=='#')
    128                 {
    129                 unexpected_line = 0;
    130                 if (buf.startsWith("#include"))
    131                         {
    132                         const char* t=strchr(buf.c_str(),'\"'),*t2=0;
    133                         if (t)
    134                                 t2=strchr(t+1,'\"');
    135                         if (t2)
     113                else if (status == BeforeUnknown)
     114                {
     115                        logPrintf("MultiParamLoader", "go", LOG_WARN, "Skipping object '%s'", lastunknown.c_str());
     116                        loadObjectNow(&emptyparam, false);
     117                        continue;
     118                }
     119                if (!loadSStringLine(file, buf))
     120                {
     121                        unexpected_line = 0;
     122                        if (!returnFromIncluded())
     123                        {
     124                                abort();
     125                                break;
     126                        }
     127                        else
     128                                continue;
     129                }
     130                linenum++;
     131                if (buf[0] == '#')
     132                {
     133                        unexpected_line = 0;
     134                        if (buf.startsWith("#include"))
     135                        {
     136                                const char* t = strchr(buf.c_str(), '\"'), *t2 = 0;
     137                                if (t)
     138                                        t2 = strchr(t + 1, '\"');
     139                                if (t2)
    136140                                {
    137                                 SString filename(t+1,t2-t-1);
    138                                 includeFile(filename);
     141                                        SString filename(t + 1, t2 - t - 1);
     142                                        includeFile(filename);
    139143                                }
    140                         else
     144                                else
    141145                                {
    142                                 const char* thisfilename=file->VgetPath();
    143                                 logPrintf("MultiParamLoader","go",LOG_WARN,"invalid \"%s\"%s%s",buf.c_str(),
    144                                          (thisfilename?" in ":""),(thisfilename?thisfilename:""));
     146                                        const char* thisfilename = file->VgetPath();
     147                                        logPrintf("MultiParamLoader", "go", LOG_WARN, "invalid \"%s\"%s%s", buf.c_str(),
     148                                                (thisfilename ? " in " : ""), (thisfilename ? thisfilename : ""));
    145149                                }
     150                                continue;
     151                        }
     152                        else if ((status != Finished) && maybeBreak(OnComment))
     153                        {
     154                                lastcomment = buf.substr(1);
     155                                break;
     156                        }
    146157                        continue;
    147                         }
    148                 else if ((status!=Finished) && maybeBreak(OnComment))
    149                         {
    150                         lastcomment=buf.substr(1);
    151                         break;
    152                         }
    153                 continue;
    154                 }
    155         buf=trim(buf);
    156         if (buf.len()==0)
    157                 unexpected_line = 0;
    158         else if ((buf.len()>1)&&(buf[buf.len()-1]==':'))
    159                 {
    160                 unexpected_line = 0;
    161                 lastunknown=0;
    162                 lastunknown=buf.substr(0,buf.len()-1);
    163                 lastobject.setEmpty();
    164                 FOREACH(ExtObject*,o,objects)
    165                         {
    166                         if (!strcmp(o->interfaceName(),lastunknown.c_str())) {lastobject=*o; break;}
     158                }
     159                buf = trim(buf);
     160                if (buf.len() == 0)
     161                        unexpected_line = 0;
     162                else if ((buf.len() > 1) && (buf[buf.len() - 1] == ':'))
     163                {
     164                        unexpected_line = 0;
     165                        lastunknown = 0;
     166                        lastunknown = buf.substr(0, buf.len() - 1);
     167                        lastobject.setEmpty();
     168                        FOREACH(ExtObject*, o, objects)
     169                        {
     170                                if (!strcmp(o->interfaceName(), lastunknown.c_str())) { lastobject = *o; break; }
    167171                        }
    168172                        if (!lastobject.isEmpty())
    169                                 {
     173                        {
    170174                                if (maybeBreak(BeforeObject))
    171175                                        break;
    172                                 }
     176                        }
    173177                        else
    174                                 {
     178                        {
    175179                                if (maybeBreak(BeforeUnknown))
    176180                                        break;
    177                                 }
    178                
    179                 }
     181                        }
     182
     183                }
     184                else
     185                {
     186                        switch (unexpected_line)
     187                        {
     188                        case 0:
     189                        {
     190                                const char* thisfilename = file->VgetPath();
     191                                logPrintf("MultiParamLoader", "go", LOG_WARN, "Ignored unexpected line %d%s",
     192                                        linenum,
     193                                        thisfilename ? SString::sprintf(" while reading '%s'", thisfilename).c_str() : "");
     194                        }
     195                                break;
     196
     197                        case 1:
     198                                logPrintf("MultiParamLoader", "go", LOG_WARN, "The following line(s) were also unexpected and were ignored");
     199                                break;
     200                        }
     201                        unexpected_line++;
     202                }
     203        }
     204        return status;
     205}
     206
     207bool MultiParamLoader::alreadyIncluded(const char* filename)
     208{
     209        int i;
     210        const char* t;
     211        for (i = 0; i < filestack.size(); i++)
     212        {
     213                t = filestack(i)->VgetPath();
     214                if (!t) continue;
     215                if (!strcmp(filename, t)) return true;
     216        }
     217        return false;
     218}
     219
     220void MultiParamLoader::includeFile(SString& filename)
     221{
     222        const char* thisfilename = file->VgetPath();
     223        SString newfilename;
     224        const char* t = thisfilename ? strrchr(thisfilename, PATH_SEPARATOR_CHAR) : 0;
     225
     226        if (thisfilename && t)
     227        {
     228                newfilename.append(thisfilename, t - thisfilename + 1);
     229                newfilename += filename;
     230        }
    180231        else
    181                 {
    182                 switch(unexpected_line)
    183                         {
    184                         case 0:
    185                         {
    186                         const char* thisfilename=file->VgetPath();
    187                         logPrintf("MultiParamLoader","go", LOG_WARN, "Ignored unexpected line %d%s",
    188                                   linenum,
    189                                   thisfilename ? SString::sprintf(" while reading '%s'",thisfilename).c_str():"");
    190                         }
    191                         break;
    192 
    193                         case 1:
    194                         logPrintf("MultiParamLoader","go", LOG_WARN, "The following line(s) were also unexpected and were ignored");
    195                         break;
    196                         }
    197                 unexpected_line++;
    198                 }
    199         }
    200 return status;
    201 }
    202 
    203 bool MultiParamLoader::alreadyIncluded(const char* filename)
    204 {
    205 int i;
    206 const char* t;
    207 for(i=0;i<filestack.size();i++)
    208         {
    209         t=filestack(i)->VgetPath();
    210         if (!t) continue;
    211         if (!strcmp(filename,t)) return true;
    212         }
    213 return false;
    214 }
    215 
    216 void MultiParamLoader::includeFile(SString& filename)
    217 {
    218 const char* thisfilename=file->VgetPath();
    219 SString newfilename;
    220 const char* t=thisfilename?strrchr(thisfilename,PATH_SEPARATOR_CHAR):0;
    221 
    222 if (thisfilename && t)
    223         {
    224         newfilename.append(thisfilename,t-thisfilename+1);
    225         newfilename+=filename;
    226         }
    227 else
    228         newfilename=filename;
    229 
    230 if (alreadyIncluded(newfilename.c_str()))
    231         {
    232         logPrintf("MultiParamLoader","include",LOG_WARN,"circular reference ignored (\"%s\")",
    233                     filename.c_str());
    234         return;
    235         }
    236 
    237 VirtFILE *f=Vfopen(newfilename.c_str(),FOPEN_READ_BINARY);
    238 if (!f)
    239         {
    240         logPrintf("MultiParamLoader","include",LOG_WARN,"\"%s\" not found",newfilename.c_str());
    241         }
    242 else
    243         {
    244         filestack+=file;
    245         file=f;
     232                newfilename = filename;
     233
     234        if (alreadyIncluded(newfilename.c_str()))
     235        {
     236                logPrintf("MultiParamLoader", "include", LOG_WARN, "circular reference ignored (\"%s\")",
     237                        filename.c_str());
     238                return;
     239        }
     240
     241        VirtFILE *f = Vfopen(newfilename.c_str(), FOPEN_READ_BINARY);
     242        if (!f)
     243        {
     244                logPrintf("MultiParamLoader", "include", LOG_WARN, "\"%s\" not found", newfilename.c_str());
     245        }
     246        else
     247        {
     248                filestack += file;
     249                file = f;
    246250        }
    247251}
     
    249253VirtFILE* MultiParamLoader::popstack()
    250254{
    251 if (!filestack.size()) return 0;
    252 VirtFILE* f=filestack(filestack.size()-1);
    253 filestack.remove(filestack.size()-1);
    254 return f;
     255        if (!filestack.size()) return 0;
     256        VirtFILE* f = filestack(filestack.size() - 1);
     257        filestack.remove(filestack.size() - 1);
     258        return f;
    255259}
    256260
    257261void MultiParamLoader::clearstack()
    258262{
    259 VirtFILE *f;
    260 while(f=popstack()) delete f;
     263        VirtFILE *f;
     264        while (f = popstack()) delete f;
    261265}
    262266
    263267bool MultiParamLoader::returnFromIncluded()
    264268{
    265 if (!filestack.size()) return false;
    266 if (file) delete file;
    267 file=popstack();
    268 return true;
    269 }
    270 
    271 int MultiParamLoader::loadObjectNow(const ExtObject& o,bool warn_unknown_fields)
    272 {
    273 Param tmp_param;
    274 ParamInterface *pi=o.getParamInterface(tmp_param);
    275 pi->load(file,warn_unknown_fields,&aborting,&linenum);
    276 status=AfterObject;
    277 return 0;
     269        if (!filestack.size()) return false;
     270        if (file) delete file;
     271        file = popstack();
     272        return true;
     273}
     274
     275int MultiParamLoader::loadObjectNow(const ExtObject& o, bool warn_unknown_fields)
     276{
     277        Param tmp_param;
     278        ParamInterface *pi = o.getParamInterface(tmp_param);
     279        ParamInterface::LoadOptions opts;
     280        opts.abortable = &aborting;
     281        opts.warn_unknown_fields = warn_unknown_fields;
     282        opts.linenum = &linenum;
     283        pi->load(ParamInterface::FormatMultiLine, file, &opts);
     284        status = AfterObject;
     285        return 0;
    278286}
    279287
    280288int MultiParamLoader::run()
    281289{
    282 int stat;
    283 breakOn(OnError);
    284 while(stat=go())
    285         if (stat==OnError)
     290        int stat;
     291        breakOn(OnError);
     292        while (stat = go())
     293                if (stat == OnError)
    286294                {
    287295                abort();
    288296                return 0;
    289297                }
    290 return 1;
     298        return 1;
    291299}
    292300
    293301SString MultiParamLoader::currentFilePathForErrorMessage()
    294302{
    295 const char* filename=getFile()->VgetPath();
    296 if (filename)
    297         return SString::sprintf(" in '%s'",filename);
    298 return SString::empty();
    299 }
     303        const char* filename = getFile()->VgetPath();
     304        if (filename)
     305                return SString::sprintf(" in '%s'", filename);
     306        return SString::empty();
     307}
  • cpp/frams/param/param.cpp

    r704 r720  
    1010#include "common/log.h"
    1111#include <frams/util/sstringutils.h>
     12#include <common/virtfile/stringfile.h>
    1213
    1314//#define SAVE_ALL_NAMES
     
    356357}
    357358
    358 void SimpleAbstractParam::save2(SString& f, void *defdata, bool addcr, bool all_names)
     359void SimpleAbstractParam::saveSingleLine(SString& f, void *defdata, bool addcr, bool all_names)
    359360{ // defdata!=NULL -> does not save default values
    360361        const char *p;
     
    421422}
    422423
    423 int ParamInterface::load(VirtFILE* f, bool warn_unknown_fields, bool *abortable, int *linenum)
     424int ParamInterface::load(FileFormat format, VirtFILE* f, LoadOptions *options)
     425{
     426        LoadOptions default_options;
     427        if (options == NULL)
     428                options = &default_options;
     429        switch (format)
     430        {
     431        case FormatMultiLine:
     432                return loadMultiLine(f, *options);
     433
     434        case FormatSingleLine:
     435        {
     436                StringFILE *sf = dynamic_cast<StringFILE*>(f);
     437                SString s;
     438                if (sf)
     439                {
     440                        s = sf->getString().c_str();
     441                        options->offset += sf->Vtell();
     442                }
     443                else
     444                {
     445                        if (!loadSStringLine(f, s))
     446                                return -1;
     447                }
     448                return loadSingleLine(s, *options);
     449        }
     450        }
     451        return -1;
     452}
     453
     454int ParamInterface::load(FileFormat format, const SString &s, LoadOptions *options)
     455{
     456        LoadOptions default_options;
     457        if (options == NULL)
     458                options = &default_options;
     459        switch (format)
     460        {
     461        case FormatMultiLine:
     462        {
     463                string std_string(s.c_str());
     464                StringFILE f(std_string);
     465                return loadMultiLine(&f, *options);
     466        }
     467
     468        case FormatSingleLine:
     469                return loadSingleLine(s, *options);
     470        }
     471        return -1;
     472}
     473
     474int ParamInterface::loadMultiLine(VirtFILE* f, LoadOptions &options)
    424475{
    425476        SString buf;
     
    434485        if ((i = findId("beforeLoad")) >= 0)
    435486                call(i, NULL, NULL);
    436         while (((!abortable) || (!*abortable)) && loadSStringLine(f, buf))
    437         {
    438                 if (linenum) (*linenum)++;
     487        while (((!options.abortable) || (!*options.abortable)) && loadSStringLine(f, buf))
     488        {
     489                if (options.linenum) (*options.linenum)++;
    439490                const char* t = buf.c_str();
    440491                p0 = t; while (isblank(*p0)) p0++;
     
    448499                        case 0:
    449500                                logPrintf("ParamInterface", "load", LOG_WARN, "Ignored unexpected line %s while reading object '%s'",
    450                                         linenum ?
    451                                         SString::sprintf("%d", *linenum).c_str()
     501                                        options.linenum ?
     502                                        SString::sprintf("%d", *options.linenum).c_str()
    452503                                        : SString::sprintf("'%s'", p0).c_str(),
    453504                                        getName());
     
    472523                                {
    473524                                        fileinfo = SString::sprintf(" while reading from '%s'", fname);
    474                                         if (linenum)
    475                                                 fileinfo += SString::sprintf(" (line %d)", *linenum);
     525                                        if (options.linenum)
     526                                                fileinfo += SString::sprintf(" (line %d)", *options.linenum);
    476527                                }
    477528                                logPrintf("ParamInterface", "load", LOG_WARN, "Multiple '%s.%s' fields found%s", getName(), id(i), fileinfo.c_str());
     
    496547                                        int ch; while ((ch = f->Vgetc()) != EOF) if (ch == '\n') break;
    497548                                        unquoteTilde(s);
    498                                         if (linenum && (flags(i)&PARAM_LINECOMMENT))
    499                                                 s = SString::sprintf("@file %s\n@line %d\n", f->VgetPath(), *linenum + 1) + s;
     549                                        if (options.linenum && (flags(i)&PARAM_LINECOMMENT))
     550                                                s = SString::sprintf("@file %s\n@line %d\n", f->VgetPath(), *options.linenum + 1) + s;
    500551                                        set(i, s.c_str());
    501                                         if (linenum)
    502                                                 (*linenum) += lfcount;
     552                                        if (options.linenum)
     553                                                (*options.linenum) += lfcount;
    503554                                }
    504555                                else
     
    510561                        }
    511562                }
    512                 else if (warn_unknown_fields)
     563                else if (options.warn_unknown_fields)
    513564                {
    514565                        SString name(p0, p_len);
     
    521572                        if (!readUntilTilde(f, s))
    522573                                closingTildeError(this, f, -1);
    523                         if (linenum)
     574                        if (options.linenum)
    524575                        {
    525576                                const char* tmp = s.c_str();
     
    530581                                        lfcount++; tmp++;
    531582                                        }
    532                                 (*linenum) += lfcount;
     583                                (*options.linenum) += lfcount;
    533584                        }
    534585                        int ch; while ((ch = f->Vgetc()) != EOF) if (ch == '\n') break;
     
    705756{
    706757        const char *t;
    707         if (((*(t = type(i))) == 'd') && (strchr(t, '~')!=NULL)) //type is int and contains enum labels
     758        if (((*(t = type(i))) == 'd') && (strchr(t, '~') != NULL)) //type is int and contains enum labels
    708759        {
    709760                paInt mn, mx, def;
     
    11311182}
    11321183
    1133 int ParamInterface::load2(const SString &s, int &poz)
     1184int ParamInterface::loadSingleLine(const SString &s, LoadOptions &options)
    11341185{
    11351186        int i; // the index number of the parameter
     
    11451196        SString tmpvalue;
    11461197        bool parse_failed = false;
    1147         if (poz >= s.len()) return fields_loaded;
    1148         t = s.c_str() + poz;
    1149 
    1150         lin = getline(s, poz, len); // all fields must be encoded in a single line
     1198        if (options.offset >= s.len()) return fields_loaded;
     1199        t = s.c_str() + options.offset;
     1200
     1201        lin = getline(s, options.offset, len); // all fields must be encoded in a single line
    11511202        if (!len) return fields_loaded; // empty line = end
    11521203        i = 0;
     
    12411292#endif
    12421293        }
    1243         return fields_loaded | (parse_failed ? LOAD2_PARSE_FAILED : 0);
     1294        if (parse_failed) options.parse_failed = true;
     1295        return fields_loaded;
    12441296}
    12451297
  • cpp/frams/param/param.h

    r650 r720  
    2828#define PARAM_NOSTATIC  256     //< (FramScript) don't access this member in a static object (ClassName.field)
    2929#define PARAM_CONST     512     //< (FramScript) constant value
    30 #define PARAM_CANOMITNAME 1024  //< affects Param::save2()/load2() - for example one-liners in f0 genetic encoding
     30#define PARAM_CANOMITNAME 1024  //< affects Param::saveSingleLine()/loadSingleLine() - for example one-liners in f0 genetic encoding
    3131#define PARAM_DONTLOAD    2048  //< Param::load() skips this field
    3232#define PARAM_NOISOLATION 4096  //< don't use proxy object in master/slave interactions
     
    170170        void quickCopyFrom(ParamInterface *src);
    171171
     172        enum FileFormat { FormatMultiLine, FormatSingleLine }; // FormatJSON in the future?
     173        struct LoadOptions {
     174                bool warn_unknown_fields; bool *abortable; int *linenum; int offset; bool parse_failed;
     175                LoadOptions() : warn_unknown_fields(false), abortable(NULL), linenum(NULL), offset(0), parse_failed(false) {}
     176        };
     177
    172178        int save(VirtFILE*, const char* altname = NULL, bool force = 0);
    173179        int saveprop(VirtFILE*, int i, const char* p, bool force = 0);
    174         int load(VirtFILE*, bool warn_unknown_fields = true, bool *abortable = NULL, int *linenum = NULL);///< @return the number of fields loaded
    175         int load2(const SString &, int &);///< @return the number of fields loaded (or'ed with LOAD2_PARSE_FAILED if a parsing error was detected)
     180
     181        int load(FileFormat format, VirtFILE*, LoadOptions *load_options = NULL);///< @return the number of fields loaded
     182        int load(FileFormat format, const SString &, LoadOptions *load_options = NULL);///< @return the number of fields loaded
     183protected:
     184        int loadMultiLine(VirtFILE*, LoadOptions &options);///< @return the number of fields loaded
     185        int loadSingleLine(const SString &, LoadOptions &options);///< @return the number of fields loaded
     186public:
    176187
    177188        static const char* SERIALIZATION_PREFIX;
    178         static const int LOAD2_PARSE_FAILED = (1 << 30); ///< this bit is set in return value from load2 if a parse error was detected while loading. usage: if (load2(...) & LOAD2_PARSE_FAILED) ...
    179         static const int LOAD2_IGNORE_PARSE_FAILED = (~LOAD2_PARSE_FAILED); ///< bitmask to be used if the parsing error is to be ignored. usage: int number_of_loaded_fields=load2(...) & LOAD2_IGNORE_PARSE_FAILED;
    180189
    181190        static bool isValidTypeDescription(const char* t);
     
    299308
    300309        int isequal(int i, void* defdata);
    301         void save2(SString&, void *defdata, bool addcr = true, bool all_names = true);
     310        void saveSingleLine(SString&, void *defdata, bool addcr = true, bool all_names = true);
    302311
    303312        virtual void setDefault();
  • cpp/frams/param/syntparam.cpp

    r286 r720  
    88#include <math.h>
    99
    10 SyntParam::SyntParam(ParamEntry *init_pe,SString* autostr,bool handle_defaults_when_saving)
     10SyntParam::SyntParam(ParamEntry *init_pe, SString* autostr, bool handle_defaults_when_saving)
    1111        :autostring(autostr)
    1212{
    13 Param::setParamTab(init_pe);
    14 pe=ParamObject::makeParamTab(this);
    15 Param::setParamTab(pe);
    16 if (handle_defaults_when_saving)
     13        Param::setParamTab(init_pe);
     14        pe = ParamObject::makeParamTab(this);
     15        Param::setParamTab(pe);
     16        if (handle_defaults_when_saving)
    1717        {
    18         def_obj=ParamObject::makeObject(pe);
    19         Param::select(def_obj);
     18                def_obj = ParamObject::makeObject(pe);
     19                Param::select(def_obj);
     20                Param::setDefault();
     21        }
     22        else
     23                def_obj = NULL;
     24        obj = ParamObject::makeObject(pe);
     25        Param::select(obj);
    2026        Param::setDefault();
    21         }
    22 else
    23         def_obj=NULL;
    24 obj=ParamObject::makeObject(pe);
    25 Param::select(obj);
    26 Param::setDefault();
    27 revert();
     27        revert();
    2828}
    2929
    3030SyntParam::SyntParam(const SyntParam& src)
    31         :Param(),autostring(src.autostring)
     31        :Param(), autostring(src.autostring)
    3232{
    33 Param::setParamTab(src.pe);
    34 pe=ParamObject::makeParamTab(this);
    35 Param::setParamTab(pe);
    36 obj=ParamObject::dupObject(src.obj);
    37 def_obj=src.def_obj ? ParamObject::dupObject(src.def_obj) : NULL;
    38 Param::select(obj);
     33        Param::setParamTab(src.pe);
     34        pe = ParamObject::makeParamTab(this);
     35        Param::setParamTab(pe);
     36        obj = ParamObject::dupObject(src.obj);
     37        def_obj = src.def_obj ? ParamObject::dupObject(src.def_obj) : NULL;
     38        Param::select(obj);
    3939}
    4040
    4141SyntParam::~SyntParam()
    4242{
    43 update();
    44 ParamObject::freeParamTab(pe);
    45 ParamObject::freeObject(obj);
    46 ParamObject::freeObject(def_obj);
     43        update();
     44        ParamObject::freeParamTab(pe);
     45        ParamObject::freeObject(obj);
     46        ParamObject::freeObject(def_obj);
    4747}
    4848
    4949void SyntParam::update(SString *s)
    5050{
    51 if (!s) s=autostring;
    52 if (s) {*s=""; Param::save2(*s,def_obj,0);}
     51        if (!s) s = autostring;
     52        if (s) { *s = ""; Param::saveSingleLine(*s, def_obj, 0); }
    5353}
    5454
    5555void SyntParam::revert(SString *s)
    5656{
    57 if (!s) s=autostring;
    58 if (s)  {
    59         int p=0;
    60         Param::load2(*s,p);
     57        if (!s) s = autostring;
     58        if (s)  {
     59                Param::load(ParamInterface::FormatSingleLine, *s);
    6160        }
    6261}
    63 
    64 
    65 
    66 
    67 
Note: See TracChangeset for help on using the changeset viewer.