Audacity 3.2.0
Classes | Public Types | Public Member Functions | Public Attributes | List of all members
anonymous_namespace{Registry.cpp}::CollectedItems Struct Reference
Collaboration diagram for anonymous_namespace{Registry.cpp}::CollectedItems:
[legend]

Classes

struct  Item
 

Public Types

using Iterator = decltype(items)::iterator
 
using NewItem = std::pair< BaseItem *, OrderingHint >
 
using NewItems = std::vector< NewItem >
 

Public Member Functions

auto Find (const Identifier &name) -> Iterator
 
auto InsertNewItemUsingPreferences (ItemOrdering &itemOrdering, BaseItem *pItem) -> bool
 
auto InsertNewItemUsingHint (BaseItem *pItem, const OrderingHint &hint, size_t endItemsCount, bool force) -> bool
 
auto MergeLater (Item &found, const Identifier &name, GroupItemBase::Ordering ordering) -> GroupItemBase *
 
void SubordinateSingleItem (Item &found, BaseItem *pItem)
 
void SubordinateMultipleItems (Item &found, GroupItemBase &items)
 
bool MergeWithExistingItem (ItemOrdering &itemOrdering, BaseItem *pItem)
 
bool MergeLikeNamedItems (ItemOrdering &itemOrdering, NewItems::const_iterator left, NewItems::const_iterator right, int iPass, size_t endItemsCount, bool force)
 
void MergeItemsAscendingNamesPass (ItemOrdering &itemOrdering, NewItems &newItems, int iPass, size_t endItemsCount, bool force)
 
void MergeItemsDescendingNamesPass (ItemOrdering &itemOrdering, NewItems &newItems, int iPass, size_t endItemsCount, bool force)
 
void MergeItems (ItemOrdering &itemOrdering, const GroupItemBase &toMerge, const OrderingHint &hint, void *pComputedItemContext)
 

Public Attributes

std::vector< Itemitems
 
std::vector< BaseItemSharedPtr > & computedItems
 

Detailed Description

Definition at line 39 of file Registry.cpp.

Member Typedef Documentation

◆ Iterator

using anonymous_namespace{Registry.cpp}::CollectedItems::Iterator = decltype( items )::iterator

Definition at line 53 of file Registry.cpp.

◆ NewItem

using anonymous_namespace{Registry.cpp}::CollectedItems::NewItem = std::pair< BaseItem*, OrderingHint >

Definition at line 81 of file Registry.cpp.

◆ NewItems

using anonymous_namespace{Registry.cpp}::CollectedItems::NewItems = std::vector< NewItem >

Definition at line 82 of file Registry.cpp.

Member Function Documentation

◆ Find()

auto anonymous_namespace{Registry.cpp}::CollectedItems::Find ( const Identifier name) -> Iterator
inline

Definition at line 54 of file Registry.cpp.

55 {
56 auto end = items.end();
57 return name.empty()
58 ? end
59 : std::find_if( items.begin(), end,
60 [&]( const Item& item ){
61 return name == item.visitNow->name; } );
62 }
wxString name
Definition: TagsEditor.cpp:166
const char * end(const char *str) noexcept
Definition: StringUtils.h:106

References details::end(), and name.

Here is the call graph for this function:

◆ InsertNewItemUsingHint()

auto anonymous_namespace{Registry.cpp}::CollectedItems::InsertNewItemUsingHint ( BaseItem *  pItem,
const OrderingHint hint,
size_t  endItemsCount,
bool  force 
) -> bool

Definition at line 288 of file Registry.cpp.

291{
292 auto begin = items.begin(), end = items.end(),
293 insertPoint = end - endItemsCount;
294
295 // pItem should have a name; if not, ignore the hint, and put it at the
296 // default place, but only if in the final pass.
297 if ( pItem->name.empty() ) {
298 if ( !force )
299 return false;
300 }
301 else {
302 switch ( hint.type ) {
304 case OrderingHint::After: {
305 // Default to the end if the name is not found.
306 auto found = Find( hint.name );
307 if ( found == end ) {
308 if ( !force )
309 return false;
310 else
311 insertPoint = found;
312 }
313 else {
314 insertPoint = found;
315 if ( hint.type == OrderingHint::After )
316 ++insertPoint;
317 }
318 break;
319 }
321 insertPoint = begin;
322 break;
324 insertPoint = end;
325 break;
327 default:
328 if ( !force )
329 return false;
330 break;
331 }
332 }
333
334 // Insert the item; the hint has been used and no longer matters
335 items.insert( insertPoint, {pItem, nullptr,
336 // Hints no longer matter:
337 {}} );
338 return true;
339}
const char * begin(const char *str) noexcept
Definition: StringUtils.h:101
enum Registry::OrderingHint::Type type
auto Find(const Identifier &name) -> Iterator
Definition: Registry.cpp:54

References details::begin(), Journal::Begin(), details::end(), and ActiveProjects::Find().

Here is the call graph for this function:

◆ InsertNewItemUsingPreferences()

auto anonymous_namespace{Registry.cpp}::CollectedItems::InsertNewItemUsingPreferences ( ItemOrdering itemOrdering,
BaseItem *  pItem 
) -> bool

Definition at line 247 of file Registry.cpp.

250{
251 // Note that if more than one plug-in registers items under the same
252 // node, then it is not specified which plug-in is handled first,
253 // the first time registration happens. It might happen that you
254 // add a plug-in, run the program, then add another, then run again;
255 // registration order determined by those actions might not
256 // correspond to the order of re-loading of modules in later
257 // sessions. But whatever ordering is chosen the first time some
258 // plug-in is seen -- that ordering gets remembered in preferences.
259
260 if ( !pItem->name.empty() ) {
261 // Check saved ordering first, and rebuild that as well as is possible
262 auto &ordering = itemOrdering.Get();
263 auto begin2 = ordering.begin(), end2 = ordering.end(),
264 found2 = std::find( begin2, end2, pItem->name );
265 if ( found2 != end2 ) {
266 auto insertPoint = items.end();
267 // Find the next name in the saved ordering that is known already
268 // in the collection.
269 while ( ++found2 != end2 ) {
270 auto known = Find( *found2 );
271 if ( known != insertPoint ) {
272 insertPoint = known;
273 break;
274 }
275 }
276 items.insert( insertPoint, {pItem, nullptr,
277 // Hints no longer matter:
278 {}} );
279 return true;
280 }
281 }
282
283 return false;
284}

References ActiveProjects::Find().

Here is the call graph for this function:

◆ MergeItems()

void anonymous_namespace{Registry.cpp}::CollectedItems::MergeItems ( ItemOrdering itemOrdering,
const GroupItemBase &  toMerge,
const OrderingHint hint,
void *  pComputedItemContext 
)

Definition at line 546 of file Registry.cpp.

549{
550 NewItems newItems;
551
552 {
553 // First do expansion of nameless groupings, and caching of computed
554 // items, just as for the previously collected items.
555 CollectedItems newCollection{ {}, computedItems };
556 CollectItems(newCollection, toMerge, hint, pComputedItemContext);
557
558 // Try to merge each, resolving name collisions with items already in the
559 // tree, and collecting those with names that don't collide.
560 for (const auto &item : newCollection.items)
561 if (!MergeWithExistingItem(itemOrdering, item.visitNow))
562 newItems.push_back({ item.visitNow, item.hint });
563 }
564
565 // Choose placements for items with NEW names.
566
567 // First sort so that like named items are together, and for the same name,
568 // items with more specific ordering hints come earlier.
569 std::sort( newItems.begin(), newItems.end(), Comp );
570
571 // Outer loop over trial passes.
572 int iPass = -1;
573 bool force = false;
574 size_t oldSize = 0;
575 size_t endItemsCount = 0;
576 auto prevSize = newItems.size();
577 while( !newItems.empty() )
578 {
579 // If several items have the same hint, we try to preserve the sort by
580 // name (an internal identifier, not necessarily user visible), just to
581 // have some determinacy. That requires passing one or the other way
582 // over newItems.
583 bool descending =
584 ( iPass == OrderingHint::After || iPass == OrderingHint::Begin );
585
586 if ( descending )
588 newItems, iPass, endItemsCount, force);
589 else
590 MergeItemsAscendingNamesPass(itemOrdering,
591 newItems, iPass, endItemsCount, force);
592
593 auto newSize = newItems.size();
594 ++iPass;
595
596 if ( iPass == 0 )
597 // Just tried insertion by preferences. Don't try it again.
598 oldSize = newSize;
599 else if ( iPass == OrderingHint::Unspecified ) {
600 if ( !force ) {
601 iPass = 0, oldSize = newSize;
602 // Are we really ready for the final pass?
603 bool progress = ( oldSize > newSize );
604 if ( progress )
605 // No. While some progress is made, don't force final placements.
606 // Retry Before and After hints.
607 ;
608 else
609 force = true;
610 }
611 }
612 else if (iPass == OrderingHint::End && endItemsCount == 0)
613 {
614 assert(newSize >= prevSize || newSize == 0);
615 // Remember the size before we put the ending items in place
616 endItemsCount = newSize - prevSize;
617 }
618
619 prevSize = newSize;
620 }
621}
bool Comp(const CollectedItems::NewItem &a, const CollectedItems::NewItem &b)
Definition: Registry.cpp:491
void CollectItems(CollectedItems &collection, const GroupItemBase &items, const OrderingHint &hint, void *pComputedItemContext)
Definition: Registry.cpp:117
bool MergeWithExistingItem(ItemOrdering &itemOrdering, BaseItem *pItem)
Definition: Registry.cpp:370
std::vector< BaseItemSharedPtr > & computedItems
Definition: Registry.cpp:50
void MergeItemsDescendingNamesPass(ItemOrdering &itemOrdering, NewItems &newItems, int iPass, size_t endItemsCount, bool force)
Definition: Registry.cpp:525
void MergeItemsAscendingNamesPass(ItemOrdering &itemOrdering, NewItems &newItems, int iPass, size_t endItemsCount, bool force)
Definition: Registry.cpp:500

References Journal::Begin(), anonymous_namespace{Registry.cpp}::CollectItems(), and anonymous_namespace{Registry.cpp}::Comp().

Here is the call graph for this function:

◆ MergeItemsAscendingNamesPass()

void anonymous_namespace{Registry.cpp}::CollectedItems::MergeItemsAscendingNamesPass ( ItemOrdering itemOrdering,
NewItems newItems,
int  iPass,
size_t  endItemsCount,
bool  force 
)

Definition at line 500 of file Registry.cpp.

502{
503 // Inner loop over ranges of like-named items.
504 auto rright = newItems.rbegin();
505 auto rend = newItems.rend();
506 while ( rright != rend ) {
507 // Find the range
508 using namespace std::placeholders;
509 auto rleft = std::find_if(
510 rright + 1, rend, std::bind( MajorComp, _1, *rright ) );
511
512 bool success = MergeLikeNamedItems(itemOrdering,
513 rleft.base(), rright.base(), iPass, endItemsCount, force);
514
515 if ( success ) {
516 auto diff = rend - rleft;
517 newItems.erase( rleft.base(), rright.base() );
518 rend = newItems.rend();
519 rleft = rend - diff;
520 }
521 rright = rleft;
522 }
523}
bool MajorComp(const CollectedItems::NewItem &a, const CollectedItems::NewItem &b)
Definition: Registry.cpp:480
bool MergeLikeNamedItems(ItemOrdering &itemOrdering, NewItems::const_iterator left, NewItems::const_iterator right, int iPass, size_t endItemsCount, bool force)
Definition: Registry.cpp:437

References anonymous_namespace{Registry.cpp}::MajorComp().

Here is the call graph for this function:

◆ MergeItemsDescendingNamesPass()

void anonymous_namespace{Registry.cpp}::CollectedItems::MergeItemsDescendingNamesPass ( ItemOrdering itemOrdering,
NewItems newItems,
int  iPass,
size_t  endItemsCount,
bool  force 
)

Definition at line 525 of file Registry.cpp.

527{
528 // Inner loop over ranges of like-named items.
529 auto left = newItems.begin();
530 while ( left != newItems.end() ) {
531 // Find the range
532 using namespace std::placeholders;
533 auto right = std::find_if(
534 left + 1, newItems.end(), std::bind( MajorComp, *left, _1 ) );
535
536 bool success = MergeLikeNamedItems(itemOrdering, left, right, iPass,
537 endItemsCount, force );
538
539 if ( success )
540 left = newItems.erase( left, right );
541 else
542 left = right;
543 }
544};

