annotate base/ById.cpp @ 1833:21c792334c2e sensible-delimited-data-strings

Rewrite all the DelimitedDataString stuff so as to return vectors of individual cell strings rather than having the classes add the delimiters themselves. Rename accordingly to names based on StringExport. Take advantage of this in the CSV writer code so as to properly quote cells that contain delimiter characters.
author Chris Cannam
date Fri, 03 Apr 2020 17:11:05 +0100
parents 871a2050236b
children
rev   line source
Chris@1742 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1742 2
Chris@1742 3 /*
Chris@1742 4 Sonic Visualiser
Chris@1742 5 An audio file viewer and annotation editor.
Chris@1742 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1742 7
Chris@1742 8 This program is free software; you can redistribute it and/or
Chris@1742 9 modify it under the terms of the GNU General Public License as
Chris@1742 10 published by the Free Software Foundation; either version 2 of the
Chris@1742 11 License, or (at your option) any later version. See the file
Chris@1742 12 COPYING included with this distribution for more information.
Chris@1742 13 */
Chris@1742 14
Chris@1742 15 #include "ById.h"
Chris@1742 16
Chris@1742 17 #include <unordered_map>
Chris@1742 18 #include <typeinfo>
Chris@1742 19
Chris@1768 20 //#define DEBUG_BY_ID 1
Chris@1768 21
Chris@1742 22 int IdAlloc::getNextId()
Chris@1742 23 {
Chris@1742 24 static int nextId = 0;
Chris@1742 25 static QMutex mutex;
Chris@1742 26 QMutexLocker locker(&mutex);
Chris@1742 27 int i = nextId;
Chris@1742 28 if (nextId == INT_MAX) {
Chris@1742 29 nextId = INT_MIN;
Chris@1742 30 } else {
Chris@1742 31 ++nextId;
Chris@1742 32 if (nextId == 0 || nextId == NO_ID) {
Chris@1742 33 throw std::runtime_error("Internal ID limit exceeded!");
Chris@1742 34 }
Chris@1742 35 }
Chris@1742 36 return i;
Chris@1742 37 }
Chris@1742 38
Chris@1806 39 // "warning: expression with side effects will be evaluated despite
Chris@1806 40 // being used as an operand to 'typeid'"
Chris@1808 41 #ifdef __clang__
Chris@1807 42 #pragma clang diagnostic ignored "-Wpotentially-evaluated-expression"
Chris@1808 43 #endif
Chris@1806 44
Chris@1742 45 class AnyById::Impl
Chris@1742 46 {
Chris@1742 47 public:
Chris@1742 48 ~Impl() {
Chris@1742 49 QMutexLocker locker(&m_mutex);
Chris@1742 50 bool empty = true;
Chris@1742 51 for (const auto &p: m_items) {
Chris@1742 52 if (p.second && p.second.use_count() > 0) {
Chris@1742 53 empty = false;
Chris@1742 54 break;
Chris@1742 55 }
Chris@1742 56 }
Chris@1742 57 if (!empty) {
Chris@1742 58 SVCERR << "WARNING: ById map is not empty at close; some items have not been released" << endl;
Chris@1742 59 SVCERR << " Unreleased items are:" << endl;
Chris@1742 60 for (const auto &p: m_items) {
Chris@1759 61 auto ptr = p.second;
Chris@1759 62 if (ptr && ptr.use_count() > 0) {
Chris@1759 63 QString message = QString("id #%1: type %2")
Chris@1759 64 .arg(p.first).arg(typeid(*ptr.get()).name());
Chris@1759 65 if (auto qobj = std::dynamic_pointer_cast<QObject>(ptr)) {
Chris@1759 66 message += QString(", object name \"%1\"")
Chris@1759 67 .arg(qobj->objectName());
Chris@1759 68 }
Chris@1759 69 message += QString(", use count %1").arg(ptr.use_count());
Chris@1759 70 SVCERR << " - " << message << endl;
Chris@1742 71 }
Chris@1742 72 }
Chris@1742 73 }
Chris@1742 74 }
Chris@1742 75
Chris@1752 76 int add(std::shared_ptr<WithId> item) {
Chris@1752 77 int id = item->getUntypedId();
Chris@1744 78 if (id == IdAlloc::NO_ID) {
Chris@1752 79 throw std::logic_error("item id should never be NO_ID");
Chris@1744 80 }
Chris@1768 81 #ifdef DEBUG_BY_ID
Chris@1761 82 SVCERR << "ById::add(#" << id << ") of type "
Chris@1761 83 << typeid(*item.get()).name() << endl;
Chris@1768 84 #endif
Chris@1742 85 QMutexLocker locker(&m_mutex);
Chris@1742 86 if (m_items.find(id) != m_items.end()) {
Chris@1742 87 SVCERR << "ById::add: item with id " << id
Chris@1742 88 << " is already recorded (existing item type is "
Chris@1742 89 << typeid(*m_items.find(id)->second.get()).name()
Chris@1742 90 << ", proposed is "
Chris@1742 91 << typeid(*item.get()).name() << ")" << endl;
Chris@1742 92 throw std::logic_error("item id is already recorded in add");
Chris@1742 93 }
Chris@1742 94 m_items[id] = item;
Chris@1752 95 return id;
Chris@1742 96 }
Chris@1742 97
Chris@1742 98 void release(int id) {
Chris@1744 99 if (id == IdAlloc::NO_ID) {
Chris@1744 100 return;
Chris@1744 101 }
Chris@1768 102 #ifdef DEBUG_BY_ID
Chris@1761 103 SVCERR << "ById::release(#" << id << ")" << endl;
Chris@1768 104 #endif
Chris@1742 105 QMutexLocker locker(&m_mutex);
Chris@1742 106 if (m_items.find(id) == m_items.end()) {
Chris@1742 107 SVCERR << "ById::release: unknown item id " << id << endl;
Chris@1742 108 throw std::logic_error("unknown item id in release");
Chris@1742 109 }
Chris@1742 110 m_items.erase(id);
Chris@1742 111 }
Chris@1742 112
Chris@1742 113 std::shared_ptr<WithId> get(int id) const {
Chris@1744 114 if (id == IdAlloc::NO_ID) {
Chris@1744 115 return {}; // this id cannot be added: avoid locking
Chris@1744 116 }
Chris@1742 117 QMutexLocker locker(&m_mutex);
Chris@1742 118 const auto &itr = m_items.find(id);
Chris@1742 119 if (itr != m_items.end()) {
Chris@1742 120 return itr->second;
Chris@1742 121 } else {
Chris@1742 122 return {};
Chris@1742 123 }
Chris@1742 124 }
Chris@1742 125
Chris@1742 126 private:
Chris@1742 127 mutable QMutex m_mutex;
Chris@1742 128 std::unordered_map<int, std::shared_ptr<WithId>> m_items;
Chris@1742 129 };
Chris@1742 130
Chris@1752 131 int
Chris@1752 132 AnyById::add(std::shared_ptr<WithId> item)
Chris@1742 133 {
Chris@1752 134 return impl().add(item);
Chris@1742 135 }
Chris@1742 136
Chris@1742 137 void
Chris@1742 138 AnyById::release(int id)
Chris@1742 139 {
Chris@1742 140 impl().release(id);
Chris@1742 141 }
Chris@1742 142
Chris@1742 143 std::shared_ptr<WithId>
Chris@1742 144 AnyById::get(int id)
Chris@1742 145 {
Chris@1742 146 return impl().get(id);
Chris@1742 147 }
Chris@1742 148
Chris@1742 149 AnyById::Impl &
Chris@1742 150 AnyById::impl()
Chris@1742 151 {
Chris@1742 152 static Impl impl;
Chris@1742 153 return impl;
Chris@1742 154 }