1bf0673 by Jos van den Oever at 2009-08-24 1
package mso.generator;
2
ab2c4b2 by Jos van den Oever at 2010-01-19 3
import java.io.File;
1bf0673 by Jos van den Oever at 2009-08-24 4
import java.io.FileWriter;
5
import java.io.IOException;
6
import java.io.PrintWriter;
2c22c86 by Jos van den Oever at 2009-08-27 7
import java.util.regex.Matcher;
8
import java.util.regex.Pattern;
1bf0673 by Jos van den Oever at 2009-08-24 9
1971b94 by Jos van den Oever at 2011-08-06 10
import mso.generator.utils.Choice;
11
import mso.generator.utils.Limitation;
12
import mso.generator.utils.MSO;
13
import mso.generator.utils.Member;
14
import mso.generator.utils.Option;
15
import mso.generator.utils.Stream;
16
import mso.generator.utils.Struct;
17
import mso.generator.utils.TypeRegistry;
18
1bf0673 by Jos van den Oever at 2009-08-24 19
public class QtParserGenerator {
20
ab2c4b2 by Jos van den Oever at 2010-01-19 21
	public class QtParserConfiguration {
22
		public String namespace;
23
		public String outputdir;
24
		public String basename;
25
		public boolean createHeader;
26
		public boolean enableXml;
27
		public boolean enableWriting;
e20cfd2 by Jos van den Oever at 2010-01-20 28
		public boolean enableIntrospection;
ab2c4b2 by Jos van den Oever at 2010-01-19 29
		public boolean enableToString;
5354439 by Jos van den Oever at 2010-01-19 30
		public boolean enableStyleTextPropAtomFix;
ab2c4b2 by Jos van den Oever at 2010-01-19 31
	}
32
33
	final public QtParserConfiguration config = new QtParserConfiguration();
34
dfb9941 by Jos van den Oever at 2010-01-20 35
	final private String generatedWarning = "/* This code was generated by msoscheme (http://gitorious.org/msoscheme) */";
36
ab2c4b2 by Jos van den Oever at 2010-01-19 37
	void generate(MSO mso) throws IOException {
38
		FileWriter fout;
39
		if (config.createHeader) {
40
			fout = new FileWriter(config.outputdir + File.separator
41
					+ config.basename + ".h");
42
		} else {
43
			fout = new FileWriter(config.outputdir + File.separator
44
					+ config.basename + ".cpp");
45
		}
1bf0673 by Jos van den Oever at 2009-08-24 46
		PrintWriter out = new PrintWriter(fout);
dfb9941 by Jos van den Oever at 2010-01-20 47
		out.println(generatedWarning);
ab2c4b2 by Jos van den Oever at 2010-01-19 48
		if (config.createHeader) {
49
			out.println("#ifndef " + config.basename.toUpperCase() + "_H");
50
			out.println("#define " + config.basename.toUpperCase() + "_H");
51
		}
1bf0673 by Jos van den Oever at 2009-08-24 52
		out.println("#include <QString>");
53
		out.println("#include <QByteArray>");
54
		out.println("#include <QVector>");
e20cfd2 by Jos van den Oever at 2010-01-20 55
		out
dfb9941 by Jos van den Oever at 2010-01-20 56
				.println("#include <QSharedPointer>// replace with QScopedPointer when switching to Qt 4.6");
ab2c4b2 by Jos van den Oever at 2010-01-19 57
		if (config.enableXml) {
58
			out.println("#include <QXmlStreamReader>");
59
		}
60
		if (config.enableWriting) {
61
			out.println("#include \"leoutputstream.h\"");
62
		}
e20cfd2 by Jos van den Oever at 2010-01-20 63
		if (config.enableIntrospection) {
64
			out.println("#include \"introspection.h\"");
65
		}
b8bf381 by Jos van den Oever at 2010-03-03 66
		out.println("class LEInputStream;");
ab2c4b2 by Jos van den Oever at 2010-01-19 67
		out.println("namespace " + config.namespace + "{");
1bf0673 by Jos van den Oever at 2009-08-24 68
ab2c4b2 by Jos van den Oever at 2010-01-19 69
		if (config.enableXml) {
70
			out.println("void skipToStartElement(QXmlStreamReader& in) {");
71
			out.println("    do {");
72
			out.println("        in.readNext();");
73
			out.println("    } while (!in.atEnd() && !in.isStartElement());");
74
			out.println("}");
75
		}
5cb0418 by Jos van den Oever at 2009-11-01 76
e20cfd2 by Jos van den Oever at 2010-01-20 77
		if (!config.enableIntrospection) {
78
			out.println("class StreamOffset {");
79
			out.println("public:");
e9902ec by Jos van den Oever at 2010-01-21 80
			out.println("    virtual ~StreamOffset() {}");
e20cfd2 by Jos van den Oever at 2010-01-20 81
			out.println("    quint32 streamOffset;");
82
			out.println("};");
83
		}
84
2c22c86 by Jos van den Oever at 2009-08-27 85
		for (Struct s : mso.structs) {
86
			out.println("class " + s.name + ";");
75317b3 by Jos van den Oever at 2009-09-12 87
			out.println("void parse" + s.name + "(LEInputStream& in, " + s.name
88
					+ "& _s);");
ab2c4b2 by Jos van den Oever at 2010-01-19 89
			if (config.enableXml) {
90
				out.println("void parse" + s.name + "(QXmlStreamReader& in, "
91
						+ s.name + "& _s);");
92
			}
93
			if (config.enableWriting) {
94
				out.println("void write(const " + s.name
95
						+ "& v, LEOutputStream& out);");
96
			}
2c22c86 by Jos van den Oever at 2009-08-27 97
		}
98
99
		for (Struct s : mso.structs) {
100
			printStructureClassDeclaration(out, s);
101
		}
102
ab2c4b2 by Jos van den Oever at 2010-01-19 103
		if (config.createHeader) {
104
			out.println("} // close namespace");
105
			out.println("#endif");
106
			out.close();
107
			fout = new FileWriter(config.outputdir + File.separator
108
					+ config.basename + ".cpp");
109
			out = new PrintWriter(fout);
dfb9941 by Jos van den Oever at 2010-01-20 110
			out.println(generatedWarning);
ab2c4b2 by Jos van den Oever at 2010-01-19 111
			out.println("#include \"" + config.basename + ".h\"");
112
			out.println("using namespace " + config.namespace + ";");
113
		}
b8bf381 by Jos van den Oever at 2010-03-03 114
		out.println("#include \"leinputstream.h\"");
ab2c4b2 by Jos van den Oever at 2010-01-19 115
e20cfd2 by Jos van den Oever at 2010-01-20 116
		if (config.enableIntrospection) {
117
			for (Struct s : mso.structs) {
118
				printStructureClassImplementation(out, s);
119
			}
2c22c86 by Jos van den Oever at 2009-08-27 120
		}
121
122
		for (Struct s : mso.structs) {
123
			printStructureParser(out, s);
ab2c4b2 by Jos van den Oever at 2010-01-19 124
			if (config.enableWriting) {
125
				printStructureWriter(out, s);
126
			}
127
			if (config.enableXml) {
128
				printStructureXmlParser(out, s);
129
			}
7ef14a6 by Jos van den Oever at 2009-08-26 130
		}
2c22c86 by Jos van den Oever at 2009-08-27 131
ab2c4b2 by Jos van den Oever at 2010-01-19 132
		if (!config.createHeader) {
133
			out.println("}");// close namespace
134
		}
5d4671d by Jos van den Oever at 2009-09-12 135
e20cfd2 by Jos van den Oever at 2010-01-20 136
		if (config.enableIntrospection) {
137
			out
138
					.println("const Introspectable* parse(const QString& key, LEInputStream& in) {");
139
			out.println("    const Introspectable* i = 0;");
140
			boolean first = true;
141
			for (Stream s : mso.streams) {
142
				out.print("    ");
143
				if (first) {
144
					first = false;
145
				} else {
146
					out.print("} else ");
147
				}
148
				out.println("if (\"" + s.key + "\" == key) {"); // TODO: fix for
149
				// \001 and \005
150
				// prefix
151
				out.println("        " + s.type + " *_t = new " + s.type
152
						+ "(0);");
153
				out.println("        parse" + s.type + "(in, *_t);");
154
				out.println("        i = _t;");
2c22c86 by Jos van den Oever at 2009-08-27 155
			}
e20cfd2 by Jos van den Oever at 2010-01-20 156
			out.println("    } else {");
157
			out.println("        TODOS* _t = new TODOS(0);");
158
			out.println("        parseTODOS(in, *_t);");
a9c0e8f by Jos van den Oever at 2009-11-04 159
			out.println("        i = _t;");
e20cfd2 by Jos van den Oever at 2010-01-20 160
			out.println("    }");
161
			out.println("    return i;");
162
			out.println("}");
1bf0673 by Jos van den Oever at 2009-08-24 163
		}
2e987d6 by Jos van den Oever at 2009-10-22 164
ab2c4b2 by Jos van den Oever at 2010-01-19 165
		if (config.enableXml) {
166
			out
167
					.println("const QMap<QString,QSharedPointer<const Introspectable> > parse(QXmlStreamReader& in) {");
168
			out
169
					.println("    QMap<QString,QSharedPointer<const Introspectable> > streams;");
170
			out.println("    // skip until first element");
171
			out.println("    while (!in.atEnd() && !in.isStartElement()) {");
172
			out.println("        in.readNext();");
173
			out.println("    }");
174
			out.println("    if (!in.isStartElement()) {");
175
			out.println("        return streams;");
176
			out.println("    }");
177
			out.println("    do {");
178
			out.println("        in.readNext();");
179
			out.println("    } while (!in.atEnd() && !in.isStartElement());");
180
			out.println("    if (!in.isStartElement()) {");
181
			out.println("        return streams;");
182
			out.println("    }");
183
			out.println("    do {");
184
			out.println("        QString name = in.name().toString();");
185
			out.println("        if (streams.contains(name)) {");
186
			out.println("            streams.clear();");
187
			out.println("            return streams;");
188
			out.println("        }");
e20cfd2 by Jos van den Oever at 2010-01-20 189
			boolean first = true;
ab2c4b2 by Jos van den Oever at 2010-01-19 190
			for (Stream s : mso.streams) {
191
				out.print("        ");
192
				if (first) {
193
					first = false;
194
				} else {
195
					out.print("} else ");
196
				}
197
				out.println("if (\"" + s.key + "\" == name) {");
198
				out
199
						.println("            QSharedPointer<Introspectable> _t(new "
200
								+ s.type + "(0));");
201
				out.println("            parse" + s.type + "(in, *static_cast<"
202
						+ s.type + "*>(_t.data()));");
203
				// out.println("            QSharedPointer<Introspectable> _t(new PowerPointStructs());");
204
				// out.println("            parsePowerPointStructs(in, *static_cast<PowerPointStructs*>(_t.data()));");
205
				out.println("            streams[name] = _t;");
2e987d6 by Jos van den Oever at 2009-10-22 206
			}
ab2c4b2 by Jos van den Oever at 2010-01-19 207
			out.println("        } else { // unknown stream should be binary");
208
			out
209
					.println("            QSharedPointer<Introspectable> _t(new TODOS(0));");
210
			out
211
					.println("            parseTODOS(in, *static_cast<TODOS*>(_t.data()));");
2e987d6 by Jos van den Oever at 2009-10-22 212
			out.println("            streams[name] = _t;");
ab2c4b2 by Jos van den Oever at 2010-01-19 213
			out.println("        }");
214
			out.println("        do {");
215
			out.println("            in.readNext();");
216
			out.println("        } while (in.isWhitespace());");
217
			out.println("    } while (in.isStartElement());");
218
			out.println("    qDebug() << in.tokenType();");
219
			out.println("    if (!in.isEndElement()) {");
220
			out
221
					.println("        qDebug() << \"parsing error: not at end of an element\";");
222
			out.println("        streams.clear();");
223
			out.println("    }");
224
			out.println("    in.readNext();");
225
			out.println("    if (!in.isEndDocument()) {");
226
			out
227
					.println("        qDebug() << \"parsing error: not at end of xml\";");
228
			out.println("        streams.clear();");
229
			out.println("    }");
230
			out.println("    return streams;");
231
			out.println("}");
232
233
			out
234
					.println("void serialize(const Introspectable* i, const QString& key, LEOutputStream& out)  {");
235
			first = true;
236
			for (Stream s : mso.streams) {
237
				out.print("    ");
238
				if (first) {
239
					first = false;
240
				} else {
241
					out.print("} else ");
242
				}
243
				out.println("if (\"" + s.key + "\" == key) {"); // TODO: fix for
244
				// \001 and \005
245
				// prefix
246
				out.println("        write(*static_cast<const " + s.type
247
						+ "*>(i), out);");
e013083 by Jos van den Oever at 2009-09-16 248
			}
ab2c4b2 by Jos van den Oever at 2010-01-19 249
			out.println("    } else {");
250
			out.println("        write(*static_cast<const TODOS*>(i), out);");
251
			out.println("    }");
252
			out.println("}");
e013083 by Jos van den Oever at 2009-09-16 253
		}
1bf0673 by Jos van den Oever at 2009-08-24 254
		out.close();
255
		fout.close();
256
	}
257
dfb9941 by Jos van den Oever at 2010-01-20 258
	private void printStructureParser(PrintWriter out, Struct s) {
ab2c4b2 by Jos van den Oever at 2010-01-19 259
		out.print("void ");
260
		if (config.namespace != null && config.namespace.length() > 0) {
261
			out.print(config.namespace + "::");
262
		}
263
		out.println("parse" + s.name + "(LEInputStream& in, " + s.name
2c22c86 by Jos van den Oever at 2009-08-27 264
				+ "& _s) {");
124a9d4 by Jos van den Oever at 2010-01-12 265
		out.println("    _s.streamOffset = in.getPosition();");
f3d6050 by Jos van den Oever at 2009-09-12 266
		if (s.containsKnownLengthArrayMember) {
267
			out.println("    int _c;");
268
		}
267ecf8 by Jos van den Oever at 2009-09-29 269
		if (s.containsArrayMember || s.containsOptionalMember
9aad1f9 by Jos van den Oever at 2010-01-27 270
				|| s.containsChoice) {
75317b3 by Jos van den Oever at 2009-09-12 271
			out.println("    LEInputStream::Mark _m;");
2c22c86 by Jos van den Oever at 2009-08-27 272
		}
9f955ab by Jos van den Oever at 2010-01-29 273
		if (s.containsOptionalMember) {
274
			out.println("    bool _possiblyPresent;");
275
		}
700ccda by Jos van den Oever at 2009-09-14 276
		if (s.containsUnknownLengthArrayMember) {
362eef6 by Jos van den Oever at 2009-10-24 277
			out.println("    bool _atend;");
700ccda by Jos van den Oever at 2009-09-14 278
		}
2c22c86 by Jos van den Oever at 2009-08-27 279
		for (Member m : s.members) {
5354439 by Jos van den Oever at 2010-01-19 280
			if (config.enableStyleTextPropAtomFix
281
					&& s.name.equals("StyleTextPropAtom")
282
					&& m.name.equals("todo")) {
283
				break;
284
			}
e9902ec by Jos van den Oever at 2010-01-21 285
			printStructureMemberParser(out, s.name, m);
2ff50d9 by Jos van den Oever at 2010-01-27 286
			if (m.type().name.contains("RecordHeader")) {
ab2c4b2 by Jos van den Oever at 2010-01-19 287
				// out.println("qDebug() << in.getPosition()<<\" \"<<\"" +
288
				// s.name
289
				// + "\"<<_s.rh.toString();");
5b40d42 by Jos van den Oever at 2010-01-05 290
			}
5354439 by Jos van den Oever at 2010-01-19 291
			if (config.enableStyleTextPropAtomFix
292
					&& s.name.equals("TextContainer") && m.name.equals("style")) {
293
				styleTextPropAtomFix2(out);
294
			}
2c22c86 by Jos van den Oever at 2009-08-27 295
		}
296
		out.println("}");
297
	}
298
dfb9941 by Jos van den Oever at 2010-01-20 299
	private void printStructureXmlParser(PrintWriter out, Struct s) {
2e987d6 by Jos van den Oever at 2009-10-22 300
		out.println("void parse" + s.name + "(QXmlStreamReader& in, " + s.name
301
				+ "& _s) {");
5cb0418 by Jos van den Oever at 2009-11-01 302
		out.println("    in.readNext();");
362eef6 by Jos van den Oever at 2009-10-24 303
		for (Member m : s.members) {
5cb0418 by Jos van den Oever at 2009-11-01 304
			printStructureMemberXmlParser(out, m);
362eef6 by Jos van den Oever at 2009-10-24 305
		}
5cb0418 by Jos van den Oever at 2009-11-01 306
		/*
307
		 * out.println("    int depth = 0;");
308
		 * out.println("    while (!in.atEnd()) {");
309
		 * out.println("        if (type == QXmlStreamReader::StartElement) {");
310
		 * out.println("            depth++;");
311
		 * out.println("        } else if (type == QXmlStreamReader::EndElement "
312
		 * + "&& --depth < 0) {"); out.println("            return;");
313
		 * out.println("        }");
314
		 * out.println("        type = in.readNext();"); out.println("    }");
315
		 */
2e987d6 by Jos van den Oever at 2009-10-22 316
		out.println("}");
5cb0418 by Jos van den Oever at 2009-11-01 317
2e987d6 by Jos van den Oever at 2009-10-22 318
	}
319
a3b7549 by Jos van den Oever at 2010-01-31 320
	static private String prependStructureToExpression(String expression,
dfb9941 by Jos van den Oever at 2010-01-20 321
			String structureName) {
2c22c86 by Jos van den Oever at 2009-08-27 322
		if (expression.length() > 0) {
323
			Pattern p = Pattern.compile("([^.\\w])([.a-zA-Z])");
324
			Matcher m = p.matcher(expression);
325
			expression = m.replaceAll("$1" + structureName + ".$2");
326
			p = Pattern.compile("^([a-zA-Z])");
327
			m = p.matcher(expression);
328
			expression = m.replaceAll(structureName + ".$1");
329
		}
330
		return expression;
331
	}
332
e9902ec by Jos van den Oever at 2010-01-21 333
	private void printStructureMemberParser(PrintWriter out, String structure,
334
			Member m) {
2c22c86 by Jos van den Oever at 2009-08-27 335
		String s = "    ";
565dd78 by Jos van den Oever at 2009-09-18 336
		String index = (m.count == null) ? "" : "[_i]";
75317b3 by Jos van den Oever at 2009-09-12 337
		if (m.condition != null) {
338
			String condition = prependStructureToExpression(m.condition, "_s");
45c451d by Jos van den Oever at 2010-01-27 339
			if (!m.isStruct) {
c9b5118 by Jos van den Oever at 2009-10-05 340
				out.println(s + "_s._has_" + m.name + " = " + condition + ";");
341
				out.println(s + "if (_s._has_" + m.name + ") {");
342
			} else {
343
				out.println(s + "if (" + condition + ") {");
344
			}
2c22c86 by Jos van den Oever at 2009-08-27 345
			s = s + "    ";
45c451d by Jos van den Oever at 2010-01-27 346
			if (m.isStruct) {
2ff50d9 by Jos van den Oever at 2010-01-27 347
				out.println(s + "_s." + m.name + " = QSharedPointer<"
348
						+ m.type().name + ">(new " + m.type().name + "(&_s));");
565dd78 by Jos van den Oever at 2009-09-18 349
				index = ".data()";
350
			}
2c22c86 by Jos van den Oever at 2009-08-27 351
		}
352
		String parse;
45c451d by Jos van den Oever at 2010-01-27 353
		if (m.isStruct) {
565dd78 by Jos van den Oever at 2009-09-18 354
			String star = (m.condition == null) ? "" : "*";
2ff50d9 by Jos van den Oever at 2010-01-27 355
			parse = "parse" + m.type().name + "(in, " + star + "_s." + m.name
356
					+ index + ");";
2c22c86 by Jos van den Oever at 2009-08-27 357
		} else {
2ff50d9 by Jos van den Oever at 2010-01-27 358
			parse = "_s." + m.name + index + " = in.read" + m.type().name
359
					+ "();";
2c22c86 by Jos van den Oever at 2009-08-27 360
		}
45c451d by Jos van den Oever at 2010-01-27 361
		if (m.isChoice) {
e9902ec by Jos van den Oever at 2010-01-21 362
			printChoiceParser(out, s, structure, m);
2c22c86 by Jos van den Oever at 2009-08-27 363
			return;
364
		}
365
		if (m.isArray && m.count == null) {
e013083 by Jos van den Oever at 2009-09-16 366
			if (m.size != null) {
367
				printFixedSizeArrayParser(out, s, m);
368
			} else {
369
				// array for which no size is given: parse items until one fails
370
				printVariableArrayParser(out, s, m);
371
			}
2c22c86 by Jos van den Oever at 2009-08-27 372
			return;
373
		}
374
		if (m.isOptional) {
375
			printOptionalMemberParser(out, s, m);
376
			return;
377
		}
75317b3 by Jos van den Oever at 2009-09-12 378
		if (m.count != null) {
379
			String count = prependStructureToExpression(m.count, "_s");
2c22c86 by Jos van den Oever at 2009-08-27 380
			out.println(s + "_c = " + count + ";");
381
		}
75317b3 by Jos van den Oever at 2009-09-12 382
		if (m.count != null) {
45c451d by Jos van den Oever at 2010-01-27 383
			if (!m.isStruct) {
a68aec3 by Jos van den Oever at 2010-01-05 384
				out.println(s + "_s." + m.name + ".resize(_c);");
28f1c56 by Jos van den Oever at 2009-09-18 385
			}
d2d3f42 by Jos van den Oever at 2010-01-30 386
			if (m.type() == m.registry.uint8) { // special case for
2ff50d9 by Jos van den Oever at 2010-01-27 387
				// reading bytearrays quickly
e013083 by Jos van den Oever at 2009-09-16 388
				out.println(s + "in.readBytes(_s." + m.name + ");");
389
			} else {
390
				out.println(s + "for (int _i=0; _i<_c; ++_i) {");
45c451d by Jos van den Oever at 2010-01-27 391
				if (m.isStruct) {
2ff50d9 by Jos van den Oever at 2010-01-27 392
					out.println(s + "    _s." + m.name + ".append("
393
							+ m.type().name + "(&_s));");
28f1c56 by Jos van den Oever at 2009-09-18 394
				}
e013083 by Jos van den Oever at 2009-09-16 395
				out.println(s + "    " + parse);
396
				printLimitationCheck(out, "        ", "_s." + m.name + "[_i]",
397
						m);
398
				out.println(s + "}");
399
			}
2c22c86 by Jos van den Oever at 2009-08-27 400
		} else {
a68aec3 by Jos van den Oever at 2010-01-05 401
			out.println(s + parse);
2c22c86 by Jos van den Oever at 2009-08-27 402
			printLimitationCheck(out, s, "_s." + m.name, m);
403
		}
75317b3 by Jos van den Oever at 2009-09-12 404
		if (m.condition != null) {
405
			out.println("    }");
2c22c86 by Jos van den Oever at 2009-08-27 406
		}
407
	}
408
dfb9941 by Jos van den Oever at 2010-01-20 409
	private void printStructureMemberXmlParser(PrintWriter out, Member m) {
5cb0418 by Jos van den Oever at 2009-11-01 410
		String s = "    ";
411
412
		out.println(s + "if (!in.isStartElement()) {");
2ff50d9 by Jos van den Oever at 2010-01-27 413
		out.println(s + "    qDebug() << \"not startelement in "
414
				+ m.type().name + " \" << in.lineNumber();");
5cb0418 by Jos van den Oever at 2009-11-01 415
		out.println(s + "    return;");
416
		out.println(s + "}");
417
		if (!m.isOptional && !m.isArray) {
418
			out.println(s + "if (in.name() != \"" + m.name + "\") {");
419
			out.println(s + "    qDebug() << \"not startelement in " + m.name
420
					+ " \" << in.lineNumber();");
421
			out.println(s + "    return;");
422
			out.println(s + "}");
423
		}
424
		if (m.isOptional) {
425
			out.println(s + "if (in.name() == \"" + m.name + "\") {");
426
			s = s + "    ";
427
		}
45c451d by Jos van den Oever at 2010-01-27 428
		if (!m.isStruct) {
5cb0418 by Jos van den Oever at 2009-11-01 429
			out.println(s + "in.readElementText();");
430
		} else {
431
			out.println(s + "skipToStartElement(in);");
a9c0e8f by Jos van den Oever at 2009-11-04 432
			// out.println(s + "parse" + m.type + "(in, _s." + m.name + ");");
5cb0418 by Jos van den Oever at 2009-11-01 433
		}
434
		// out.println(s + "if (in.name() == \"" + m.name + "\") {");
435
		if (m.isOptional) {
436
			out.println("    }");
437
		}
438
	}
439
dfb9941 by Jos van den Oever at 2010-01-20 440
	private void printStructureWriter(PrintWriter out, Struct s) {
e013083 by Jos van den Oever at 2009-09-16 441
		out.println("void write(const " + s.name
442
				+ "& _s, LEOutputStream& out) {");
443
		for (Member m : s.members) {
444
			printStructureMemberWriter(out, m);
445
		}
446
		out.println("}");
447
	}
448
dfb9941 by Jos van den Oever at 2010-01-20 449
	private void printStructureMemberWriter(PrintWriter out, Member m) {
e013083 by Jos van den Oever at 2009-09-16 450
		String s = "    ";
451
		if (m.condition != null) {
452
			out.println("    if (" + getExpression("_s", m.condition) + ") {");
453
			s = s + "    ";
454
		}
45c451d by Jos van den Oever at 2010-01-27 455
		if (m.isChoice) {
e013083 by Jos van den Oever at 2009-09-16 456
			boolean first = true;
2ff50d9 by Jos van den Oever at 2010-01-27 457
			for (String t : ((Choice) m.type()).getChoiceNames()) {
e013083 by Jos van den Oever at 2009-09-16 458
				out.print(s);
459
				if (!first) {
460
					out.print("} else ");
461
				}
462
				first = false;
e9902ec by Jos van den Oever at 2010-01-21 463
				out.println("if (_s." + m.name + ".is<" + t + ">()) {");
464
				out.println(s + "    write(*_s." + m.name + ".get<" + t
465
						+ ">(), out);");
e013083 by Jos van den Oever at 2009-09-16 466
			}
467
			out.println(s + "}");
468
		} else if (m.isArray) {
d2d3f42 by Jos van den Oever at 2010-01-30 469
			if (m.type() == m.registry.uint8) {
e013083 by Jos van den Oever at 2009-09-16 470
				out.println(s + "out.writeBytes(_s." + m.name + ");");
471
			} else {
97257cd by Jos van den Oever at 2010-01-28 472
				String t = getTypeName(m.type());
e013083 by Jos van den Oever at 2009-09-16 473
				out.println(s + "foreach (" + t + " _i, _s." + m.name + ") {");
45c451d by Jos van den Oever at 2010-01-27 474
				if (m.isStruct) {
e013083 by Jos van den Oever at 2009-09-16 475
					out.println(s + "    write(_i, out);");
476
				} else {
2ff50d9 by Jos van den Oever at 2010-01-27 477
					out.println(s + "    out.write" + m.type().name + "(_i);");
e013083 by Jos van den Oever at 2009-09-16 478
				}
479
				out.println(s + "}");
480
			}
45c451d by Jos van den Oever at 2010-01-27 481
		} else if (m.isStruct) {
e013083 by Jos van den Oever at 2009-09-16 482
			out.print(s);
565dd78 by Jos van den Oever at 2009-09-18 483
			if (m.isOptional || m.condition != null) {
e013083 by Jos van den Oever at 2009-09-16 484
				out.print("if (_s." + m.name + ") write(*");
485
			} else {
486
				out.print("write(");
487
			}
488
			out.println("_s." + m.name + ", out);");
489
		} else {
2ff50d9 by Jos van den Oever at 2010-01-27 490
			out.println(s + "out.write" + m.type().name + "(_s." + m.name
491
					+ ");");
e013083 by Jos van den Oever at 2009-09-16 492
		}
493
		if (m.condition != null) {
494
			out.println("    }");
495
		}
496
	}
497
97257cd by Jos van den Oever at 2010-01-28 498
	private String getTypeName(TypeRegistry.Type t) {
2ff50d9 by Jos van den Oever at 2010-01-27 499
		TypeRegistry r = t.registry;
500
		if (t instanceof Choice) {
97257cd by Jos van den Oever at 2010-01-28 501
			return createChoiceClass(t.name, (Choice) t);
2ff50d9 by Jos van den Oever at 2010-01-27 502
		} else if (t == r.bit) {
1bf0673 by Jos van den Oever at 2009-08-24 503
			return "bool";
2ff50d9 by Jos van den Oever at 2010-01-27 504
		} else if (t == r.uint2 || t == r.uint3 || t == r.uint4 || t == r.uint5
505
				|| t == r.uint6 || t == r.uint7 || t == r.uint8) {
1bf0673 by Jos van den Oever at 2009-08-24 506
			return "quint8";
c1d8729 by Jos van den Oever at 2010-09-27 507
		} else if (t == r.uint9 || t == r.uint12 || t == r.uint13
508
				|| t == r.uint14 || t == r.uint15
509
				|| t == r.uint16) {
1bf0673 by Jos van den Oever at 2009-08-24 510
			return "quint16";
2ff50d9 by Jos van den Oever at 2010-01-27 511
		} else if (t == r.uint20 || t == r.uint30 || t == r.uint32) {
1bf0673 by Jos van den Oever at 2009-08-24 512
			return "quint32";
2ff50d9 by Jos van den Oever at 2010-01-27 513
		} else if (t == r.int16) {
1bf0673 by Jos van den Oever at 2009-08-24 514
			return "qint16";
2ff50d9 by Jos van den Oever at 2010-01-27 515
		} else if (t == r.int32) {
1bf0673 by Jos van den Oever at 2009-08-24 516
			return "qint32";
517
		}
97257cd by Jos van den Oever at 2010-01-28 518
		return t.name;
1bf0673 by Jos van den Oever at 2009-08-24 519
	}
520
2ff50d9 by Jos van den Oever at 2010-01-27 521
	private String createChoiceClass(String name, Choice c) {
e9902ec by Jos van den Oever at 2010-01-21 522
		String base = "StreamOffset";
523
		if (config.enableIntrospection) {
524
			base = "Introspectable";
525
		}
97257cd by Jos van den Oever at 2010-01-28 526
		String choice = "class " + name + " : public QSharedPointer<" + base
527
				+ "> {\n";
dfb9941 by Jos van den Oever at 2010-01-20 528
		choice += "    public:\n";
97257cd by Jos van den Oever at 2010-01-28 529
		choice += "        " + name + "() {}\n";
2ff50d9 by Jos van den Oever at 2010-01-27 530
		for (String s : c.getChoiceNames()) {
97257cd by Jos van den Oever at 2010-01-28 531
			choice += "        explicit " + name + "(" + s
e9902ec by Jos van den Oever at 2010-01-21 532
					+ "* a) :QSharedPointer<" + base + ">(a) {}\n";
dfb9941 by Jos van den Oever at 2010-01-20 533
		}
e9902ec by Jos van den Oever at 2010-01-21 534
		choice += "        template <typename T> T*get() { return dynamic_cast<T*>(this->data()); }\n";
535
		choice += "        template <typename T> const T*get() const { return dynamic_cast<const T*>(this->data()); }\n";
536
		choice += "        template <typename T> bool is() const { return get<T>(); }\n";
dfb9941 by Jos van den Oever at 2010-01-20 537
		choice += "    };\n";
97257cd by Jos van den Oever at 2010-01-28 538
		choice += "    " + name;
dfb9941 by Jos van den Oever at 2010-01-20 539
		return choice;
540
	}
541
542
	private String getMemberDeclaration(Member m) {
97257cd by Jos van den Oever at 2010-01-28 543
		String t = getTypeName(m.type());
28f1c56 by Jos van den Oever at 2009-09-18 544
		if (m.isArray) {
45c451d by Jos van den Oever at 2010-01-27 545
			if (m.isStruct) {
2ff50d9 by Jos van den Oever at 2010-01-27 546
				return "QList<" + m.type().name + "> " + m.name;
28f1c56 by Jos van den Oever at 2009-09-18 547
			} else {
97257cd by Jos van den Oever at 2010-01-28 548
				if ("quint8".equals(t)) {
28f1c56 by Jos van den Oever at 2009-09-18 549
					return "QByteArray " + m.name;
550
				} else {
97257cd by Jos van den Oever at 2010-01-28 551
					return "QVector<" + t + "> " + m.name;
28f1c56 by Jos van den Oever at 2009-09-18 552
				}
1bf0673 by Jos van den Oever at 2009-08-24 553
			}
45c451d by Jos van den Oever at 2010-01-27 554
		} else if (m.isStruct && (m.isOptional || m.condition != null)) {
97257cd by Jos van den Oever at 2010-01-28 555
			return "QSharedPointer<" + t + "> " + m.name;
1bf0673 by Jos van den Oever at 2009-08-24 556
		}
97257cd by Jos van den Oever at 2010-01-28 557
		return t + " " + m.name;
1bf0673 by Jos van den Oever at 2009-08-24 558
	}
559
dfb9941 by Jos van den Oever at 2010-01-20 560
	private String memberToString(Member m, String prefix) {
2c22c86 by Jos van den Oever at 2009-08-27 561
		String s;
562
		String mn = prefix + m.name;
75317b3 by Jos van den Oever at 2009-09-12 563
		if (m.isArray) {
564
			s = "\"[array of " + mn + "]\"";
565
		} else {
2ff50d9 by Jos van den Oever at 2010-01-27 566
			if (m.isInteger) {
75317b3 by Jos van den Oever at 2009-09-12 567
				s = "QString::number(" + mn + ") + \"(\" + QString::number("
568
						+ mn + ",16).toUpper() + \")\"";
2ff50d9 by Jos van den Oever at 2010-01-27 569
			} else if (m.type() == m.type().registry.bit) {
75317b3 by Jos van den Oever at 2009-09-12 570
				s = "QString::number(" + mn + ")";
45c451d by Jos van den Oever at 2010-01-27 571
			} else if (m.isChoice) {
2c22c86 by Jos van den Oever at 2009-08-27 572
				s = "\"<choice>\"";
565dd78 by Jos van den Oever at 2009-09-18 573
			} else if (m.isOptional || m.condition != null) {
75317b3 by Jos van den Oever at 2009-09-12 574
				s = "((" + mn + ")?" + mn + "->toString() :\"null\")";
2c22c86 by Jos van den Oever at 2009-08-27 575
			} else {
576
				s = mn + ".toString()";
1bf0673 by Jos van den Oever at 2009-08-24 577
			}
2c22c86 by Jos van den Oever at 2009-08-27 578
		}
579
		return s;
580
	}
581
dfb9941 by Jos van den Oever at 2010-01-20 582
	private void styleTextPropAtomFix(PrintWriter out) {
5354439 by Jos van den Oever at 2010-01-19 583
		out.println("    RecordHeader rh;");
584
		out.println("    QList<TextPFRun> rgTextPFRun;");
585
		out.println("    QList<TextCFRun> rgTextCFRun;");
586
	}
587
dfb9941 by Jos van den Oever at 2010-01-20 588
	private void styleTextPropAtomFix2(PrintWriter out) {
e5aacb6 by Jos van den Oever at 2010-01-24 589
		out.println("    if (_s.style) {");
590
		out.println("        quint32 count = 0;");
591
		out.println("        if (_s.text.is<TextCharsAtom>()) {");
2ff50d9 by Jos van den Oever at 2010-01-27 592
		out
593
				.println("            count = _s.text.get<TextCharsAtom>()->textChars.size();");
e5aacb6 by Jos van den Oever at 2010-01-24 594
		out.println("        }");
595
		out.println("        if (_s.text.is<TextBytesAtom>()) {");
2ff50d9 by Jos van den Oever at 2010-01-27 596
		out
597
				.println("            count = _s.text.get<TextBytesAtom>()->textChars.size();");
e5aacb6 by Jos van den Oever at 2010-01-24 598
		out.println("        }");
5354439 by Jos van den Oever at 2010-01-19 599
		out.println("        quint32 sum = 0;");
600
		out.println("        do {");
91c88bc by Jos van den Oever at 2010-01-20 601
		out
e5aacb6 by Jos van den Oever at 2010-01-24 602
				.println("        _s.style->rgTextPFRun.append(TextPFRun(_s.style.data()));");
91c88bc by Jos van den Oever at 2010-01-20 603
		out
604
				.println("            parseTextPFRun(in, _s.style->rgTextPFRun.last());");
605
		out.println("            sum += _s.style->rgTextPFRun.last().count;");
5354439 by Jos van den Oever at 2010-01-19 606
		out.println("        } while (sum <= count);");
607
		out.println("        sum = 0;");
608
		out.println("        do {");
91c88bc by Jos van den Oever at 2010-01-20 609
		out
610
				.println("            _s.style->rgTextCFRun.append(TextCFRun(_s.style.data()));");
611
		out
612
				.println("            parseTextCFRun(in, _s.style->rgTextCFRun.last());");
613
		out.println("            sum += _s.style->rgTextCFRun.last().count;");
7dd12a4 by Jos van den Oever at 2010-01-22 614
		out.println("        } while (sum <= count);");
5354439 by Jos van den Oever at 2010-01-19 615
		out.println("    }");
616
	}
617
dfb9941 by Jos van den Oever at 2010-01-20 618
	private void printStructureClassDeclaration(PrintWriter out, Struct s) {
ab2c4b2 by Jos van den Oever at 2010-01-19 619
		out.print("class " + s.name);
e20cfd2 by Jos van den Oever at 2010-01-20 620
		if (config.enableIntrospection) {
621
			out.println(" : public Introspectable {");
622
			out.println("private:");
623
			out.println("    class _Introspection;");
624
		} else {
625
			out.println(" : public StreamOffset {");
626
627
		}
2c22c86 by Jos van den Oever at 2009-08-27 628
		out.println("public:");
e20cfd2 by Jos van den Oever at 2010-01-20 629
		if (config.enableIntrospection) {
630
			out.println("    static const Introspection _introspection;");
631
		}
2c22c86 by Jos van den Oever at 2009-08-27 632
		for (Member m : s.members) {
45c451d by Jos van den Oever at 2010-01-27 633
			if (!m.isStruct && m.condition != null) {
c9b5118 by Jos van den Oever at 2009-10-05 634
				out.println("    bool _has_" + m.name + ";");
635
			}
636
		}
5354439 by Jos van den Oever at 2010-01-19 637
		if (config.enableStyleTextPropAtomFix
638
				&& s.name.equals("StyleTextPropAtom")) {
639
			styleTextPropAtomFix(out);
640
		} else {
641
			for (Member m : s.members) {
642
				String d = getMemberDeclaration(m);
643
				out.println("    " + d + ";");
644
			}
1bf0673 by Jos van den Oever at 2009-08-24 645
		}
e20cfd2 by Jos van den Oever at 2010-01-20 646
		boolean first = true;
647
		if (config.enableIntrospection) {
648
			out.print("    explicit " + s.name
649
					+ "(const Introspectable* parent)");
650
			out.print("\n       :Introspectable(parent)");
651
			first = false;
652
			for (Member m : s.members) {
97257cd by Jos van den Oever at 2010-01-28 653
				if (m.isStruct && !m.isArray && !m.isOptional && !(m.isChoice)
654
						&& m.condition == null) {
e20cfd2 by Jos van den Oever at 2010-01-20 655
					if (first) {
656
						out.print("\n       :");
657
						first = false;
658
					} else {
659
						out.print(",\n        ");
660
					}
661
					out.print(m.name + "(this)");
662
				}
a9c0e8f by Jos van den Oever at 2009-11-04 663
			}
e20cfd2 by Jos van den Oever at 2010-01-20 664
			out.println(" {}");
665
		} else {
e9902ec by Jos van den Oever at 2010-01-21 666
			out.println("    " + s.name + "(void* /*dummy*/ = 0) {}");
a9c0e8f by Jos van den Oever at 2009-11-04 667
		}
1bf0673 by Jos van den Oever at 2009-08-24 668
669
		// function toString
ab2c4b2 by Jos van den Oever at 2010-01-19 670
		if (config.enableToString) {
671
			out.println("    QString toString() {");
672
			out.println("        QString _s = \"" + s.name + ":\";");
673
			for (Member m : s.members) {
674
				out.print("        _s = _s + \"" + m.name + ": \" + ");
675
				out.print(memberToString(m, ""));
676
				out.println(" + \", \";");
677
			}
678
			out.println("        return _s;");
679
			out.println("    }");
5b40d42 by Jos van den Oever at 2010-01-05 680
		}
e20cfd2 by Jos van den Oever at 2010-01-20 681
		if (config.enableIntrospection) {
682
			out
683
					.println("    const Introspection* getIntrospection() const { return &_introspection; }");
684
		}
1bf0673 by Jos van den Oever at 2009-08-24 685
		out.println("};");
686
687
	}
688
dfb9941 by Jos van den Oever at 2010-01-20 689
	private void printStructureClassImplementation(PrintWriter out, Struct s) {
370ab52 by Jos van den Oever at 2009-09-14 690
		final int nm = s.members.size();
691
		final String ns = s.name + "::_Introspection";
692
		out.println("class " + ns + " {");
693
		out.println("public:");
694
		out.println("    static const QString name;");
695
		out.println("    static const int numberOfMembers;");
696
		out.println("    static const QString names[" + nm + "];");
697
		out.println("    static int (* const numberOfInstances[" + nm
698
				+ "])(const Introspectable*);");
699
		out.println("    static QVariant (* const value[" + nm
700
				+ "])(const Introspectable*, int position);");
701
		out.println("    static const Introspectable* (* const introspectable["
702
				+ nm + "])(const Introspectable*, int position);");
703
		for (Member m : s.members) {
5354439 by Jos van den Oever at 2010-01-19 704
			if (s.name.equals("StyleTextPropAtom")
705
					&& config.enableStyleTextPropAtomFix
706
					&& m.name.equals("todo")) {
707
				break;
708
			}
45c451d by Jos van den Oever at 2010-01-27 709
			if (!m.isStruct && !(m.isChoice)) {
c9b5118 by Jos van den Oever at 2009-10-05 710
				if (m.condition != null) {
711
					out.println("    static int count_" + m.name
712
							+ "(const Introspectable* i) {");
713
					out.println("        return static_cast<const " + s.name
714
							+ "*>(i)->_has_" + m.name + " ?1 :0;");
715
					out.println("    }");
716
				}
565dd78 by Jos van den Oever at 2009-09-18 717
			} else if (m.isOptional || m.condition != null) {
370ab52 by Jos van den Oever at 2009-09-14 718
				out.println("    static int count_" + m.name
719
						+ "(const Introspectable* i) {");
c5e2e64 by Jos van den Oever at 2009-09-29 720
				out.println("        return get_" + m.name + "(i, 0) ?1 :0;");
370ab52 by Jos van den Oever at 2009-09-14 721
				out.println("    }");
722
			} else if (m.isArray) {
723
				out.println("    static int count_" + m.name
724
						+ "(const Introspectable* i) {");
725
				out.println("        return static_cast<const " + s.name
726
						+ "*>(i)->" + m.name + ".size();");
727
				out.println("    }");
728
			}
45c451d by Jos van den Oever at 2010-01-27 729
			if (m.isStruct || m.isChoice) {
370ab52 by Jos van den Oever at 2009-09-14 730
				out.println("    static const Introspectable* get_" + m.name
731
						+ "(const Introspectable* i, int j) {");
732
			} else {
733
				out.println("    static QVariant get_" + m.name
734
						+ "(const Introspectable* i, int j) {");
735
			}
5c794b7 by Jos van den Oever at 2009-09-18 736
			String dm = "static_cast<const " + s.name + "*>(i)->" + m.name + "";
45c451d by Jos van den Oever at 2010-01-27 737
			if (!(m.isChoice)) {
5c794b7 by Jos van den Oever at 2009-09-18 738
				out.print("        ");
45c451d by Jos van den Oever at 2010-01-27 739
				if (!m.isStruct) {
2ff50d9 by Jos van den Oever at 2010-01-27 740
					if (m.isArray && m.type() != m.type().registry.uint8) {
5c794b7 by Jos van den Oever at 2009-09-18 741
						out.println("return qVariantFromValue(" + dm + ");");
742
					} else {
743
						out.println("return " + dm + ";");
744
					}
745
				} else if (m.isArray) {
746
					out.println("return &(" + dm + "[j]);");
565dd78 by Jos van den Oever at 2009-09-18 747
				} else if (m.isOptional || m.condition != null) {
5c794b7 by Jos van den Oever at 2009-09-18 748
					out.println("return " + dm + ".data();");
749
				} else {
750
					out.println("return &(" + dm + ");");
370ab52 by Jos van den Oever at 2009-09-14 751
				}
752
			} else {
e9902ec by Jos van den Oever at 2010-01-21 753
				out.println("        return static_cast<const " + s.name
754
						+ "*>(i)->" + m.name + ".data();");
370ab52 by Jos van den Oever at 2009-09-14 755
			}
756
			out.println("    }");
757
		}
758
		out.println("};");
759
		out.println("const QString " + ns + "::name(\"" + s.name + "\");");
760
		out.println("const int " + ns + "::numberOfMembers(" + nm + ");");
761
		out.println("const QString " + ns + "::names[" + nm + "] = {");
762
		for (Member m : s.members) {
763
			out.println("    \"" + m.name + "\",");
764
		}
765
		out.println("};");
766
		out.println("int (* const " + ns + "::numberOfInstances[" + nm
767
				+ "])(const Introspectable*) = {");
768
		for (Member m : s.members) {
c9b5118 by Jos van den Oever at 2009-10-05 769
			if (m.condition != null
45c451d by Jos van den Oever at 2010-01-27 770
					|| ((m.isStruct || m.isChoice) && (m.isOptional || m.isArray))) {
370ab52 by Jos van den Oever at 2009-09-14 771
				out.println("    _Introspection::count_" + m.name + ",");
772
			} else {
5c794b7 by Jos van den Oever at 2009-09-18 773
				// arrays of simple types count as one instance
370ab52 by Jos van den Oever at 2009-09-14 774
				out.println("    Introspection::one,");
775
			}
776
		}
777
		out.println("};");
778
		out.println("QVariant (* const " + ns + "::value[" + nm
779
				+ "])(const Introspectable*, int position) = {");
780
		for (Member m : s.members) {
5354439 by Jos van den Oever at 2010-01-19 781
			if (s.name.equals("StyleTextPropAtom")
782
					&& config.enableStyleTextPropAtomFix
783
					&& m.name.equals("todo")) {
784
				break;
45c451d by Jos van den Oever at 2010-01-27 785
			} else if (m.isStruct || m.isChoice) {
370ab52 by Jos van den Oever at 2009-09-14 786
				out.println("    Introspection::nullValue,");
787
			} else {
788
				out.println("    _Introspection::get_" + m.name + ",");
789
			}
790
		}
791
		out.println("};");
792
		out.println("const Introspectable* (* const " + ns
793
				+ "::introspectable[" + nm
794
				+ "])(const Introspectable*, int position) = {");
795
		for (Member m : s.members) {
45c451d by Jos van den Oever at 2010-01-27 796
			if (m.isStruct || m.isChoice) {
370ab52 by Jos van den Oever at 2009-09-14 797
				out.println("    _Introspection::get_" + m.name + ",");
798
			} else {
799
				out.println("    Introspection::null,");
800
			}
801
		}
802
		out.println("};");
803
		out.println("const Introspection " + s.name + "::_introspection(");
804
		out
805
				.println("    \""
806
						+ s.name
807
						+ "\", "
808
						+ s.members.size()
809
						+ ", _Introspection::names, _Introspection::numberOfInstances, _Introspection::value, _Introspection::introspectable);");
2c22c86 by Jos van den Oever at 2009-08-27 810
	}
811
e9902ec by Jos van den Oever at 2010-01-21 812
	private void printChoiceParser(PrintWriter out, String s, String structure,
813
			Member m) {
97257cd by Jos van den Oever at 2010-01-28 814
		Choice c = (Choice) m.type();
815
		if (c.commonType == null) {
816
			printUnsureChoiceParser(out, s, structure, m);
817
		} else {
818
			printSureChoiceParser(out, s, structure, m);
819
		}
820
	}
821
9f955ab by Jos van den Oever at 2010-01-29 822
	String getClause(String name, TypeRegistry.Type t, Option.Lim lim) {
823
		String ls = "";
97257cd by Jos van den Oever at 2010-01-28 824
		if (lim.limitations != null && lim.limitations.length > 0) {
825
			for (int i = 0; i < lim.limitations.length; ++i) {
826
				Limitation l = lim.limitations[i];
827
				String condition = l.expression;
828
				String mname = name;
829
				if (t instanceof Struct) {
830
					mname += "." + l.name;
831
				}
832
				if (condition == null) {
833
					condition = getCondition(mname, l);
834
				} else {
835
					condition = getExpression(mname, condition);
836
				}
837
				if (ls.length() > 0) {
838
					ls += "&&";
839
				}
840
				ls += "(" + condition + ")";
841
			}
842
		} else if (lim.lims != null && lim.lims.length > 0) {
843
			for (int i = 0; i < lim.lims.length; ++i) {
9f955ab by Jos van den Oever at 2010-01-29 844
				Option.Lim l = lim.lims[i];
845
				String condition = getClause(name, t, l);
97257cd by Jos van den Oever at 2010-01-28 846
				if (ls.length() > 0) {
847
					ls += "||";
848
				}
849
				ls += "(" + condition + ")";
850
			}
851
		}
9f955ab by Jos van den Oever at 2010-01-29 852
		return ls.replace("..", ".");
97257cd by Jos van den Oever at 2010-01-28 853
	}
854
855
	private void printSureChoiceParser(PrintWriter out, String s,
856
			String structure, Member m) {
857
		out.println(s + "_m = in.setMark();");
858
		Choice c = (Choice) m.type();
859
		String type = getTypeName(c.commonType);
860
		if (c.commonType instanceof Struct) {
861
			out.println(s + type + " _choice(&_s);");
862
			out.println(s + "parse" + type + "(in, _choice);");
863
		} else {
864
			out.println(s + type + " _choice = in.read" + c.commonType.name
865
					+ "();");
866
		}
867
		out.println(s + "in.rewind(_m);");
b2c861d by Jos van den Oever at 2011-08-02 868
		out.println(s + "qint64 startPos = in.getPosition();");
97257cd by Jos van den Oever at 2010-01-28 869
		for (int i = 0; i < c.options.size(); ++i) {
870
			out.print(s);
871
			Option o = c.options.get(i);
9f955ab by Jos van den Oever at 2010-01-29 872
			String clause = getClause("_choice", o.limitsType, o.lim);
b2c861d by Jos van den Oever at 2011-08-02 873
			out.print("if (startPos == in.getPosition()");
97257cd by Jos van den Oever at 2010-01-28 874
			if (clause == null || (!m.isOptional && i == c.options.size() - 1)) {
b2c861d by Jos van den Oever at 2011-08-02 875
				out.println(") {");
97257cd by Jos van den Oever at 2010-01-28 876
			} else {
b2c861d by Jos van den Oever at 2011-08-02 877
				out.println(" && (" + clause + ")) {");
97257cd by Jos van den Oever at 2010-01-28 878
			}
879
			out.println(s + "    _s." + m.name + " = " + structure + "::"
880
					+ m.type().name + "(new " + o.type.name + "(&_s));");
881
			out.println(s + "    parse" + o.type.name + "(in, *(" + o.type.name
882
					+ "*)_s." + m.name + ".data());");
b2c861d by Jos van den Oever at 2011-08-02 883
			out.println(s + "}");
97257cd by Jos van den Oever at 2010-01-28 884
		}
885
	}
886
887
	private void printUnsureChoiceParser(PrintWriter out, String s,
888
			String structure, Member m) {
2c22c86 by Jos van den Oever at 2009-08-27 889
		String closing = "";
890
		String exception = "_x";
75317b3 by Jos van den Oever at 2009-09-12 891
		String choice;
267ecf8 by Jos van den Oever at 2009-09-29 892
		out.println(s + "_m = in.setMark();");
2ff50d9 by Jos van den Oever at 2010-01-27 893
		Choice c = (Choice) m.type();
894
		String choices[] = c.getChoiceNames();
4c82fdb by Jos van den Oever at 2009-10-19 895
		int length = (m.isOptional) ? choices.length : choices.length - 1;
267ecf8 by Jos van den Oever at 2009-09-29 896
		for (int i = 0; i < length; ++i) {
4c82fdb by Jos van den Oever at 2009-10-19 897
			choice = choices[i];
2c22c86 by Jos van den Oever at 2009-08-27 898
			out.println(s + "try {");
e9902ec by Jos van den Oever at 2010-01-21 899
			out.println(s + "    _s." + m.name + " = " + structure + "::"
4d13121 by Jos van den Oever at 2010-01-28 900
					+ c.name + "(new " + choice + "(&_s));");
e9902ec by Jos van den Oever at 2010-01-21 901
			out.println(s + "    parse" + choice + "(in, *(" + choice + "*)_s."
902
					+ m.name + ".data());");
2c22c86 by Jos van den Oever at 2009-08-27 903
			out.println(s + "} catch (IncorrectValueException " + exception
904
					+ ") {");
e9902ec by Jos van den Oever at 2010-01-21 905
			out.println(s + "    _s." + m.name + ".clear();");
2c22c86 by Jos van den Oever at 2009-08-27 906
			out.println(s + "    in.rewind(_m);");
907
			exception = exception + "x";
908
			closing = closing + "}";
909
		}
267ecf8 by Jos van den Oever at 2009-09-29 910
		if (!m.isOptional) {
4c82fdb by Jos van den Oever at 2009-10-19 911
			choice = choices[choices.length - 1];
e9902ec by Jos van den Oever at 2010-01-21 912
			out.println(s + "    _s." + m.name + " = " + structure + "::"
4d13121 by Jos van den Oever at 2010-01-28 913
					+ c.name + "(new " + choice + "(&_s));");
e9902ec by Jos van den Oever at 2010-01-21 914
			out.println(s + "    parse" + choice + "(in, *(" + choice + "*)_s."
915
					+ m.name + ".data());");
267ecf8 by Jos van den Oever at 2009-09-29 916
		}
75317b3 by Jos van den Oever at 2009-09-12 917
		out.println(s + closing);
2c22c86 by Jos van den Oever at 2009-08-27 918
	}
919
dfb9941 by Jos van den Oever at 2010-01-20 920
	private void printFixedSizeArrayParser(PrintWriter out, String s, Member m) {
a2a1ba0 by Sebastian Sauer at 2010-08-05 921
		out.println(s + "qint64 _startPos = in.getPosition();");
63e62fc by Jos van den Oever at 2010-09-15 922
		/* _totalSize should really be just getExpression("_s", m.size)
923
		   The check for the end of the stream is only a workaround for
924
		   a limitation in the current Excel file parser. In Excel,
925
		   the stream is split up in blocks and the current code parses
926
		   these blocks separately and reassembles them later instead of
927
		   assembling the raw data transparantly in a stream. */
a2a1ba0 by Sebastian Sauer at 2010-08-05 928
		out.println(s + "int _totalSize = qMin(" + getExpression("_s", m.size)
929
				+ ", quint32(in.getSize() - _startPos));");
930
		out.println(s + "_atend = in.getPosition() - _startPos >= _totalSize;");
362eef6 by Jos van den Oever at 2009-10-24 931
		out.println(s + "while (!_atend) {");
2ff50d9 by Jos van den Oever at 2010-01-27 932
		out.println(s + "    _s." + m.name + ".append(" + m.type().name
933
				+ "(&_s));");
934
		out.println(s + "    parse" + m.type().name + "(in, _s." + m.name
a9c0e8f by Jos van den Oever at 2009-11-04 935
				+ ".last());");
a2a1ba0 by Sebastian Sauer at 2010-08-05 936
		out.println(s + "    _atend = in.getPosition() - _startPos >= _totalSize;");
e013083 by Jos van den Oever at 2009-09-16 937
		out.println(s + "}");
938
	}
939
dfb9941 by Jos van den Oever at 2010-01-20 940
	private void printVariableArrayParser(PrintWriter out, String s, Member m) {
700ccda by Jos van den Oever at 2009-09-14 941
		out.println(s + "_atend = false;");
2c22c86 by Jos van den Oever at 2009-08-27 942
		out.println(s + "while (!_atend) {");
943
		out.println(s + "    _m = in.setMark();");
944
		out.println(s + "    try {");
2ff50d9 by Jos van den Oever at 2010-01-27 945
		out.println(s + "        _s." + m.name + ".append(" + m.type().name
e20cfd2 by Jos van den Oever at 2010-01-20 946
				+ "(&_s));");
2ff50d9 by Jos van den Oever at 2010-01-27 947
		out.println(s + "        parse" + m.type().name + "(in, _s." + m.name
a9c0e8f by Jos van den Oever at 2009-11-04 948
				+ ".last());");
2c22c86 by Jos van den Oever at 2009-08-27 949
		out.println(s + "    } catch(IncorrectValueException _e) {");
a9c0e8f by Jos van den Oever at 2009-11-04 950
		out.println(s + "        _s." + m.name + ".removeLast();");
2c22c86 by Jos van den Oever at 2009-08-27 951
		out.println(s + "        _atend = true;");
952
		out.println(s + "        in.rewind(_m);");
75317b3 by Jos van den Oever at 2009-09-12 953
		out.println(s + "    } catch(EOFException _e) {");
a9c0e8f by Jos van den Oever at 2009-11-04 954
		out.println(s + "        _s." + m.name + ".removeLast();");
2c22c86 by Jos van den Oever at 2009-08-27 955
		out.println(s + "        _atend = true;");
956
		out.println(s + "        in.rewind(_m);");
957
		out.println(s + "    }");
958
		out.println(s + "}");
959
	}
960
dfb9941 by Jos van den Oever at 2010-01-20 961
	private void printOptionalMemberParser(PrintWriter out, String s, Member m) {
2c22c86 by Jos van den Oever at 2009-08-27 962
		out.println(s + "_m = in.setMark();");
9f955ab by Jos van den Oever at 2010-01-29 963
		Option o = new Option((Struct) m.type(), null);
964
		String type = getTypeName(o.limitsType);
73319fb by Jos van den Oever at 2010-03-12 965
		out.println(s + "try {");
9f955ab by Jos van den Oever at 2010-01-29 966
		out.println(s + "    " + type + " _optionCheck(&_s);");
967
		out.println(s + "    parse" + type + "(in, _optionCheck);");
968
		out.println(s + "    _possiblyPresent = "
969
				+ getClause("_optionCheck", o.limitsType, o.lim) + ";");
73319fb by Jos van den Oever at 2010-03-12 970
		out.println(s + "} catch(EOFException _e) {");
971
		out.println(s + "    _possiblyPresent = false;");
9f955ab by Jos van den Oever at 2010-01-29 972
		out.println(s + "}");
73319fb by Jos van den Oever at 2010-03-12 973
9f955ab by Jos van den Oever at 2010-01-29 974
		out.println(s + "in.rewind(_m);");
975
		out.println(s + "_m = in.setMark();");
976
		out.println(s + "if (_possiblyPresent) {");
977
		out.println(s + "    try {");
978
		out.println(s + "        _s." + m.name + " = QSharedPointer<"
2ff50d9 by Jos van den Oever at 2010-01-27 979
				+ m.type().name + ">(new " + m.type().name + "(&_s));");
9f955ab by Jos van den Oever at 2010-01-29 980
		out.println(s + "        parse" + m.type().name + "(in, *_s." + m.name
a9c0e8f by Jos van den Oever at 2009-11-04 981
				+ ".data());");
9f955ab by Jos van den Oever at 2010-01-29 982
		out.println(s + "    } catch(IncorrectValueException _e) {");
983
		out.println(s + "        _s." + m.name + ".clear();");
984
		out.println(s + "        in.rewind(_m);");
985
		out.println(s + "    } catch(EOFException _e) {");
986
		out.println(s + "        _s." + m.name + ".clear();");
987
		out.println(s + "        in.rewind(_m);");
988
		out.println(s + "    }");
2c22c86 by Jos van den Oever at 2009-08-27 989
		out.println(s + "}");
990
	}
991
dfb9941 by Jos van den Oever at 2010-01-20 992
	private void printLimitationCheck(PrintWriter out, String s, String name,
993
			Member m) {
2c22c86 by Jos van den Oever at 2009-08-27 994
		for (Limitation l : m.limitations) {
995
			String mname = l.name;
996
			if (!"".equals(mname)) {
997
				mname = name + "." + mname;
998
			} else {
999
				mname = name;
1000
			}
45c451d by Jos van den Oever at 2010-01-27 1001
			if (!m.isStruct) {
97257cd by Jos van den Oever at 2010-01-28 1002
				mname = "((" + getTypeName(m.type()) + ")" + mname + ")";
75317b3 by Jos van den Oever at 2009-09-12 1003
			}
2c22c86 by Jos van den Oever at 2009-08-27 1004
			String condition = l.expression;
1005
			if (condition == null) {
1006
				condition = getCondition(mname, l);
1007
			} else {
1008
				condition = getExpression(mname, condition);
1009
			}
1010
1011
			out.println(s + "if (!(" + condition + ")) {");
1012
			String exceptionType = "IncorrectValueException";
1013
			out.println(s + "    throw " + exceptionType
9c08e45 by Jos van den Oever at 2009-09-20 1014
					+ "(in.getPosition(), \"" + condition + "\");");
2c22c86 by Jos van den Oever at 2009-08-27 1015
			out.println(s + "}");
1016
		}
1017
	}
1bf0673 by Jos van den Oever at 2009-08-24 1018
a3b7549 by Jos van den Oever at 2010-01-31 1019
	static String getExpression(String structure, String expression) {
2c22c86 by Jos van den Oever at 2009-08-27 1020
		if (Pattern.matches(".*[A-Za-z].*", expression)) {
1021
			return prependStructureToExpression(expression, structure);
1022
		}
1023
		return structure + expression;
1bf0673 by Jos van den Oever at 2009-08-24 1024
	}
1025
a3b7549 by Jos van den Oever at 2010-01-31 1026
	static String getCondition(String name, Limitation l) {
2c22c86 by Jos van den Oever at 2009-08-27 1027
		String value = l.value;
1028
		String cmp = " == ";
1029
		String cmb = " || ";
1030
		if (value.startsWith("!")) {
1031
			value = value.substring(1);
1032
			cmp = " != ";
1033
			cmb = " && ";
1034
		}
1035
		if (value.contains("|")) {
1036
			String values[] = value.split("\\|");
1037
			String c = name + cmp + values[0];
1038
			for (int i = 1; i < values.length; ++i) {
1039
				c = c + cmb + name + cmp + values[i];
7ef14a6 by Jos van den Oever at 2009-08-26 1040
			}
2c22c86 by Jos van den Oever at 2009-08-27 1041
			return c;
1042
		}
1043
		if (!"".equals(value)) {
1044
			return name + cmp + value;
1bf0673 by Jos van den Oever at 2009-08-24 1045
		}
2c22c86 by Jos van den Oever at 2009-08-27 1046
		return l.value;
1bf0673 by Jos van den Oever at 2009-08-24 1047
	}
1048
}