References anonymous_namespace{Registry.cpp}::MajorComp().

Here is the call graph for this function:

◆ MergeLater()

auto anonymous_namespace{Registry.cpp}::CollectedItems::MergeLater ( Item found,
const Identifier name,
GroupItemBase::Ordering  ordering 
) -> GroupItemBase *

Definition at line 341 of file Registry.cpp.

343{
344 auto subGroup = found.mergeLater;
345 if (!subGroup) {
346 auto newGroup = std::make_shared<PlaceHolder>(name, ordering);
347 computedItems.push_back(newGroup);
348 subGroup = found.mergeLater = newGroup.get();
349 }
350 return subGroup;
351}

References name.

◆ MergeLikeNamedItems()

bool anonymous_namespace{Registry.cpp}::CollectedItems::MergeLikeNamedItems ( ItemOrdering itemOrdering,
NewItems::const_iterator  left,
NewItems::const_iterator  right,
int  iPass,
size_t  endItemsCount,
bool  force 
)

Definition at line 437 of file Registry.cpp.

440{
441 // Try to place the first item of the range.
442 // If such an item is a group, then we always retain the kind of
443 // grouping that was registered. (Which doesn't always happen when
444 // there is name collision in MergeWithExistingItem.)
445 auto iter = left;
446 auto &item = *iter;
447 auto pItem = item.first;
448 const auto &hint = item.second;
449 bool success = false;
450 if ( iPass == -1 )
451 // A first pass consults preferences.
452 success = InsertNewItemUsingPreferences( itemOrdering, pItem );
453 else if ( iPass == hint.type ) {
454 // Later passes for choosing placements.
455 // Maybe it fails in this pass, because a placement refers to some
456 // other name that has not yet been placed.
457 success =
458 InsertNewItemUsingHint( pItem, hint, endItemsCount, force );
459 wxASSERT( !force || success );
460 }
461
462 if ( success ) {
463 // Resolve collisions among remaining like-named items.
464 ++iter;
465 if ( iter != right && iPass != 0 &&
466 iter->second.type != OrderingHint::Unspecified &&
467 !( iter->second == hint ) ) {
468 // A diagnostic message sometimes
469 ReportConflictingPlacements( itemOrdering.key, pItem->name );
470 }
471 while ( iter != right )
472 // Re-invoke MergeWithExistingItem for this item, which is known
473 // to have a name collision, so ignore the return value.
474 MergeWithExistingItem(itemOrdering, iter++ -> first);
475 }
476
477 return success;
478}
void ReportConflictingPlacements(const wxString &key, const Identifier &name)
Definition: Registry.cpp:205
auto InsertNewItemUsingHint(BaseItem *pItem, const OrderingHint &hint, size_t endItemsCount, bool force) -> bool
Definition: Registry.cpp:288
auto InsertNewItemUsingPreferences(ItemOrdering &itemOrdering, BaseItem *pItem) -> bool
Definition: Registry.cpp:247

References anonymous_namespace{Registry.cpp}::ItemOrdering::key, and anonymous_namespace{Registry.cpp}::ReportConflictingPlacements().

Here is the call graph for this function:

◆ MergeWithExistingItem()

bool anonymous_namespace{Registry.cpp}::CollectedItems::MergeWithExistingItem ( ItemOrdering itemOrdering,
BaseItem *  pItem 
)

Definition at line 370 of file Registry.cpp.

