Coverage Report

Created: 2026-03-12 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: