Stan  2.10.0
probability, sampling & optimization
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  namespace {
24  typedef
25  std::map<std::string,
26  std::pair<std::vector<double>,
27  std::vector<size_t> > >
28  vars_map_r;
29 
30  typedef
31  std::map<std::string,
32  std::pair<std::vector<int>,
33  std::vector<size_t> > >
34  vars_map_i;
35  }
36 
54  private:
55  vars_map_r& vars_r_;
56  vars_map_i& vars_i_;
57  std::string key_;
58  std::vector<double> values_r_;
59  std::vector<int> values_i_;
60  std::vector<size_t> dims_;
61  std::vector<size_t> dims_verify_;
62  std::vector<bool> dims_unknown_;
63  size_t dim_idx_;
64  size_t dim_last_;
65  bool is_int_;
66 
67  void reset() {
68  key_.clear();
69  values_r_.clear();
70  values_i_.clear();
71  dims_.clear();
72  dims_verify_.clear();
73  dims_unknown_.clear();
74  dim_idx_ = 0;
75  dim_last_ = 0;
76  is_int_ = true;
77  }
78 
79  bool is_init() {
80  return (key_.size() == 0
81  && values_r_.size() == 0
82  && values_i_.size() == 0
83  && dims_.size() == 0
84  && dims_verify_.size() == 0
85  && dims_unknown_.size() == 0
86  && dim_idx_ == 0
87  && dim_last_ == 0
88  && is_int_);
89  }
90 
91 
92  public:
101  json_data_handler(vars_map_r& vars_r, vars_map_i& vars_i) :
102  json_handler(), vars_r_(vars_r), vars_i_(vars_i),
103  key_(), values_r_(), values_i_(),
104  dims_(), dims_verify_(), dims_unknown_(),
105  dim_idx_(), dim_last_(), is_int_() {
106  }
107 
108  void start_text() {
109  vars_i_.clear();
110  vars_r_.clear();
111  reset();
112  }
113 
114  void end_text() {
115  reset();
116  }
117 
118  void start_array() {
119  if (0 == key_.size()) {
120  throw json_error("expecting JSON object, found array");
121  }
122  if (dim_idx_ > 0 && dim_last_ == dim_idx_) {
123  std::stringstream errorMsg;
124  errorMsg << "variable: " << key_
125  << ", error: non-scalar array value";
126  throw json_error(errorMsg.str());
127  }
128  incr_dim_size();
129  dim_idx_++;
130  if (dims_.size() < dim_idx_) {
131  dims_.push_back(0);
132  dims_unknown_.push_back(true);
133  dims_verify_.push_back(0);
134  } else {
135  dims_verify_[dim_idx_-1] = 0;
136  }
137  }
138 
139  void end_array() {
140  if (dims_[dim_idx_-1] == 0) {
141  std::stringstream errorMsg;
142  errorMsg << "variable: " << key_
143  << ", error: empty array not allowed";
144  throw json_error(errorMsg.str());
145  }
146  if (dims_unknown_[dim_idx_-1] == true) {
147  dims_unknown_[dim_idx_-1] = false;
148  } else if (dims_verify_[dim_idx_-1] != dims_[dim_idx_-1]) {
149  std::stringstream errorMsg;
150  errorMsg << "variable: " << key_ << ", error: non-rectangular array";
151  throw json_error(errorMsg.str());
152  }
153  if (0 == dim_last_
154  && ((is_int_ && values_i_.size() > 0) || (values_r_.size() > 0)))
155  dim_last_ = dim_idx_;
156  dim_idx_--;
157  }
158 
159  void start_object() {
160  if (!is_init()) {
161  std::stringstream errorMsg;
162  errorMsg << "variable: " << key_
163  << ", error: nested objects not allowed";
164  throw json_error(errorMsg.str());
165  }
166  }
167 
168  void end_object() {
170  reset();
171  }
172 
173  void null() {
174  std::stringstream errorMsg;
175  errorMsg << "variable: " << key_ << ", error: null values not allowed";
176  throw json_error(errorMsg.str());
177  }
178 
179  void boolean(bool p) {
180  std::stringstream errorMsg;
181  errorMsg << "variable: " << key_
182  << ", error: boolean values not allowed";
183  throw json_error(errorMsg.str());
184  }
185 
186  void string(const std::string& s) {
187  double tmp;
188  if (0 == s.compare("-inf")) {
189  tmp = -std::numeric_limits<double>::infinity();
190  } else if (0 == s.compare("inf")) {
191  tmp = std::numeric_limits<double>::infinity();
192  } else {
193  std::stringstream errorMsg;
194  errorMsg << "variable: " << key_
195  << ", error: string values not allowed";
196  throw json_error(errorMsg.str());
197  }
198  if (is_int_) {
199  for (std::vector<int>::iterator it = values_i_.begin();
200  it != values_i_.end(); ++it)
201  values_r_.push_back(*it);
202  }
203  is_int_ = false;
204  values_r_.push_back(tmp);
205  incr_dim_size();
206  }
207 
208  void key(const std::string& key) {
210  reset();
211  key_ = key;
212  }
213 
214  void number_double(double x) {
215  set_last_dim();
216  if (is_int_) {
217  for (std::vector<int>::iterator it = values_i_.begin();
218  it != values_i_.end(); ++it)
219  values_r_.push_back(*it);
220  }
221  is_int_ = false;
222  values_r_.push_back(x);
223  incr_dim_size();
224  }
225 
226  // NOLINTNEXTLINE(runtime/int)
227  void number_long(long n) {
228  set_last_dim();
229  if (is_int_) {
230  values_i_.push_back(n);
231  } else {
232  values_r_.push_back(n);
233  }
234  incr_dim_size();
235  }
236 
237  // NOLINTNEXTLINE(runtime/int)
238  void number_unsigned_long(unsigned long n) {
239  set_last_dim();
240  if (is_int_) {
241  values_i_.push_back(n);
242  } else {
243  values_r_.push_back(n);
244  }
245  incr_dim_size();
246  }
247 
249  if (0 == key_.size()) return;
250 
251  // redefinition or variables not allowed
252  if (vars_r_.find(key_) != vars_r_.end()
253  || vars_i_.find(key_) != vars_i_.end()) {
254  std::stringstream errorMsg;
255  errorMsg << "attempt to redefine variable: " << key_;
256  throw json_error(errorMsg.str());
257  }
258 
259  // transpose order of array values to column-major
260  if (is_int_) {
261  std::pair<std::vector<int>,
262  std::vector<size_t> > pair;
263  if (dims_.size() > 1) {
264  std::vector<int> cm_values_i(values_i_.size());
265  to_column_major(cm_values_i, values_i_, dims_);
266  pair = make_pair(cm_values_i, dims_);
267 
268  } else {
269  pair = make_pair(values_i_, dims_);
270  }
271  vars_i_[key_] = pair;
272  } else {
273  std::pair<std::vector<double>,
274  std::vector<size_t> > pair;
275  if (dims_.size() > 1) {
276  std::vector<double> cm_values_r(values_r_.size());
277  to_column_major(cm_values_r, values_r_, dims_);
278  pair = make_pair(cm_values_r, dims_);
279  } else {
280  pair = make_pair(values_r_, dims_);
281  }
282  vars_r_[key_] = pair;
283  }
284  }
285 
286  void incr_dim_size() {
287  if (dim_idx_ > 0) {
288  if (dims_unknown_[dim_idx_-1])
289  dims_[dim_idx_-1]++;
290  else
291  dims_verify_[dim_idx_-1]++;
292  }
293  }
294 
295  template <typename T>
296  void to_column_major(std::vector<T>& cm_vals,
297  const std::vector<T>& rm_vals,
298  const std::vector<size_t>& dims) {
299  for (size_t i = 0; i< rm_vals.size(); i++) {
300  size_t idx = convert_offset_rtl_2_ltr(i, dims);
301  cm_vals[idx] = rm_vals[i];
302  }
303  }
304 
305  void set_last_dim() {
306  if (dim_last_ > 0 && dim_idx_ < dim_last_) {
307  std::stringstream errorMsg;
308  errorMsg << "variable: " << key_ << ", error: non-rectangular array";
309  throw json_error(errorMsg.str());
310  }
311  dim_last_ = dim_idx_;
312  }
313 
314  // convert row-major offset to column-major offset
315  size_t convert_offset_rtl_2_ltr(size_t rtl_offset,
316  const std::vector<size_t>& dims) {
317  size_t rtl_dsize = 1;
318  for (size_t i = 1; i < dims.size(); i++)
319  rtl_dsize *= dims[i];
320 
321  // array index should be valid, but check just in case
322  if (rtl_offset >= rtl_dsize*dims[0]) {
323  std::stringstream errorMsg;
324  errorMsg << "variable: " << key_ << ", unexpected error";
325  throw json_error(errorMsg.str());
326  }
327 
328  // calculate offset by working left-to-right to get array indices
329  // for row-major offset left-most dimensions are divided out
330  // for column-major offset successive dimensions are multiplied in
331  size_t rem = rtl_offset;
332  size_t ltr_offset = 0;
333  size_t ltr_dsize = 1;
334  for (size_t i = 0; i < dims.size()-1; i++) {
335  size_t idx = rem / rtl_dsize;
336  ltr_offset += idx * ltr_dsize;
337  rem = rem - idx * rtl_dsize;
338  rtl_dsize = rtl_dsize / dims[i+1];
339  ltr_dsize *= dims[i];
340  }
341  ltr_offset += rem * ltr_dsize; // for loop stops 1 early
342 
343  return ltr_offset;
344  }
345  };
346 
347  }
348 
349 }
350 
351 #endif
void end_object()
Handle the end of an object.
void start_object()
Handle the start of an object.
Probability, optimization and sampling library.
Abstract base class for JSON handlers.
void key(const std::string &key)
Handle the specified object key.
A json_data_handler is an implementation of a json_handler that restricts the allowed JSON text a set...
void start_text()
Handle the the start of the text.
void null()
Handle the null literal value.
void string(const std::string &s)
Handle the specified string value.
void boolean(bool p)
Handle the boolean literal value of the specified polarity.
void end_text()
Handle the the end of the text.
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)
void end_array()
Handle the end of an array.
Exception type for JSON errors.
Definition: json_error.hpp:14
void number_double(double x)
Handle a the specified double-precision floating point value.
json_data_handler(vars_map_r &vars_r, vars_map_i &vars_i)
Construct a json_data_handler object.
void start_array()
Handle the start of an array.
void number_long(long n)
Handle a the specified long integer value.
void number_unsigned_long(unsigned long n)
Handle a the specified unsigned long integer value.

     [ Stan Home Page ] © 2011–2016, Stan Development Team.