26#include <unordered_map>
35#include "MusxInstance.h"
37#include "BaseClasses.h"
41#include "ShapeDesigner.h"
42#include "SmartShape.h"
45#ifndef DOXYGEN_SHOULD_IGNORE_THIS
49template<
class>
class PoolAccessor;
59template <
typename Pool,
typename T>
63template <
typename Pool,
typename T>
75template <
typename ObjectBaseType>
93 std::optional<Cmper> c1 = std::nullopt,
94 std::optional<Cmper> c2 = std::nullopt,
120 std::string result = std::string(
nodeId) +
" part " + std::to_string(
partId);
123 result +=
" cmpers [" + std::to_string(
cmper1.value()) +
", " + std::to_string(
cmper2.value()) +
"]";
125 result +=
" cmper " + std::to_string(
cmper1.value());
129 result +=
" inci " + std::to_string(
inci.value());
136 template <
typename T>
137 std::shared_ptr<const T> bindWithPartId(std::shared_ptr<const T> obj,
Cmper requestedPartId)
const
139 if constexpr (std::is_base_of_v<OthersBase, T> || std::is_base_of_v<DetailsBase, T>) {
140 if (obj && obj->getRequestedPartId() != requestedPartId) {
141 return PartContextCloner::copyWithPartId(obj, requestedPartId);
147 inline static ObjectKey makeEndKey(
const ObjectKey& key)
152 key.cmper1.value_or((std::numeric_limits<Cmper>::max)()),
153 key.cmper2.value_or((std::numeric_limits<Cmper>::max)()),
154 key.inci.value_or((std::numeric_limits<Inci>::max)())
158 template <
typename T>
159 inline static MusxInstance<T> checkedStaticCast([[maybe_unused]]
const ObjectKey& key,
const ObjectPtr& p)
161 static_assert(std::is_base_of_v<ObjectBaseType, T>,
"T must derive from ObjectBaseType");
162 if constexpr (!std::is_same_v<T, ObjectBaseType>) {
163 assert(T::XmlNodeName == key.nodeId &&
"nodeId/type mismatch: pool invariant violated");
169 return std::static_pointer_cast<T>(p);
172 inline static bool logicalLess(
const ObjectKey& a,
const ObjectKey& b)
174 return std::tie(a.cmper1, a.cmper2, a.inci) < std::tie(b.cmper1, b.cmper2, b.inci);
177 inline static bool logicalEq(
const ObjectKey& a,
const ObjectKey& b)
179 return a.cmper1 == b.cmper1 && a.cmper2 == b.cmper2 && a.inci == b.inci;
194 if (key.
inci.has_value()) {
196 noInciKey.
inci = std::nullopt;
197 auto currentIncis = getArray<ObjectBaseType>(noInciKey, key.
partId);
198 if (key.
inci.value() !=
int(currentIncis.size())) {
199 MUSX_INTEGRITY_ERROR(
"Node " + std::string(key.
nodeId) +
" has inci " + std::to_string(key.
inci.value()) +
" that is out of sequence.");
202 auto shareModeIt = m_shareMode.find(key.
nodeId);
203 auto [poolIt, emplaced] = m_pool.emplace(std::move(key),
object);
205 MUSX_INTEGRITY_ERROR(
"Attempted to add same key more than once: " + poolIt->first.description());
207 if (shareModeIt == m_shareMode.end()) {
208 m_shareMode.emplace(poolIt->first.nodeId, object->getShareMode());
209 }
else if (object->getShareMode() != shareModeIt->second && object->getShareMode() !=
Base::ShareMode::All) {
211 m_shareMode[poolIt->first.nodeId] =
object->getShareMode();
213 MUSX_INTEGRITY_ERROR(
"Share mode for added " + std::string(poolIt->first.nodeId) +
" object [" + std::to_string(
int(object->getShareMode()))
214 +
"] does not match previous [" + std::to_string(
int(shareModeIt->second)) +
"]");
232 template <
typename T>
237 auto rangeStart = m_pool.lower_bound(key);
238 auto rangeEnd = m_pool.upper_bound(makeEndKey(key));
240 for (
auto it = rangeStart; it != rangeEnd; ++it) {
241 auto typedPtr = bindWithPartId<T>(checkedStaticCast<T>(key, it->second), requestedPartId);
242 result.push_back(typedPtr);
259 template <
typename T>
264 auto it = m_shareMode.find(key.
nodeId);
267 if (it != m_shareMode.end()) {
268 forShareMode = it->second;
273 return getArray<T>(key, key.
partId);
278 return getArray<T>(scoreKey, key.
partId);
281 const auto partStart = m_pool.lower_bound(key);
282 const auto partEnd = m_pool.upper_bound(makeEndKey(key));
284 const auto scoreStart = m_pool.lower_bound(scoreKey);
285 const auto scoreEnd = m_pool.upper_bound(makeEndKey(scoreKey));
287 auto partIt = partStart;
288 auto scoreIt = scoreStart;
291 auto pushInstance = [&](
const auto& it) {
292 auto typed = bindWithPartId<T>(checkedStaticCast<T>(key, it->second), key.
partId);
293 result.push_back(typed);
295 while (partIt != partEnd || scoreIt != scoreEnd) {
296 if (scoreIt == scoreEnd) {
297 pushInstance(partIt++);
300 if (partIt == partEnd) {
301 pushInstance(scoreIt++);
306 if (logicalEq(pk, sk)) {
307 pushInstance(partIt++);
309 }
else if (logicalLess(pk, sk)) {
310 pushInstance(partIt++);
312 pushInstance(scoreIt++);
329 template <
typename T>
332 auto it = m_pool.find(key);
333 if (it == m_pool.end()) {
336 return checkedStaticCast<T>(key, it->second);
352 template <
typename T>
355 if (
auto partVersion = getSource<T>(key)) {
363 auto it = m_shareMode.find(key.
nodeId);
370 return getSource<T>(scoreKey);
386 template <
typename T>
389 return bindWithPartId<T>(getEffectiveSourceForPart<T>(key), key.
partId);
397 : m_document(document), m_shareMode(knownShareModes) {}
401 std::unordered_map<std::string_view, dom::Base::ShareMode> m_shareMode;
403 std::map<ObjectKey, ObjectPtr> m_pool;
420 void add(std::string_view nodeName,
const std::shared_ptr<OptionsBase>& instance)
422 const Base* basePtr = instance.get();
424 MUSX_INTEGRITY_ERROR(
"Options node " + std::string(nodeName) +
" hase non-score part id [" + std::to_string(basePtr->
getSourcePartId()) +
"]");
430 template <
typename T>
433 static_assert(is_pool_type_v<OptionsPool, T>,
"Type T is not registered in OptionsPool");
438 template <
typename T>
441 static_assert(is_pool_type_v<OptionsPool, T>,
"Type T is not registered in OptionsPool");
480 void add(std::string_view nodeName,
const std::shared_ptr<OthersBase>& instance)
481 { m_pool.
add({nodeName, instance->getSourcePartId(), instance->getCmper(), std::nullopt, instance->getInci()}, instance); }
484 template <
typename T>
487 static_assert(is_pool_type_v<OthersPool, T>,
"Type T is not registered in OthersPool");
492 template <
typename T>
495 static_assert(is_pool_type_v<OthersPool, T>,
"Type T is not registered in OthersPool");
496 return m_pool.
getEffectiveForPart<T>({ T::XmlNodeName, partId, cmper, std::nullopt, inci });
523 void add(std::string_view nodeName,
const std::shared_ptr<DetailsBase>& instance)
524 { m_pool.
add({nodeName, instance->getSourcePartId(), instance->getCmper1(), instance->getCmper2(), instance->getInci()}, instance); }
527 template <
typename T,
typename = std::enable_if_t<is_pool_type_v<DetailsPool, T>>>
529 {
return m_pool.template getArrayForPart<T>({ T::XmlNodeName, partId }); }
532 template <
typename T,
typename std::enable_if_t<!std::is_base_of_v<EntryDetailsBase, T>,
int> = 0>
535 static_assert(is_pool_type_v<DetailsPool, T>,
"Type T is not registered in DetailsPool");
536 return m_pool.template getArrayForPart<T>({ T::XmlNodeName, partId, cmper1, cmper2 });
540 template <
typename T,
typename std::enable_if_t<std::is_base_of_v<EntryDetailsBase, T>,
int> = 0>
543 static_assert(is_pool_type_v<DetailsPool, T>,
"Type T is not registered in DetailsPool");
544 return m_pool.template getArrayForPart<T>({ T::XmlNodeName, partId,
Cmper(entnum >> 16),
Cmper(entnum & 0xffff) });
548 template <
typename T,
typename std::enable_if_t<!std::is_base_of_v<EntryDetailsBase, T>,
int> = 0>
551 static_assert(is_pool_type_v<DetailsPool, T>,
"Type T is not registered in DetailsPool");
556 template <
typename T,
typename std::enable_if_t<std::is_base_of_v<EntryDetailsBase, T>,
int> = 0>
559 static_assert(is_pool_type_v<DetailsPool, T>,
"Type T is not registered in DetailsPool");
569 template <
typename T,
typename std::enable_if_t<std::is_base_of_v<NoteDetailsBase, T>,
int> = 0>
572 static_assert(is_pool_type_v<DetailsPool, T>,
"Type T is not registered in DetailsPool");
573 auto details = getArray<T>(
577 for (
const auto& detail : details) {
578 if (detail->getNoteId() == noteInfo->getNoteId()) {
599 auto [it, emplaced] = m_pool.emplace(entryNumber, instance);
601 MUSX_INTEGRITY_ERROR(
"Entry number " + std::to_string(entryNumber) +
" added twice.");
608 const auto it = m_pool.find(entryNumber);
609 if (it == m_pool.end()) {
617 std::unordered_map<EntryNumber, std::shared_ptr<Entry>> m_pool;
619 friend class bench::PoolAccessor<
EntryPool>;
628 friend class bench::PoolAccessor<
TextsPool>;
635 void add(std::string_view nodeName,
const std::shared_ptr<TextsBase>& instance)
637 const Base* basePtr = instance.get();
639 MUSX_INTEGRITY_ERROR(
"Texts node " + std::string(nodeName) +
" hase non-score part id [" + std::to_string(basePtr->
getSourcePartId()) +
"]");
641 m_pool.
add({ nodeName, basePtr->
getSourcePartId(), instance->getTextNumber() }, instance);
645 template <
typename T>
648 static_assert(is_pool_type_v<TextsPool, T>,
"Type T is not registered in TextsPool");
653 template <
typename T>
656 static_assert(is_pool_type_v<TextsPool, T>,
"Type T is not registered in TextsPool");
Base class to enforce polymorphism across all DOM classes.
Definition BaseClasses.h:83
Cmper getSourcePartId() const
Gets the source partId for this instance. If an instance is fully shared with the score,...
Definition BaseClasses.h:124
ShareMode
Describes how this instance is shared between part and score.
Definition BaseClasses.h:91
A pool that manages collections of DetailsBase objects, organized by XML node names and Cmper values.
Definition ObjectPool.h:509
MusxInstanceList< T > getArray(Cmper partId) const
version of ObjectPool::getArray for getting all of them
Definition ObjectPool.h:528
MusxInstance< T > getForNote(const NoteInfoPtr ¬eInfo, const std::optional< Cmper > &forPartId=std::nullopt)
Returns the detail for a particular note.
Definition ObjectPool.h:570
DetailsPool(const DocumentWeakPtr &document)
Constructor.
Definition ObjectPool.h:515
MusxInstance< T > get(Cmper partId, EntryNumber entnum, std::optional< Inci > inci=std::nullopt) const
Get a single EntryDetailsBase item out of the pool.
Definition ObjectPool.h:557
MusxInstanceList< T > getArray(Cmper partId, EntryNumber entnum) const
EntryDetailsPool version of ObjectPool::getArray.
Definition ObjectPool.h:541
MusxInstance< T > get(Cmper partId, Cmper cmper1, Cmper cmper2, std::optional< Inci > inci=std::nullopt) const
Get a single DetailsBase item out of the pool (not EntryDetailsBase)
Definition ObjectPool.h:549
void add(std::string_view nodeName, const std::shared_ptr< DetailsBase > &instance)
DetailsPool version of ObjectPool::add.
Definition ObjectPool.h:523
MusxInstanceList< T > getArray(Cmper partId, Cmper cmper1, std::optional< Cmper > cmper2=std::nullopt) const
DetailsPool version of ObjectPool::getArray.
Definition ObjectPool.h:533
std::shared_ptr< const EntryFrame > getFrame() const
Returns the frame.
Definition Entries.h:606
Entry pool.
Definition ObjectPool.h:591
EntryPool(const DocumentWeakPtr &document)
Constructor function.
Definition ObjectPool.h:594
void add(EntryNumber entryNumber, const std::shared_ptr< Entry > &instance)
Add an entry to the EntryPool. (Used by the factory.)
Definition ObjectPool.h:597
MusxInstance< Entry > get(EntryNumber entryNumber) const
Get an entry from the EntryPool.
Definition ObjectPool.h:606
Provides optional per-type extension methods for MusxInstanceList.
Definition MusxInstance.h:103
Wraps an EntryInfo instance and a note index.
Definition Entries.h:1545
EntryInfoPtr getEntryInfo() const
Gets the entry info for this note.
Definition Entries.h:1585
A pool that manages collections of OthersBase objects, organized by XML node names and Cmper values.
Definition ObjectPool.h:77
ObjectPool(const DocumentWeakPtr &document, const std::unordered_map< std::string_view, dom::Base::ShareMode > &knownShareModes={})
Constructs the object pool.
Definition ObjectPool.h:396
virtual ~ObjectPool()=default
virtual destructor
MusxInstance< T > getSource(const ObjectKey &key) const
Retrieves the first (and usually only) object of a specific type from the pool.
Definition ObjectPool.h:330
MusxInstanceList< T > getArrayForPart(const ObjectKey &key) const
Retrieves a vector of objects of a specific type from the pool.
Definition ObjectPool.h:260
MusxInstanceList< T > getArray(const ObjectKey &key, Cmper requestedPartId) const
Retrieves a vector of objects of a specific type from the pool.
Definition ObjectPool.h:233
MusxInstance< T > getEffectiveSourceForPart(const ObjectKey &key) const
Retrieves the first (and usually only) object of a specific type from the pool for a part.
Definition ObjectPool.h:353
void add(ObjectKey key, ObjectPtr object)
Adds an ObjectBaseType object to the pool.
Definition ObjectPool.h:192
MusxInstance< T > getEffectiveForPart(const ObjectKey &key) const
Retrieves the first (and usually only) object of a specific type from the pool for a part.
Definition ObjectPool.h:387
std::shared_ptr< ObjectBaseType > ObjectPtr
shared pointer to ObjectBaseType
Definition ObjectPool.h:80
A pool that manages collections of OptionsBase objects that have no Cmper value.
Definition ObjectPool.h:411
void add(std::string_view nodeName, const std::shared_ptr< OptionsBase > &instance)
Scalar version of ObjectPool::add.
Definition ObjectPool.h:420
MusxInstance< T > get() const
Get a single item out of the pool.
Definition ObjectPool.h:439
MusxInstanceList< T > getArray() const
Scalar version of ObjectPool::getArray.
Definition ObjectPool.h:431
OptionsPool(const DocumentWeakPtr &document)
Constructor function.
Definition ObjectPool.h:417
A pool that manages collections of OthersBase objects.
Definition ObjectPool.h:453
MusxInstance< T > get(Cmper partId, Cmper cmper, std::optional< Inci > inci=std::nullopt) const
Get a single item out of the pool.
Definition ObjectPool.h:493
void add(std::string_view nodeName, const std::shared_ptr< OthersBase > &instance)
OthersPool version of ObjectPool::add.
Definition ObjectPool.h:480
OthersPool(const DocumentWeakPtr &document)
Constructor.
Definition ObjectPool.h:465
MusxInstanceList< T > getArray(Cmper partId, std::optional< Cmper > cmper=std::nullopt) const
OthersPool version of ObjectPool::getArray.
Definition ObjectPool.h:485
Text pool.
Definition ObjectPool.h:626
MusxInstanceList< T > getArray(std::optional< Cmper > cmper=std::nullopt) const
Texts version of ObjectPool::getArray.
Definition ObjectPool.h:646
TextsPool(const DocumentWeakPtr &document)
Constructor fundtion.
Definition ObjectPool.h:632
MusxInstance< T > get(Cmper cmper) const
Get a single item out of the pool.
Definition ObjectPool.h:654
void add(std::string_view nodeName, const std::shared_ptr< TextsBase > &instance)
Texts version of ObjectPool::add.
Definition ObjectPool.h:635
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition SmartShape.h:684
static constexpr std::string_view XmlNodeName
XML node name for this type.
Definition Details.h:1865
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Details.h:1940
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Others.h:397
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Others.h:1637
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Others.h:1619
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Others.h:1785
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Others.h:2024
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Others.h:2090
static MusxInstance< StaffComposite > createCurrent(const DocumentPtr &document, Cmper partId, StaffCmper staffId, MeasCmper measId, Edu eduPosition)
Calculates the current staff at the specified metric position by applying all relevant staff styles,...
Definition Staff.cpp:1065
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Staff.h:687
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Others.h:2774
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Others.h:2807
Represents the definition of a Finale staff.
Definition Staff.h:52
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Staff.h:507
static constexpr std::string_view XmlNodeName
The XML node name for this type.
Definition Others.h:2832
std::shared_ptr< OthersPool > OthersPoolPtr
Shared OthersPool pointer.
Definition ObjectPool.h:500
int16_t MeasCmper
Enigma meas Cmper (may be negative when not applicable)
Definition Fundamentals.h:64
std::shared_ptr< const T > MusxInstance
Defines the type of a musx instance stored in a pool.
Definition MusxInstance.h:39
constexpr Cmper SCORE_PARTID
The part id of the score.
Definition Fundamentals.h:79
constexpr bool is_pool_type_v
Value shortcut for is_pool_type.
Definition ObjectPool.h:64
std::shared_ptr< DetailsPool > DetailsPoolPtr
Shared DetailsPool pointer.
Definition ObjectPool.h:587
uint16_t Cmper
Enigma "comperator" key type.
Definition Fundamentals.h:55
std::shared_ptr< TextsPool > TextsPoolPtr
Shared OthersPool pointer.
Definition ObjectPool.h:661
int32_t Edu
"Enigma Durational Units" value (1024 per quarter note)
Definition Fundamentals.h:61
std::shared_ptr< OptionsPool > OptionsPoolPtr
Shared OptionsPool pointer.
Definition ObjectPool.h:446
std::weak_ptr< Document > DocumentWeakPtr
Shared weak Document pointer.
Definition BaseClasses.h:57
int32_t EntryNumber
Entry identifier.
Definition Fundamentals.h:69
std::shared_ptr< Document > DocumentPtr
Shared Document pointer.
Definition BaseClasses.h:55
int16_t StaffCmper
Enigma staff (staffId) Cmper (may be negative when not applicable)
Definition Fundamentals.h:65
std::shared_ptr< EntryPool > EntryPoolPtr
Shared EntryPool pointer.
Definition ObjectPool.h:622
object model for musx file (enigmaxml)
Definition BaseClasses.h:36
key type for storing in pool
Definition ObjectPool.h:82
std::optional< Cmper > cmper2
optional cmper2 for Details.
Definition ObjectPool.h:86
ObjectKey(std::string_view n, Cmper p, std::optional< Cmper > c1=std::nullopt, std::optional< Cmper > c2=std::nullopt, std::optional< int > i=std::nullopt)
explicit constructor for optional parameters
Definition ObjectPool.h:91
std::optional< Cmper > cmper1
optional cmper1 for Others, Texts, Details.
Definition ObjectPool.h:85
Cmper partId
the part this item is associated with (or 0 for score).
Definition ObjectPool.h:84
bool operator<(const ObjectKey &other) const
comparison operator for std::map
Definition ObjectPool.h:100
std::string_view nodeId
the identifier for this node. usually the XML node name.
Definition ObjectPool.h:83
std::optional< int > inci
optional inci for multi-inci classes
Definition ObjectPool.h:88
std::string description() const
provides a description of the key for diagnostic purposes
Definition ObjectPool.h:118
Type trait to determine if a class in a given pool.
Definition ObjectPool.h:60