1 /***************************************************************************
2 datendatei.cpp - description
3 -------------------
4 begin : Sun Jul 1 2001
5 copyright : (C) 2001 by Immi
6 email : cuyo@karimmi.de
7
8 Modified 2002,2005,2006,2010,2011,2014 by the cuyo developers
9
10 ***************************************************************************/
11
12 /***************************************************************************
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 ***************************************************************************/
20
21 #include "cuyointl.h"
22
23 #include "datendatei.h"
24 #include "knoten.h"
25
26
27 /** In parser.yy definiert. */
28 void parse(const Str & name, DefKnoten * erg);
29
30
DatenDatei()31 DatenDatei::DatenDatei():
32 mDaten(new DefKnoten()) /* Leerer Knoten ohne Vater */
33 {
34 /* Das Squirrel sitzt am Anfang ganz oben */
35 initSquirrel();
36 }
37
~DatenDatei()38 DatenDatei::~DatenDatei() {
39 delete mDaten;
40 }
41
42
43
44
45 /** Entfernt alles, was bisher geladen wurde. Aufrufen, wenn man alles
46 neu laden m�chte. */
leeren()47 void DatenDatei::leeren() {
48 delete mDaten;
49 mDaten = new DefKnoten();
50
51 /* Squirrel neu setzen. (Sonst stimmt der Pointer nicht mehr.) */
52 initSquirrel();
53 }
54
55
56
57 /** L�dt die angegebene Datei. (Kann mehrmals aufgerufen werden, um
58 mehrere Dateien gleichzeitig zu laden.) */
laden(const Str & name)59 void DatenDatei::laden(const Str & name) {
60 parse(name, mDaten);
61 }
62
63
64
65
66
67
68 /***** Squirrel-Methoden *****/
69
70
71 /** Setzt das Squirrel an die Wurzel des Baums. */
initSquirrel()72 void DatenDatei::initSquirrel() {
73 mSquirrelPosString = "";
74 mSquirrelKnoten = mDaten;
75 mSquirrelCodeKnoten = mDaten;
76 }
77
78
79 /** Liefert true, wenn das Squirrel sich an einer Stelle des Baums
80 befindet, die existiert. */
existiertSquirrelKnoten() const81 bool DatenDatei::existiertSquirrelKnoten() const {
82 return mSquirrelKnoten;
83 }
84
85
86 /** Liefert die Position des Squirrels als String. */
getSquirrelPosString() const87 Str DatenDatei::getSquirrelPosString() const {
88 return mSquirrelPosString;
89 }
90
91
92 /** Das Eichh�rnchen klettert weiter weg von der Wurzel. Wird von
93 DatenDateiPush benutzt. */
kletterWeiter(const Str & na,const Version & version)94 void DatenDatei::kletterWeiter(const Str & na, const Version & version) {
95
96 /* Neuen Abschnittnamen bauen */
97 if (!mSquirrelPosString.isEmpty())
98 mSquirrelPosString += '/';
99 mSquirrelPosString += na;
100
101 /* Knoten zum neuen Abschnitt suchen */
102 mSquirrelKnoten = (DefKnoten *) getEintragKnoten(na, version, true,
103 type_DefKnoten);
104
105 /* Wenn dieser Unterabschnitt existiert, dann auch die Codeen
106 dort suchen. */
107 if (mSquirrelKnoten)
108 mSquirrelCodeKnoten = mSquirrelKnoten;
109 }
110
111
112
113 /** Liefert die Squirrel-Position zur�ck (und zwar
114 mSquirrelCodeKnoten; siehe dort). */
getSquirrelPos() const115 DefKnoten * DatenDatei::getSquirrelPos() const {
116 return mSquirrelCodeKnoten;
117 }
118
119
120
121 /***** Eintrag-Methoden *****/
122
123
124
125
126 /** Liefert den angegebenen Eintrag beim Squirrel.
127 Pr�ft, ob der Typ der gew�nschte ist.
128 Liefert 0, wenn's den Eintrag nicht gibt, aber defaultVorhanden.
129 Throwt bei sonstigem Fehler. */
getEintragKnoten(const Str & schluessel,const Version & version,bool defaultVorhanden,int typ) const130 Knoten * DatenDatei::getEintragKnoten(const Str & schluessel,
131 const Version & version,
132 bool defaultVorhanden, int typ) const {
133
134 if (!mSquirrelKnoten) {
135 if (defaultVorhanden)
136 return 0;
137 else throw Fehler("%s required but not defined",schluessel.data());
138 }
139
140 Knoten * ret = mSquirrelKnoten->getKind(schluessel,version,
141 defaultVorhanden);
142
143 if (ret)
144 if (typ != type_egal && ret->type() != typ)
145 throw Fehler("Wrong type on the righthand side of %s%s=",
146 schluessel.data(), version.toString().data());
147
148 return ret;
149 }
150
151
152
153
154 /** Gibt's den Eintrag? */
hatEintrag(const Str & schluessel) const155 bool DatenDatei::hatEintrag(const Str & schluessel) const {
156 return mSquirrelKnoten->enthaelt(schluessel);
157 }
158
159 /** Liefert den Eintrag, wenn er existiert, sonst null, wenn
160 defaultVorhanden, sonst wird gethrowt. */
getEintrag(const Str & schluessel,const Version & version,bool defaultVorhanden,int typ) const161 const DatenKnoten * DatenDatei::getEintrag(const Str & schluessel,
162 const Version & version,
163 bool defaultVorhanden,
164 int typ
165 /*= type_EgalDatum*/) const {
166 Knoten * e = getEintragKnoten(schluessel, version, defaultVorhanden,
167 type_ListenKnoten);
168 if (e)
169 return ((ListenKnoten *) e)->getDatum(0)->assert_datatype(typ);
170 else
171 return 0;
172 }
173
174 /** Dito f�r W�rter. Default f�r def ist "". */
getWortEintragOhneDefault(const Str & schluessel,const Version & version) const175 Str DatenDatei::getWortEintragOhneDefault(const Str & schluessel,
176 const Version & version) const {
177 return getEintrag(schluessel,version,false,type_WortDatum)->getWort();
178 }
179
getWortEintragMitDefault(const Str & schluessel,const Version & version,Str def) const180 Str DatenDatei::getWortEintragMitDefault(const Str & schluessel,
181 const Version & version,
182 Str def /*= Str()*/) const {
183 const DatenKnoten * e = getEintrag(schluessel,version,true,type_WortDatum);
184 if (e)
185 return e->getWort();
186 else
187 return def;
188 }
189
190 /** Liefert den Eintrag als Zahl. */
getZahlEintragOhneDefault(const Str & schluessel,const Version & version) const191 int DatenDatei::getZahlEintragOhneDefault(const Str & schluessel,
192 const Version & version) const {
193 return getEintrag(schluessel,version,false,type_ZahlDatum)->getZahl(0);
194 }
195
getZahlEintragMitDefault(const Str & schluessel,const Version & version,int def) const196 int DatenDatei::getZahlEintragMitDefault(const Str & schluessel,
197 const Version & version,
198 int def /*= 0*/) const {
199 const DatenKnoten * e = getEintrag(schluessel,version,true,type_ZahlDatum);
200 if (e) {
201 return e->getZahl(0);
202 } else
203 return def;
204 }
205
intZuBool(int i)206 bool intZuBool(int i) {
207 switch (i) {
208 case 0: return false;
209 case 1: return true;
210 default: throw Fehler("0 or 1 expected, got %d.",i);
211 }
212 }
213
getBoolEintragOhneDefault(const Str & schluessel,const Version & version) const214 bool DatenDatei::getBoolEintragOhneDefault(const Str & schluessel,
215 const Version & version) const {
216 return intZuBool(getZahlEintragOhneDefault(schluessel,version));
217 }
218
219
getBoolEintragMitDefault(const Str & schluessel,const Version & version,bool def) const220 bool DatenDatei::getBoolEintragMitDefault(const Str & schluessel,
221 const Version & version,
222 bool def) const {
223 return intZuBool(getZahlEintragMitDefault(schluessel,version,(def ? 1 : 0)));
224 }
225
226
227 /** Liefert den Eintrag als Farbe. */
getFarbEintragOhneDefault(const Str & schluessel,const Version & version) const228 Color DatenDatei::getFarbEintragOhneDefault(const Str & schluessel,
229 const Version & version) const {
230 ListenKnoten * e = getListenEintrag(schluessel,version,false);
231 if (e->getLaenge() != 3)
232 throw Fehler("%s","Color (r,g,b) expected");
233
234 return Color(e->getDatum(0)->assert_datatype(type_ZahlDatum)->getZahl(),
235 e->getDatum(1)->assert_datatype(type_ZahlDatum)->getZahl(),
236 e->getDatum(2)->assert_datatype(type_ZahlDatum)->getZahl());
237 }
238
getFarbEintragMitDefault(const Str & schluessel,const Version & version,const Color & def) const239 Color DatenDatei::getFarbEintragMitDefault(const Str & schluessel,
240 const Version & version,
241 const Color & def /*= black*/) const {
242 ListenKnoten * e = getListenEintrag(schluessel,version,true);
243
244 if (e == 0) return def;
245
246 if (e->getLaenge() != 3)
247 throw Fehler("%s","Color (r,g,b) expected");
248
249 return Color(e->getDatum(0)->assert_datatype(type_ZahlDatum)->getZahl(),
250 e->getDatum(1)->assert_datatype(type_ZahlDatum)->getZahl(),
251 e->getDatum(2)->assert_datatype(type_ZahlDatum)->getZahl());
252 }
253
254 /** Liefert einen Eintrag als Knoten */
getListenEintrag(const Str & schluessel,const Version & version,bool defaultVorhanden) const255 ListenKnoten * DatenDatei::getListenEintrag(const Str & schluessel,
256 const Version & version,
257 bool defaultVorhanden) const {
258 Knoten * e = getEintragKnoten(schluessel, version, defaultVorhanden,
259 type_ListenKnoten);
260 if (e) {
261 /* Fr�her freute sich der Aufrufer dar�ber, da� er wusste, da� die
262 Liste nur W�rter enth�lt. Es k�nnten noch Probleme existieren */
263 ListenKnoten * ret = (ListenKnoten*) e;
264 for (int i = 0; i < ret->getLaenge(); i++)
265 if (ret->getKind(i)->type() != type_DatenKnoten)
266 throw Fehler("%s","List of atomic data expected");
267 return ret;
268 } else
269 return 0;
270 }
271
272
273
274 /** Sucht einen Code beim Squirrel oder n�her an der Wurzel.
275 Beh�lt den Besitz am Code/an der VarDefinition.
276 Throwt bei nicht-existenz. */
getCode(const Str & name,const Version & version,bool defaultVorhanden)277 Code * DatenDatei::getCode(const Str & name,
278 const Version & version, bool defaultVorhanden) {
279
280 /* Einen Codeabschnitt sollte es eigentlich immer geben - zumindest
281 wenn die Datei auf ist. Aber die sollte immer auf sein. */
282 CASSERT(mSquirrelCodeKnoten);
283
284 return (Code *) mSquirrelCodeKnoten->getDefinition(namespace_prozedur,
285 name, version,
286 defaultVorhanden);
287 }
288
getVarDef(const Str & name,const Version & version,bool defaultVorhanden)289 VarDefinition * DatenDatei::getVarDef(const Str & name,
290 const Version & version,
291 bool defaultVorhanden) {
292
293 /* Einen Codeabschnitt sollte es eigentlich immer geben - zumindest
294 wenn die Datei auf ist. Aber die sollte immer auf sein. */
295 CASSERT(mSquirrelCodeKnoten);
296
297 return (VarDefinition *) mSquirrelCodeKnoten->getDefinition(
298 namespace_variable, name, version, defaultVorhanden);
299 }
300
301
302
303
304
305 /***************************************************************************/
306
307
308
309
310
DatenDateiPush(DatenDatei & c,const Str & name,const Version & version,bool verlange)311 DatenDateiPush::DatenDateiPush(DatenDatei & c,
312 const Str & name, const Version & version,
313 bool verlange /*= true*/): mConf(c) {
314 mMerkName = mConf.mSquirrelPosString;
315 mMerkKnoten = mConf.mSquirrelKnoten;
316 mMerkCodeKnoten = mConf.mSquirrelCodeKnoten;
317 mConf.kletterWeiter(name,version);
318 if (verlange && !mConf.existiertSquirrelKnoten())
319 throw Fehler("Section %s does not exist.",
320 mConf.getSquirrelPosString().data());
321 }
322
~DatenDateiPush()323 DatenDateiPush::~DatenDateiPush() {
324 mConf.mSquirrelPosString = mMerkName;
325 mConf.mSquirrelKnoten = mMerkKnoten;
326 mConf.mSquirrelCodeKnoten = mMerkCodeKnoten;
327 }
328
329
330