372{
373 // Assume no null pointers remain after CollectItems:
374 const auto &name = pItem->name;
375 const auto found = Find( name );
376 if (found != items.end()) {
377 // Collision of names between collection and registry!
378 // There are 2 * 2 = 4 cases, as each of the two are group items or
379 // not.
380 auto pCollectionGroup = dynamic_cast< GroupItemBase * >( found->visitNow );
381 auto pRegistryGroup = dynamic_cast< GroupItemBase * >( pItem );
382 if (pCollectionGroup) {
383 if (pRegistryGroup) {
384 // This is the expected case of collision.
385 // Subordinate items from one of the groups will be merged in
386 // another call to MergeItems at a lower level of path.
387 // Note, however, that at most one of the two should be a
388 // strongly ordered item; if not, we must lose the extra
389 // information carried by one of them.
390 bool pCollectionGrouping =
391 (pCollectionGroup->GetOrdering() != GroupItemBase::Strong);
392 auto pRegistryGrouping =
393 (pRegistryGroup->GetOrdering() != GroupItemBase::Strong);
394 if ( !(pCollectionGrouping || pRegistryGrouping) )
395 ReportGroupGroupCollision( itemOrdering.key, name );
396
397 if ( pCollectionGrouping && !pRegistryGrouping ) {
398 // Swap their roles
399 found->visitNow = pRegistryGroup;
400 SubordinateMultipleItems(*found, *pCollectionGroup);
401 }
402 else
403 SubordinateMultipleItems(*found, *pRegistryGroup);
404 }
405 else {
406 // Registered non-group item collides with a previously defined
407 // group.
408 // Resolve this by subordinating the non-group item below
409 // that group.
410 SubordinateSingleItem(*found, pItem);
411 }
412 }
413 else {
414 if (pRegistryGroup) {
415 // Subordinate the previously merged single item below the
416 // newly merged group.
417 // In case the name occurred in two different static registries,
418 // the final merge is the same, no matter which is treated first.
419 auto demoted = found->visitNow;
420 found->visitNow = pRegistryGroup;
421 SubordinateSingleItem(*found, demoted);
422 }
423 else
424 // Collision of non-group items is the worst case!
425 // The later-registered item is lost.
426 // Which one you lose might be unpredictable when both originate
427 // from static registries.
428 ReportItemItemCollision( itemOrdering.key, name );
429 }
430 return true;
431 }
432 else
433 // A name is registered that is not known in the collection.
434 return false;
435}
void ReportItemItemCollision(const wxString &key, const Identifier &name)
Definition: Registry.cpp:198
void ReportGroupGroupCollision(const wxString &key, const Identifier &name)
Definition: Registry.cpp:191
void SubordinateMultipleItems(Item &found, GroupItemBase &items)
Definition: Registry.cpp:361
void SubordinateSingleItem(Item &found, BaseItem *pItem)
Definition: Registry.cpp:353

References ActiveProjects::Find(), anonymous_namespace{Registry.cpp}::ItemOrdering::key, name, anonymous_namespace{Registry.cpp}::ReportGroupGroupCollision(), and anonymous_namespace{Registry.cpp}::ReportItemItemCollision().

Here is the call graph for this function:

◆ SubordinateMultipleItems()

void anonymous_namespace{Registry.cpp}::CollectedItems::SubordinateMultipleItems ( Item found,
GroupItemBase &  items 
)

Definition at line 361 of file Registry.cpp.

362{
363 auto subGroup = MergeLater(found, items.name, items.GetOrdering());
364 for (const auto &pItem : items)
365 subGroup->push_back(std::make_unique<IndirectItemBase>(
366 // shared pointer with vacuous deleter
367 std::shared_ptr<BaseItem>(pItem.get(), [](void*){})));
368}
auto MergeLater(Item &found, const Identifier &name, GroupItemBase::Ordering ordering) -> GroupItemBase *
Definition: Registry.cpp:341

◆ SubordinateSingleItem()

void anonymous_namespace{Registry.cpp}::CollectedItems::SubordinateSingleItem ( Item found,
BaseItem *  pItem 
)

Definition at line 353 of file Registry.cpp.

354{
355 MergeLater(found, pItem->name, GroupItemBase::Weak)->push_back(
356 std::make_unique<IndirectItemBase>(
357 // shared pointer with vacuous deleter
358 std::shared_ptr<BaseItem>(pItem, [](void*){})));
359}

Member Data Documentation

◆ computedItems

std::vector< BaseItemSharedPtr >& anonymous_namespace{Registry.cpp}::CollectedItems::computedItems

◆ items

std::vector< Item > anonymous_namespace{Registry.cpp}::CollectedItems::items

Definition at line 49 of file Registry.cpp.

Referenced by anonymous_namespace{Registry.cpp}::CollectItem().


The documentation for this struct was generated from the following file: