Flow123d
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
flow123d
src
input
json_to_storage.hh
Go to the documentation of this file.
1
/*
2
* json_to_storage.hh
3
*
4
* Created on: May 7, 2012
5
* Author: jb
6
*
7
* TODO:
8
* EI_InputType - passing pointer is not save. The object can be deleted during stack unfolding.
9
* Error_info can not be used for abstract types (of course), the only save way is to
10
* use boost::shared_ptr, so make the copy our self by make_shared and then only pass the pointer.
11
*
12
* These problems can be eliminated, when all Type instances are static.
13
*
14
* TODO:
15
* - check cyclic references, drop const for json_spirit pointers and modify REF keys
16
* when dereferenced and modify it back when we return.
17
* (e.g. add a new entry into map
18
* TODO:
19
* Find deleting of a null pointer in json_spirit library. Possibly implement
20
* output of true stack for GNU.
21
*/
22
23
#ifndef JSON_TO_STORAGE_HH_
24
#define JSON_TO_STORAGE_HH_
25
26
27
#include <sstream>
28
29
#include "
json_spirit/json_spirit.h
"
30
#include "
input/input_type.hh
"
31
32
#include "
input/accessors.hh
"
33
#include "
input/storage.hh
"
34
35
36
namespace
Input {
37
38
39
40
/**
41
* @brief Class used by JSONToStorage class to iterate over the JSON tree provided by json_spirit library.
42
*
43
* This class keeps whole path from the root of the JSON tree to the current node. We store nodes along path in \p nodes_
44
* and address of the node in \p path_.
45
*
46
* The class also contains methods for processing of special keys 'REF' and 'TYPE'. The reference is record with only one key
47
* 'REF' with a string value that contains address of the reference. The string with the address is extracted by \p JSONToStorage::get_ref_from_head
48
* then the JSONPath corresponding to the address is provided by method \p JSONtoStorage::find_ref_node.
49
*/
50
class
JSONPath
{
51
public
:
52
/**
53
* Thrown if a reference in the input file
54
*/
55
56
TYPEDEF_ERR_INFO
(EI_ErrorAddress,
JSONPath
);
57
TYPEDEF_ERR_INFO
(EI_RefAddress,
JSONPath
);
58
TYPEDEF_ERR_INFO
(EI_JsonFile,
const
string
);
59
TYPEDEF_ERR_INFO
(EI_RefStr,
const
string
);
60
TYPEDEF_ERR_INFO
(EI_Specification,
const
string
);
61
DECLARE_INPUT_EXCEPTION
(ExcRefOfWrongType,
62
<<
"Reference at address "
63
<< EI_ErrorAddress::qval <<
" has wrong type, should by string."
);
64
DECLARE_INPUT_EXCEPTION
(ExcReferenceNotFound,
65
<<
"Error in input file: "
<< EI_JsonFile::qval <<
"\nReference {REF=\""
<< EI_RefStr::val <<
"\"} at address "
<< EI_RefAddress::qval <<
" not found.\n"
66
<<
"failed to follow at address: "
<< EI_ErrorAddress::qval <<
" because "
<< EI_Specification::val);
67
68
69
70
typedef
json_spirit::mValue
Node
;
71
72
JSONPath
(
const
Node
& root_node);
73
74
/**
75
* Dive into json_spirit hierarchy. Store current path and returns pointer to new json_spirit node.
76
* If the json_spirit type do not match returns NULL.
77
*/
78
const
Node
*
down
(
unsigned
int
index);
79
const
Node
*
down
(
const
string
& key);
80
81
/**
82
* Return one level up in the hierrarchy.
83
*/
84
void
up
();
85
86
/**
87
* Move to root node.
88
*/
89
void
go_to_root
();
90
91
/**
92
* Pointer to JSON Value object at current path.
93
*/
94
inline
const
Node
*
head
()
const
95
{
return
nodes_
.back(); }
96
97
/**
98
* Returns level of actual path. Root has level == 0.
99
*/
100
inline
int
level
()
const
101
{
return
nodes_
.size() - 1; }
102
103
/**
104
* Check if current head node is a JSON Object containing one key REF of type string.
105
* If yes, returns the string through reference @p ref_address.
106
*/
107
bool
get_ref_from_head
(
string
& ref_address);
108
109
/**
110
* Creates a new JSONPath object given by address string possibly relative to the current
111
* path.
112
*/
113
JSONPath
find_ref_node
(
const
string
& ref_address);
114
115
/**
116
* Output to the given stream.
117
*/
118
void
output
(ostream &stream)
const
;
119
120
/**
121
* Returns string address of current position.
122
*/
123
string
str
();
124
125
/**
126
* Put actual address to previous_references_ set
127
*/
128
void
put_address
();
129
130
private
:
131
/**
132
* One level of the @p path_ is either index (nonnegative int) in array or string key in a json object.
133
* For the first type we save index into first part of the pair and empty string to the second.
134
* For the later type of level, we save -1 for index and the key into the secodn part of the pair.
135
*/
136
vector< pair<int, string>
>
path_
;
137
vector<const Node *>
nodes_
;
138
std::set<string>
previous_references_
;
139
140
141
};
142
143
/**
144
* Output operator for JSONPath. Mainly for debugging purposes and error messages.
145
*/
146
std::ostream&
operator<<
(std::ostream& stream,
const
JSONPath
& path);
147
148
149
/**
150
* @brief Reader for (slightly) modified JSON files.
151
*
152
* This class implements a reader of modified JSON file format. The modifications include
153
* shell-like comments (using hash '#' character), this is implemented in comment_filter.hh, optional quoting of
154
* keys in JSON objects that do not contain spaces, and possibility to use '=' instead of ':'. So you can write:
155
* @code
156
* { key1="text", key2=2, "key 3"=4 }
157
* @endcode
158
* Note, however, that our input interface allows only C identifiers for keys. The reader use json_spirit library
159
* (based on Spirit parser from Boost) with slightly modified grammar.
160
*
161
* The input file is at first read and parsed by json_spirit. Then JSONToStorage pass through tree with parsed data along
162
* with passing through declaration tree. The input data are check against declaration and stored in the Storage tree.
163
*
164
* Accessor to the root record is provided by JSONToStorage::get_root_interface<T> method template.
165
*
166
* @ingroup input
167
*/
168
class
JSONToStorage
{
169
public
:
170
/*
171
* Exceptions.
172
*/
173
// unfortunately following is not safe:
174
// TYPEDEF_ERR_INFO(EI_InputType, Type::TypeBase const *);
175
176
/// General exception during conversion from JSON tree to storage.
177
TYPEDEF_ERR_INFO
(EI_InputType,
string
);
178
TYPEDEF_ERR_INFO
(EI_File,
const
string
);
179
TYPEDEF_ERR_INFO
(EI_Specification,
const
string
);
180
TYPEDEF_ERR_INFO
(EI_JSON_Type,
const
string
);
181
TYPEDEF_ERR_INFO
( EI_ErrorAddress,
JSONPath
);
182
DECLARE_INPUT_EXCEPTION
( ExcInputError, <<
"Error in input file: "
<< EI_File::qval <<
" at address: "
<< EI_ErrorAddress::qval <<
"\n"
183
<< EI_Specification::val <<
"\n"
184
<<
"JSON type: "
<< EI_JSON_Type::qval <<
"\n"
185
<<
"Expected type:\n"
<< EI_InputType::val );
186
187
188
TYPEDEF_ERR_INFO
( EI_JSONLine,
unsigned
int
);
189
TYPEDEF_ERR_INFO
( EI_JSONColumn,
unsigned
int
);
190
TYPEDEF_ERR_INFO
( EI_JSONReason,
string
);
191
DECLARE_INPUT_EXCEPTION
( ExcNotJSONFormat, <<
"Not valid JSON file "
<< EI_File::qval <<
". Error at line "
192
<< EI_JSONLine::val <<
" : col "
<< EI_JSONColumn::val
193
<<
" ; reason: "
<< EI_JSONReason::val <<
"\n"
);
194
195
196
/**
197
* Read a storage from input stream. Parameter @p root_type
198
* provides input type tree declaration. See @p read_from_stream for details.
199
*/
200
JSONToStorage
(istream &in,
const
Type::TypeBase
&root_type);
201
202
/**
203
* Read a storage from string (e.g. complex default value).
204
*/
205
JSONToStorage
(
const
string
&default_str,
const
Type::TypeBase
&root_type);
206
207
/**
208
* Returns the root accessor. The template type \p T should correspond
209
* to the kind of the input type at root of the declaration tree.
210
*/
211
template
<
class
T>
212
T
get_root_interface
()
const
;
213
214
215
protected
:
216
217
/**
218
* Default constructor.
219
* Provides common initialization for public constructors.
220
*/
221
JSONToStorage
();
222
223
/**
224
* This method actually reads the given stream \p in, checks the data just read against the declaration tree given by \p root_type, and
225
* store the data into private storage tree using \p StorageBase classes.
226
*/
227
void
read_stream
(istream &in,
const
Type::TypeBase
&root_type);
228
229
/**
230
* Getter for root of the storage tree.
231
*/
232
const
StorageBase
*
get_storage
()
233
{
return
storage_
;}
234
235
236
/**
237
* Check correctness of the input given by json_spirit node at head() of JSONPath @p p
238
* against type specification @p type. Die on input error (and return NULL).
239
* For correct input, creates the storage tree and returns pointer to its root node.
240
*/
241
StorageBase
*
make_storage
(
JSONPath
&p,
const
Type::TypeBase
*type);
242
243
StorageBase
*
make_storage
(
JSONPath
&p,
const
Type::Record
*record);
244
StorageBase
*
make_storage
(
JSONPath
&p,
const
Type::AbstractRecord
*abstr_rec);
245
StorageBase
*
make_storage
(
JSONPath
&p,
const
Type::Array
*array);
246
247
StorageBase
*
make_selection_storage_without_catch
(
JSONPath
&p,
const
Type::Selection
*selection);
248
StorageBase
*
make_storage
(
JSONPath
&p,
const
Type::Selection
*selection);
249
StorageBase
*
make_storage
(
JSONPath
&p,
const
Type::Bool
*
bool_type
);
250
StorageBase
*
make_storage
(
JSONPath
&p,
const
Type::Integer
*
int_type
);
251
StorageBase
*
make_storage
(
JSONPath
&p,
const
Type::Double
*double_type);
252
StorageBase
*
make_storage
(
JSONPath
&p,
const
Type::String
*string_type);
253
254
/**
255
* Dispatch according to @p type and create corresponding storage from the given string.
256
*/
257
StorageBase
*
make_storage_from_default
(
const
string
&dflt_str,
const
Type::TypeBase
*type);
258
259
260
261
/// helper envelope for get_root_interface
262
//StorageArray *envelope;
263
264
/// Storage of the read and checked input data
265
StorageBase
*
storage_
;
266
267
/// Root of the declaration tree of the data in the storage.
268
const
Type::TypeBase
*
root_type_
;
269
270
/**
271
* Names of all possible node types in parsed JSON tree provided by JSON Spirit library.
272
* Initialized in constructor.
273
*
274
*/
275
vector<string>
json_type_names
;
276
277
/**
278
* List of paths specifications of the keys that wasn't read by the JSON reader.
279
*/
280
//vector<string> ignored_keys;
281
282
};
283
284
285
286
287
288
289
290
/********************************************88
291
* Implementation
292
*/
293
294
template
<
class
T>
295
T
JSONToStorage::get_root_interface
()
const
296
{
297
ASSERT
(
storage_
,
"NULL pointer to storage !!! \n"
);
298
299
Address
addr(
storage_
,
root_type_
);
300
// try to create an iterator just to check type
301
Iterator<T>
( *
root_type_
, addr, 0);
302
303
auto
tmp_root_type =
static_cast<
const
typename T::InputType &
>
(*root_type_);
304
return
T( addr, tmp_root_type );
305
}
306
307
308
309
310
}
// namespace Input
311
312
313
314
#endif
/* JSON_TO_STORAGE_HH_ */
Generated on Thu May 29 2014 23:14:48 for Flow123d by
1.8.4