json_data_handler.hpp
Go to the documentation of this file.
1 #ifndef STAN_IO_JSON_JSON_DATA_HANDLER_HPP
2 #define STAN_IO_JSON_JSON_DATA_HANDLER_HPP
3 
4 #include <boost/throw_exception.hpp>
5 #include <boost/lexical_cast.hpp>
10 #include <cctype>
11 #include <iostream>
12 #include <limits>
13 #include <map>
14 #include <sstream>
15 #include <string>
16 #include <vector>
17 #include <utility>
18 
19 namespace stan {
20 
21  namespace json {
22 
23  typedef
24  std::map<std::string,
25  std::pair<std::vector<double>,
26  std::vector<size_t> > >
28 
29  typedef
30  std::map<std::string,
31  std::pair<std::vector<int>,
32  std::vector<size_t> > >
34 
35  /**
36  * A <code>json_data_handler</code> is an implementation of a
37  * <code>json_handler</code> that restricts the allowed JSON text
38  * a set of Stan variable declarations in JSON format.
39  * Each Stan variable consists of a JSON key : value pair.
40  * The key is a string and the value is either a single numeric
41  * scalar value or a JSON array of numeric values.
42  *
43  * <p>The <code>json_data_handler</code> checks that the top-level
44  * JSON object contains a set of name-value pairs
45  * where the values can be either numeric scalar objects or
46  * or numeric arrays of any dimensionality. Arrays must be rectangular.
47  * Empty arrays are not allowed, nor are arrays of empty arrays.
48  * The strings \"inf\" and \"-inf\" are mapped to positive and negative
49  * infinity, respectively.
50  */
52  private:
55  std::string key_;
56  std::vector<double> values_r_;
57  std::vector<int> values_i_;
58  std::vector<size_t> dims_;
59  std::vector<size_t> dims_verify_;
60  std::vector<bool> dims_unknown_;
61  size_t dim_idx_;
62  size_t dim_last_;
63  bool is_int_;
64 
65  void reset() {
66  key_.clear();
67  values_r_.clear();
68  values_i_.clear();
69  dims_.clear();
70  dims_verify_.clear();
71  dims_unknown_.clear();
72  dim_idx_ = 0;
73  dim_last_ = 0;
74  is_int_ = true;
75  }
76 
77  bool is_init() {
78  return (key_.size() == 0
79  && values_r_.size() == 0
80  && values_i_.size() == 0
81  && dims_.size() == 0
82  && dims_verify_.size() == 0
83  && dims_unknown_.size() == 0
84  && dim_idx_ == 0
85  && dim_last_ == 0
86  && is_int_);
87  }
88 
89 
90  public:
91  /**
92  * Construct a json_data_handler object.
93  *
94  * <b>Warning:</b> This method does not close the input stream.
95  *
96  * @param vars_r name-value map for real-valued variables
97  * @param vars_i name-value map for int-valued variables
98  */
100  : json_handler(), vars_r_(vars_r), vars_i_(vars_i),
101  key_(), values_r_(), values_i_(),
102  dims_(), dims_verify_(), dims_unknown_(),
103  dim_idx_(0), dim_last_(0), is_int_(true) {
104  }
105 
106  void start_text() {
107  vars_i_.clear();
108  vars_r_.clear();
109  reset();
110  }
111 
112  void end_text() {
113  reset();
114  }
115 
116  void start_array() {
117  if (0 == key_.size()) {
118  throw json_error("expecting JSON object, found array");
119  }
120  if (dim_idx_ > 0 && dim_last_ == dim_idx_) {
121  std::stringstream errorMsg;
122  errorMsg << "variable: " << key_
123  << ", error: non-scalar array value";
124  throw json_error(errorMsg.str());
125  }
126  incr_dim_size();
127  dim_idx_++;
128  if (dims_.size() < dim_idx_) {
129  dims_.push_back(0);
130  dims_unknown_.push_back(true);
131  dims_verify_.push_back(0);
132  } else {
133  dims_verify_[dim_idx_-1] = 0;
134  }
135  }
136 
137  void end_array() {
138  if (dims_[dim_idx_-1] == 0) {
139  std::stringstream errorMsg;
140  errorMsg << "variable: " << key_
141  << ", error: empty array not allowed";
142  throw json_error(errorMsg.str());
143  }
144  if (dims_unknown_[dim_idx_-1] == true) {
145  dims_unknown_[dim_idx_-1] = false;
146  } else if (dims_verify_[dim_idx_-1] != dims_[dim_idx_-1]) {
147  std::stringstream errorMsg;
148  errorMsg << "variable: " << key_ << ", error: non-rectangular array";
149  throw json_error(errorMsg.str());
150  }
151  if (0 == dim_last_
152  && ((is_int_ && values_i_.size() > 0) || (values_r_.size() > 0)))
153  dim_last_ = dim_idx_;
154  dim_idx_--;
155  }
156 
157  void start_object() {
158  if (!is_init()) {
159  std::stringstream errorMsg;
160  errorMsg << "variable: " << key_
161  << ", error: nested objects not allowed";
162  throw json_error(errorMsg.str());
163  }
164  }
165 
166  void end_object() {
168  reset();
169  }
170 
171  void null() {
172  std::stringstream errorMsg;
173  errorMsg << "variable: " << key_ << ", error: null values not allowed";
174  throw json_error(errorMsg.str());
175  }
176 
177  void boolean(bool p) {
178  std::stringstream errorMsg;
179  errorMsg << "variable: " << key_
180  << ", error: boolean values not allowed";
181  throw json_error(errorMsg.str());
182  }
183 
184  void string(const std::string& s) {
185  double tmp;
186  if (0 == s.compare("-inf")) {
187  tmp = -std::numeric_limits<double>::infinity();
188  } else if (0 == s.compare("inf")) {
189  tmp = std::numeric_limits<double>::infinity();
190  } else {
191  std::stringstream errorMsg;
192  errorMsg << "variable: " << key_
193  << ", error: string values not allowed";
194  throw json_error(errorMsg.str());
195  }
196  if (is_int_) {
197  for (std::vector<int>::iterator it = values_i_.begin();
198  it != values_i_.end(); ++it)
199  values_r_.push_back(*it);
200  }
201  is_int_ = false;
202  values_r_.push_back(tmp);
203  incr_dim_size();
204  }
205 
206  void key(const std::string& key) {
208  reset();
209  key_ = key;
210  }
211 
212  void number_double(double x) {
213  set_last_dim();
214  if (is_int_) {
215  for (std::vector<int>::iterator it = values_i_.begin();
216  it != values_i_.end(); ++it)
217  values_r_.push_back(*it);
218  }
219  is_int_ = false;
220  values_r_.push_back(x);
221  incr_dim_size();
222  }
223 
224  // NOLINTNEXTLINE(runtime/int)
225  void number_long(long n) {
226  set_last_dim();
227  if (is_int_) {
228  values_i_.push_back(n);
229  } else {
230  values_r_.push_back(n);
231  }
232  incr_dim_size();
233  }
234 
235  // NOLINTNEXTLINE(runtime/int)
236  void number_unsigned_long(unsigned long n) {
237  set_last_dim();
238  if (is_int_) {
239  values_i_.push_back(n);
240  } else {
241  values_r_.push_back(n);
242  }
243  incr_dim_size();
244  }
245 
247  if (0 == key_.size()) return;
248 
249  // redefinition or variables not allowed
250  if (vars_r_.find(key_) != vars_r_.end()
251  || vars_i_.find(key_) != vars_i_.end()) {
252  std::stringstream errorMsg;
253  errorMsg << "attempt to redefine variable: " << key_;
254  throw json_error(errorMsg.str());
255  }
256 
257  // transpose order of array values to column-major
258  if (is_int_) {
259  std::pair<std::vector<int>,
260  std::vector<size_t> > pair;
261  if (dims_.size() > 1) {
262  std::vector<int> cm_values_i(values_i_.size());
263  to_column_major(cm_values_i, values_i_, dims_);
264  pair = make_pair(cm_values_i, dims_);
265 
266  } else {
267  pair = make_pair(values_i_, dims_);
268  }
269  vars_i_[key_] = pair;
270  } else {
271  std::pair<std::vector<double>,
272  std::vector<size_t> > pair;
273  if (dims_.size() > 1) {
274  std::vector<double> cm_values_r(values_r_.size());
275  to_column_major(cm_values_r, values_r_, dims_);
276  pair = make_pair(cm_values_r, dims_);
277  } else {
278  pair = make_pair(values_r_, dims_);
279  }
280  vars_r_[key_] = pair;
281  }
282  }
283 
284  void incr_dim_size() {
285  if (dim_idx_ > 0) {
286  if (dims_unknown_[dim_idx_-1])
287  dims_[dim_idx_-1]++;
288  else
289  dims_verify_[dim_idx_-1]++;
290  }
291  }
292 
293  template <typename T>
294  void to_column_major(std::vector<T>& cm_vals,
295  const std::vector<T>& rm_vals,
296  const std::vector<size_t>& dims) {
297  for (size_t i = 0; i< rm_vals.size(); i++) {
298  size_t idx = convert_offset_rtl_2_ltr(i, dims);
299  cm_vals[idx] = rm_vals[i];
300  }
301  }
302 
303  void set_last_dim() {
304  if (dim_last_ > 0 && dim_idx_ < dim_last_) {
305  std::stringstream errorMsg;
306  errorMsg << "variable: " << key_ << ", error: non-rectangular array";
307  throw json_error(errorMsg.str());
308  }
309  dim_last_ = dim_idx_;
310  }
311 
312  // convert row-major offset to column-major offset
313  size_t convert_offset_rtl_2_ltr(size_t rtl_offset,
314  const std::vector<size_t>& dims) {
315  size_t rtl_dsize = 1;
316  for (size_t i = 1; i < dims.size(); i++)
317  rtl_dsize *= dims[i];
318 
319  // array index should be valid, but check just in case
320  if (rtl_offset >= rtl_dsize*dims[0]) {
321  std::stringstream errorMsg;
322  errorMsg << "variable: " << key_ << ", unexpected error";
323  throw json_error(errorMsg.str());
324  }
325 
326  // calculate offset by working left-to-right to get array indices
327  // for row-major offset left-most dimensions are divided out
328  // for column-major offset successive dimensions are multiplied in
329  size_t rem = rtl_offset;
330  size_t ltr_offset = 0;
331  size_t ltr_dsize = 1;
332  for (size_t i = 0; i < dims.size()-1; i++) {
333  size_t idx = rem / rtl_dsize;
334  ltr_offset += idx * ltr_dsize;
335  rem = rem - idx * rtl_dsize;
336  rtl_dsize = rtl_dsize / dims[i+1];
337  ltr_dsize *= dims[i];
338  }
339  ltr_offset += rem * ltr_dsize; // for loop stops 1 early
340 
341  return ltr_offset;
342  }
343  };
344 
345  }
346 
347 }
348 
349 #endif
set< int >::iterator it
std::vector< double > values_r_
const char * p
Definition: xmltok.h:285
void key(const std::string &key)
Float_t tmp
Definition: plot.C:36
std::pair< Spectrum *, CheatDecomp * > make_pair(SpectrumLoaderBase &loader_data, SpectrumLoaderBase &loader_mc, HistAxis *axis, Cut *cut, const SystShifts &shift, const Var &wei)
Definition: DataMCLoad.C:336
std::map< std::string, std::pair< std::vector< double >, std::vector< size_t > > > vars_map_r
const XML_Char * s
Definition: expat.h:262
std::vector< size_t > dims_verify_
void string(const std::string &s)
void to_column_major(std::vector< T > &cm_vals, const std::vector< T > &rm_vals, const std::vector< size_t > &dims)
size_t convert_offset_rtl_2_ltr(size_t rtl_offset, const std::vector< size_t > &dims)
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
json_data_handler(vars_map_r &vars_r, vars_map_i &vars_i)
std::map< std::string, std::pair< std::vector< int >, std::vector< size_t > > > vars_map_i
void number_unsigned_long(unsigned long n)