Guitarix
gx_json.h
Go to the documentation of this file.
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_JSON_H_
26 #define SRC_HEADERS_GX_JSON_H_
27 
28 namespace gx_engine {
29 class GxMachine;
30 class GxMachineRemote;
31 }
32 
33 namespace gx_system {
34 
35 /****************************************************************
36  ** class JsonParser, class JsonWriter, class JsonException
37  ** classes for reading and writing JSON files
38  */
39 
40 class JsonException: public exception {
41  protected:
42  Glib::ustring what_str;
43  public:
44  JsonException(const Glib::ustring& desc);
45  ~JsonException() throw() { }
46  virtual const char* what() const throw() { return what_str.c_str(); }
47 };
48 
50  public:
51  JsonExceptionEOF(const char* desc): JsonException(desc) {}
52  ~JsonExceptionEOF() throw() { }
53 };
54 
55 class JsonWriter {
56  private:
57  ostream *os;
58  bool first;
59  int deferred_nl;
60  string indent;
61  void snl(bool v) { if (deferred_nl >= 0) deferred_nl = (v ? 1 : 0); }
62  void komma();
63  void space();
64  void iplus();
65  void iminus();
66  public:
67  JsonWriter(ostream* o = 0, bool enable_newlines = true);
68  virtual ~JsonWriter();
69  void reset();
70  void set_stream(ostream* o) { os = o; }
71  bool good() { return os->good(); }
72  void flush();
73  virtual void close();
74  bool is_closed() { return !os; }
75  void write(float v, bool nl = false);
76  void write(double v, bool nl = false);
77  void write(int i, bool nl = false);
78  void write(unsigned int i, bool nl = false);
79  void write(const char* p, bool nl = false);
80  void write(const string& s, bool nl = false) { write(s.c_str(), nl); }
81  void write_kv(const char *key, float v) { write_key(key); write(v, true); }
82  void write_kv(const char *key, double v) { write_key(key); write(v, true); }
83  void write_kv(const char *key, int i) { write_key(key); write(i, true); }
84  void write_kv(const char *key, unsigned int i) { write_key(key); write(i, true); }
85  void write_kv(const char *key, const char* p) { write_key(key); write(p, true); }
86  void write_kv(const char *key, const std::string& s) { write_key(key); write(s, true); }
87  void write_lit(const string& s, bool nl = false);
88  void begin_object(bool nl = false);
89  void end_object(bool nl = false);
90  void begin_array(bool nl = false);
91  void end_array(bool nl = false);
92  void write_key(const char* p, bool nl = false);
93  void write_key(const string& p, bool nl = false);
94  void write_null(bool nl = false) { write_lit("null", nl); }
95  void newline() { snl(true); }
96 };
97 
98 
100 private:
101  ostringstream stream;
102 public:
103  JsonStringWriter(): JsonWriter(0, false) { set_stream(&stream); }
104  void send_notify_begin(const char *method);
105  void send_notify_end();
106  void reset() { stream.str(""); }
107  void finish() { stream << endl; }
108  std::string get_string() { return stream.str(); }
109 };
110 
111 
112 class JsonParser {
113  public:
114  JsonParser(istream* i = 0);
115  virtual ~JsonParser();
116  virtual void close();
117  void reset();
118  bool is_closed() { return !is; }
119  void set_stream(istream* i) { is = i; }
120  istream *get_stream() { return is; }
121  enum token {
122  no_token = 0x0000,
123  end_token = 0x0001,
124  begin_object = 0x002,
125  end_object = 0x0004,
126  begin_array = 0x0008,
127  end_array = 0x0010,
128  value_string = 0x0020,
129  value_number = 0x0040,
130  value_key = 0x0080,
131  value_null = 0x0100,
132  value_false = 0x0200,
133  value_true = 0x0400,
134  value_bool = 0x0600, // value_false | value_true
135  };
136  const char* get_token_name(token tok);
137  bool good() { return is->good(); }
138  token next(token expect = no_token);
139  token peek() { return next_tok; }
140  streampos get_streampos() { return next_pos + streamoff(-1); }
141  void set_streampos(streampos pos);
142  void check_expect(token expect) { if ((cur_tok & expect) == 0) throw_unexpected(expect); }
143  inline string current_value() const { return str; }
144  int current_value_int() { return atoi(str.c_str()); }
145  unsigned int current_value_uint() { return atoi(str.c_str()); }
147  istringstream b(str);
148  float f;
149  b >> f;
150  return f;
151  }
153  istringstream b(str);
154  double d;
155  b >> d;
156  return d;
157  }
158  bool read_kv(const char *key, float& v);
159  bool read_kv(const char *key, double& v);
160  bool read_kv(const char *key, int& i);
161  bool read_kv(const char *key, unsigned int& i);
162  bool read_kv(const char *key, std::string& s);
163  bool read_kv(const char *key, Glib::ustring& s);
164  template<class T> inline bool read_kv(const char *key, T& v) {
165  int i;
166  if (read_kv(key, i)) {
167  v = static_cast<T>(i);
168  return true;
169  }
170  return false;
171  }
172  void copy_object(JsonWriter& jw);
173  void skip_object();
174  void throw_unexpected(token expect);
175  private:
176  istream* is;
177  int depth;
178  token cur_tok;
179  string str;
180  bool nl;
181  int next_depth;
182  token next_tok;
183  string next_str;
184  string log_tok;
185  streampos next_pos;
186  const char* readcode();
187  string readstring();
188  token read_value_token(char c);
189  string readnumber(char c);
190  void read_next();
191 };
192 
193 
194 class JsonSubParser: public JsonParser {
195 private:
196  std::streampos position;
197 public:
198  JsonSubParser(JsonParser& jp, streampos pos);
199  ~JsonSubParser();
200 };
201 
203 private:
204  std::stringstream stream;
205 public:
207  void put(char c) { stream.put(c); }
208  std::ostream& get_ostream() { return stream; }
209  void start_parser() { stream.seekg(0); set_stream(&stream); }
210  std::string get_string() { return stream.str(); }
211  void reset() { stream.str(""); JsonParser::reset(); }
212  char peek_first_char() { stream >> ws; return stream.peek(); }
213 };
214 
215 
216 /****************************************************************
217  ** Setting file handling
218  ** class SettingsFileHeader, class StateFile, class PresetFile,
219  ** class AbstractStateIO, class AbstractPresetIO
220  ** class PresetBanks
221  ** class GxSettingsBase
222  */
223 
225  int file_major;
226  int file_minor;
227  string file_gx_version;
228 public:
229  enum {
230  major = 1,
231  minor = 2
232  };
233  static const string gx_version; // = GX_VERSION
235  : file_major(), file_minor(), file_gx_version() {}
236  void read(JsonParser&);
237  static void write(JsonWriter&);
238  void set_to_current() { file_major = major; file_minor = minor; file_gx_version = gx_version; }
239  int get_major() const { return file_major; }
240  int get_minor() const { return file_minor; }
241  string get_revision() const { return file_gx_version; }
242  bool is_major_diff() const { return major != file_major; }
243  bool is_minor_diff() const { return minor != file_minor; }
244  bool is_current() const { return !is_major_diff() && !is_minor_diff(); }
245  bool is_equal() const { return is_current() && gx_version == file_gx_version; }
246  string display() const { ostringstream s; s << file_major << "." << file_minor << "." << file_gx_version; return s.str(); }
247  Glib::ustring version_string() const { return Glib::ustring::compose("%1.%2", file_major, file_minor); }
248  inline Glib::ustring current_version_string() const { return Glib::ustring::compose("%1.%2", int(major), int(minor)); }
249  static bool make_empty_settingsfile(const string& name);
250  static void write_current_major_minor(JsonWriter& jw);
251  void write_major_minor(JsonWriter& jw);
252  void read_major_minor(JsonParser& jp);
253 };
254 
255 class StateFile {
256 private:
257  string filename;
258  istream *is;
259  time_t mtime;
260  SettingsFileHeader header;
261  void open();
262 public:
264  : filename(), is(0), mtime(), header() {}
265  ~StateFile() { delete is; }
266  void set_filename(const string& fn);
267  const SettingsFileHeader& get_header() const { return header; }
268  string get_filename() const { return filename; }
269  JsonParser *create_reader();
270  JsonWriter *create_writer(bool *preserve_preset);
271  void ensure_is_current();
272 };
273 
275 private:
276  string filename;
277  string tmpfile;
278  ofstream os;
279 protected:
280  istream *is;
281 public:
284  void close();
285  void close_nocheck();
286  void abort();
287  PresetTransformer(string filename, istream* is);
289 };
290 
291 enum {
295 };
296 
297 class PresetFileGui;
298 
299 class PresetFile : boost::noncopyable {
300 public:
301  enum { PRESET_SEP = -1, PRESET_SCRATCH = 0, PRESET_FILE = 1, PRESET_FACTORY = 2 };
302 protected:
303  class Position {
304  public:
305  Glib::ustring name;
306  streampos pos;
307  Position(Glib::ustring n, streampos p): name(n), pos(p) {}
308  };
309  std::string filename;
310  ifstream *is;
311  time_t mtime;
313  std::vector<Position> entries;
314  Glib::ustring name;
315  int tp;
316  int flags;
318 protected:
319  void open();
320 public:
321  typedef std::vector<Position>::iterator iterator;
322  PresetFile();
323  ~PresetFile() { delete is; }
324  void readJSON_remote(JsonParser& jp);
325  void writeJSON_remote(JsonWriter& jw);
326  bool open_file(const Glib::ustring& name, const std::string& path, int tp, int flags);
327  bool create_file(const Glib::ustring& name, const std::string& path, int tp, int flags);
328  bool set_factory(const Glib::ustring& name_, const std::string& path);
329  bool readJSON(const std::string& dirpath, JsonParser &jp, bool *mtime_diff);
330  void writeJSON(JsonWriter& jw);
331  void reopen() { if (!is && !filename.empty()) open(); }
332  void open(const std::string& fname);
333  void close() { delete is; is = 0; }
334  bool fail();
335  bool ensure_is_current();
336  void check_flags();
337  const std::string& get_filename() const { return filename; }
338  const SettingsFileHeader& get_header();
339  int size();
340  void fill_names(vector<Glib::ustring>&);
341  const Glib::ustring& get_name(int n);
342  int get_index(const Glib::ustring& name);
343  JsonParser *create_reader(int n);
344  JsonParser *create_reader(const Glib::ustring& name) {
345  return create_reader(get_index(name)); }
347  return create_writer(get_name(n)); }
348  JsonWriter *create_writer(const Glib::ustring& name);
349  JsonWriter *create_writer_at(const Glib::ustring& pos, const Glib::ustring& name);
350  PresetTransformer *create_transformer();
351  bool clear();
352  bool erase(const Glib::ustring& name);
353  bool rename(const Glib::ustring& name, Glib::ustring newname);
354  bool has_entry(const Glib::ustring& name) { return get_index(name) >= 0; }
355  void append(const Glib::ustring& name);
356  void insert_before(const Glib::ustring& nm, const Glib::ustring& newentry);
357  void insert_after(const Glib::ustring& nm, const Glib::ustring& newentry);
358  int get_flags() const { return flags; }
359  void set_flags(int f) { flags = f; }
360  void set_flag(int flag, bool v) { flags = (flags & ~flag) | (v ? flag : 0); }
361  int get_type() const { return tp; }
362  const Glib::ustring& get_name() const { return name; }
363  bool set_name(const Glib::ustring& n, const std::string& newfile);
364  bool remove_file();
365  iterator begin();
366  iterator end() { return entries.end(); }
367  bool is_mutable() const { return (tp == PRESET_SCRATCH || tp == PRESET_FILE) && !flags; }
368  PresetFileGui *get_guiwrapper();
369 };
370 
371 class PresetFileGui: private PresetFile {
372 private:
373  PresetFileGui();
374  ~PresetFileGui();
375  friend class PresetFile;
376  friend class gx_engine::GxMachine;
378 public:
379  using PresetFile::get_header;
380  using PresetFile::size;
381  using PresetFile::fill_names;
382  using PresetFile::get_name;
383  using PresetFile::get_index;
384  using PresetFile::has_entry;
385  using PresetFile::get_flags;
386  using PresetFile::get_type;
387  using PresetFile::begin;
388  using PresetFile::end;
389  using PresetFile::is_mutable;
390  operator PresetFile*() { return this; }
391 };
392 
393 inline PresetFileGui *PresetFile::get_guiwrapper() { return static_cast<PresetFileGui*>(this); }
394 
396 public:
397  virtual ~AbstractStateIO();
398  virtual void read_state(JsonParser&,const SettingsFileHeader&) = 0;
399  virtual void commit_state() = 0;
400  virtual void write_state(JsonWriter&, bool) = 0;
401 };
402 
404 public:
405  virtual ~AbstractPresetIO();
406  virtual void read_preset(JsonParser&,const SettingsFileHeader&) = 0;
407  virtual void read_online(JsonParser&) = 0;
408  virtual void commit_preset() = 0;
409  virtual void write_preset(JsonWriter&) = 0;
410  virtual void copy_preset(JsonParser&,const SettingsFileHeader&,JsonWriter&) = 0;
411 };
412 
413 class PresetBanks {
414 private:
415  typedef std::list<PresetFile*> bl_type;
416  bl_type banklist;
417  std::string filepath;
418  time_t mtime;
419  std::string preset_dir;
420  void parse_factory_list(const std::string& path);
421  void parse_bank_list(bl_type::iterator pos);
422  void collect_lost_banks(const char* scratchpad_name, const char* scratchpad_file);
424 public:
425  class iterator {
426  private:
427  bl_type::iterator it;
428  public:
429  iterator(bl_type::iterator i): it(i) {}
430  bool operator!=(const iterator& i) const { return it != i.it; }
431  iterator& operator++() { ++it; return *this; }
432  PresetFile* operator->() { return *it; }
433  PresetFile* operator*() { return *it; }
434  };
435  PresetBanks();
436  ~PresetBanks();
437  void readJSON_remote(gx_system::JsonParser& jp);
438  bool check_reparse();
439  void parse(const std::string& bank_path, const std::string& preset_dir,
440  const std::string& factory_path, const char* scratchpad_name, const char* scratchpad_file);
441  PresetFile* get_file(const Glib::ustring& bank) const;
442  int get_index(const Glib::ustring& bank) const;
443  iterator begin() { return iterator(banklist.begin()); }
444  iterator end() { return iterator(banklist.end()); }
445  bool remove(const Glib::ustring& bank);
446  void save();
447  int size() { return banklist.size(); }
448  Glib::ustring get_name(int n);
449  void insert(PresetFile* f) { banklist.push_front(f); save(); }
450  bool has_entry(const Glib::ustring& bank) const { return get_file(bank) != 0; }
451  bool has_file(const std::string& file) const;
452  bool rename(const Glib::ustring& oldname, const Glib::ustring& newname, const std::string& newfile);
453  void reorder(const std::vector<Glib::ustring>& neworder);
454  static void make_valid_utf8(Glib::ustring& s);
455  static std::string add_preset_postfix(const std::string& filename);
456  static bool strip_preset_postfix(std::string& name);
457  void make_bank_unique(Glib::ustring& name, std::string *file = 0);
458 };
459 
461 protected:
466  Glib::ustring current_bank;
467  Glib::ustring current_name;
469  sigc::signal<void> selection_changed;
470  sigc::signal<void> presetlist_changed;
471  bool loadsetting(PresetFile *p, const Glib::ustring& name);
472 protected:
473  void loadstate();
474  void set_io(AbstractStateIO* st, AbstractPresetIO* pr) { state_io = st; preset_io = pr; }
475 public:
476  inline sigc::signal<void>& signal_selection_changed() {
477  return selection_changed; }
478  inline sigc::signal<void>& signal_presetlist_changed() {
479  return presetlist_changed; }
481  ~GxSettingsBase();
482  const Glib::ustring& get_current_bank() { return current_bank; }
483  PresetFile *get_current_bank_file() { return setting_is_preset() ? banks.get_file(current_bank) : 0; }
484  const Glib::ustring& get_current_name() { return current_name; }
485  void set_statefilename(const std::string& fn) { statefile.set_filename(fn); }
486  void save_to_state(bool preserve_preset=false);
487  void set_source_to_state();
488  void erase_preset(const Glib::ustring& name);
489  bool setting_is_preset() { return !current_bank.empty(); }
490  bool convert_preset(PresetFile& pf);
491  void reorder_preset(PresetFile& pf, const std::vector<Glib::ustring>& neworder);
492  void erase_preset(PresetFile& pf, const Glib::ustring& name);
493  void save(PresetFile& pf, const Glib::ustring& name);
494  void append(PresetFile& pf, const Glib::ustring& src, PresetFile& pftgt, const Glib::ustring& name);
495  void insert_before(PresetFile& pf, const Glib::ustring& src, PresetFile& pftgt, const Glib::ustring& pos, const Glib::ustring& name);
496  void insert_after(PresetFile& pf, const Glib::ustring& src, PresetFile& pftgt, const Glib::ustring& pos, const Glib::ustring& name);
497  void load_preset(PresetFile *pf, const Glib::ustring& name);
498  void load_online_presets();
499  bool rename_bank(const Glib::ustring& oldname, const Glib::ustring& newname, const std::string& newfile);
500  bool remove_bank(const Glib::ustring& bank);
501  bool rename_preset(PresetFile& pf, const Glib::ustring& oldname, const Glib::ustring& newname);
502 };
503 
504 } /* end of gx_system namespace */
505 #endif // SRC_HEADERS_GX_JSON_H_
iterator end()
Definition: gx_json.h:366
gx_engine::EngineControl & seq
Definition: gx_json.h:468
CmdConnection::msg_type end
Definition: jsonrpc.cpp:256
void write_kv(const char *key, float v)
Definition: gx_json.h:81
void set_io(AbstractStateIO *st, AbstractPresetIO *pr)
Definition: gx_json.h:474
bool has_entry(const Glib::ustring &name)
Definition: gx_json.h:354
Glib::ustring what_str
Definition: gx_json.h:42
bool operator!=(const iterator &i) const
Definition: gx_json.h:430
PresetFile * get_current_bank_file()
Definition: gx_json.h:483
void set_stream(ostream *o)
Definition: gx_json.h:70
Position(Glib::ustring n, streampos p)
Definition: gx_json.h:307
std::ostream & get_ostream()
Definition: gx_json.h:208
unsigned int current_value_uint()
Definition: gx_json.h:145
void insert(PresetFile *f)
Definition: gx_json.h:449
Glib::ustring name
Definition: gx_json.h:314
std::string get_string()
Definition: gx_json.h:108
sigc::signal< void > selection_changed
Definition: gx_json.h:469
PresetFile * get_file(const Glib::ustring &bank) const
Definition: gx_json.cpp:1623
const Glib::ustring & get_name() const
Definition: gx_json.h:362
void write_kv(const char *key, double v)
Definition: gx_json.h:82
void set_flag(int flag, bool v)
Definition: gx_json.h:360
void write_kv(const char *key, unsigned int i)
Definition: gx_json.h:84
std::string filename
Definition: gx_json.h:309
std::vector< Position >::iterator iterator
Definition: gx_json.h:321
sigc::signal< void > presetlist_changed
Definition: gx_json.h:470
int get_type() const
Definition: gx_json.h:361
void set_flags(int f)
Definition: gx_json.h:359
std::vector< Position > entries
Definition: gx_json.h:313
bool is_mutable() const
Definition: gx_json.h:367
sigc::signal< void > & signal_selection_changed()
Definition: gx_json.h:476
bool is_major_diff() const
Definition: gx_json.h:242
void write_kv(const char *key, const std::string &s)
Definition: gx_json.h:86
SettingsFileHeader header
Definition: gx_json.h:312
void check_expect(token expect)
Definition: gx_json.h:142
void set_filename(const string &fn)
Definition: gx_json.cpp:746
void write(const string &s, bool nl=false)
Definition: gx_json.h:80
string get_filename() const
Definition: gx_json.h:268
sigc::signal< void > & signal_presetlist_changed()
Definition: gx_json.h:478
void write_null(bool nl=false)
Definition: gx_json.h:94
void set_statefilename(const std::string &fn)
Definition: gx_json.h:485
AbstractPresetIO * preset_io
Definition: gx_json.h:463
void set_stream(istream *i)
Definition: gx_json.h:119
bool read_kv(const char *key, T &v)
Definition: gx_json.h:164
istream * get_stream()
Definition: gx_json.h:120
virtual const char * what() const
Definition: gx_json.h:46
std::string get_string()
Definition: gx_json.h:210
AbstractStateIO * state_io
Definition: gx_json.h:462
streampos get_streampos()
Definition: gx_json.h:140
SettingsFileHeader header
Definition: gx_json.h:283
const Glib::ustring & get_current_name()
Definition: gx_json.h:484
const SettingsFileHeader & get_header() const
Definition: gx_json.h:267
Glib::ustring current_name
Definition: gx_json.h:467
string current_value() const
Definition: gx_json.h:143
JsonWriter * create_writer(int n)
Definition: gx_json.h:346
Glib::ustring current_bank
Definition: gx_json.h:466
bool has_entry(const Glib::ustring &bank) const
Definition: gx_json.h:450
int flag
Definition: ladspaback.cpp:55
void write_kv(const char *key, int i)
Definition: gx_json.h:83
JsonParser * create_reader(const Glib::ustring &name)
Definition: gx_json.h:344
JsonExceptionEOF(const char *desc)
Definition: gx_json.h:51
string display() const
Definition: gx_json.h:246
int get_flags() const
Definition: gx_json.h:358
static const string gx_version
Definition: gx_json.h:233
float current_value_float()
Definition: gx_json.h:146
string get_revision() const
Definition: gx_json.h:241
iterator begin()
Definition: gx_json.h:443
bool is_minor_diff() const
Definition: gx_json.h:243
const std::string & get_filename() const
Definition: gx_json.h:337
Glib::ustring current_version_string() const
Definition: gx_json.h:248
double current_value_double()
Definition: gx_json.h:152
void write_kv(const char *key, const char *p)
Definition: gx_json.h:85
iterator(bl_type::iterator i)
Definition: gx_json.h:429
const Glib::ustring & get_current_bank()
Definition: gx_json.h:482
Glib::ustring version_string() const
Definition: gx_json.h:247