2 Copyright (C) 2014 Paul Davis
3 Author: David Robillard
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 2 of the License, or (at your option)
10 This program is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 675 Mass Ave, Cambridge, MA 02139, USA.
20 #ifndef __ardour_variant_h__
21 #define __ardour_variant_h__
29 #include "ardour/libardour_visibility.h"
30 #include "evoral/types.hpp"
31 #include "pbd/compose.h"
35 /** A value with dynamic type (tagged union). */
36 class LIBARDOUR_API Variant
40 NOTHING, ///< Nothing (void)
41 BEATS, ///< Beats+ticks
43 DOUBLE, ///< C double (64-bit IEEE-754)
44 FLOAT, ///< C float (32-bit IEEE-754)
45 INT, ///< Signed 32-bit int
46 LONG, ///< Signed 64-bit int
47 PATH, ///< File path string
48 STRING, ///< Raw string (no semantics)
52 Variant() : _type(NOTHING) { _long = 0; }
54 explicit Variant(bool value) : _type(BOOL) { _bool = value; }
55 explicit Variant(double value) : _type(DOUBLE) { _double = value; }
56 explicit Variant(float value) : _type(FLOAT) { _float = value; }
57 explicit Variant(int32_t value) : _type(INT) { _int = value; }
58 explicit Variant(int64_t value) : _type(LONG) { _long = value; }
60 explicit Variant(const Evoral::Beats& beats)
65 /** Make a variant of a specific string type (string types only) */
66 Variant(Type type, const std::string& value)
71 /** Make a numeric variant from a double (numeric types only).
73 * If conversion is impossible, the variant will have type NOTHING.
75 Variant(Type type, double value)
83 _double = (double)value;
86 _float = (float)value;
89 _int = (int32_t)lrint(std::max((double)INT32_MIN,
90 std::min(value, (double)INT32_MAX)));
93 _long = (int64_t)lrint(std::max((double)INT64_MIN,
94 std::min(value, (double)INT64_MAX)));
97 _beats = Evoral::Beats(value);
105 /** Convert a numeric variant to a double. */
106 double to_double() const {
108 case BOOL: return _bool;
109 case DOUBLE: return _double;
110 case FLOAT: return _float;
111 case INT: return _int;
112 case LONG: return _long;
113 case BEATS: return _beats.to_double();
118 bool get_bool() const { ensure_type(BOOL); return _bool; }
119 double get_double() const { ensure_type(DOUBLE); return _double; }
120 float get_float() const { ensure_type(FLOAT); return _float; }
121 int get_int() const { ensure_type(INT); return _int; }
122 long get_long() const { ensure_type(LONG); return _long; }
124 bool operator==(bool v) const { return _type == BOOL && _bool == v; }
125 double operator==(double v) const { return _type == DOUBLE && _double == v; }
126 float operator==(float v) const { return _type == FLOAT && _float == v; }
127 int operator==(int v) const { return _type == INT && _int == v; }
128 long operator==(long v) const { return _type == LONG && _long == v; }
130 Variant& operator=(bool v) { _type = BOOL; _bool = v; return *this; }
131 Variant& operator=(double v) { _type = DOUBLE; _double = v; return *this; }
132 Variant& operator=(float v) { _type = FLOAT; _float = v; return *this; }
133 Variant& operator=(int v) { _type = INT; _int = v; return *this; }
134 Variant& operator=(long v) { _type = LONG; _long = v; return *this; }
136 const std::string& get_path() const { ensure_type(PATH); return _string; }
137 const std::string& get_string() const { ensure_type(STRING); return _string; }
138 const std::string& get_uri() const { ensure_type(URI); return _string; }
140 bool operator==(const Variant& v) const {
141 if (_type != v._type) {
146 case NOTHING: return true;
147 case BEATS: return _beats == v._beats;
148 case BOOL: return _bool == v._bool;
149 case DOUBLE: return _double == v._double;
150 case FLOAT: return _float == v._float;
151 case INT: return _int == v._int;
152 case LONG: return _long == v._long;
155 case URI: return _string == v._string;
161 bool operator==(const Evoral::Beats& v) const {
162 return _type == BEATS && _beats == v;
165 bool operator!() const { return _type == NOTHING; }
167 Variant& operator=(Evoral::Beats v) {
173 const Evoral::Beats& get_beats() const {
174 ensure_type(BEATS); return _beats;
177 Type type() const { return _type; }
179 static bool type_is_numeric(Type type) {
181 case BOOL: case DOUBLE: case FLOAT: case INT: case LONG: case BEATS:
189 static const char* type_name(const Type type) {
190 static const char* names[] = {
191 "bool", "double", "float", "int", "long", "path", "string", "uri"
197 void ensure_type(const Type type) const {
199 throw std::domain_error(
200 string_compose("get_%1 called on %2 variant",
201 type_name(type), type_name(_type)));
205 Type _type; ///< Type tag
206 std::string _string; ///< PATH, STRING, URI
207 Evoral::Beats _beats; ///< BEATS
209 // Union of all primitive numeric types
219 } // namespace ARDOUR
221 #endif // __ardour_variant_h__