source: cpp/frams/param/multiparamload.cpp @ 273

Last change on this file since 273 was 268, checked in by Maciej Komosinski, 9 years ago

ParamInterface::load warns on unknown fields and skips comments

  • Property svn:eol-style set to native
File size: 4.6 KB
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 1999-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include "multiparamload.h"
6#include <frams/util/sstringutils.h>
7#include "common/framsg.h"
8#include <ctype.h>
9
10void MultiParamLoader::init()
11{
12file=0; ownfile=0;
13status=0;
14reset();
15}
16
17void MultiParamLoader::reset()
18{
19status=0;
20breakcond=OnError;
21emptyparam.setParamTab(empty_paramtab);
22}
23
24int MultiParamLoader::findObject(const ExtObject &o)
25{
26for(int i=0;i<objects.size();i++)
27        if ((*objects(i))==o)
28                return i;
29return -1;
30}
31
32void MultiParamLoader::removeObject(const ExtObject &o)
33{
34int i=findObject(o);
35if (i>=0)
36        {
37        delete objects(i);
38        objects-=i;
39        }
40}
41
42void MultiParamLoader::clearObjects()
43{
44FOREACH(ExtObject*,o,objects)
45        delete o;
46objects.clear();
47}
48
49void MultiParamLoader::load()
50{
51clearstack();
52if (!file)
53        {
54        lasterror="can't open file";
55        status=OnError;
56        return;
57        }
58status=Loading;
59}
60
61void MultiParamLoader::abort()
62{
63if (file && ownfile)
64        {
65        fclose(file);
66        file=0;
67        }
68clearstack();
69status=Finished;
70}
71
72void MultiParamLoader::load(VirtFILE *f)
73{
74abort();
75ownfile=0;
76file=f;
77load();
78}
79
80void MultiParamLoader::load(const char* filename)
81{
82abort();
83ownfile=1;
84file=Vfopen(filename,FOPEN_READ_BINARY);
85load();
86}
87
88int MultiParamLoader::go()
89{
90SString buf;
91if (status==OnError) return status;
92while (!finished())
93        {
94        if ((status==BeforeObject) || ((status==BeforeUnknown) && !lastobject.isEmpty()))
95                {
96                Param tmp_param;
97                ParamInterface *pi=lastobject.getParamInterface(tmp_param);
98                pi->load(file);
99                if ((status!=Finished) && maybeBreak(AfterObject))
100                        break;
101                continue;
102                }
103        else if (status==BeforeUnknown)
104                {
105                FMprintf("MultiParamLoader","go",FMLV_WARN,"Skipping object '%s'",(const char*)lastunknown);
106                loadObjectNow(&emptyparam,false);
107                continue;
108                }
109        if (!loadSStringLine(file,buf))
110                {
111                if (!returnFromIncluded())
112                        {
113                        abort();
114                        break;
115                        }
116                else
117                        continue;
118                }
119        if (buf[0]=='#')
120                {
121                if (buf.startsWith("#include"))
122                        {
123                        const char* t=strchr((const char*)buf,'\"'),*t2=0;
124                        if (t)
125                                t2=strchr(t+1,'\"');
126                        if (t2)
127                                {
128                                SString filename(t+1,t2-t-1);
129                                includeFile(filename);
130                                }
131                        else
132                                {
133                                const char* thisfilename=file->VgetPath();
134                                FMprintf("MultiParamLoader","go",FMLV_WARN,"invalid \"%s\"%s%s",(const char*)buf,
135                                         (thisfilename?" in ":""),(thisfilename?thisfilename:""));
136                                }
137                        continue;
138                        }
139                else if ((status!=Finished) && maybeBreak(OnComment))
140                        {
141                        lastcomment=buf.substr(1);
142                        break;
143                        }
144                continue;
145                }
146        buf=trim(buf);
147        if ((buf.len()>1)&&(buf[buf.len()-1]==':'))
148                {
149                lastunknown=0;
150                lastunknown=buf.substr(0,buf.len()-1);
151                lastobject.setEmpty();
152                FOREACH(ExtObject*,o,objects)
153                        {
154                        if (!strcmp(o->interfaceName(),lastunknown)) {lastobject=*o; break;}
155                        }
156                        if (!lastobject.isEmpty())
157                                {
158                                if (maybeBreak(BeforeObject))
159                                        break;
160                                }
161                        else
162                                {
163                                if (maybeBreak(BeforeUnknown))
164                                        break;
165                                }
166               
167                }
168        }
169return status;
170}
171
172bool MultiParamLoader::alreadyIncluded(const char* filename)
173{
174int i;
175const char* t;
176for(i=0;i<filestack.size();i++)
177        {
178        t=filestack(i)->VgetPath();
179        if (!t) continue;
180        if (!strcmp(filename,t)) return true;
181        }
182return false;
183}
184
185void MultiParamLoader::includeFile(SString& filename)
186{
187const char* thisfilename=file->VgetPath();
188SString newfilename;
189const char* t=thisfilename?strrchr(thisfilename,PATH_SEPARATOR_CHAR):0;
190
191if (thisfilename && t)
192        {
193        newfilename.append(thisfilename,t-thisfilename+1);
194        newfilename+=filename;
195        }
196else
197        newfilename=filename;
198
199if (alreadyIncluded(newfilename))
200        {
201        FMprintf("MultiParamLoader","include",FMLV_WARN,"circular reference ignored (\"%s\")",
202                    (const char*)filename);
203        return;
204        }
205
206VirtFILE *f=Vfopen(newfilename,FOPEN_READ_BINARY);
207if (!f)
208        {
209        FMprintf("MultiParamLoader","include",FMLV_WARN,"\"%s\" not found",(const char*)newfilename);
210        }
211else
212        {
213        filestack+=file;
214        file=f;
215        }
216}
217
218VirtFILE* MultiParamLoader::popstack()
219{
220if (!filestack.size()) return 0;
221VirtFILE* f=filestack(filestack.size()-1);
222filestack.remove(filestack.size()-1);
223return f;
224}
225
226void MultiParamLoader::clearstack()
227{
228VirtFILE *f;
229while(f=popstack()) fclose(f);
230}
231
232bool MultiParamLoader::returnFromIncluded()
233{
234if (!filestack.size()) return false;
235if (file) fclose(file);
236file=popstack();
237return true;
238}
239
240int MultiParamLoader::loadObjectNow(const ExtObject& o,bool warn_unknown_fields)
241{
242Param tmp_param;
243ParamInterface *pi=o.getParamInterface(tmp_param);
244pi->load(file,warn_unknown_fields);
245status=AfterObject;
246return 0;
247}
248
249int MultiParamLoader::run()
250{
251int stat;
252breakOn(OnError);
253while(stat=go())
254        if (stat==OnError)
255                {
256                abort();
257                return 0;
258                }
259return 1;
260}
Note: See TracBrowser for help on using the repository browser.