1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 
4 /*
5     Rosegarden
6     A sequencer and musical notation editor.
7     Copyright 2000-2021 the Rosegarden development team.
8     See the AUTHORS file for more details.
9 
10     This program is free software; you can redistribute it and/or
11     modify it under the terms of the GNU General Public License as
12     published by the Free Software Foundation; either version 2 of the
13     License, or (at your option) any later version.  See the file
14     COPYING included with this distribution for more information.
15 */
16 
17 #ifndef RG_PROPERTY_H
18 #define RG_PROPERTY_H
19 
20 #include "RealTime.h"
21 
22 #include <QDebug>
23 
24 #include <string>
25 
26 #include <rosegardenprivate_export.h>
27 
28 namespace Rosegarden
29 {
30 
31 enum PropertyType { Int, String, Bool, RealTimeT };
32 
33 template <PropertyType P>
34 class ROSEGARDENPRIVATE_EXPORT PropertyDefn
35 {
36 public:
37     struct PropertyDefnNotDefined {
PropertyDefnNotDefinedPropertyDefnNotDefined38         PropertyDefnNotDefined() { throw(0); }
39     };
40     typedef PropertyDefnNotDefined basic_type;
41 
typeName()42     static std::string typeName() { return "Undefined"; }
43     static basic_type parse(std::string);
44     static std::string unparse(basic_type);
45 };
46 
47 template <PropertyType P>
48 typename PropertyDefn<P>::basic_type
parse(std::string)49 PropertyDefn<P>::parse(std::string)
50 {
51     throw(0);
52     return "";
53 }
54 
55 template <PropertyType P>
56 std::string
unparse(typename PropertyDefn<P>::basic_type)57 PropertyDefn<P>::unparse(typename PropertyDefn<P>::basic_type)
58 {
59     throw(0);
60     return "";
61 }
62 
63 
64 template <>
65 class PropertyDefn<Int>
66 {
67 public:
68     typedef long basic_type;
69 
70     static std::string typeName();
71     static basic_type parse(std::string s);
72     static std::string unparse(basic_type i);
73 };
74 
75 
76 template <>
77 class PropertyDefn<String>
78 {
79 public:
80     typedef std::string basic_type;
81 
82     static std::string typeName();
83     static basic_type parse(std::string s);
84     static std::string unparse(basic_type i);
85 };
86 
87 template <>
88 class PropertyDefn<Bool>
89 {
90 public:
91     typedef bool basic_type;
92 
93     static std::string typeName();
94     static basic_type parse(std::string s);
95     static std::string unparse(basic_type i);
96 };
97 
98 template <>
99 class PropertyDefn<RealTimeT>
100 {
101 public:
102     typedef RealTime basic_type;
103 
104     static std::string typeName();
105     static basic_type parse(std::string s);
106     static std::string unparse(basic_type i);
107 };
108 
109 
110 class ROSEGARDENPRIVATE_EXPORT PropertyStoreBase {
111 public:
112     virtual ~PropertyStoreBase();
113 
114     virtual PropertyType getType() const = 0;
115     virtual std::string getTypeName() const = 0;
116     virtual PropertyStoreBase *clone() = 0;
117     virtual std::string unparse() const = 0;
118 
119     virtual size_t getStorageSize() const = 0; // for debugging
120 
121 #ifndef NDEBUG
122     virtual void dump(std::ostream&) const = 0;
123 #else
dump(std::ostream &)124     virtual void dump(std::ostream&) const { }
125 #endif
126 };
127 
128 #ifndef NDEBUG
129 inline std::ostream& operator<<(std::ostream &out, PropertyStoreBase &e)
130 { e.dump(out); return out; }
131 #endif
132 
133 inline QDebug &operator<<(QDebug &dbg, const PropertyStoreBase &psb)
134 {
135     dbg << psb.getTypeName().c_str() << "-" << psb.unparse().c_str();
136     return dbg;
137 }
138 
139 template <PropertyType P>
140 class ROSEGARDENPRIVATE_EXPORT PropertyStore : public PropertyStoreBase
141 {
142 public:
PropertyStore(typename PropertyDefn<P>::basic_type d)143     PropertyStore(typename PropertyDefn<P>::basic_type d) :
144         m_data(d) { }
PropertyStore(const PropertyStore<P> & p)145     PropertyStore(const PropertyStore<P> &p) :
146         PropertyStoreBase(p), m_data(p.m_data) { }
147     PropertyStore &operator=(const PropertyStore<P> &p);
148 
149     PropertyType getType() const override;
150     std::string getTypeName() const override;
151 
152     PropertyStoreBase* clone() override;
153 
154     std::string unparse() const override;
155 
getData()156     typename PropertyDefn<P>::basic_type getData() { return m_data; }
setData(typename PropertyDefn<P>::basic_type data)157     void setData(typename PropertyDefn<P>::basic_type data) { m_data = data; }
158 
159     size_t getStorageSize() const override;
160 
161 #ifndef NDEBUG
162     void dump(std::ostream&) const override;
163 #endif
164 
165 private:
166     typename PropertyDefn<P>::basic_type m_data;
167 };
168 
169 template <PropertyType P>
170 PropertyStore<P>&
171 PropertyStore<P>::operator=(const PropertyStore<P> &p) {
172     if (this != &p) {
173         m_data = p.m_data;
174     }
175     return *this;
176 }
177 
178 template <PropertyType P>
179 PropertyType
getType()180 PropertyStore<P>::getType() const
181 {
182     return P;
183 }
184 
185 template <PropertyType P>
186 std::string
getTypeName()187 PropertyStore<P>::getTypeName() const
188 {
189     return PropertyDefn<P>::typeName();
190 }
191 
192 template <PropertyType P>
193 PropertyStoreBase*
clone()194 PropertyStore<P>::clone()
195 {
196     return new PropertyStore<P>(*this);
197 }
198 
199 template <PropertyType P>
200 std::string
unparse()201 PropertyStore<P>::unparse() const
202 {
203     return PropertyDefn<P>::unparse(m_data);
204 }
205 
206 #ifndef NDEBUG
207 template <PropertyType P>
208 void
dump(std::ostream & out)209 PropertyStore<P>::dump(std::ostream &out) const
210 {
211     out << getTypeName() << " - " << unparse();
212 }
213 #endif
214 
215 }
216 
217 
218 #endif
219