File: FXJSON.h

package info (click to toggle)
gogglesmm 1.2.5-6
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 16,812 kB
  • sloc: cpp: 231,960; ansic: 893; xml: 222; makefile: 33
file content (298 lines) | stat: -rw-r--r-- 10,293 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
/********************************************************************************
*                                                                               *
*                      J S O N   R e a d e r  &  W r i t e r                    *
*                                                                               *
*********************************************************************************
* Copyright (C) 2013,2022 by Jeroen van der Zijp.   All Rights Reserved.        *
*********************************************************************************
* This library is free software; you can redistribute it and/or modify          *
* it under the terms of the GNU Lesser General Public License as published by   *
* the Free Software Foundation; either version 3 of the License, or             *
* (at your option) any later version.                                           *
*                                                                               *
* This library is distributed in the hope that it will be useful,               *
* but WITHOUT ANY WARRANTY; without even the implied warranty of                *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
* GNU Lesser General Public License for more details.                           *
*                                                                               *
* You should have received a copy of the GNU Lesser General Public License      *
* along with this program.  If not, see <http://www.gnu.org/licenses/>          *
********************************************************************************/
#ifndef FXJSON_H
#define FXJSON_H

#ifndef FXPARSEBUFFER_H
#include "FXParseBuffer.h"
#endif

namespace FX {


/**
* The FXJSON serializer loads or saves an FXVariant to a JSON text file.
* Since FXVariant can contain an arbitrarily complex data structure, this
* provides applications with a convenient way to load and save state information
* in a well-defined and human-readable file format.
* The base class implements serialization/deserialization to/from an external
* buffer.
*
* Subclasses FXJSONFile and FXJSONString serialize from/to strings and disk-
* based files, respectively.
* The new JSON5 standard may also be parsed, allowing for single- and multi-line
* nested comments to be embedded in the input, and makes quotation of variable
* names optional.  In addition, JSON5 also allows use of single quotes (') as
* well as double quotes (").
*
* Syntax errors in the input cause the parser to return an error, and allow
* diagnosis of the problem and its location in the file by line number, column
* number, and byte-offset from the start of the file.
*
* When writing a json stream, the generated output may be formatted in different
* ways. The flow-mode controls the overall layout of the resulting text output;
* when flow is set to Stream, all output is generated with no formatting to
* improve human legibility.  This is the most space-friendly format possible.
* If flow is set to Compact, a human readable, compact format, aiming to
* maximize the amount of information on each line is generated.
* When flow is set to Pretty, a nicely indented, but extremely "airy" output
* results, and the resulting document will contain many, many lines with
* little data.
*
* Numeric values are printed with configurable precision; (default=15 digits
* which results in minimal information loss for real numbers).
* For Pretty flow format, output may be indented in multiples of the indent
* level (default=2).  Depending on flow setting, lines may be wrapped at a
* maximum number of columns (default=80).
* Output strings containing reserved characters may have to be escaped.
* For UTF8 characters, there are 3 options for escaping.
*
*   - Escape mode 0: UTF8 characters are passed unescaped.
*   - Escape mode 1: UTF8 characters are escaped as \xXX.
*   - Escape mode 2: UTF8 will be escaed using Unicode escape sequences of
*     the for \uXXXX or \uXXXX\uXXXX (two surrogate-pairs  escape codes
*     for code points exceeding 16 bits).
*
* The default setting is to allow UTF8 characters in the output, but be aware
* that such outputs need UTF8-capable viewer software to be rendered properly.
* Finally, in JSON5 mode (version set to 5), variable names may be written as
* unquoted strings if their syntax allows for it; in JSON5 mode, single quotes
* may be selected to improve human legibility.
*/
class FXAPI FXJSON : public FXParseBuffer {
public:

  /// JSON deserializer error codes
  enum Error {
    ErrOK,              /// No errors
    ErrSave,            /// Unable to save
    ErrLoad,            /// Unable to load
    ErrToken,           /// Illegal token
    ErrColon,           /// Expected colon ':'
    ErrComma,           /// Expected comma ','
    ErrBracket,         /// Expected closing bracket
    ErrBrace,           /// Expected closing brace
    ErrQuotes,          /// Expected closing quotes
    ErrQuote,           /// Expected closing quote
    ErrNumber,          /// Numeric conversion
    ErrIdent,           /// Unexpected identifier
    ErrEnd              /// Unexpected end of file
    };

  /// JSON serializer flow modes
  enum Flow {
    Stream,             /// Stream-of-consciousness output
    Compact,            /// Compact, human readable output (default)
    Pretty              /// Pretty printed, indented output
    };
protected:
  enum Token {
    TK_ERROR,
    TK_EOF,
    TK_COMMA,
    TK_COLON,
    TK_IDENT,
    TK_NAN,
    TK_INF,
    TK_NULL,
    TK_FALSE,
    TK_TRUE,
    TK_STRING,
    TK_PLUS,
    TK_MINUS,
    TK_INT,
    TK_HEX,
    TK_REAL,
    TK_LBRACK,
    TK_LBRACE,
    TK_RBRACK,
    TK_RBRACE
    };
protected:
  FXString  value;      // Token value
  FXlong    offset;     // Position from start
  Token     token;      // Token
  FXint     column;     // Column number
  FXint     indent;     // Indent level
  FXint     line;       // Line number
  FXint     wrap;       // Line wrap column
  FXchar    quote;      // Quote type used
  FXuchar   flow;       // Output flow
  FXuchar   prec;       // Float precision
  FXuchar   fmt;        // Float format
  FXuchar   esc;        // Escape mode
  FXuchar   dent;       // Indentation amount
  FXuchar   ver;        // Version
protected:
  static const FXchar *const errors[];
protected:
  virtual Token next();
  Token ident();
  Token string();
  static Token identoken(const FXString& str);
  Error loadMap(FXVariant& var);
  Error loadArray(FXVariant& var);
  Error loadVariant(FXVariant& var);
  Error saveString(const FXString& str);
  Error saveIdent(const FXString& str);
  Error saveMap(const FXVariant& var);
  Error saveArray(const FXVariant& var);
  Error saveVariant(const FXVariant& var);
private:
  FXJSON(const FXJSON&);
  FXJSON &operator=(const FXJSON&);
public:

  /**
  * Initialize JSON serializer.
  */
  FXJSON();

  /**
  * Initialize JSON serializer with buffer of size and direction.
  * Text location (column, line number, byte offset) is reset.
  */
  FXJSON(FXchar* buffer,FXuval sz=8192,Direction d=Load);

  /**
  * Open JSON parse buffer with given size and direction.
  * Text location (column, line number, byte offset) is reset.
  */
  FXbool open(FXchar* buffer=nullptr,FXuval sz=8192,Direction d=Load);

  /**
  * Return current line number.
  */
  FXint getLine() const { return line; }

  /**
  * Return current column number.
  */
  FXint getColumn() const { return column; }

  /**
  * Return offset from begin of file.
  */
  FXlong getOffset() const { return offset; }

  /**
  * Load a variant from JSON stream.
  * Return false if stream wasn't opened for loading, or syntax error.
  */
  virtual Error load(FXVariant& variant);

  /**
  * Save a variant to JSON stream.
  * Return false if stream wasn't opened for saving, or disk was full.
  */
  virtual Error save(const FXVariant& variant);

  /**
  * Returns error for given error code.
  */
  static const FXchar* getError(Error err){ return errors[err]; }

  /**
  * Floating point output precision control.
  * This controls the number of significant digits written to
  * the output.  The default is 15.
  */
  void setNumericPrecision(FXint p){ prec=p; }
  FXint getNumericPrecision() const { return prec; }

  /**
  * Floating point output format control.
  * The format mode is interpreted as follows:
  *
  *   0   No exponent.
  *   1   Exponent.
  *   2   Output exponent when required.
  *
  * The default mode is 2.
  */
  void setNumericFormat(FXint f){ fmt=f; }
  FXint getNumericFormat() const { return fmt; }

  /**
  * Change output flow format (Stream, Compact, Pretty).
  * Stream is the most compact, but pretty much unreadable by humans; it
  * aims to be compact.
  * Compact is very human-readable while at the same time using minimum number
  * of lines to represent the output.
  * Pretty will print one item on each line, with indentation.  It is very easily
  * readable but produces large numbers of text lines.
  */
  void setOutputFlow(FXint f){ flow=f; }
  FXint getOutputFlow() const { return flow; }

  /**
  * Change indentation level for pretty print flow, the amount of
  * indentation applied for each level.
  */
  void setIndentation(FXint d){ dent=d; }
  FXint getIndentation() const { return dent; }

  /**
  * Change column at which lines are wrapped.
  */
  void setLineWrap(FXint w){ wrap=w; }
  FXint getLineWrap() const { return wrap; }

  /**
  * Change string escape mode.
  * The escape mode is interpreted as follows:
  *
  *  0  Don't escape unicode in strings;
  *  1  Escape unicode as \xXX
  *  2  Escape unicode as \uXXXX or \uXXXX\uXXXX.
  *
  * Default is to escape control characters only.
  */
  void setEscapeMode(FXint e){ esc=e; }
  FXint getEscapeMode() const { return esc; }

  /**
  * Change json version.
  */
  void setVersion(FXint v){ ver=v; }
  FXint getVersion() const { return ver; }

  /**
  * Change quote type, either (') or (").
  */
  void setQuote(FXint q){ quote=q; }
  FXint getQuote() const { return quote; }

  /**
  * Close stream and delete buffer, if owned.
  * To permit diagnostics, text location not reset.
  */
  FXbool close();

  /**
  * Close JSON stream and clean up.
  */
  virtual ~FXJSON();
  };

}

#endif