pianod2
multisource multiuser scriptable networked music player
musiclibraryhash.h
Go to the documentation of this file.
1 
9 #pragma once
10 
11 #include <string>
12 #include <unordered_map>
13 #include <functional>
14 
15 #include "utility.h"
16 #include "musiclibrary.h"
17 
18 namespace MusicLibrary {
19 
20  /*
21  * Supporting functions
22  */
23 
26  inline std::string persistentId (MusicThingie::Type item_type, const std::string &key) {
27  const char type_code[2] = {static_cast<char> (item_type), '\0'};
28  return type_code + std::to_string (create_key_from_string (key));
29  }
30 
31 
32 
34  template <class TThing, class TParent>
36  : allocate (alloc) {
37  }
38 
40  template <class TThing, class TParent>
42 #ifndef NDEBUG
43  for (auto &item : *this) {
44  assert (item.second->getUseCount() == 1);
45  }
46 #endif
47  clear();
48  }
49 
52  template <class TThing, class TParent>
53  void ThingieContainer<TThing, TParent>::purge (bool pred (const TThing *)) {
54  auto it = this->begin();
55  while (it != this->end()) {
56  auto element = it++;
57  if (pred (element->second)) {
58  element->second->release();
59  this->erase (element);
60  }
61  }
62  }
63 
65  template <class TThing, class TParent>
67  while (this->begin() != this->end()) {
68  this->begin()->second->release();
69  this->erase (this->begin());
70  }
71  }
72 
74  template <class TThing, class TParent>
75  TThing *ThingieContainer<TThing, TParent>::getById (const std::string &key) const {
76  const auto iterator = this->find (key);
77  return (iterator == this->end() ? nullptr : iterator->second);
78  }
79 
81  template <class TThing, class TParent>
82  TThing *ThingieContainer<TThing, TParent>::getById (const Parsnip::Data &data, const char *field) {
83  return getById (data[field].asString());
84  }
85 
87  template <class TThing, class TParent>
88  TThing *ThingieContainer<TThing, TParent>::getByName (const std::string &name, TParent *parent) const {
89  for (auto item : *this) {
90  if (item.second->parent() == parent && *(item.second) == name) {
91  return item.second;
92  }
93  }
94  return nullptr;
95  }
96 
100  template <class TThing, class TParent>
102  const char type[2] = {static_cast<char> (item_type), '\0'};
103  while (true) {
104  long candidate = random();
105  std::string newid = type + std::to_string (candidate);
106  if (!getById (newid))
107  return newid;
108  }
109  }
110 
115  template <class TThing, class TParent>
116  TThing *ThingieContainer<TThing, TParent>::addItem (const std::string &name, std::string id, TParent *parent) {
117  std::string newid (id.empty() ? getNewId (TThing::typetype()) : id);
118  TThing *thing = allocate (parent, newid, name);
119  assert (this->find (newid) == this->end());
120  (*this)[newid] = thing;
121  thing->retain();
122  return thing;
123  }
124 
134  template <class TThing, class TParent>
135  TThing *ThingieContainer<TThing, TParent>::addOrGetItem (const std::string &name, std::string id, TParent *parent) {
136  assert (parent);
137  TThing *thing;
138  if (id.empty()) {
139  // Hash the name for a candidate ID
140  id = persistentId (TThing::typetype(), name);
141  thing = getById (id);
142  if (thing && thing->parent() == parent && *thing == name) {
143  return thing;
144  }
145  // If there was no match, leave ID set to the candidate ID.
146  if (thing)
147  id = "";
148  thing = getByName (name, parent);
149  } else {
150  thing = getById (id);
151  }
152  if (thing)
153  return thing;
154  return addItem (name, id, parent);
155  }
156 
163  template <class TThing, class TParent>
165  TParent *parent,
166  const std::string &namefield,
167  const std::string &idfield) {
168  const std::string &name = data[namefield].asString();
169  const std::string &id = data[idfield].asString();
170  TThing *item = addOrGetItem (name, id, parent);
171  assert (item);
172  item->restore (data);
173  return item;
174  }
175 
176 } // namespace MusicLibrary
TThing * getById(const std::string &key) const
Get a thing by its id.
Definition: musiclibraryhash.h:75
std::string getNewId(MusicThingie::Type item_type) const
Construct unique, random ID for a new item.
Definition: musiclibraryhash.h:101
~ThingieContainer()
Destructor: Release all contents prior to destruction.
Definition: musiclibraryhash.h:41
TThing * addItem(const std::string &name, std::string id, TParent *parent)
Construct a new item instance and add it to the hash by its ID.
Definition: musiclibraryhash.h:116
TThing * getByName(const std::string &name, TParent *parent) const
Search the things looking for a name and parent match.
Definition: musiclibraryhash.h:88
TThing * addOrGetItem(const std::string &name, std::string id, TParent *parent)
Retrieve an item by ID or by name.
Definition: musiclibraryhash.h:135
ThingieContainer(const Allocator &alloc)
Constructor: Construct a new ThingieContainer and assign it an allocator.
Definition: musiclibraryhash.h:35
void purge(bool pred(const TThing *))
Remove items according to the predicate.
Definition: musiclibraryhash.h:53
void clear()
Remove all items from the hash table.
Definition: musiclibraryhash.h:66
std::function< TThing *(TParent *const, const std::string &, const std::string &)> Allocator
Definition: musiclibrary.h:291
Type
Definition: musictypes.h:86
Generic data type.
Definition: parsnip.h:81
const StringType & asString() const
Retrieve string value.
Definition: parsnip_types.cpp:133
PlayList / Artist / Album / Song types that are interbred to form a library.
Memory-based index/database of music library contents.
Definition: musiclibrary.cpp:37
std::string persistentId(MusicThingie::Type item_type, const std::string &key)
Use an item's type and a string key generate a id string.
Definition: musiclibraryhash.h:26
lamerkey_t create_key_from_string(const char *source)
Generate a key from a string.
Definition: utility.cpp:316
Various helpful templates, classes and functions.