MUSX Document Model
Loading...
Searching...
No Matches
BaseClasses.h
1/*
2 * Copyright (C) 2025, Robert Patterson
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22#pragma once
23
24#include <cassert>
25#include <filesystem>
26#include <set>
27
28#include "musx/dom/Fundamentals.h"
29#include "musx/xml/XmlInterface.h"
30#include "musx/util/Logger.h"
31
32namespace musx {
33
38namespace dom {
39
43class integrity_error : public std::runtime_error
44{
45public:
46 using std::runtime_error::runtime_error;
47};
48
49class Document;
51using DocumentPtr = std::shared_ptr<Document>;
53using DocumentWeakPtr = std::weak_ptr<Document>;
54
59class Base
60{
61public:
63 using SharedNodes = std::set<std::string>;
64
67 enum class ShareMode
68 {
69 // this enum was giving Doxygen fits until I switched to using the slash-splat-bang-lt comment commands.
70 All,
71 Partial,
72 None
73 };
74
78 virtual ~Base() noexcept(false) = default;
79
86 {
87 auto document = m_document.lock();
88 assert(document); // program bug if this pointer goes out of scope.
89 if (!document) {
90 throw std::logic_error("Document pointer is no longer valid.");
91 }
92 return document;
93 }
94
104 virtual Cmper getPartId() const { return m_partId; }
105
109 ShareMode getShareMode() const { return m_shareMode; }
110
114 const SharedNodes& getUnlinkedNodes() const { return m_unlinkedNodes; }
115
119 void addUnlinkedNode(const std::string& nodeName)
120 {
121 m_unlinkedNodes.insert(nodeName);
122 }
123
132 virtual void integrityCheck() { }
133
144 virtual bool requireAllFields() const { return true; }
145
146protected:
154 Base(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode)
155 : m_document(document), m_partId(partId), m_shareMode(shareMode) {}
156
157 Base(const Base&) = default;
158 Base(Base&&) noexcept = default;
159
161 Base& operator=(const Base&) { return *this; }
163 Base& operator=(Base&&) noexcept { return *this; }
164
165private:
166 const DocumentWeakPtr m_document;
167 const Cmper m_partId;
168 const ShareMode m_shareMode;
169 SharedNodes m_unlinkedNodes;
170};
171
177class CommonClassBase : public Base
178{
179public:
186 : Base(document, SCORE_PARTID, ShareMode::All) {}
187
188protected:
189 // Because the part ID and share mode are hard-coded for this category of classes,
190 // these Base functions do not return useful results. However, we allow our subclasses
191 // to use their own versions of these functions (esp. `getPartId`) to avoid promiscuous
192 // hard-coding of SCORE_PARTID. The rules may change in the future.
193 using Base::getPartId;
194 using Base::getShareMode;
196};
197
203class OptionsBase : public Base {
204protected:
212 OptionsBase(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode)
213 : Base(document, partId, shareMode) {}
214};
215
222class OthersBase : public Base
223{
224protected:
234 OthersBase(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode, Cmper cmper, std::optional<Inci> inci = std::nullopt)
235 : Base(document, partId, shareMode), m_cmper(cmper), m_inci(inci) {}
236
237public:
243 Cmper getCmper() const { return m_cmper; }
244
250 std::optional<Inci> getInci() const { return m_inci; }
251
252private:
253 Cmper m_cmper;
254 std::optional<Inci> m_inci;
255};
256
260template <typename ElementType, size_t REQUIRED_SIZE = 0>
262{
263private:
264 virtual std::string_view xmlTag() const = 0;
265
266public:
268 explicit OthersArray(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode, Cmper cmper)
269 : OthersBase(document, partId, shareMode, cmper)
270 {
271 }
272
273 std::vector<ElementType> values;
275
277 void integrityCheck() override
278 {
280 if constexpr (REQUIRED_SIZE > 0) {
281 const size_t originalSize = values.size();
282 values.resize(REQUIRED_SIZE); // resize first, in case MUSX_INTEGRITY_ERROR throws. (Avoid unreachable code warning.)
283 if (originalSize < REQUIRED_SIZE) {
284 MUSX_INTEGRITY_ERROR("Array with xml tag " + std::string(xmlTag()) + " and cmper " + std::to_string(getCmper())
285 + " has fewer than " + std::to_string(REQUIRED_SIZE) + " elements.");
286 }
287 }
288 }
289};
290
297class DetailsBase : public Base
298{
299protected:
310 DetailsBase(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode, Cmper cmper1, Cmper cmper2, std::optional<Inci> inci = std::nullopt)
311 : Base(document, partId, shareMode), m_cmper1(cmper1), m_cmper2(cmper2), m_inci(inci) {}
312
313public:
317 Cmper getCmper1() const { return m_cmper1; }
318
322 Cmper getCmper2() const { return m_cmper2; }
323
327 std::optional<Inci> getInci() const { return m_inci; }
328
329private:
330 Cmper m_cmper1;
331 Cmper m_cmper2;
332 std::optional<Inci> m_inci;
333};
334
339{
340protected:
350 EntryDetailsBase(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode, EntryNumber entnum, std::optional<Inci> inci = std::nullopt)
351 : DetailsBase(document, partId, shareMode, Cmper(entnum >> 16), Cmper(entnum & 0xffff), inci) {}
352
353public:
357 EntryNumber getEntryNumber() const { return EntryNumber(getCmper1()) << 16 | EntryNumber(getCmper2()); }
358
359private:
362};
363
364class NoteInfoPtr;
365
368{
369public:
371 virtual NoteNumber getNoteId() const = 0;
372
373protected:
376};
377
378class FontInfo;
384class TextsBase : public Base
385{
386public:
395 TextsBase(const DocumentWeakPtr& document, Cmper partId, ShareMode shareMode, Cmper textNumber)
396 : Base(document, partId, shareMode), m_textNumber(textNumber) {}
397
398 std::string text;
399
403 Cmper getTextNumber() const { return m_textNumber; }
404
408 void setTextNumber(Cmper textNumber) { m_textNumber = textNumber; }
409
414 std::shared_ptr<FontInfo> parseFirstFontInfo() const;
415
416private:
417 Cmper m_textNumber;
418};
419
420} // namespace dom
421} // namespace musx
Base class to enforce polymorphism across all DOM classes.
Definition BaseClasses.h:60
DocumentPtr getDocument() const
Gets a reference to the Document.
Definition BaseClasses.h:85
virtual void integrityCheck()
Allows a class to determine if it has been properly contructed by the factory and fix issues that it ...
Definition BaseClasses.h:132
virtual bool requireAllFields() const
Specifies if the parser should alert (print or throw) when an unknown xml tag is found for this class...
Definition BaseClasses.h:144
Base(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode)
Constructs the base class.
Definition BaseClasses.h:154
ShareMode getShareMode() const
Gets the sharing mode for this instance.
Definition BaseClasses.h:109
std::set< std::string > SharedNodes
The container type for shared nodes.
Definition BaseClasses.h:63
Base & operator=(Base &&) noexcept
no-op move assignment operator allows subclasses to move their values.
Definition BaseClasses.h:163
const SharedNodes & getUnlinkedNodes() const
Gets the unlinked nodes for this instance. (Only populated for ShareMode::Partial)
Definition BaseClasses.h:114
void addUnlinkedNode(const std::string &nodeName)
Adds a shared node for this instance.
Definition BaseClasses.h:119
ShareMode
Describes how this instance is shared between part and score.
Definition BaseClasses.h:68
virtual ~Base() noexcept(false)=default
Virtual destructor for polymorphic behavior.
virtual Cmper getPartId() const
Gets the partId for this instance (or SCORE_PARTID for score)
Definition BaseClasses.h:104
Base(const Base &)=default
explicit default copy constructor
Base(Base &&) noexcept=default
explicit default move constructor
Base class for classes that are commonly used among others, details, entries, and/or texts....
Definition BaseClasses.h:178
CommonClassBase(const DocumentWeakPtr &document)
Constructs a CommonClassBase object.
Definition BaseClasses.h:185
Base class for all "details" types.
Definition BaseClasses.h:298
DetailsBase(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode, Cmper cmper1, Cmper cmper2, std::optional< Inci > inci=std::nullopt)
Constructs a DetailsBase object.
Definition BaseClasses.h:310
Cmper getCmper1() const
Gets the cmper1 key value.
Definition BaseClasses.h:317
Cmper getCmper2() const
Gets the cmper2 key value.
Definition BaseClasses.h:322
std::optional< Inci > getInci() const
Gets the optional array index (inci).
Definition BaseClasses.h:327
Represents a document object that encapsulates the entire EnigmaXML structure.
Definition Document.h:51
Base class for all "details" types that use entnum rather than cmper and cmper.
Definition BaseClasses.h:339
EntryDetailsBase(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode, EntryNumber entnum, std::optional< Inci > inci=std::nullopt)
Constructs a EntryDetailsBase object.
Definition BaseClasses.h:350
EntryNumber getEntryNumber() const
Gets the entnum key value.
Definition BaseClasses.h:357
Represents the default font settings for a particular element type.
Definition CommonClasses.h:110
Base class note details. Note details are entry details associated with a note ID.
Definition BaseClasses.h:368
virtual NoteNumber getNoteId() const =0
Required virtual function that returns the note id.
Base class for all "options" types.
Definition BaseClasses.h:203
OptionsBase(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode)
Constructs the OptionsBase and validates XmlNodeName in the derived class.
Definition BaseClasses.h:212
Template pattern for OthersBase items consisting of an array of a single item.
Definition BaseClasses.h:262
std::vector< ElementType > values
Definition BaseClasses.h:273
OthersArray(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode, Cmper cmper)
Constructor function.
Definition BaseClasses.h:268
void integrityCheck() override
Override of Base::integrityCheck.
Definition BaseClasses.h:277
Base class for all "others" types.
Definition BaseClasses.h:223
std::optional< Inci > getInci() const
Gets the optional array index (inci).
Definition BaseClasses.h:250
OthersBase(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode, Cmper cmper, std::optional< Inci > inci=std::nullopt)
Constructs an OthersBase object.
Definition BaseClasses.h:234
Cmper getCmper() const
Gets the cmper key value.
Definition BaseClasses.h:243
Base class for all text blocks.
Definition BaseClasses.h:385
Cmper getTextNumber() const
Returns the raw text number.
Definition BaseClasses.h:403
std::string text
Raw Enigma string (with Enigma string tags), encoded UTF-8.
Definition BaseClasses.h:398
std::shared_ptr< FontInfo > parseFirstFontInfo() const
Returns a shared pointer to a FontInfo instance that reflects the first font information in the text.
Definition Implementations.cpp:3244
TextsBase(const DocumentWeakPtr &document, Cmper partId, ShareMode shareMode, Cmper textNumber)
Constructs a TextsBase object.
Definition BaseClasses.h:395
void setTextNumber(Cmper textNumber)
Sets the raw text number.
Definition BaseClasses.h:408
Exception for integrity errors. (Used when MUSX_THROW_ON_INTEGRITY_CHECK_FAIL is defined....
Definition BaseClasses.h:44
constexpr Cmper SCORE_PARTID
The part id of the score.
Definition Fundamentals.h:80
uint16_t Cmper
Enigma "comperator" key type.
Definition Fundamentals.h:55
std::weak_ptr< Document > DocumentWeakPtr
Shared weak Document pointer.
Definition BaseClasses.h:53
int32_t EntryNumber
Entry identifier.
Definition Fundamentals.h:68
uint16_t NoteNumber
Note identifier.
Definition Fundamentals.h:69
std::shared_ptr< Document > DocumentPtr
Shared Document pointer.
Definition BaseClasses.h:51
object model for musx file (enigmaxml)
Definition BaseClasses.h:32