From 7e7b35fa71eb36d9accdc1c8f2690eedd94dac91 Mon Sep 17 00:00:00 2001 From: Matthew James Briggs Date: Thu, 20 Aug 2026 13:58:27 +0000 Subject: [PATCH 1/2] feat: model MusicXML ids with an api::Id type An id attribute is not any old string. It has to follow the XML name rules, and until now mx enforced that only at the last moment, inside mx::impl, by handing the text to core::Token on the way out. The caller never learned that their id had changed. Replace std::optional id with std::optional on all 41 api id members. api::Id holds a core::Token behind a pimpl, so the text is scrubbed once, as the Id is built, and mx::impl passes the token itself to mx::core. No second conversion is possible. Callers who need to know whether their text was legal compare Id::value() with what they passed in. Id copies, assigns, compares, sorts, and hashes like a plain value. std::hash is specialized for it, so an Id works as a key in std::map and std::unordered_map. Copies share one immutable token instead of allocating, and a moved-from Id still holds a token, so reading one is harmless. IdAccess (private to mx) is the only door between Id and its token. The public header names no core type. The id explanation moves from ApiCommon.h to Id.h, where the type it describes lives. SegnoData and CodaData keep their legacy std::string id plus isIdSpecified; those belong with the rest of issue 249. --- .../mx/api/AccordionRegistrationData.h | 3 +- src/include/mx/api/ApiCommon.h | 11 - src/include/mx/api/BarlineData.h | 5 +- src/include/mx/api/ClefData.h | 5 +- src/include/mx/api/CurveData.h | 13 +- src/include/mx/api/DampData.h | 5 +- src/include/mx/api/DirectionData.h | 5 +- src/include/mx/api/EyeglassesData.h | 3 +- src/include/mx/api/FiguredBassData.h | 5 +- src/include/mx/api/HarpPedalsData.h | 3 +- src/include/mx/api/Id.h | 103 ++++++++++ src/include/mx/api/ImageData.h | 3 +- src/include/mx/api/KeyData.h | 5 +- src/include/mx/api/LyricData.h | 5 +- src/include/mx/api/MarkDataChoice.h | 7 +- src/include/mx/api/MeasureData.h | 5 +- src/include/mx/api/NoteData.h | 9 +- src/include/mx/api/OtherDirectionData.h | 3 +- src/include/mx/api/PedalLineData.h | 5 +- src/include/mx/api/PercussionData.h | 3 +- src/include/mx/api/PrincipalVoiceData.h | 3 +- src/include/mx/api/RehearsalData.h | 5 +- src/include/mx/api/ScordaturaData.h | 3 +- src/include/mx/api/SoundData.h | 5 +- src/include/mx/api/SpannerData.h | 9 +- src/include/mx/api/StaffDivideData.h | 3 +- src/include/mx/api/StringMuteData.h | 3 +- src/include/mx/api/SymbolData.h | 5 +- src/include/mx/api/TempoData.h | 3 +- src/include/mx/api/TimeChoice.h | 5 +- src/include/mx/api/TransposeData.h | 5 +- src/include/mx/api/TupletData.h | 9 +- src/include/mx/api/WedgeData.h | 9 +- src/include/mx/api/WordsData.h | 5 +- src/private/mx/api/Id.cpp | 100 +++++++++ src/private/mx/api/IdAccess.h | 28 +++ src/private/mx/impl/ArpeggiateFunctions.cpp | 6 +- src/private/mx/impl/DirectionReader.cpp | 60 ++---- src/private/mx/impl/DirectionWriter.cpp | 57 ++---- src/private/mx/impl/DirectionWriter.h | 2 +- src/private/mx/impl/IdFunctions.h | 21 +- src/private/mx/impl/MetronomeReader.cpp | 6 +- .../mx/impl/NonArpeggiateFunctions.cpp | 6 +- src/private/mx/impl/NotationsWriter.cpp | 15 +- src/private/mx/impl/NoteFunctions.cpp | 5 +- src/private/mxtest/api/IdAttributeApiTest.cpp | 189 ++++++++++++++---- 46 files changed, 525 insertions(+), 248 deletions(-) create mode 100644 src/include/mx/api/Id.h create mode 100644 src/private/mx/api/Id.cpp create mode 100644 src/private/mx/api/IdAccess.h diff --git a/src/include/mx/api/AccordionRegistrationData.h b/src/include/mx/api/AccordionRegistrationData.h index 39a1be178..48f4724d3 100644 --- a/src/include/mx/api/AccordionRegistrationData.h +++ b/src/include/mx/api/AccordionRegistrationData.h @@ -7,6 +7,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -31,7 +32,7 @@ class AccordionRegistrationData PositionData positionData; FontData fontData; std::optional color; - std::optional id; + std::optional id; AccordionRegistrationData() : high{false}, middle{}, low{false}, positionData{}, fontData{}, color{}, id{} { diff --git a/src/include/mx/api/ApiCommon.h b/src/include/mx/api/ApiCommon.h index 6efabd4b0..3ff4433aa 100644 --- a/src/include/mx/api/ApiCommon.h +++ b/src/include/mx/api/ApiCommon.h @@ -32,17 +32,6 @@ constexpr int NUMBER_LEVEL_UNSPECIFIED = -1; // MusicXML 'number' attributes, e. constexpr int VALUE_UNSPECIFIED = -1; // other absent-able ints, e.g. DirectionData::voice constexpr Double DOUBLE_UNSPECIFIED = -1.0; // absent-able doubles, e.g. StaffData::staffSize -// MusicXML lets most elements carry an optional id attribute, a name that identifies that one -// element within the document. Software uses it to point at a particular note, measure, or -// marking -- to line playback up with the score, to hang an annotation on a note, or to link one -// file to another. Every mx::api type that models such an element has an `id` member. Leave it -// empty and no id attribute is written. -// -// An id must be unique within the document and must follow the XML name rules: a letter or an -// underscore first, then letters, digits, dots, hyphens, or underscores. mx repairs an id that -// breaks the name rules when it writes the file, but it does not check uniqueness, so an id you -// invent must not collide with one already in the score. - // Intentional ternary: absent-able bools use Bool::unspecified, not std::optional. // See "mx::api conventions" in AGENTS.md. enum class Bool diff --git a/src/include/mx/api/BarlineData.h b/src/include/mx/api/BarlineData.h index 05857f979..691bf2e82 100644 --- a/src/include/mx/api/BarlineData.h +++ b/src/include/mx/api/BarlineData.h @@ -5,6 +5,7 @@ #pragma once #include "mx/api/ApiCommon.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -116,8 +117,8 @@ class BarlineData RepeatWinged repeatWinged; HorizontalAlignment location; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; BarlineData() : tickTimePosition{0}, barlineType{BarlineType::normal}, ending{}, repeat{false}, repeatTimes{0}, diff --git a/src/include/mx/api/ClefData.h b/src/include/mx/api/ClefData.h index 81a788a87..e91d4b299 100644 --- a/src/include/mx/api/ClefData.h +++ b/src/include/mx/api/ClefData.h @@ -5,6 +5,7 @@ #pragma once #include "mx/api/ApiCommon.h" +#include "mx/api/Id.h" #include #include @@ -71,8 +72,8 @@ class ClefData // unspecified -> omit the attribute, yes/no -> write print-object verbatim. Bool printObject; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; std::string toString() const; diff --git a/src/include/mx/api/CurveData.h b/src/include/mx/api/CurveData.h index 178919df6..5b5408cff 100644 --- a/src/include/mx/api/CurveData.h +++ b/src/include/mx/api/CurveData.h @@ -6,6 +6,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" +#include "mx/api/Id.h" #include "mx/api/LineData.h" #include "mx/api/PositionData.h" #include "mx/api/SpannerNumber.h" @@ -104,8 +105,8 @@ struct CurveStart ColorData colorData; // The id attribute of the element this curve end is written as -- for a slur, - // for a tie (see ApiCommon.h). - std::optional id; + // for a tie (see Id.h). + std::optional id; CurveStart(CurveType inCurveType) : curveType{inCurveType}, number{}, curvePoints{}, curveOrientation{CurveOrientation::unspecified}, @@ -127,8 +128,8 @@ struct CurveContinue double bezierOffset2; // The id attribute of the element this curve end is written as -- for a slur, - // for a tie (see ApiCommon.h). - std::optional id; + // for a tie (see Id.h). + std::optional id; CurveContinue(CurveType inCurveType) : curveType{inCurveType}, number{}, curvePoints{}, isBezierX2Specified{false}, bezierX2{0.0}, @@ -144,8 +145,8 @@ struct CurveStop CurvePoints curvePoints; // The id attribute of the element this curve end is written as -- for a slur, - // for a tie (see ApiCommon.h). - std::optional id; + // for a tie (see Id.h). + std::optional id; CurveStop(CurveType inCurveType) : curveType{inCurveType}, number{}, curvePoints{}, id{} { diff --git a/src/include/mx/api/DampData.h b/src/include/mx/api/DampData.h index eb17e7ffa..7870ef57d 100644 --- a/src/include/mx/api/DampData.h +++ b/src/include/mx/api/DampData.h @@ -7,6 +7,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -26,7 +27,7 @@ class DampData PositionData positionData; FontData fontData; std::optional color; - std::optional id; + std::optional id; DampData() : positionData{}, fontData{}, color{}, id{} { @@ -49,7 +50,7 @@ class DampAllData PositionData positionData; FontData fontData; std::optional color; - std::optional id; + std::optional id; DampAllData() : positionData{}, fontData{}, color{}, id{} { diff --git a/src/include/mx/api/DirectionData.h b/src/include/mx/api/DirectionData.h index 6981d2200..b1adcd8d9 100644 --- a/src/include/mx/api/DirectionData.h +++ b/src/include/mx/api/DirectionData.h @@ -8,6 +8,7 @@ #include "mx/api/ChordData.h" #include "mx/api/DirectionChoice.h" #include "mx/api/FiguredBassData.h" +#include "mx/api/Id.h" #include "mx/api/SoundData.h" #include @@ -81,8 +82,8 @@ struct DirectionData // serialize as their own elements, not as direction-type content. std::vector figuredBasses; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; DirectionData() : tickTimePosition{0}, placement{Placement::unspecified}, systemRelation{SystemRelation::unspecified}, offset{}, diff --git a/src/include/mx/api/EyeglassesData.h b/src/include/mx/api/EyeglassesData.h index 39a3e7135..28a25140d 100644 --- a/src/include/mx/api/EyeglassesData.h +++ b/src/include/mx/api/EyeglassesData.h @@ -7,6 +7,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -27,7 +28,7 @@ class EyeglassesData PositionData positionData; FontData fontData; std::optional color; - std::optional id; + std::optional id; EyeglassesData() : positionData{}, fontData{}, color{}, id{} { diff --git a/src/include/mx/api/FiguredBassData.h b/src/include/mx/api/FiguredBassData.h index a4ff4d9eb..65f2a23e5 100644 --- a/src/include/mx/api/FiguredBassData.h +++ b/src/include/mx/api/FiguredBassData.h @@ -5,6 +5,7 @@ #pragma once #include "mx/api/ApiCommon.h" +#include "mx/api/Id.h" #include #include @@ -49,8 +50,8 @@ class FiguredBassData // The optional , in ticks. A value less than 0 means 'unspecified' (no duration child). int durationTimeTicks; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; FiguredBassData() : figures{}, parentheses{Bool::unspecified}, durationTimeTicks{VALUE_UNSPECIFIED}, id{} { diff --git a/src/include/mx/api/HarpPedalsData.h b/src/include/mx/api/HarpPedalsData.h index 3b00837e3..01de07a0f 100644 --- a/src/include/mx/api/HarpPedalsData.h +++ b/src/include/mx/api/HarpPedalsData.h @@ -7,6 +7,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/PitchData.h" #include "mx/api/PositionData.h" @@ -57,7 +58,7 @@ class HarpPedalsData PositionData positionData; FontData fontData; std::optional color; - std::optional id; + std::optional id; HarpPedalsData() : pedalTunings{}, positionData{}, fontData{}, color{}, id{} { diff --git a/src/include/mx/api/Id.h b/src/include/mx/api/Id.h new file mode 100644 index 000000000..3640e0520 --- /dev/null +++ b/src/include/mx/api/Id.h @@ -0,0 +1,103 @@ +// MusicXML Class Library +// Copyright (c) by Matthew James Briggs +// Distributed under the MIT License + +#pragma once + +#include "mx/api/ApiCommon.h" + +#include +#include +#include +#include + +namespace mx +{ +namespace api +{ + +// The id attribute of a MusicXML element. An id is a name that identifies one element within the +// document. Software uses it to point at a particular note, measure, or marking -- to line playback +// up with the score, to hang an annotation on a note, or to link one file to another. +// +// An id must follow the XML name rules. The first character is a letter or an underscore. The rest +// are letters, digits, dots, hyphens, or underscores. Building an Id scrubs out anything else, so +// an id that breaks the rules cannot exist. Text with nothing usable left, empty text included, +// becomes "X". Building the Id is the only place this happens: mx writes the id exactly as the Id +// holds it. +// +// Scrubbing is silent. To find out whether your text was already a legal id, compare it with the +// id you built: +// +// const auto id = Id{myText}; +// if (id.value() != myText) +// { +// // myText was not a legal id; decide what to do about it +// } +// +// An id must also be unique within the document. Uniqueness is a property of the whole score, not +// of one name, so Id cannot check it. An id you invent must not collide with one already in the +// score. +// +// To write no id attribute at all, leave the std::optional that holds the Id empty. +// +// Copy, assign, compare, sort, and hash an Id the way you would any other value. Two Ids are equal +// when their text is equal, and std::hash is specialized for Id, so an Id works as a key in both +// std::map and std::unordered_map. +class Id +{ + public: + Id(std::string text); + Id(const char *text); + + Id(const Id &other); + Id(Id &&other) noexcept; + Id &operator=(const Id &other); + Id &operator=(Id &&other) noexcept; + ~Id(); + + const std::string &value() const; + + bool operator==(const Id &other) const; + bool operator<(const Id &other) const; + + private: + // Holds the same type mx writes the attribute with, which is why the text cannot be scrubbed a + // second time. The definition is private to mx. + class Impl; + explicit Id(std::shared_ptr impl); + friend struct IdAccess; + + std::shared_ptr myImpl; +}; + +MXAPI_NOT_EQUALS_AND_VECTORS(Id); + +inline bool operator>(const Id &lhs, const Id &rhs) +{ + return rhs < lhs; +} + +inline bool operator<=(const Id &lhs, const Id &rhs) +{ + return !(rhs < lhs); +} + +inline bool operator>=(const Id &lhs, const Id &rhs) +{ + return !(lhs < rhs); +} + +} // namespace api +} // namespace mx + +namespace std +{ +template <> struct hash +{ + std::size_t operator()(const mx::api::Id &id) const noexcept + { + return std::hash{}(id.value()); + } +}; +} // namespace std diff --git a/src/include/mx/api/ImageData.h b/src/include/mx/api/ImageData.h index 0a9a1cb07..f90588403 100644 --- a/src/include/mx/api/ImageData.h +++ b/src/include/mx/api/ImageData.h @@ -5,6 +5,7 @@ #pragma once #include "mx/api/ApiCommon.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -29,7 +30,7 @@ class ImageData std::optional height; std::optional width; PositionData positionData; - std::optional id; + std::optional id; ImageData() : source{}, type{}, height{}, width{}, positionData{}, id{} { diff --git a/src/include/mx/api/KeyData.h b/src/include/mx/api/KeyData.h index ff4666ae0..46822bba8 100644 --- a/src/include/mx/api/KeyData.h +++ b/src/include/mx/api/KeyData.h @@ -4,6 +4,7 @@ #pragma once #include "mx/api/ApiCommon.h" +#include "mx/api/Id.h" #include "mx/api/KeyComponent.h" #include @@ -124,8 +125,8 @@ struct KeyData // alterations. When custom is non-empty, then fifths and mode are ignored. std::vector nonTraditional; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; KeyData() : fifths{0}, cancel{0}, cancelLocation{CancelLocation::unspecified}, mode{KeyMode::unspecified}, diff --git a/src/include/mx/api/LyricData.h b/src/include/mx/api/LyricData.h index e08993b94..28e50457a 100644 --- a/src/include/mx/api/LyricData.h +++ b/src/include/mx/api/LyricData.h @@ -5,6 +5,7 @@ #pragma once #include "mx/api/ApiCommon.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include "mx/api/PrintData.h" @@ -54,8 +55,8 @@ class LyricData PositionData positionData; PrintData printData; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; }; MXAPI_EQUALS_BEGIN(LyricData) diff --git a/src/include/mx/api/MarkDataChoice.h b/src/include/mx/api/MarkDataChoice.h index 4eff58120..7b9b73b47 100644 --- a/src/include/mx/api/MarkDataChoice.h +++ b/src/include/mx/api/MarkDataChoice.h @@ -6,6 +6,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/DynamicsData.h" +#include "mx/api/Id.h" #include #include @@ -59,7 +60,7 @@ struct ArpeggiateMarkData Bool unbroken = Bool::unspecified; // The element's `id` attribute (MusicXML 3.1). - std::optional id; + std::optional id; }; MXAPI_EQUALS_BEGIN(ArpeggiateMarkData) @@ -89,7 +90,7 @@ struct NonArpeggiateMarkData std::optional number; // The element's `id` attribute (MusicXML 3.1). - std::optional id; + std::optional id; }; MXAPI_EQUALS_BEGIN(NonArpeggiateMarkData) @@ -126,7 +127,7 @@ struct OtherNotationMarkData OtherNotationType type = OtherNotationType::single; std::optional number; std::optional smufl; - std::optional id; + std::optional id; }; MXAPI_EQUALS_BEGIN(OtherNotationMarkData) diff --git a/src/include/mx/api/MeasureData.h b/src/include/mx/api/MeasureData.h index 6968b6daa..6c3259ab3 100644 --- a/src/include/mx/api/MeasureData.h +++ b/src/include/mx/api/MeasureData.h @@ -6,6 +6,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/BarlineData.h" +#include "mx/api/Id.h" #include "mx/api/KeyData.h" #include "mx/api/PartSymbolData.h" #include "mx/api/StaffData.h" @@ -111,8 +112,8 @@ class MeasureData // before this field existed. std::vector transpositions; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; MeasureData() : staves{}, timeSignature{}, number{}, measureNumbering{MeasureNumbering::unspecified}, diff --git a/src/include/mx/api/NoteData.h b/src/include/mx/api/NoteData.h index d746d18b7..28074a6a1 100644 --- a/src/include/mx/api/NoteData.h +++ b/src/include/mx/api/NoteData.h @@ -6,6 +6,7 @@ #include "mx/api/CurveData.h" #include "mx/api/DurationData.h" +#include "mx/api/Id.h" #include "mx/api/LyricData.h" #include "mx/api/NoteAttachmentData.h" #include "mx/api/PitchData.h" @@ -82,8 +83,8 @@ struct TieLetRing bool isColorSpecified; ColorData colorData; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; TieLetRing() : positionData{}, curveOrientation{CurveOrientation::unspecified}, isColorSpecified{false}, colorData{}, id{} @@ -208,8 +209,8 @@ class NoteData // will be parsed into these strings. do not use commas in your misc // data strings as these are the delimiter - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; std::vector miscData; }; diff --git a/src/include/mx/api/OtherDirectionData.h b/src/include/mx/api/OtherDirectionData.h index e9296ffd7..7eda94432 100644 --- a/src/include/mx/api/OtherDirectionData.h +++ b/src/include/mx/api/OtherDirectionData.h @@ -7,6 +7,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -30,7 +31,7 @@ class OtherDirectionData PositionData positionData; FontData fontData; std::optional color; - std::optional id; + std::optional id; OtherDirectionData() : text{}, printObject{Bool::unspecified}, smufl{}, positionData{}, fontData{}, color{}, id{} { diff --git a/src/include/mx/api/PedalLineData.h b/src/include/mx/api/PedalLineData.h index 8606bcfc9..4c1b59ef6 100644 --- a/src/include/mx/api/PedalLineData.h +++ b/src/include/mx/api/PedalLineData.h @@ -5,6 +5,7 @@ #pragma once #include "mx/api/ApiCommon.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -53,8 +54,8 @@ struct PedalLineData int tickTimePosition; PositionData positionData; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; PedalLineData() : kind{PedalLineKind::unspecified}, tickTimePosition{0}, positionData{}, id{} { diff --git a/src/include/mx/api/PercussionData.h b/src/include/mx/api/PercussionData.h index 8fc25f55d..a2ea4abb5 100644 --- a/src/include/mx/api/PercussionData.h +++ b/src/include/mx/api/PercussionData.h @@ -7,6 +7,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -482,7 +483,7 @@ class PercussionData PositionData positionData; FontData fontData; std::optional color; - std::optional id; + std::optional id; PercussionData() : choice{}, enclosure{Enclosure::unspecified}, positionData{}, fontData{}, color{}, id{} { diff --git a/src/include/mx/api/PrincipalVoiceData.h b/src/include/mx/api/PrincipalVoiceData.h index a009124bf..e84911e22 100644 --- a/src/include/mx/api/PrincipalVoiceData.h +++ b/src/include/mx/api/PrincipalVoiceData.h @@ -7,6 +7,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -49,7 +50,7 @@ class PrincipalVoiceData PositionData positionData; FontData fontData; std::optional color; - std::optional id; + std::optional id; PrincipalVoiceData() : type{PrincipalVoiceType::start}, symbol{PrincipalVoiceSymbol::hauptstimme}, text{}, positionData{}, diff --git a/src/include/mx/api/RehearsalData.h b/src/include/mx/api/RehearsalData.h index a34430155..e299c6962 100644 --- a/src/include/mx/api/RehearsalData.h +++ b/src/include/mx/api/RehearsalData.h @@ -7,6 +7,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -35,8 +36,8 @@ class RehearsalData // and says which edge of the text the position refers to; MusicXML defines both. HorizontalAlignment justify; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; RehearsalData() : text{}, positionData{}, isColorSpecified{false}, colorData{}, fontData{}, enclosure{Enclosure::unspecified}, diff --git a/src/include/mx/api/ScordaturaData.h b/src/include/mx/api/ScordaturaData.h index e0d35240a..da82c0587 100644 --- a/src/include/mx/api/ScordaturaData.h +++ b/src/include/mx/api/ScordaturaData.h @@ -5,6 +5,7 @@ #pragma once #include "mx/api/ApiCommon.h" +#include "mx/api/Id.h" #include "mx/api/PitchData.h" #include @@ -49,7 +50,7 @@ class ScordaturaData { public: std::vector accords; - std::optional id; + std::optional id; ScordaturaData() : accords{}, id{} { diff --git a/src/include/mx/api/SoundData.h b/src/include/mx/api/SoundData.h index 121a12999..35e471525 100644 --- a/src/include/mx/api/SoundData.h +++ b/src/include/mx/api/SoundData.h @@ -5,6 +5,7 @@ #pragma once #include "mx/api/ApiCommon.h" +#include "mx/api/Id.h" #include #include @@ -87,8 +88,8 @@ struct SoundData std::optional swing; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; SoundData() : tempo{DOUBLE_UNSPECIFIED}, dynamics{DOUBLE_UNSPECIFIED}, dacapo{Bool::unspecified}, diff --git a/src/include/mx/api/SpannerData.h b/src/include/mx/api/SpannerData.h index dd7c55d8a..78a3b8c48 100644 --- a/src/include/mx/api/SpannerData.h +++ b/src/include/mx/api/SpannerData.h @@ -5,6 +5,7 @@ #pragma once #include "mx/api/ApiCommon.h" +#include "mx/api/Id.h" #include "mx/api/LineData.h" #include "mx/api/PositionData.h" #include "mx/api/PrintData.h" @@ -27,8 +28,8 @@ struct SpannerStart LineData lineData; // The id attribute of the element this spanner end is written as -- , - // , or (see ApiCommon.h). - std::optional id; + // , or (see Id.h). + std::optional id; SpannerStart() : number{}, tickTimePosition{0}, positionData{}, printData{}, lineData{}, id{} { @@ -43,8 +44,8 @@ struct SpannerStop LineData lineData; // The id attribute of the element this spanner end is written as -- , - // , or (see ApiCommon.h). - std::optional id; + // , or (see Id.h). + std::optional id; SpannerStop() : number{}, tickTimePosition{0}, positionData{}, lineData{}, id{} { diff --git a/src/include/mx/api/StaffDivideData.h b/src/include/mx/api/StaffDivideData.h index 88b7ff898..fb5644e16 100644 --- a/src/include/mx/api/StaffDivideData.h +++ b/src/include/mx/api/StaffDivideData.h @@ -7,6 +7,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -37,7 +38,7 @@ class StaffDivideData PositionData positionData; FontData fontData; std::optional color; - std::optional id; + std::optional id; StaffDivideData() : type{StaffDivideType::down}, positionData{}, fontData{}, color{}, id{} { diff --git a/src/include/mx/api/StringMuteData.h b/src/include/mx/api/StringMuteData.h index b156caba0..5c2414867 100644 --- a/src/include/mx/api/StringMuteData.h +++ b/src/include/mx/api/StringMuteData.h @@ -7,6 +7,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -34,7 +35,7 @@ class StringMuteData PositionData positionData; FontData fontData; std::optional color; - std::optional id; + std::optional id; StringMuteData() : type{StringMuteType::on}, positionData{}, fontData{}, color{}, id{} { diff --git a/src/include/mx/api/SymbolData.h b/src/include/mx/api/SymbolData.h index 3b215534b..ad9d65eb0 100644 --- a/src/include/mx/api/SymbolData.h +++ b/src/include/mx/api/SymbolData.h @@ -7,6 +7,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ColorData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/PositionData.h" #include @@ -41,8 +42,8 @@ class SymbolData // symbol-formatting attributes mirror the text-formatting ones on ``. HorizontalAlignment justify; - // The element's id attribute (see ApiCommon.h). - std::optional id; + // The element's id attribute (see Id.h). + std::optional id; SymbolData() : smufl{}, positionData{}, fontData{}, color{}, enclosure{Enclosure::unspecified}, diff --git a/src/include/mx/api/TempoData.h b/src/include/mx/api/TempoData.h index 383817671..0d491557d 100644 --- a/src/include/mx/api/TempoData.h +++ b/src/include/mx/api/TempoData.h @@ -7,6 +7,7 @@ #include "mx/api/ColorData.h" #include "mx/api/DurationData.h" #include "mx/api/FontData.h" +#include "mx/api/Id.h" #include "mx/api/NoteRelationData.h" #include "mx/api/PositionData.h" #include "mx/api/PrintData.h" @@ -126,7 +127,7 @@ class TempoData PositionData positionData; FontData fontData; std::optional color; - std::optional id; + std::optional id; HorizontalAlignment justify; Bool printObject; TempoChoice choice; diff --git a/src/include/mx/api/TimeChoice.h b/src/include/mx/api/TimeChoice.h index d26ba44e2..e1f742dcd 100644 --- a/src/include/mx/api/TimeChoice.h +++ b/src/include/mx/api/TimeChoice.h @@ -6,6 +6,7 @@ #include "mx/api/ApiCommon.h" #include "mx/api/ComplexTimeSignature.h" +#include "mx/api/Id.h" #include "mx/api/TimeSignatureData.h" #include @@ -59,9 +60,9 @@ class TimeChoice // Print/hide the time signature (