aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/ResTraits.hh
diff options
context:
space:
mode:
authorPavel Labath <pavelo@centrum.sk>2011-06-11 11:00:45 (GMT)
committerPavel Labath <pavelo@centrum.sk>2011-11-01 09:52:46 (GMT)
commit8c208459910f1dddcfdeb00567b990eebfc218b8 (patch)
tree47c442f906124306a52e13641d28fc6cd1ac513e /src/FbTk/ResTraits.hh
parent60cd98604ae0ee62d64e3bc852898f69dae221d4 (diff)
downloadfluxbox_paul-8c208459910f1dddcfdeb00567b990eebfc218b8.zip
fluxbox_paul-8c208459910f1dddcfdeb00567b990eebfc218b8.tar.bz2
Simplify FbTk::Resource template class
by outsourcing the conversion from string/lua to the specific type (and back) to a separate class. This change touches a lot of files because the interface of FbTk::Resource changed slightly. However, the changes are minor.
Diffstat (limited to 'src/FbTk/ResTraits.hh')
-rw-r--r--src/FbTk/ResTraits.hh208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/FbTk/ResTraits.hh b/src/FbTk/ResTraits.hh
new file mode 100644
index 0000000..32be48d
--- /dev/null
+++ b/src/FbTk/ResTraits.hh
@@ -0,0 +1,208 @@
1// ResTraits.hh
2// Copyright (c) 2011 Pavel Labath (pavelo at centrum dot sk)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22#ifndef FBTK_RESTRAITS_HH
23#define FBTK_RESTRAITS_HH
24
25#include <stdexcept>
26#include <vector>
27
28#include "Luamm.hh"
29#include "StringUtil.hh"
30
31namespace FbTk {
32
33struct ConversionError: public std::runtime_error {
34 ConversionError(const std::string &msg) : std::runtime_error(msg) {}
35};
36
37/* Classes that "know" how to convert from string and lua representations
38 * into corresponding C++ types
39 */
40
41template<typename T>
42struct IntTraits {
43 typedef T Type;
44 static std::string toString(T x) { return StringUtil::number2String(x); }
45 static void toLua(T x, lua::state &l) { l.pushnumber(x); }
46
47 static T fromString(const std::string &x) {
48 T t;
49 if(StringUtil::extractNumber(x, t))
50 return t;
51 throw ConversionError("Cannot convert to integer from '" + x + "'");
52 }
53
54 static T fromLua(lua::state &l) {
55 lua::stack_sentry s(l, -1);
56
57 if(l.isnumber(-1))
58 return l.tonumber(-1);
59 else if(l.isstring(-1))
60 return fromString(l.tostring(-1));
61 throw ConversionError( std::string("Cannot convert to integer from lua type ")
62 + l.type_name(l.type(-1)) );
63 }
64};
65
66struct StringTraits {
67 typedef std::string Type;
68 static std::string toString(const std::string &x) { return x; }
69 static void toLua(const std::string &x, lua::state &l) { l.pushstring(x); }
70 static std::string fromString(const std::string &x) { return x; }
71
72 static std::string fromLua(lua::state &l) {
73 lua::stack_sentry s(l, -1);
74
75 if(l.isstring(-1) || l.isnumber(-1))
76 return fromString(l.tostring(-1));
77 throw ConversionError( std::string("Cannot convert to string from lua type ")
78 + l.type_name(l.type(-1)) );
79 }
80};
81
82struct BoolTraits {
83 typedef bool Type;
84 static std::string toString(bool x) { return x ? "true" : "false"; }
85 static void toLua(bool x, lua::state &l) { l.pushboolean(x); }
86 static bool fromString(const std::string &x) {
87 return strcasecmp(x.c_str(), "true") == 0;
88 }
89
90 static bool fromLua(lua::state &l) {
91 lua::stack_sentry s(l, -1);
92
93 if(l.isstring(-1))
94 return fromString(l.tostring(-1));
95 else if(l.isnumber(-1))
96 return l.tointeger(-1) != 0;
97 else
98 return l.toboolean(-1);
99 }
100};
101
102/**
103 * To use this class, one must first define a mapping between enum values and their names using
104 * the s_map array. A NULL value for name signals the end of the array. E.g.,
105 *
106 * template<>
107 * EnumTraits<Foo>::Pair EnumTraits<Foo>::s_map[] = { {"Bar", Bar}, {"Baz", Baz} {NULL, Baz} };
108 */
109template<typename T>
110struct EnumTraits {
111 typedef T Type;
112 struct Pair {
113 const char *name;
114 T value;
115 };
116 static const Pair s_map[];
117
118 static std::string toString(T x) {
119 for(const Pair *p = s_map; p->name; ++p) {
120 if(p->value == x)
121 return p->name;
122 }
123 throw ConversionError("Unknown value for enum");
124 }
125
126 static void toLua(T x, lua::state &l) { l.pushstring(toString(x)); }
127
128 static T fromString(const std::string &x) {
129 for(const Pair *p = s_map; p->name; ++p) {
130 if(strcasecmp(p->name, x.c_str()) == 0)
131 return p->value;
132 }
133 throw ConversionError("Cannot convert to enum from '" + x + "'");
134 }
135
136 static T fromLua(lua::state &l) {
137 lua::stack_sentry s(l, -1);
138
139 if(l.isstring(-1) || l.isnumber(-1))
140 return fromString(l.tostring(-1));
141 throw ConversionError( std::string("Cannot convert to enum from lua type ")
142 + l.type_name(l.type(-1)) );
143 }
144};
145
146template<typename Traits>
147struct VectorTraits {
148 typedef std::vector<typename Traits::Type> Type;
149 static std::string toString(const Type &x) {
150 std::string retval;
151 for(size_t i = 0; i < x.size(); ++i) {
152 retval.append(Traits::toString(x[i]));
153 retval.append(" ");
154 }
155
156 return retval;
157 }
158
159 static void toLua(const Type &x, lua::state &l) {
160 l.checkstack(2);
161 l.createtable(x.size());
162 lua::stack_sentry s(l);
163
164 for(size_t i = 0; i < x.size(); ++i) {
165 Traits::toLua(x[i], l);
166 l.rawseti(-2, i);
167 }
168 }
169
170 static Type fromString(const std::string &x) {
171 std::vector<std::string> val;
172 StringUtil::stringtok(val, x);
173 Type retval;
174
175 for(size_t i = 0; i < val.size(); i++) {
176 try {
177 retval.push_back(Traits::fromString(val[i]));
178 }
179 catch(std::runtime_error &) {
180 }
181 }
182
183 return retval;
184 }
185
186 static Type fromLua(lua::state &l) {
187 l.checkstack(1);
188 lua::stack_sentry s(l, -1);
189 Type retval;
190
191 if(l.type(-1) == lua::TTABLE) {
192 for(size_t i = 0; l.rawgeti(-1, i), !l.isnil(-1); ++i) {
193 try {
194 retval.push_back(Traits::fromLua(l));
195 }
196 catch(std::runtime_error &) {
197 }
198 }
199 return retval;
200 }
201 throw ConversionError( std::string("Cannot convert to vector from lua type ")
202 + l.type_name(l.type(-1)) );
203 }
204};
205
206} // end namespace FbTk
207
208#endif // FBTK_RESTRAITS_HH