1 /*
2  * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert
3  * Copyright (C) 2011 Pete Shorthose
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  * --------------------------------------------------------------------------
19  */
20 
21 /* ------- This is the System namespace ------- */
22 
23 #pragma once
24 
25 #ifndef SRC_HEADERS_GX_SYSTEM_H_
26 #define SRC_HEADERS_GX_SYSTEM_H_
27 
28 #ifndef NDEBUG
29 #include <fenv.h>
30 
31 #ifdef __i386__
32 #define FE_DENORM __FE_DENORM
clear_fpu_status_bits()33 inline void clear_fpu_status_bits() { __asm__ ("fnclex"); }
get_fpu_status_bits()34 inline unsigned int get_fpu_status_bits() {
35     unsigned int fpu_status __attribute__ ((__mode__ (__HI__)));
36     __asm__("fnstsw %0" : "=m" (*&fpu_status));
37 	return fpu_status;
38 }
39 #else
clear_fpu_status_bits()40 inline void clear_fpu_status_bits() { feclearexcept(FE_ALL_EXCEPT); }
get_fpu_status_bits()41 inline unsigned int get_fpu_status_bits() {
42     fexcept_t flagp;
43     int ret = fegetexceptflag(&flagp, FE_ALL_EXCEPT);
44     assert(ret == 0);
45     return flagp;
46 }
47 #endif //__i386__
48 #endif // !NDEBUG
49 #ifdef __SSE__
50 
51 /* On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
52    flags to avoid costly denormals */
53 #ifdef __SSE3__
54 #ifndef _PMMINTRIN_H_INCLUDED
55 #include <pmmintrin.h>
56 #endif //ndef
AVOIDDENORMALS()57 inline void AVOIDDENORMALS() {
58     _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
59     _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
60 }
61 #else
62 #ifndef _XMMINTRIN_H_INCLUDED
63 #include <xmmintrin.h>
64 #endif //ndef
AVOIDDENORMALS()65 inline void AVOIDDENORMALS() { _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); }
66 #endif //__SSE3__
67 
68 #else
69 #ifndef _XMMINTRIN_H_INCLUDED
_MM_SET_EXCEPTION_STATE(unsigned int __mask)70 inline void _MM_SET_EXCEPTION_STATE(unsigned int __mask) {}
_MM_GET_EXCEPTION_STATE(void)71 inline unsigned int _MM_GET_EXCEPTION_STATE(void) { return 0; }
72 #endif //ndef
AVOIDDENORMALS()73 inline void AVOIDDENORMALS() {}
74 
75 #endif //__SSE__
76 
77 
78 /* constant defines */
79 #define ASCII_START (48)
80 #define GDK_NO_MOD_MASK (GdkModifierType)0
81 #define SYSTEM_OK   (0)
82 
83 
84 namespace gx_system {
85 
86 /****************************************************************
87  ** "atomic" value access
88  */
89 
atomic_set(volatile int * p,int v)90 inline void atomic_set(volatile int* p, int v) {
91     g_atomic_int_set(p, v);
92 }
93 
atomic_set(volatile unsigned int * p,unsigned int v)94 inline void atomic_set(volatile unsigned int* p, unsigned int v) {
95     g_atomic_int_set(reinterpret_cast<volatile int*>(p), v);
96 }
97 
atomic_get(volatile int & p)98 inline int atomic_get(volatile int& p) {
99     return g_atomic_int_get(&p);
100 }
101 
atomic_get(volatile unsigned int & p)102 inline unsigned int atomic_get(volatile unsigned int& p) {
103     return g_atomic_int_get(reinterpret_cast<volatile int*>(&p));
104 }
105 
atomic_inc(volatile int * p)106 inline void atomic_inc(volatile int* p) {
107     g_atomic_int_inc(p);
108 }
109 
atomic_inc(volatile unsigned int * p)110 inline void atomic_inc(volatile unsigned int* p) {
111     g_atomic_int_inc(reinterpret_cast<volatile int*>(p));
112 }
113 
atomic_compare_and_exchange(volatile int * p,int oldv,int newv)114 inline bool atomic_compare_and_exchange(volatile int *p, int oldv, int newv) {
115     return g_atomic_int_compare_and_exchange(p, oldv, newv);
116 }
117 
118 template <class T>
atomic_set(T ** p,T * v)119 inline void atomic_set(T **p, T *v) {
120     g_atomic_pointer_set(p, v);
121 }
122 
123 template <class T>
atomic_set_0(T ** p)124 inline void atomic_set_0(T **p) {
125     g_atomic_pointer_set(p, 0);
126 }
127 
128 template <class T>
atomic_get(T * & p)129 inline T *atomic_get(T*& p) {
130     return static_cast<T*>(g_atomic_pointer_get(&p));
131 }
132 
133 template <class T>
atomic_compare_and_exchange(T ** p,T * oldv,T * newv)134 inline bool atomic_compare_and_exchange(T **p, T *oldv, T *newv) {
135     return g_atomic_pointer_compare_and_exchange(reinterpret_cast<void**>(p), static_cast<void*>(oldv), newv);
136 }
137 
138 
139 /****************************************************************
140  ** Measuring times
141  */
142 
143 #ifndef NDEBUG
144 
145 class Accum {
146  private:
147     int n;
148     int mn;
149     int mx;
150     float sx;
151     float sx2;
152  public:
Accum()153     Accum() { reset(); }
reset()154     inline void reset() {
155         n = 0;
156         mn = 1e9;
157         mx = 0;
158         sx = 0;
159         sx2 = 0;
160     }
161     void add(int diff);
count()162     int count() const { return n; }
mean()163     float mean() const { return sx / n; }
stddev()164     float stddev() const { return std::sqrt((n * sx2 - sx * sx) / (n * (n-1))); }
minimum()165     float minimum() const { return mn; }
maximum()166     float maximum() const { return mx; }
167 };
168 
add(int diff)169 inline void Accum::add(int diff) {
170     n += 1;
171     sx += diff;
172     sx2 += static_cast<float>(diff) * diff;
173     mn = std::min(mn, diff);
174     mx = std::max(mx, diff);
175 }
176 
177 
178 struct Measure {
179     Accum period;
180     Accum duration;
181     Accum duration1;
182     Accum duration2;
183     unsigned int FPUStatus1;
184     unsigned int MXStatus1;
185     unsigned int FPUStatus2;
186     unsigned int MXStatus2;
ns2msMeasure187     inline float ns2ms(int n) const { return n * 1e-6; }
188     void reset();
MeasureMeasure189     Measure() { reset(); }
190     void print_accum(const Accum& accum, const char* prefix, bool verbose, int total = 0) const;
191     void print(bool verbose) const;
192 };
193 
194 class MeasureThreadsafe {
195  private:
196     Measure m[2];
197     Measure *pmeasure;
198     timespec t1s;
199     timespec t1e;
200     timespec t2s;
201     timespec t1old;
202     unsigned int FPUStatus;
203     unsigned int MXStatus;
access()204     inline Measure *access() { return atomic_get(pmeasure); }
205     inline int ts_diff(const timespec& ts1, const timespec& ts2);
206  public:
207     MeasureThreadsafe();
start()208     inline void start() {
209 	clear_fpu_status_bits();
210 	_MM_SET_EXCEPTION_STATE(0);
211 	clock_gettime(CLOCK_MONOTONIC, &t1s);
212     }
pause()213     inline void pause() {
214 	clock_gettime(CLOCK_MONOTONIC, &t1e);
215 	FPUStatus = get_fpu_status_bits();
216 	MXStatus = _MM_GET_EXCEPTION_STATE();
217     }
cont()218     inline void cont() {
219 	clear_fpu_status_bits();
220 	_MM_SET_EXCEPTION_STATE(0);
221 	clock_gettime(CLOCK_MONOTONIC, &t2s);
222     }
223     inline void stop();
224     void print(bool verbose = false);
225 };
226 
227 /* return time difference in ns, fail if > sec (doesn't fit int 32 bit int) */
ts_diff(const timespec & ts1,const timespec & ts2)228 inline int MeasureThreadsafe::ts_diff(const timespec& ts1, const timespec& ts2) {
229     time_t df = ts1.tv_sec - ts2.tv_sec;
230     if (std::abs(df) > 2) {
231         return -1; // failed
232     }
233     return df * 1000000000 + (ts1.tv_nsec - ts2.tv_nsec);
234 }
235 
236 
stop()237 inline void MeasureThreadsafe::stop() {
238     Measure& m = *access();
239     timespec n;
240     clock_gettime(CLOCK_MONOTONIC, &n);
241     m.FPUStatus2 |= get_fpu_status_bits();
242     m.MXStatus2 |= _MM_GET_EXCEPTION_STATE();
243     m.FPUStatus1 |= FPUStatus;
244     m.MXStatus1 |= MXStatus;
245     if (!(t1old.tv_sec == 0 && t1old.tv_nsec == 0)) {
246         m.period.add(ts_diff(t1s, t1old));
247     }
248     t1old = t1s;
249     m.duration1.add(ts_diff(t1e, t1s));
250     m.duration2.add(ts_diff(n, t2s));
251     m.duration.add(ts_diff(n, t1s));
252 }
253 
254 extern MeasureThreadsafe measure;
255 
256 void add_time_measurement();
257 
measure_start()258 inline void measure_start() { measure.start(); }
measure_pause()259 inline void measure_pause() { measure.pause(); }
measure_cont()260 inline void measure_cont() { measure.cont(); }
measure_stop()261 inline void measure_stop()  { measure.stop(); }
262 
263 #else
264 
measure_start()265 inline void measure_start() {}
measure_pause()266 inline void measure_pause() {}
measure_cont()267 inline void measure_cont() {}
measure_stop()268 inline void measure_stop()  {}
269 
270 #endif
271 
272 /****************************************************************/
273 
274 class SkinHandling {
275 public:
276     Glib::ustring name;
277     std::vector<Glib::ustring> skin_list;
SkinHandling(const std::string & styledir)278     SkinHandling(const std::string& styledir)
279 	: name(), skin_list() { set_styledir(styledir); }
280     void set_styledir(const std::string& styledir);
281     bool is_in_list(const std::string& skin_name);
282     const Glib::ustring& operator[](unsigned int idx);
283     unsigned int index(const Glib::ustring& skin_name);
284     string get_cssfile() const;
285     void set_default_skin_name();
286 };
287 
288 /****************************************************************/
289 
290 class PathList {
291 public:
292     typedef std::list< Glib::RefPtr<Gio::File> > pathlist;
293     typedef std::list< Glib::RefPtr<Gio::File> >::const_iterator iterator;
294 private:
295     pathlist dirs;
296 public:
297     PathList(const char *env_name = 0);
add(const std::string & d)298     void add(const std::string& d) { dirs.push_back(Gio::File::create_for_path(d)); }
299     bool contains(const std::string& d) const;
300     bool find_dir(std::string *d, const std::string& filename) const;
size()301     size_t size() { return dirs.size(); }
begin()302     iterator begin() { return dirs.begin(); }
end()303     iterator end() { return dirs.end(); }
304 };
305 
306 
307 /****************************************************************/
308 
309 class PrefixConverter {
310 public:
311     typedef std::map<char,std::string> symbol_path_map;
312 private:
313     symbol_path_map dirs;
314 public:
PrefixConverter()315     PrefixConverter(): dirs() {}
~PrefixConverter()316     ~PrefixConverter() {}
317     std::string replace_symbol(const std::string& dir) const;
318     std::string replace_path(const std::string& dir) const;
319     void add(char s, const std::string& d);
320 };
321 
322 
323 /*****************************************************************
324  ** class DirectoryListing
325  */
326 
327 class FileName {
328 public:
329     std::string filename;
330     Glib::ustring displayname;
FileName(const std::string & filename_,const Glib::ustring & displayname_)331     FileName(const std::string& filename_, const Glib::ustring& displayname_)
332 	: filename(filename_), displayname(displayname_) {}
333 };
334 
335 class IRFileListing {
336 public:
337 private:
338     std::vector<FileName> listing;
339 public:
340     IRFileListing(const std::string& path);
~IRFileListing()341     ~IRFileListing() {}
get_listing()342     std::vector<FileName>& get_listing() { return listing; }
343 };
344 
345 void list_subdirs(PathList pl, std::vector<FileName>& dirs);
346 
347 /****************************************************************
348  ** class CmdlineOptions
349  */
350 
351 #define RPCPORT_DEFAULT (-2)
352 #define RPCPORT_NONE (-1)
353 
354 class BasicOptions: boost::noncopyable {
355 private:
356     std::string user_dir;
357     std::string user_IR_dir;
358     std::string sys_IR_dir;
359     PathList IR_pathlist;
360     PrefixConverter IR_prefixmap;
361     static BasicOptions *instance;
362 protected:
363     std::string builder_dir;
364 
365 private:
366     friend BasicOptions& get_options();
367 protected:
368     static void make_ending_slash(std::string& dirpath);
369 public:
370     BasicOptions();
371     ~BasicOptions();
get_user_filepath(const std::string & basename)372     std::string get_user_filepath(const std::string& basename) const { return user_dir + basename; }
get_user_ir_filepath(const std::string & basename)373     std::string get_user_ir_filepath(const std::string& basename) const { return user_IR_dir + basename; }
get_builder_filepath(const std::string & basename)374     std::string get_builder_filepath(const std::string& basename) const { return builder_dir + basename; }
set_user_dir(std::string dir)375     void set_user_dir(std::string dir) { user_dir = dir; }
set_user_IR_dir(std::string dir)376     void set_user_IR_dir(std::string dir) { user_IR_dir = dir; }
get_user_dir()377     const std::string& get_user_dir() const { return user_dir; }
get_user_IR_dir()378     const std::string& get_user_IR_dir() const { return user_IR_dir; }
get_sys_IR_dir()379     const std::string& get_sys_IR_dir() const { return sys_IR_dir; }
get_IR_pathlist()380     const PathList& get_IR_pathlist() const { return IR_pathlist; }
get_IR_prefixmap()381     const PrefixConverter& get_IR_prefixmap() const { return IR_prefixmap; }
382 };
383 
384 class CmdlineOptions: public BasicOptions, public Glib::OptionContext {
385 private:
386     Glib::OptionGroup main_group;
387     Glib::OptionGroup optgroup_style;
388     Glib::OptionGroup optgroup_jack;
389     Glib::OptionGroup optgroup_overload;
390     Glib::OptionGroup optgroup_file;
391     Glib::OptionGroup optgroup_debug;
392     std::string path_to_program;
393     bool version;
394     bool clear;
395     Glib::ustring jack_input;
396     Glib::ustring jack_midi;
397     Glib::ustring jack_instance;
398     std::vector<Glib::ustring> jack_outputs;
399     Glib::ustring jack_uuid;
400     Glib::ustring jack_uuid2;
401     bool jack_noconnect;
402     bool jack_single;
403     Glib::ustring jack_servername;
404     std::string load_file;
405     std::string style_dir;
406     std::string factory_dir;
407     std::string pixmap_dir;
408     std::string old_user_dir;
409     std::string preset_dir;
410     std::string pluginpreset_dir;
411     std::string lv2_preset_dir;
412     std::string temp_dir;
413     std::string plugin_dir;
414     std::string loop_dir;
415     Glib::ustring rcset;
416     bool nogui;
417     int rpcport;
418     Glib::ustring rpcaddress;
419     bool onlygui;
420     bool liveplaygui;
421     bool hideonquit;
422     bool mute;
423     Glib::ustring setbank;
424     Glib::ustring cmdline_bank;
425     Glib::ustring cmdline_preset;
426     Glib::ustring tuner_tet;
427     Glib::ustring tuner_ref;
428     int sporadic_overload;
429     int idle_thread_timeout;
430     bool convolver_watchdog;
431     bool watchdog_warning;
432     bool xrun_watchdog;
433     bool lterminal;
434     bool a_save;
435     bool auto_save;
436     std::string get_opskin();
437 
438 public:
439 #ifndef NDEBUG
440     bool dump_parameter;
441 #endif
442     SkinHandling skin;
443 
444     void read_ui_vars();
445     void write_ui_vars();
446     // saved in ui_rc:
447     int mainwin_visible;
448     int mainwin_x;
449     int mainwin_y;
450     int mainwin_height;
451     int window_height;
452     int preset_window_height;
453     int mul_buffer;
454     bool no_warn_latency;
455     bool system_order_rack_h;
456     bool system_show_value;
457     bool system_show_tooltips;
458     bool system_animations;
459     bool system_show_presets;
460     bool system_show_toolbar;
461     bool system_show_rack;
462     bool system_midiout;
463     bool system_tuner_midiout;
464     bool reload_lv2_presets;
465 
466 public:
467     CmdlineOptions();
468     ~CmdlineOptions();
469     void process(int argc, char** argv);
get_path_to_program()470     const std::string& get_path_to_program() const { return path_to_program; }
get_style_filepath(const std::string & basename)471     std::string get_style_filepath(const std::string& basename) const { return style_dir + basename; }
get_current_style_cssfile()472     std::string get_current_style_cssfile() const { return get_style_filepath(skin.get_cssfile()); }
get_pixmap_filepath(const std::string & basename)473     std::string get_pixmap_filepath(const std::string& basename) const { return pixmap_dir + basename; }
get_preset_filepath(const std::string & basename)474     std::string get_preset_filepath(const std::string& basename) const { return preset_dir + basename; }
get_plugin_filepath(const std::string & basename)475     std::string get_plugin_filepath(const std::string& basename) const { return plugin_dir + basename; }
get_factory_filepath(const std::string & basename)476     std::string get_factory_filepath(const std::string& basename) const { return factory_dir + basename; }
get_temp_filepath(const std::string & basename)477     std::string get_temp_filepath(const std::string& basename) const { return temp_dir + basename; }
get_pluginpreset_filepath(const std::string & id,bool factory)478     std::string get_pluginpreset_filepath(const std::string& id, bool factory) const {
479 	return (factory ? factory_dir : pluginpreset_dir) + id; }
get_lv2_preset_filepath(const std::string & id)480     std::string get_lv2_preset_filepath(const std::string& id) const {
481 	return (lv2_preset_dir) + id; }
get_old_user_dir()482     const std::string& get_old_user_dir() const { return old_user_dir; }
get_plugin_dir()483     const std::string& get_plugin_dir() const { return plugin_dir; }
get_preset_dir()484     const std::string& get_preset_dir() const { return preset_dir; }
get_pluginpreset_dir()485     const std::string& get_pluginpreset_dir() const { return pluginpreset_dir; }
get_lv2_preset_dir()486     const std::string& get_lv2_preset_dir() const { return lv2_preset_dir; }
get_loop_dir()487     const std::string& get_loop_dir() const { return loop_dir; }
get_temp_dir()488     const std::string& get_temp_dir() const { return temp_dir; }
489 
set_plugin_dir(std::string dir)490     void set_plugin_dir(std::string dir) { plugin_dir = dir; }
set_preset_dir(std::string dir)491     void set_preset_dir(std::string dir) { preset_dir = dir; }
set_pluginpreset_dir(std::string dir)492     void set_pluginpreset_dir(std::string dir) { pluginpreset_dir = dir; }
set_lv2_preset_dir(std::string dir)493     void set_lv2_preset_dir(std::string dir) { lv2_preset_dir = dir; }
set_loop_dir(std::string dir)494     void set_loop_dir(std::string dir) { loop_dir = dir; }
set_temp_dir(std::string dir)495     void set_temp_dir(std::string dir) { temp_dir = dir; }
496 
get_factory_dir()497     const std::string& get_factory_dir() const { return factory_dir; }
get_style_dir()498     const std::string& get_style_dir() const { return style_dir; }
get_ladspa_config_filename()499     std::string get_ladspa_config_filename() const { return get_user_filepath("ladspa_defs.js"); }
get_online_config_filename()500     std::string get_online_config_filename() const { return get_user_filepath("musical-artifacts.js"); }
get_online_presets_filename()501     std::string get_online_presets_filename() const { return get_user_filepath("artifacts.js"); }
get_rcset()502     const Glib::ustring& get_rcset() const { return rcset; }
get_clear_rc()503     bool get_clear_rc() const { return clear; }
get_nogui()504     bool get_nogui() const { return nogui; }
get_liveplaygui()505     bool get_liveplaygui() const { return liveplaygui; }
get_hideonquit()506     bool get_hideonquit() const { return hideonquit; }
set_hideonquit(bool set)507     void set_hideonquit(bool set) { hideonquit = set; }
get_mute()508     bool get_mute() const { return mute; }
get_setbank()509     const Glib::ustring& get_setbank() { return setbank; }
set_bank_preset(const Glib::ustring & bank,const Glib::ustring & preset)510     void set_bank_preset(const Glib::ustring& bank, const Glib::ustring& preset) {
511         cmdline_bank = bank; cmdline_preset = preset; }
get_cmdline_bank()512     const Glib::ustring& get_cmdline_bank() { return cmdline_bank; }
get_cmdline_preset()513     const Glib::ustring& get_cmdline_preset() { return cmdline_preset; }
get_tuner_tet()514     const Glib::ustring& get_tuner_tet() { return tuner_tet; }
get_tuner_ref()515     const Glib::ustring& get_tuner_ref() { return tuner_ref; }
get_rpcport()516     int get_rpcport() const { return rpcport; }
set_rpcport(int port)517     void set_rpcport(int port) { rpcport = port; }
get_rpcaddress()518     const Glib::ustring& get_rpcaddress() { return rpcaddress; }
set_rpcaddress(const Glib::ustring & address)519     void set_rpcaddress(const Glib::ustring& address) { rpcaddress = address; }
get_loadfile()520     const std::string& get_loadfile() const { return load_file; }
get_jack_instancename()521     const Glib::ustring& get_jack_instancename() const { return jack_instance; }
set_jack_instancename(std::string name)522     void set_jack_instancename(std::string name) {  jack_instance = name; }
get_jack_uuid()523     const Glib::ustring& get_jack_uuid() const { return jack_uuid; }
get_jack_uuid2()524     const Glib::ustring& get_jack_uuid2() const { return jack_uuid2; }
get_jack_midi()525     const Glib::ustring& get_jack_midi() const { return jack_midi; }
get_jack_input()526     const Glib::ustring& get_jack_input() const { return jack_input; }
get_jack_servername()527     const Glib::ustring& get_jack_servername() const { return jack_servername; }
get_jack_noconnect()528     bool get_jack_noconnect() const { return jack_noconnect; }
get_jack_single()529     bool get_jack_single() const { return jack_single; }
set_jack_noconnect(bool set)530     void set_jack_noconnect(bool set) { jack_noconnect = set; }
set_jack_single(bool set)531     void set_jack_single(bool set) { jack_single = set; }
get_opt_save_on_exit()532     bool get_opt_save_on_exit() const { return a_save; }
get_opt_autosave()533     bool get_opt_autosave() const { return auto_save; }
set_opt_autosave(bool set)534     void set_opt_autosave(bool set) { auto_save = set; }
535     Glib::ustring get_jack_output(unsigned int n) const;
get_idle_thread_timeout()536     int get_idle_thread_timeout() const { return idle_thread_timeout; }
get_sporadic_overload()537     int get_sporadic_overload() const { return sporadic_overload; }
get_xrun_watchdog()538     bool get_xrun_watchdog() const { return xrun_watchdog; }
get_convolver_watchdog()539     bool get_convolver_watchdog() const { return convolver_watchdog; }
get_watchdog_warning()540     bool get_watchdog_warning() const { return watchdog_warning; }
541 };
542 
get_options()543 inline BasicOptions& get_options() {
544     assert(BasicOptions::instance);
545     return *BasicOptions::instance;
546 }
547 
548 
549 /****************************************************************
550  ** misc function declarations
551  */
552 
553 int  gx_system_call(const std::string&, bool devnull = false, bool escape = false);
554 void strip(Glib::ustring& s);
555 
556 template <class T>
to_string(const T & t)557 inline std::string to_string(const T& t) {
558     std::stringstream ss;
559     ss << t;
560     return ss.str();
561 }
562 
563 std::string encode_filename(const std::string& s);
564 std::string decode_filename(const std::string& s);
565 
566 } /* end of gx_system namespace */
567 
568 #endif  // SRC_HEADERS_GX_SYSTEM_H_
569