/src/libmwaw/src/lib/RagTime5StructManager.hxx
Line | Count | Source |
1 | | /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ |
2 | | |
3 | | /* libmwaw |
4 | | * Version: MPL 2.0 / LGPLv2+ |
5 | | * |
6 | | * The contents of this file are subject to the Mozilla Public License Version |
7 | | * 2.0 (the "License"); you may not use this file except in compliance with |
8 | | * the License or as specified alternatively below. You may obtain a copy of |
9 | | * the License at http://www.mozilla.org/MPL/ |
10 | | * |
11 | | * Software distributed under the License is distributed on an "AS IS" basis, |
12 | | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
13 | | * for the specific language governing rights and limitations under the |
14 | | * License. |
15 | | * |
16 | | * Major Contributor(s): |
17 | | * Copyright (C) 2002 William Lachance (wrlach@gmail.com) |
18 | | * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) |
19 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
20 | | * Copyright (C) 2006, 2007 Andrew Ziem |
21 | | * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) |
22 | | * |
23 | | * |
24 | | * All Rights Reserved. |
25 | | * |
26 | | * For minor contributions see the git repository. |
27 | | * |
28 | | * Alternatively, the contents of this file may be used under the terms of |
29 | | * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), |
30 | | * in which case the provisions of the LGPLv2+ are applicable |
31 | | * instead of those above. |
32 | | */ |
33 | | |
34 | | #ifndef RAG_TIME_5_STRUCT_MANAGER |
35 | | # define RAG_TIME_5_STRUCT_MANAGER |
36 | | |
37 | | #include <map> |
38 | | #include <ostream> |
39 | | #include <sstream> |
40 | | #include <string> |
41 | | #include <vector> |
42 | | |
43 | | #include "libmwaw_internal.hxx" |
44 | | #include "MWAWDebug.hxx" |
45 | | #include "MWAWEntry.hxx" |
46 | | |
47 | | class RagTime5Document; |
48 | | |
49 | | //! main zone in a RagTime v5-v6 document |
50 | | class RagTime5Zone |
51 | | { |
52 | | public: |
53 | | //! constructor |
54 | | RagTime5Zone(MWAWInputStreamPtr const &input, libmwaw::DebugFile &asc) |
55 | 3.69M | : m_level(-1) |
56 | 3.69M | , m_parentName("") |
57 | 3.69M | , m_defPosition(0) |
58 | 3.69M | , m_entry() |
59 | 3.69M | , m_name("") |
60 | 3.69M | , m_hiLoEndian(true) |
61 | 3.69M | , m_entriesList() |
62 | 3.69M | , m_childIdToZoneMap() |
63 | 3.69M | , m_isInitialised(false) |
64 | 3.69M | , m_isParsed(false) |
65 | 3.69M | , m_extra("") |
66 | 3.69M | , m_input() |
67 | 3.69M | , m_defaultInput(input) |
68 | 3.69M | , m_asciiName("") |
69 | 3.69M | , m_asciiFile(&asc) |
70 | 3.69M | , m_mainAsciiFile(&asc) |
71 | 3.69M | , m_localAsciiFile() |
72 | 3.69M | { |
73 | 11.0M | for (auto &id : m_ids) id=0; |
74 | 11.0M | for (auto &idFlag : m_idsFlag) idFlag=0; |
75 | 7.38M | for (auto &kind : m_kinds) kind=""; |
76 | 7.38M | for (auto &variableD : m_variableD) variableD=0; |
77 | 3.69M | } |
78 | | //! destructor |
79 | | virtual ~RagTime5Zone(); |
80 | | //! returns the zone name |
81 | | std::string getZoneName() const; |
82 | | //! returns the main type |
83 | | std::string getKindLastPart(bool main=true) const |
84 | 6.21M | { |
85 | 6.21M | std::string res(m_kinds[main ? 0 : 1]); |
86 | 6.21M | std::string::size_type pos = res.find_last_of(':'); |
87 | 6.21M | if (pos == std::string::npos) return res; |
88 | 5.21M | return res.substr(pos+1); |
89 | 6.21M | } |
90 | | |
91 | | //! operator<< |
92 | | friend std::ostream &operator<<(std::ostream &o, RagTime5Zone const &z); |
93 | | //! returns the current input |
94 | | MWAWInputStreamPtr getInput() |
95 | 8.04M | { |
96 | 8.04M | return m_input; |
97 | 8.04M | } |
98 | | //! reset the current input |
99 | | void setInput(MWAWInputStreamPtr const &input) |
100 | 2.53M | { |
101 | 2.53M | m_input = input; |
102 | 2.53M | } |
103 | | //! returns true if the input correspond to the basic file |
104 | | bool isMainInput() const |
105 | 4.52M | { |
106 | 4.52M | return m_input.get()==m_defaultInput.get(); |
107 | 4.52M | } |
108 | | //! returns the current ascii file |
109 | | libmwaw::DebugFile &ascii() |
110 | 4.52M | { |
111 | 4.52M | if (!isMainInput() && !m_localAsciiFile) |
112 | 439k | createAsciiFile(); |
113 | 4.52M | return *m_asciiFile; |
114 | 4.52M | } |
115 | | //! defines the ascii name |
116 | | void setAsciiFileName(std::string const &name) |
117 | 1.96M | { |
118 | 1.96M | m_asciiName = name; |
119 | 1.96M | } |
120 | | //! creates the ascii file |
121 | | void createAsciiFile(); |
122 | | //! mark a zone as bad |
123 | | void addErrorInDebugFile(std::string const &zoneName); |
124 | | |
125 | | //! the zone level |
126 | | int m_level; |
127 | | //! the parent name |
128 | | std::string m_parentName; |
129 | | //! the position of the definition in the main zones |
130 | | long m_defPosition; |
131 | | //! the zone types: normal and packing |
132 | | std::string m_kinds[2]; |
133 | | //! the zone entry |
134 | | MWAWEntry m_entry; |
135 | | //! the zone name ( mainly used for debugging) |
136 | | std::string m_name; |
137 | | //! true if the endian is hilo |
138 | | bool m_hiLoEndian; |
139 | | //! the zone id |
140 | | int m_ids[3]; |
141 | | //! the zone flag |
142 | | int m_idsFlag[3]; |
143 | | //! the list of original entries |
144 | | std::vector<MWAWEntry> m_entriesList; |
145 | | //! the child zones |
146 | | std::map<int,std::shared_ptr<RagTime5Zone> > m_childIdToZoneMap; |
147 | | //! the content of the zone D if it exists |
148 | | int m_variableD[2]; |
149 | | //! a flag to know if the zone is initialised (stream, hiLoEndian) |
150 | | mutable bool m_isInitialised; |
151 | | //! a flag to know if the zone is parsed |
152 | | mutable bool m_isParsed; |
153 | | //! extra data |
154 | | std::string m_extra; |
155 | | protected: |
156 | | //! the main input |
157 | | MWAWInputStreamPtr m_input; |
158 | | //! the main file input |
159 | | MWAWInputStreamPtr m_defaultInput; |
160 | | //! the ascii file name ( used if we need to create a ascii file) |
161 | | std::string m_asciiName; |
162 | | //! the ascii file corresponding to an input |
163 | | libmwaw::DebugFile *m_asciiFile; |
164 | | //! the main ascii file (used to print error) |
165 | | libmwaw::DebugFile *m_mainAsciiFile; |
166 | | //! the local ascii file ( if we need to create a new input) |
167 | | std::shared_ptr<libmwaw::DebugFile> m_localAsciiFile; |
168 | | private: |
169 | | RagTime5Zone(RagTime5Zone const &orig) = delete; |
170 | | RagTime5Zone &operator=(RagTime5Zone const &orig) = delete; |
171 | | }; |
172 | | |
173 | | //! basic class used to store RagTime 5/6 structures |
174 | | class RagTime5StructManager |
175 | | { |
176 | | public: |
177 | | struct Field; |
178 | | //! constructor |
179 | | explicit RagTime5StructManager(RagTime5Document &doc); |
180 | | //! destructor |
181 | | ~RagTime5StructManager(); |
182 | | |
183 | | //! try to read a list of type definition |
184 | | bool readTypeDefinitions(RagTime5Zone &zone); |
185 | | //! try to read a field |
186 | | bool readField(MWAWInputStreamPtr input, long endPos, libmwaw::DebugFile &ascFile, |
187 | | Field &field, long fSz=0); |
188 | | //! try to read a compressed long |
189 | | static bool readCompressedLong(MWAWInputStreamPtr &input, long endPos, long &val); |
190 | | //! try to read a unicode string |
191 | | static bool readUnicodeString(MWAWInputStreamPtr input, long endPos, librevenge::RVNGString &string); |
192 | | //! try to read n data id |
193 | | static bool readDataIdList(MWAWInputStreamPtr input, int n, std::vector<int> &listIds); |
194 | | |
195 | | //! debug: print a file type |
196 | | static std::string printType(unsigned long fileType); |
197 | | |
198 | | //! a tabulation in RagTime 5/6 structures |
199 | | struct TabStop { |
200 | | //! constructor |
201 | | TabStop() |
202 | 4.09k | : m_position(0) |
203 | 4.09k | , m_type(1) |
204 | 4.09k | , m_leaderChar(0) |
205 | 4.09k | { |
206 | 4.09k | } |
207 | | //! operator<< |
208 | | friend std::ostream &operator<<(std::ostream &o, TabStop const &tab) |
209 | 4 | { |
210 | 4 | o << tab.m_position; |
211 | 4 | switch (tab.m_type) { |
212 | 0 | case 1: |
213 | 0 | break; |
214 | 0 | case 2: |
215 | 0 | o << "R"; |
216 | 0 | break; |
217 | 0 | case 3: |
218 | 0 | o << "C"; |
219 | 0 | break; |
220 | 0 | case 4: |
221 | 0 | o << "D"; |
222 | 0 | break; |
223 | 0 | case 5: // Kintou Waritsuke: sort of center |
224 | 0 | o << "K"; |
225 | 0 | break; |
226 | 4 | default: |
227 | 4 | o << ":#type=" << tab.m_type; |
228 | 4 | break; |
229 | 4 | } |
230 | 4 | if (tab.m_leaderChar>0) |
231 | 0 | o << ":leader=" << char(tab.m_leaderChar); |
232 | 4 | return o; |
233 | 4 | } |
234 | | //! the position |
235 | | float m_position; |
236 | | //! the type |
237 | | int m_type; |
238 | | //! the unicode leader char |
239 | | uint16_t m_leaderChar; |
240 | | }; |
241 | | //! a field of RagTime 5/6 structures |
242 | | struct Field { |
243 | | //! the different type |
244 | | enum Type { T_Unknown, T_Bool, T_Double, T_Long, T_2Long, T_FieldList, T_LongList, T_DoubleList, T_TabList, |
245 | | T_Code, T_Color, T_CondColor, T_PrintInfo, T_String, T_Unicode, T_ZoneId, T_LongDouble, T_Unstructured |
246 | | }; |
247 | | |
248 | | //! constructor |
249 | | Field() |
250 | 4.56M | : m_type(T_Unknown) |
251 | 4.56M | , m_fileType(0) |
252 | 4.56M | , m_name("") |
253 | 4.56M | , m_doubleValue(0) |
254 | 4.56M | , m_color() |
255 | 4.56M | , m_string("") |
256 | 4.56M | , m_longList() |
257 | 4.56M | , m_doubleList() |
258 | 4.56M | , m_numLongByData(1) |
259 | 4.56M | , m_tabList() |
260 | 4.56M | , m_fieldList() |
261 | 4.56M | , m_entry() |
262 | 4.56M | , m_extra("") |
263 | 4.56M | { |
264 | 9.12M | for (auto &val : m_longValue) val=0; |
265 | 4.56M | } |
266 | 1.16M | Field(Field const &)=default; |
267 | | //! destructor |
268 | | ~Field() |
269 | 5.72M | { |
270 | 5.72M | } |
271 | | //! operator<< |
272 | | friend std::ostream &operator<<(std::ostream &o, Field const &field); |
273 | | //! the field type |
274 | | Type m_type; |
275 | | //! the file type |
276 | | unsigned long m_fileType; |
277 | | //! the field type name |
278 | | std::string m_name; |
279 | | //! the long value |
280 | | long m_longValue[2]; |
281 | | //! the double value |
282 | | double m_doubleValue; |
283 | | //! the color |
284 | | MWAWColor m_color; |
285 | | //! small string use to store a string or a 4 char code |
286 | | librevenge::RVNGString m_string; |
287 | | //! the list of long value |
288 | | std::vector<long> m_longList; |
289 | | //! the list of double value |
290 | | std::vector<double> m_doubleList; |
291 | | //! the number of long by data (in m_longList) |
292 | | int m_numLongByData; |
293 | | //! the list of tabStop |
294 | | std::vector<TabStop> m_tabList; |
295 | | //! the list of field |
296 | | std::vector<Field> m_fieldList; |
297 | | //! entry to defined the position of a String or Unstructured data |
298 | | MWAWEntry m_entry; |
299 | | //! extra data |
300 | | std::string m_extra; |
301 | | }; |
302 | | //! a zone link in RagTime 5/6 structures |
303 | | struct ZoneLink { |
304 | | //! constructor |
305 | | ZoneLink() |
306 | 53.8k | : m_dataId(0) |
307 | 53.8k | , m_valuesList() |
308 | 53.8k | , m_extra("") |
309 | 53.8k | { |
310 | 107k | for (auto &id : m_subZoneId) id=0; |
311 | 53.8k | } |
312 | | //! returns the sub zone id |
313 | | int getSubZoneId(int i) const |
314 | 11.7k | { |
315 | 11.7k | if (i<0 || i>=2) { |
316 | 0 | MWAW_DEBUG_MSG(("RagTime5StructManager::ZoneLink::getSubZoneId: called with bad value=%d\n", i)); |
317 | 0 | return 0; |
318 | 0 | } |
319 | 11.7k | return (m_subZoneId[0]&0x3fffffff); |
320 | 11.7k | } |
321 | | //! operator<< |
322 | | friend std::ostream &operator<<(std::ostream &o, ZoneLink const &link) |
323 | 0 | { |
324 | 0 | if (link.m_dataId) o << "data" << link.m_dataId << "A,"; |
325 | 0 | if (link.m_subZoneId[0]) { |
326 | 0 | if (link.m_subZoneId[0]> 0&& (static_cast<unsigned long>(link.m_subZoneId[0])&0xc0000000)==0) |
327 | 0 | o << "data[subId]=" << link.m_subZoneId[0] << ","; |
328 | 0 | else |
329 | 0 | o << "data[subId]=" << (link.m_subZoneId[0]&0x3fffffff) << "[" << (((unsigned long)link.m_subZoneId[0])>>30) << "],"; |
330 | 0 | } |
331 | 0 | if (link.m_subZoneId[1]) { |
332 | 0 | if (link.m_subZoneId[1]>0 && (static_cast<unsigned long>(link.m_subZoneId[1])&0xff000000)==0) |
333 | 0 | o << "orig[subId]=" << link.m_subZoneId[1] << ","; |
334 | 0 | else |
335 | 0 | o << "orig[subId]=" << (link.m_subZoneId[1]&0x00ffffff) << "[" << (((unsigned long)link.m_subZoneId[1])>>24) << "],"; |
336 | 0 | } |
337 | 0 | for (size_t i=0; i<link.m_valuesList.size(); ++i) { |
338 | 0 | if (!link.m_valuesList[i]) continue; |
339 | 0 | o << "f" << i << "=" << link.m_valuesList[i] << ","; |
340 | 0 | } |
341 | 0 | return o; |
342 | 0 | } |
343 | | //! the data id (or 0) |
344 | | int m_dataId; |
345 | | //! the sub id zones |
346 | | long m_subZoneId[2]; |
347 | | //! list of potential values |
348 | | std::vector<long> m_valuesList; |
349 | | //! extra data |
350 | | std::string m_extra; |
351 | | }; |
352 | | //! virtual class use to parse the field data |
353 | | struct FieldParser { |
354 | | //! constructor |
355 | | explicit FieldParser(std::string const &zoneName) |
356 | 142k | : m_regroupFields(false) |
357 | 142k | , m_name(zoneName) |
358 | 142k | { |
359 | 142k | } |
360 | | //! destructor |
361 | | virtual ~FieldParser(); |
362 | | //! return the debug name corresponding to a zone |
363 | | virtual std::string getZoneName() const |
364 | 57.3k | { |
365 | 57.3k | return m_name; |
366 | 57.3k | } |
367 | | //! return the debug name corresponding to a field |
368 | | virtual std::string getZoneName(int n) const |
369 | 204k | { |
370 | 204k | std::stringstream s; |
371 | 204k | s << m_name << "-" << n; |
372 | 204k | return s.str(); |
373 | 204k | } |
374 | | //! parse a header field |
375 | | virtual bool parseHeaderField(Field &field, RagTime5Zone &/*zone*/, int /*n*/, libmwaw::DebugStream &f) |
376 | 61.0k | { |
377 | 61.0k | f << field; |
378 | 61.0k | return true; |
379 | 61.0k | } |
380 | | //! parse a field |
381 | | virtual bool parseField(Field &field, RagTime5Zone &/*zone*/, int /*n*/, libmwaw::DebugStream &f) |
382 | 226k | { |
383 | 226k | f << field; |
384 | 226k | return true; |
385 | 226k | } |
386 | | //! a flag use to decide if we output one debug message by field or not |
387 | | bool m_regroupFields; |
388 | | protected: |
389 | | //! the field name |
390 | | std::string m_name; |
391 | | private: |
392 | | FieldParser(FieldParser const &orig) = delete; |
393 | | FieldParser &operator=(FieldParser const &orig) = delete; |
394 | | }; |
395 | | //! virtual class use to parse the unstructured data |
396 | | struct DataParser { |
397 | | //! constructor |
398 | | explicit DataParser(std::string const &zoneName); |
399 | | //! destructor |
400 | | virtual ~DataParser(); |
401 | | //! return the debug name corresponding to a zone |
402 | | virtual std::string getZoneName() const |
403 | 151k | { |
404 | 151k | return m_name; |
405 | 151k | } |
406 | | //! return the debug name corresponding to a field |
407 | | virtual std::string getZoneName(int n) const |
408 | 453k | { |
409 | 453k | std::stringstream s; |
410 | 453k | s << m_name << "-" << n; |
411 | 453k | return s.str(); |
412 | 453k | } |
413 | | //! parse a data |
414 | | virtual bool parseData(MWAWInputStreamPtr &/*input*/, long /*endPos*/, RagTime5Zone &/*zone*/, int /*n*/, libmwaw::DebugStream &/*f*/) |
415 | 16.2k | { |
416 | 16.2k | return true; |
417 | 16.2k | } |
418 | | protected: |
419 | | //! the field name |
420 | | std::string m_name; |
421 | | private: |
422 | | DataParser(DataParser const &orig) = delete; |
423 | | DataParser &operator=(DataParser const &orig) = delete; |
424 | | }; |
425 | | |
426 | | /** basic parser to read image/main graphic position properties*/ |
427 | | struct GObjPropFieldParser final : public FieldParser { |
428 | | //! constructor |
429 | | explicit GObjPropFieldParser(std::string const &name) |
430 | 42.5k | : FieldParser(name) |
431 | 42.5k | , m_clusterId(0) |
432 | 42.5k | { |
433 | 42.5k | } |
434 | | //! parse a field |
435 | | bool parseField(Field &field, RagTime5Zone &zone, int n, libmwaw::DebugStream &f) final; |
436 | | |
437 | | //! the id of the zone corresponding to this property (always a clust graph ?) |
438 | | int m_clusterId; |
439 | | }; |
440 | | |
441 | | private: |
442 | | //! the main document |
443 | | RagTime5Document &m_document; |
444 | | |
445 | | RagTime5StructManager(RagTime5StructManager const &orig) = delete; |
446 | | RagTime5StructManager operator=(RagTime5StructManager const &orig) = delete; |
447 | | }; |
448 | | |
449 | | #endif |
450 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |