cgv
Loading...
Searching...
No Matches
config_file.cxx
1#include "view.h"
2#include "gui_driver.h"
3
4#include <cgv/utils/scan.h>
5#include <cgv/utils/file.h>
6#include <cgv/utils/tokenizer.h>
7#include <cgv/base/register.h>
8#include <cgv/reflect/find_reflection_handler.h>
9#include <cgv/reflect/reflect_enum.h>
10#include <algorithm>
11
12using namespace cgv::base;
13using namespace cgv::reflect;
14using namespace cgv::utils;
15
17{
18 bool out_of_date;
19 unsigned pos, len;
21 bool operator < (const config_file_view& cfv) const { return pos < cfv.pos; }
22};
23
25{
26protected:
27 std::string file_name;
28 std::string content;
29 std::vector<config_file_view> views;
30 unsigned nr_out_of_date;
31public:
32 gui_config_file_observer(const std::string& fn, const std::string& c) : file_name(fn), content(c)
33 {
34 nr_out_of_date = 0;
35 }
36 void add_view(const config_file_view& cfv)
37 {
38 views.push_back(cfv);
39 std::sort(views.begin(), views.end());
40 }
41 void inc_out_of_date_count() {
42 ++nr_out_of_date;
43 update_config_file();
44 }
45 void update_view(cgv::gui::view_ptr v)
46 {
47 for (unsigned i=0; i<views.size(); ++i)
48 if (views[i].view == v) {
49 if (!views[i].out_of_date) {
50 views[i].out_of_date = true;
51 inc_out_of_date_count();
52 }
53 }
54 }
55 void update_config_file()
56 {
57 std::string new_content;
58 unsigned off = 0;
59 int delta_pos = 0;
60 for (unsigned i=0; i<views.size(); ++i) {
61 std::string new_value((const char*)views[i].view->get_user_data());
62 std::size_t new_len = new_value.length();
63 new_content += content.substr(off, views[i].pos - off);
64 new_content += new_value;
65 off = views[i].pos+views[i].len;
66 views[i].pos += delta_pos;
67 delta_pos += (int)new_len - (int)(views[i].len);
68 views[i].len = (unsigned)new_len;
69 views[i].out_of_date = false;
70 }
71 new_content += content.substr(off);
72 cgv::utils::file::write(file_name, new_content.c_str(), new_content.size(), true);
73 content = new_content;
74 }
75 void multi_observe(base_ptr bp, const std::string& property_assignments, size_t off);
76};
77
78template <typename T>
79class config_view : public cgv::gui::view<T>
80{
82public:
83 config_view(const std::string& _name, const T& _value, gui_config_file_observer* _obs) : cgv::gui::view<T>(_name, _value), observer(_obs) {}
84 void update()
85 {
86 observer->update_view(cgv::gui::view_ptr(this));
87 }
88 void* get_user_data() const
89 {
90 static std::string last_value;
92 return const_cast<char*>(last_value.c_str());
93 }
94};
95
96template<> class config_view<std::string> : public cgv::gui::view<std::string>
97{
99public:
100 config_view(const std::string& _name, const std::string& _value, gui_config_file_observer* _obs) : view<std::string>(_name, _value), observer(_obs) {}
101 void update()
102 {
103 observer->update_view(cgv::gui::view_ptr(this));
104 }
105 void* get_user_data() const
106 {
107 static std::string last_value;
109 for (unsigned i=0; i<last_value.size(); ++i)
110 if (last_value[i] == '"' || last_value[i] == '\\') {
111 last_value.insert(i,1,'\\');
112 ++i;
113 }
114 last_value = std::string("\"")+last_value+"\"";
115 return const_cast<char*>(last_value.c_str());
116 }
117};
118
119template<> class config_view<bool> : public cgv::gui::view<bool>
120{
121 gui_config_file_observer* observer;
122public:
123 config_view(const std::string& _name, const bool& _value, gui_config_file_observer* _obs) : view<bool>(_name, _value), observer(_obs) {}
124 void update()
125 {
126 observer->update_view(cgv::gui::view_ptr(this));
127 }
128 void* get_user_data() const
129 {
130 static std::string last_value;
131 last_value = get_value() ? "true" : "false";
132 return const_cast<char*>(last_value.c_str());
133 }
134};
135
136class enum_config_view : public cgv::gui::view<cgv::type::int32_type>
137{
138 abst_enum_reflection_traits* enum_traits;
139 gui_config_file_observer* observer;
140public:
141 enum_config_view(const std::string& _name, void *member_ptr, cgv::reflect::abst_enum_reflection_traits* aert, gui_config_file_observer* _obs) : view<cgv::type::int32_type>(_name, *((cgv::type::int32_type*)member_ptr)), enum_traits(aert), observer(_obs) {}
142 void update()
143 {
144 observer->update_view(cgv::gui::view_ptr(this));
145 }
146 void* get_user_data() const
147 {
148 static std::string last_value;
149 last_value = enum_traits->get_enum_name(get_value());
150 return const_cast<char*>(last_value.c_str());
151 }
152};
153
155{
156 // split into single assignments
157 std::vector<token> toks;
158 bite_all(tokenizer(property_assignments).set_skip("'\"","'\"","\\\\").set_ws(";"),toks);
159 // for each assignment
160 for (size_t i=0; i<toks.size(); ++i) {
161 std::vector<token> sides;
162 bite_all(tokenizer(toks[i]).set_skip("'\"","'\"","\\\\").set_ws("="),sides);
163 if (sides.size() != 2) {
164 std::cerr << "property assignment >" << to_string(toks[i]).c_str() << "< does not match pattern lhs=rhs" << std::endl;
165 continue;
166 }
167 std::string lhs(to_string(sides[0]));
169 bp->self_reflect(rsrh);
171 void* member_ptr = 0;
172 if (rsrh.found_target()) {
173 member_ptr = rsrh.get_member_ptr();
174 cfv.len = (unsigned) sides[1].get_length();
175 cfv.pos = (unsigned) (off+sides[1].begin-&property_assignments[0]);
176 cfv.out_of_date = false;
177 switch (rsrh.get_reflection_traits()->get_type_id()) {
178 case cgv::type::info::TI_BOOL: cfv.view = new config_view<bool>(lhs,*((bool*)member_ptr),this); break;
179 case cgv::type::info::TI_INT8 : cfv.view = new config_view<cgv::type::int8_type>(lhs,*((cgv::type::int8_type*)member_ptr),this); break;
189 case cgv::type::info::TI_STRING : cfv.view = new config_view<std::string>(lhs,*((std::string*)member_ptr),this); break;
190 default:
191 {
193 if (aert) {
194 cfv.view = new enum_config_view(lhs, member_ptr, dynamic_cast<cgv::reflect::abst_enum_reflection_traits*>(aert->clone()), this);
195 }
196 else {
197 std::cerr << "could not create config view for permanent attribute " << lhs << std::endl;
198 exit(0);
199 }
200 break;
201 }
202 }
203 cfv.view->attach_to_reference(member_ptr);
204 this->add_view(cfv);
205 }
206 else
207 std::cout << "did not find reference to member " << lhs << std::endl;
208
209 std::string rhs(to_string(sides[1]));
210 if (rhs == "?") {
211 if (member_ptr) {
212 cfv.out_of_date = true;
213 this->inc_out_of_date_count();
214 }
215 }
216 else if (rhs[0] == '"' || rhs[0] == '\'') {
217 size_t n = rhs.size()-1;
218 char open = rhs[0];
219 if (rhs[n] == rhs[0])
220 --n;
221 rhs = rhs.substr(1, n);
222 for (size_t i=1; i<rhs.size(); ++i) {
223 if (rhs[i-1] == '\\' && (rhs[i] == '\\' || rhs[i] == open))
224 rhs.erase(i-1,1);
225 }
226 bp->set_void(lhs,"string",&rhs);
227 }
228 else if (rhs == "true" || rhs == "false") {
229 bool value = rhs == "true";
230 bp->set_void(lhs, "bool", &value);
231 }
232 else if (is_digit(rhs[0]) || rhs[0] == '.' || rhs[0] == '+' || rhs[0] == '-') {
233 int int_value;
234 if (is_integer(rhs,int_value)) {
235 bp->set_void(lhs, "int32", &int_value);
236 }
237 else {
238 double value = atof(rhs.c_str());
239 bp->set_void(lhs, "flt64", &value);
240 }
241 }
242 else
243 bp->set_void(lhs,"string",&rhs);
244 }
245}
246
247
249{
250protected:
251 static std::map<std::string,config_file_observer*>& ref_config_file_observer_map()
252 {
253 static std::map<std::string,config_file_observer*> cfom;
254 return cfom;
255 }
256public:
257 config_file_observer* find_config_file_observer(const std::string& file_name, const std::string& content)
258 {
260 if (ref_config_file_observer_map().find(file_name) == ref_config_file_observer_map().end()) {
261 cfo = new gui_config_file_observer(file_name, content);
262 ref_config_file_observer_map()[file_name] = cfo;
263 }
264 else
265 cfo = ref_config_file_observer_map()[file_name];
266 return cfo;
267 }
269 bool process_gui_file(const std::string& file_name)
270 {
272 if (d)
273 return d->process_gui_file(file_name);
274 return false;
275 }
276};
277
279{
280 cfg_reg_type(const char* dummy)
281 {
283 }
284};
285
286#include "lib_begin.h"
287
288extern CGV_API cfg_reg_type cfg_reg;
289
290cfg_reg_type cfg_reg("");
virtual bool set_void(const std::string &property, const std::string &value_type, const void *value_ptr)
abstract interface for the setter of a dynamic property.
Definition base.cxx:181
virtual bool self_reflect(cgv::reflect::reflection_handler &)
used for simple self reflection
Definition base.cxx:161
complete implementation of method actions that only call one method when entering a node
Definition action.h:113
reference counted pointer, which can work together with types that are derived from ref_counted,...
Definition ref_ptr.h:160
class for gui elements that view values of the type specified in the template argument
Definition view.h:45
const T & get_value() const
return the current value
Definition view.h:54
The cgv::reflect::find_reflection_hander steers traversal to a specific member and calls the virtual ...
the tokenizer allows to split text into tokens in a convenient way.
Definition tokenizer.h:68
void update()
this virtual update allows for example to ask a view to update the viewed value. The default implemen...
void * get_user_data() const
this virtual method allows to pass application specific data for internal purposes
void update()
this virtual update allows for example to ask a view to update the viewed value. The default implemen...
void * get_user_data() const
this virtual method allows to pass application specific data for internal purposes
void update()
this virtual update allows for example to ask a view to update the viewed value. The default implemen...
void * get_user_data() const
this virtual method allows to pass application specific data for internal purposes
void * get_user_data() const
this virtual method allows to pass application specific data for internal purposes
void update()
this virtual update allows for example to ask a view to update the viewed value. The default implemen...
bool process_gui_file(const std::string &file_name)
process a gui file
config_file_observer * find_config_file_observer(const std::string &file_name, const std::string &content)
create or find a config_file_observer from the given file name and the read content of the config fil...
void multi_observe(base_ptr bp, const std::string &property_assignments, size_t off)
to be implemented method that adds permanent registration for a list of property assignments
the base namespace holds the base hierarchy, support for plugin registration and signals
Definition action.cxx:4
void register_config_file_driver(config_file_driver *cfd)
method to register a config_file_driver
Definition register.cxx:687
gui_driver_ptr get_gui_driver()
return the currently registered gui driver or an empty pointer if non has been registered
in this namespace reflection of types is implemented
@ TI_INT16
signed integer stored in 8 bits
Definition type_id.h:20
@ TI_INT8
boolean
Definition type_id.h:19
@ TI_INT32
signed integer stored in 16 bits
Definition type_id.h:21
@ TI_STRING
wide character type
Definition type_id.h:31
@ TI_FLT32
floating point type stored in 16 bits
Definition type_id.h:28
@ TI_UINT32
unsigned integer stored in 16 bits
Definition type_id.h:25
@ TI_UINT8
signed integer stored in 64 bits
Definition type_id.h:23
@ TI_INT64
signed integer stored in 32 bits
Definition type_id.h:22
@ TI_BOOL
void
Definition type_id.h:18
@ TI_UINT16
unsigned integer stored in 8 bits
Definition type_id.h:24
@ TI_FLT64
floating point type stored in 32 bits
Definition type_id.h:29
@ TI_UINT64
unsigned integer stored in 32 bits
Definition type_id.h:26
namespace that holds tools that dont fit any other namespace
bool is_digit(char c)
check if char is a digit
Definition scan.cxx:20
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
bool is_integer(const char *begin, const char *end, int &value)
check if the text range (begin,end( defines an integer value. If yes, store the value in the passed r...
Definition scan.cxx:367
void bite_all(tokenizer &t, std::vector< token > &result)
bite all tokens into a token vector
Definition tokenizer.h:121
Helper functions to process strings.
abstract interface for a config file driver that handles permanent registration and gui config files.
Definition register.h:555
abstract interface for observers of config files.
Definition register.h:547
type independent functionality for all enum fallback implementations
std::string get_enum_name(unsigned i) const
return the name of the i-th enum item