Coverage Report

Created: 2026-09-06 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libetonyek/src/lib/NUM1Parser.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/*
3
 * This file is part of the libetonyek project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 */
9
10
#include "NUM1Parser.h"
11
12
#include "libetonyek_xml.h"
13
#include "IWORKCellCommentDrawableInfoElement.h"
14
#include "IWORKChainedTokenizer.h"
15
#include "IWORKChartInfoElement.h"
16
#include "IWORKDiscardContext.h"
17
#include "IWORKGeometryElement.h"
18
#include "IWORKGroupElement.h"
19
#include "IWORKImageElement.h"
20
#include "IWORKMediaElement.h"
21
#include "IWORKMetadataElement.h"
22
#include "IWORKPathElement.h"
23
#include "IWORKRefContext.h"
24
#include "IWORKShapeContext.h"
25
#include "IWORKStyleContainer.h"
26
#include "IWORKStyleContext.h"
27
#include "IWORKStylesContext.h"
28
#include "IWORKStylesheetBase.h"
29
#include "IWORKTabularInfoElement.h"
30
#include "IWORKTextElement.h"
31
#include "IWORKToken.h"
32
#include "NUMCollector.h"
33
#include "NUM1Dictionary.h"
34
#include "NUM1Token.h"
35
#include "NUM1XMLContextBase.h"
36
37
namespace libetonyek
38
{
39
40
namespace
41
{
42
43
unsigned getVersion(const int token)
44
0
{
45
0
  switch (token)
46
0
  {
47
0
  case NUM1Token::VERSION_STR_2 :
48
0
    return 2;
49
0
  default:
50
0
    break;
51
0
  }
52
53
0
  return 0;
54
0
}
55
56
}
57
58
namespace
59
{
60
class StickyNoteElement : public NUM1XMLElementContextBase
61
{
62
public:
63
  explicit StickyNoteElement(NUM1ParserState &state);
64
65
private:
66
  void startOfElement() override;
67
  IWORKXMLContextPtr_t element(int name) override;
68
  void endOfElement() override;
69
70
  IWORKStylePtr_t m_graphicStyle;
71
};
72
73
StickyNoteElement::StickyNoteElement(NUM1ParserState &state)
74
0
  : NUM1XMLElementContextBase(state)
75
0
  , m_graphicStyle()
76
0
{
77
0
}
78
79
void StickyNoteElement::startOfElement()
80
0
{
81
0
  if (isCollector())
82
0
  {
83
0
    assert(!getState().m_currentText);
84
0
    getState().m_currentText = getCollector().createText(getState().m_langManager);
85
0
    getCollector().startLevel();
86
0
  }
87
0
}
88
89
typedef IWORKStyleContainer<+IWORKToken::NS_URI_SF | IWORKToken::graphic_style, +IWORKToken::NS_URI_SF | IWORKToken::graphic_style_ref> GraphicStyleContext;
90
91
IWORKXMLContextPtr_t StickyNoteElement::element(const int name)
92
0
{
93
0
  switch (name)
94
0
  {
95
0
  case +IWORKToken::NS_URI_SF | IWORKToken::geometry :
96
0
    return std::make_shared<IWORKGeometryElement>(getState());
97
0
  case +IWORKToken::NS_URI_SF | IWORKToken::path : // use me
98
0
    return std::make_shared<IWORKPathElement>(getState());
99
0
  case +IWORKToken::NS_URI_SF | IWORKToken::style : // use me
100
0
    return std::make_shared<GraphicStyleContext>(getState(), m_graphicStyle, getState().getDictionary().m_graphicStyles);
101
0
  case +IWORKToken::NS_URI_SF | IWORKToken::text :
102
0
    return std::make_shared<IWORKTextElement>(getState());
103
0
  case +IWORKToken::NS_URI_SF | IWORKToken::wrap : // README
104
0
    return IWORKXMLContextPtr_t();
105
0
  default:
106
0
    ETONYEK_DEBUG_MSG(("StickyNoteElement::element[NUM1Parser.cpp]: unknown element\n"));
107
0
    break;
108
0
  }
109
110
0
  return IWORKXMLContextPtr_t();
111
0
}
112
113
void StickyNoteElement::endOfElement()
114
0
{
115
0
  if (isCollector())
116
0
  {
117
0
    getCollector().collectText(getState().m_currentText);
118
0
    getState().m_currentText.reset();
119
0
    getCollector().collectStickyNote();
120
121
0
    getCollector().endLevel();
122
0
  }
123
0
}
124
}
125
namespace
126
{
127
128
class DrawablesElement : public NUM1XMLElementContextBase
129
{
130
public:
131
  explicit DrawablesElement(NUM1ParserState &state);
132
133
private:
134
  void startOfElement() override;
135
  void attribute(int name, const char *value) override;
136
  IWORKXMLContextPtr_t element(int name) override;
137
  void endOfElement() override;
138
};
139
140
DrawablesElement::DrawablesElement(NUM1ParserState &state)
141
0
  : NUM1XMLElementContextBase(state)
142
0
{
143
0
}
144
145
void DrawablesElement::startOfElement()
146
0
{
147
0
  if (isCollector())
148
0
    getCollector().startLevel();
149
0
}
150
151
void DrawablesElement::attribute(int, const char *)
152
0
{
153
0
}
154
155
IWORKXMLContextPtr_t DrawablesElement::element(const int name)
156
0
{
157
0
  switch (name)
158
0
  {
159
  // case IWORKToken::NS_URI_SF | IWORKToken::body_placeholder_ref :
160
  //   return std::make_shared<PlaceholderRefContext>(getState(), false);
161
0
  case +IWORKToken::NS_URI_SF | IWORKToken::cell_comment_drawable_info:
162
0
    return std::make_shared<IWORKCellCommentDrawableInfoElement>(getState());
163
0
  case +IWORKToken::NS_URI_SF | IWORKToken::chart_info :
164
0
    return std::make_shared<IWORKChartInfoElement>(getState());
165
  // case IWORKToken::NS_URI_SF | IWORKToken::connection_line :
166
  //   return std::make_shared<ConnectionLineElement>(getState());
167
0
  case +IWORKToken::NS_URI_SF | IWORKToken::group :
168
0
    return std::make_shared<IWORKGroupElement>(getState());
169
0
  case +IWORKToken::NS_URI_SF | IWORKToken::image :
170
0
    return std::make_shared<IWORKImageElement>(getState());
171
  // case IWORKToken::NS_URI_SF | IWORKToken::line :
172
  //   return std::make_shared<LineElement>(getState());
173
0
  case +IWORKToken::NS_URI_SF | IWORKToken::media :
174
0
    return std::make_shared<IWORKMediaElement>(getState());
175
0
  case +IWORKToken::NS_URI_SF | IWORKToken::shape :
176
0
    return std::make_shared<IWORKShapeContext>(getState());
177
0
  case +IWORKToken::NS_URI_SF | IWORKToken::sticky_note :
178
0
    return std::make_shared<StickyNoteElement>(getState());
179
0
  case +IWORKToken::NS_URI_SF | IWORKToken::tabular_info :
180
0
    return std::make_shared<IWORKTabularInfoElement>(getState());
181
  // case IWORKToken::NS_URI_SF | IWORKToken::title_placeholder_ref :
182
  //   return std::make_shared<PlaceholderRefContext>(getState(), true);
183
0
  default:
184
0
    break;
185
0
  }
186
187
0
  return IWORKXMLContextPtr_t();
188
0
}
189
190
void DrawablesElement::endOfElement()
191
0
{
192
0
  if (isCollector())
193
0
    getCollector().endLevel();
194
0
}
195
196
}
197
198
namespace
199
{
200
201
class LayerElement : public NUM1XMLElementContextBase
202
{
203
public:
204
  explicit LayerElement(NUM1ParserState &state);
205
206
private:
207
  IWORKXMLContextPtr_t element(int name) override;
208
};
209
210
LayerElement::LayerElement(NUM1ParserState &state)
211
0
  : NUM1XMLElementContextBase(state)
212
0
{
213
0
}
214
215
IWORKXMLContextPtr_t LayerElement::element(const int name)
216
0
{
217
0
  switch (name)
218
0
  {
219
0
  case +IWORKToken::NS_URI_SF | IWORKToken::drawables :
220
0
    return std::make_shared<DrawablesElement>(getState());
221
0
  default:
222
0
    break;
223
0
  }
224
225
0
  return IWORKXMLContextPtr_t();
226
0
}
227
228
}
229
230
namespace
231
{
232
233
class LayersElement : public NUM1XMLElementContextBase
234
{
235
public:
236
  explicit LayersElement(NUM1ParserState &state);
237
238
private:
239
  IWORKXMLContextPtr_t element(int name) override;
240
};
241
242
LayersElement::LayersElement(NUM1ParserState &state)
243
0
  : NUM1XMLElementContextBase(state)
244
0
{
245
0
}
246
247
IWORKXMLContextPtr_t LayersElement::element(const int name)
248
0
{
249
0
  switch (name)
250
0
  {
251
0
  case +IWORKToken::NS_URI_SF | IWORKToken::layer :
252
0
    return std::make_shared<LayerElement>(getState());
253
0
  default:
254
0
    break;
255
0
  }
256
257
0
  return IWORKXMLContextPtr_t();
258
0
}
259
260
}
261
262
namespace
263
{
264
265
class PageInfoElement : public NUM1XMLElementContextBase
266
{
267
public:
268
  explicit PageInfoElement(NUM1ParserState &state);
269
270
private:
271
  IWORKXMLContextPtr_t element(int name) override;
272
  void endOfElement() override;
273
};
274
275
PageInfoElement::PageInfoElement(NUM1ParserState &state)
276
0
  : NUM1XMLElementContextBase(state)
277
0
{
278
0
}
279
280
IWORKXMLContextPtr_t PageInfoElement::element(const int name)
281
0
{
282
0
  switch (name)
283
0
  {
284
0
  case +IWORKToken::NS_URI_SF | IWORKToken::layers :
285
0
    return std::make_shared<LayersElement>(getState());
286
0
  default:
287
0
    break;
288
0
  }
289
290
0
  return IWORKXMLContextPtr_t();
291
0
}
292
293
void PageInfoElement::endOfElement()
294
0
{
295
0
}
296
297
}
298
299
namespace
300
{
301
302
class StylesContext : public NUM1XMLContextBase<IWORKStylesContext>
303
{
304
public:
305
  StylesContext(NUM1ParserState &state, bool anonymous);
306
307
private:
308
  IWORKXMLContextPtr_t element(int name) override;
309
};
310
311
StylesContext::StylesContext(NUM1ParserState &state, const bool anonymous)
312
0
  : NUM1XMLContextBase<IWORKStylesContext>(state, anonymous)
313
0
{
314
0
}
315
316
IWORKXMLContextPtr_t StylesContext::element(const int name)
317
0
{
318
0
  switch (name)
319
0
  {
320
0
  case +IWORKToken::NS_URI_SF | IWORKToken::workspace_style :
321
0
  case +NUM1Token::NS_URI_LS | NUM1Token::workspace_style :
322
0
    return std::make_shared<IWORKStyleContext>(getState(), &getState().getDictionary().m_workspaceStyles);
323
0
  default:
324
0
    break;
325
0
  }
326
327
0
  return NUM1XMLContextBase<IWORKStylesContext>::element(name);
328
0
}
329
330
}
331
332
namespace
333
{
334
335
class StylesheetElement : public NUM1XMLContextBase<IWORKStylesheetBase>
336
{
337
public:
338
  explicit StylesheetElement(NUM1ParserState &state);
339
  IWORKXMLContextPtr_t element(int name) override;
340
};
341
342
StylesheetElement::StylesheetElement(NUM1ParserState &state)
343
0
  : NUM1XMLContextBase<IWORKStylesheetBase>(state)
344
0
{
345
0
}
346
347
IWORKXMLContextPtr_t StylesheetElement::element(const int name)
348
0
{
349
0
  switch (name)
350
0
  {
351
0
  case +IWORKToken::NS_URI_SF | IWORKToken::styles :
352
0
    return std::make_shared<StylesContext>(getState(), false);
353
0
  case +IWORKToken::NS_URI_SF | IWORKToken::anon_styles :
354
0
    return std::make_shared<StylesContext>(getState(), true);
355
0
  default:
356
0
    break;
357
0
  }
358
0
  return NUM1XMLContextBase<IWORKStylesheetBase>::element(name);
359
0
}
360
}
361
362
namespace
363
{
364
365
class WorkSpaceElement : public NUM1XMLElementContextBase
366
{
367
public:
368
  explicit WorkSpaceElement(NUM1ParserState &state);
369
370
private:
371
  void attribute(const int name, const char *value) override;
372
  IWORKXMLContextPtr_t element(int name) override;
373
  void endOfElement() override;
374
375
  boost::optional<std::string> m_spaceName;
376
  bool m_opened;
377
};
378
379
WorkSpaceElement::WorkSpaceElement(NUM1ParserState &state)
380
0
  : NUM1XMLElementContextBase(state)
381
0
  , m_spaceName()
382
0
  , m_opened(false)
383
0
{
384
0
}
385
386
void WorkSpaceElement::attribute(const int name, const char *value)
387
0
{
388
0
  switch (name)
389
0
  {
390
0
  case +NUM1Token::NS_URI_LS | NUM1Token::workspace_name:
391
0
    m_spaceName = value;
392
0
    break;
393
0
  default:
394
0
    NUM1XMLElementContextBase::attribute(name, value);
395
0
    break;
396
0
  }
397
0
}
398
399
IWORKXMLContextPtr_t WorkSpaceElement::element(const int name)
400
0
{
401
0
  if (isCollector() && !m_opened)
402
0
  {
403
0
    m_opened=true;
404
0
    getCollector().startWorkSpace(m_spaceName);
405
0
  }
406
0
  switch (name)
407
0
  {
408
0
  case +NUM1Token::NS_URI_LS | NUM1Token::page_info:
409
0
    return std::make_shared<PageInfoElement>(getState());
410
0
  default:
411
0
    break;
412
0
  }
413
414
0
  return IWORKXMLContextPtr_t();
415
0
}
416
417
void WorkSpaceElement::endOfElement()
418
0
{
419
0
  if (isCollector() && m_opened)
420
0
    getCollector().endWorkSpace(getState().m_tableNameMap);
421
0
}
422
423
}
424
425
namespace
426
{
427
428
class WorkSpaceArrayElement : public NUM1XMLElementContextBase
429
{
430
public:
431
  explicit WorkSpaceArrayElement(NUM1ParserState &state);
432
433
private:
434
  IWORKXMLContextPtr_t element(int name) override;
435
};
436
437
WorkSpaceArrayElement::WorkSpaceArrayElement(NUM1ParserState &state)
438
0
  : NUM1XMLElementContextBase(state)
439
0
{
440
0
}
441
442
IWORKXMLContextPtr_t WorkSpaceArrayElement::element(const int name)
443
0
{
444
0
  switch (name)
445
0
  {
446
0
  case +NUM1Token::NS_URI_LS | NUM1Token::workspace:
447
0
    return std::make_shared<WorkSpaceElement>(getState());
448
0
  default:
449
0
    break;
450
0
  }
451
452
0
  return IWORKXMLContextPtr_t();
453
0
}
454
455
}
456
457
namespace
458
{
459
460
class DocumentElement : public NUM1XMLElementContextBase
461
{
462
public:
463
  explicit DocumentElement(NUM1ParserState &state);
464
465
private:
466
  void startOfElement() override;
467
  void attribute(int name, const char *value) override;
468
  IWORKXMLContextPtr_t element(int name) override;
469
  void endOfElement() override;
470
};
471
472
DocumentElement::DocumentElement(NUM1ParserState &state)
473
0
  : NUM1XMLElementContextBase(state)
474
0
{
475
0
}
476
477
void DocumentElement::startOfElement()
478
0
{
479
0
  if (isCollector())
480
0
    getCollector().startDocument();
481
0
}
482
483
void DocumentElement::attribute(const int name, const char *const value)
484
0
{
485
0
  switch (name)
486
0
  {
487
0
  case +NUM1Token::NS_URI_LS | NUM1Token::version :
488
0
  {
489
0
    const unsigned version = getVersion(getToken(value));
490
0
    if (0 == version)
491
0
    {
492
0
      ETONYEK_DEBUG_MSG(("unknown version %s\n", value));
493
0
    }
494
0
  }
495
0
  break;
496
0
  default:
497
0
    break;
498
0
  }
499
0
}
500
501
IWORKXMLContextPtr_t DocumentElement::element(const int name)
502
0
{
503
0
  switch (name)
504
0
  {
505
0
  case +IWORKToken::NS_URI_SF | IWORKToken::metadata :
506
0
    return std::make_shared<IWORKMetadataElement>(getState());
507
0
  case +NUM1Token::NS_URI_LS | NUM1Token::stylesheet :
508
0
    return std::make_shared<StylesheetElement>(getState());
509
0
  case +NUM1Token::NS_URI_LS | NUM1Token::workspace_array :
510
0
    return std::make_shared<WorkSpaceArrayElement>(getState());
511
0
  default:
512
0
    break;
513
0
  }
514
515
0
  return IWORKXMLContextPtr_t();
516
0
}
517
518
void DocumentElement::endOfElement()
519
0
{
520
0
  if (isCollector())
521
0
    getCollector().endDocument();
522
0
}
523
524
}
525
526
namespace
527
{
528
529
class XMLDocument : public NUM1XMLElementContextBase
530
{
531
public:
532
  explicit XMLDocument(NUM1ParserState &state);
533
534
private:
535
  IWORKXMLContextPtr_t element(int name) override;
536
};
537
538
XMLDocument::XMLDocument(NUM1ParserState &state)
539
0
  : NUM1XMLElementContextBase(state)
540
0
{
541
0
}
542
543
IWORKXMLContextPtr_t XMLDocument::element(const int name)
544
0
{
545
0
  switch (name)
546
0
  {
547
0
  case +NUM1Token::NS_URI_LS | NUM1Token::document :
548
0
    return std::make_shared<DocumentElement>(m_state);
549
0
  default:
550
0
    break;
551
0
  }
552
553
0
  return IWORKXMLContextPtr_t();
554
0
}
555
556
}
557
558
namespace
559
{
560
561
class DiscardContext : public NUM1XMLContextBase<IWORKDiscardContext>
562
{
563
public:
564
  explicit DiscardContext(NUM1ParserState &state);
565
566
private:
567
  IWORKXMLContextPtr_t element(int name) override;
568
};
569
570
DiscardContext::DiscardContext(NUM1ParserState &state)
571
0
  : NUM1XMLContextBase<IWORKDiscardContext>(state)
572
0
{
573
0
}
574
575
IWORKXMLContextPtr_t DiscardContext::element(const int name)
576
0
{
577
0
  switch (name)
578
0
  {
579
0
  case +NUM1Token::NS_URI_LS | NUM1Token::stylesheet :
580
0
    return std::make_shared<StylesheetElement>(getState());
581
0
  case +NUM1Token::NS_URI_LS | NUM1Token::workspace_style :
582
0
    return std::make_shared<IWORKStyleContext>(getState(), &getState().getDictionary().m_workspaceStyles);
583
0
  default:
584
0
    break;
585
0
  }
586
587
0
  return shared_from_this();
588
0
}
589
590
}
591
592
NUM1Parser::NUM1Parser(const RVNGInputStreamPtr_t &input, const RVNGInputStreamPtr_t &package, NUMCollector &collector, NUM1Dictionary *const dict)
593
0
  : IWORKParser(input, package)
594
0
  , m_state(*this, collector, *dict)
595
0
{
596
0
}
597
598
NUM1Parser::~NUM1Parser()
599
0
{
600
0
}
601
602
IWORKXMLContextPtr_t NUM1Parser::createDocumentContext()
603
0
{
604
0
  return std::make_shared<XMLDocument>(m_state);
605
0
}
606
607
IWORKXMLContextPtr_t NUM1Parser::createDiscardContext()
608
0
{
609
0
  return std::make_shared<DiscardContext>(m_state);
610
0
}
611
612
const IWORKTokenizer &NUM1Parser::getTokenizer() const
613
0
{
614
0
  static IWORKChainedTokenizer tokenizer(NUM1Token::getTokenizer(), IWORKToken::getTokenizer());
615
0
  return tokenizer;
616
0
}
617
618
}
619
620
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */