summaryrefslogtreecommitdiffstats
path: root/src/base/PropertyName.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/PropertyName.h')
-rw-r--r--src/base/PropertyName.h158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/base/PropertyName.h b/src/base/PropertyName.h
new file mode 100644
index 0000000..f9e8c20
--- /dev/null
+++ b/src/base/PropertyName.h
@@ -0,0 +1,158 @@
+// -*- c-basic-offset: 4 -*-
+
+
+/*
+ Rosegarden
+ A sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral right of the authors to claim authorship of this work
+ has been asserted.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#ifndef _PROPERTY_NAME_H_
+#define _PROPERTY_NAME_H_
+
+#include <string>
+#include <map>
+#include <iostream>
+
+namespace Rosegarden
+{
+
+/**
+
+ A PropertyName is something that can be constructed from a string,
+ compared quickly as an int, hashed as a key in a hash map, and
+ streamed out again as a string. It must have accompanying functors
+ PropertyNamesEqual and PropertyNameHash which compare and hash
+ PropertyName objects.
+
+ The simplest implementation is a string:
+
+ typedef std::string PropertyName;
+
+ struct PropertyNamesEqual {
+ bool operator() (const PropertyName &s1, const PropertyName &s2) const {
+ return s1 == s2;
+ }
+ };
+
+ struct PropertyNameHash {
+ static std::hash<const char *> _H;
+ size_t operator() (const PropertyName &s) const {
+ return _H(s.c_str());
+ }
+ };
+
+ std::hash<const char *> PropertyNameHash::_H;
+
+ but our implementation is faster in practice: while it behaves
+ outwardly like a string, for the Event that makes use of it,
+ it performs much like a machine integer. It also shares
+ strings, reducing storage sizes if there are many names in use.
+
+ A big caveat with this class is that it is _not_ safe to persist
+ the values of PropertyNames and assume that the original strings
+ can be recovered; they can't. The values are assigned on demand,
+ and there's no guarantee that a given string will always map to
+ the same value (on separate invocations of the program). This
+ is why there's no PropertyName(int) constructor and no mechanism
+ for storing PropertyNames in properties. (Of course, you can
+ store the string representation of a PropertyName in a property;
+ but that's slow.)
+
+*/
+
+class PropertyName
+{
+public:
+ PropertyName() : m_value(-1) { }
+ PropertyName(const char *cs) { std::string s(cs); m_value = intern(s); }
+ PropertyName(const std::string &s) : m_value(intern(s)) { }
+ PropertyName(const PropertyName &p) : m_value(p.m_value) { }
+ ~PropertyName() { }
+
+ PropertyName &operator=(const char *cs) {
+ std::string s(cs);
+ m_value = intern(s);
+ return *this;
+ }
+ PropertyName &operator=(const std::string &s) {
+ m_value = intern(s);
+ return *this;
+ }
+ PropertyName &operator=(const PropertyName &p) {
+ m_value = p.m_value;
+ return *this;
+ }
+
+ bool operator==(const PropertyName &p) const {
+ return m_value == p.m_value;
+ }
+ bool operator< (const PropertyName &p) const {
+ return m_value < p.m_value;
+ }
+
+ const char *c_str() const {
+ return getName().c_str();
+ }
+
+ std::string getName() const /* throw (CorruptedValue) */;
+
+ int getValue() const { return m_value; }
+
+ static const PropertyName EmptyPropertyName;
+
+private:
+ typedef std::map<std::string, int> intern_map;
+ typedef intern_map::value_type intern_pair;
+
+ typedef std::map<int, std::string> intern_reverse_map;
+ typedef intern_reverse_map::value_type intern_reverse_pair;
+
+ static intern_map *m_interns;
+ static intern_reverse_map *m_internsReversed;
+ static int m_nextValue;
+
+ int m_value;
+
+ static int intern(const std::string &s);
+};
+
+inline std::ostream& operator<<(std::ostream &out, const PropertyName &n) {
+ out << n.getName();
+ return out;
+}
+
+inline std::string operator+(const std::string &s, const PropertyName &n) {
+ return s + n.getName();
+}
+
+struct PropertyNamesEqual
+{
+ bool operator() (const PropertyName &s1, const PropertyName &s2) const {
+ return s1 == s2;
+ }
+};
+
+struct PropertyNameHash
+{
+ size_t operator() (const PropertyName &s) const {
+ return static_cast<size_t>(s.getValue());
+ }
+};
+
+}
+
+#endif