Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 <cctype>
5 #include <iostream>
6 #include <limits>
7 #include <map>
8 #include <sstream>
9 #include <string>
10 #include <vector>
11 #include <boost/throw_exception.hpp>
12 #include <boost/lexical_cast.hpp>
13 #include <stan/math/matrix.hpp>
14 #include <stan/io/var_context.hpp>
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  }
37 
55  private:
56  vars_map_r& vars_r_;
57  vars_map_i& vars_i_;
58  std::string key_;
59  std::vector<double> values_r_;
60  std::vector<int> values_i_;
61  std::vector<size_t> dims_;
62  std::vector<size_t> dims_verify_;
63  std::vector<bool> dims_unknown_;
64  size_t dim_idx_;
65  size_t dim_last_;
66  bool is_int_;
67 
68  void reset() {
69  key_.clear();
70  values_r_.clear();
71  values_i_.clear();
72  dims_.clear();
73  dims_verify_.clear();
74  dims_unknown_.clear();
75  dim_idx_ = 0;
76  dim_last_ = 0;
77  is_int_ = true;
78  }
79 
80  bool is_init() {
81  return (key_.size() == 0
82  && values_r_.size() == 0
83  && values_i_.size() == 0
84  && dims_.size() == 0
85  && dims_verify_.size() == 0
86  && dims_unknown_.size() == 0
87  && dim_idx_ == 0
88  && dim_last_ == 0
89  && is_int_);
90  }
91 
92 
93  public:
102  json_data_handler(vars_map_r& vars_r, vars_map_i& vars_i) :
103  json_handler(), vars_r_(vars_r), vars_i_(vars_i),
104  key_(), values_r_(), values_i_(),
105  dims_(), dims_verify_(), dims_unknown_(),
106  dim_idx_(), dim_last_(), is_int_() {
107  }
108 
109  void start_text() {
110  vars_i_.clear();
111  vars_r_.clear();
112  reset();
113  }
114 
115  void end_text() {
116  reset();
117  }
118 
119  void start_array() {
120  if (0 == key_.size()) {
121  throw json_error("expecting JSON object, found array");
122  }
123  if (dim_idx_ > 0 && dim_last_ == dim_idx_) {
124  std::stringstream errorMsg;
125  errorMsg << "variable: " << key_ << ", 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_ << ", error: empty array not allowed";
143  throw json_error(errorMsg.str());
144  }
145  if (dims_unknown_[dim_idx_-1] == true) {
146  dims_unknown_[dim_idx_-1] = false;
147  } else if (dims_verify_[dim_idx_-1] != dims_[dim_idx_-1]) {
148  std::stringstream errorMsg;
149  errorMsg << "variable: " << key_ << ", error: non-rectangular array";
150  throw json_error(errorMsg.str());
151  }
152  if (0 == dim_last_
153  && ((is_int_ && values_i_.size() > 0) || (values_r_.size() > 0)))
154  dim_last_ = dim_idx_;
155  dim_idx_--;
156  }
157 
158  void start_object() {
159  if (!is_init()) {
160  std::stringstream errorMsg;
161  errorMsg << "variable: " << key_ << ", 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_ << ", error: boolean values not allowed";
180  throw json_error(errorMsg.str());
181  }
182 
183  void string(const std::string& s) {
184  double tmp;
185  if (0 == s.compare("-inf")) {
186  tmp = -std::numeric_limits<double>::infinity();
187  } else if (0 == s.compare("inf")) {
188  tmp = std::numeric_limits<double>::infinity();
189  } else {
190  std::stringstream errorMsg;
191  errorMsg << "variable: " << key_ << ", error: string values not allowed";
192  throw json_error(errorMsg.str());
193  }
194  if (is_int_) {
195  for (std::vector<int>::iterator it = values_i_.begin(); it != values_i_.end(); ++it)
196  values_r_.push_back(*it);
197  }
198  is_int_ = false;
199  values_r_.push_back(tmp);
200  incr_dim_size();
201  }
202 
203  void key(const std::string& key) {
205  reset();
206  key_ = key;
207  }
208 
209  void number_double(double x) {
210  set_last_dim();
211  if (is_int_) {
212  for (std::vector<int>::iterator it = values_i_.begin();
213  it != values_i_.end(); ++it)
214  values_r_.push_back(*it);
215  }
216  is_int_ = false;
217  values_r_.push_back(x);
218  incr_dim_size();
219  }
220 
221  void number_long(long n) {
222  set_last_dim();
223  if (is_int_) {
224  values_i_.push_back(n);
225  } else {
226  values_r_.push_back(n);
227  }
228  incr_dim_size();
229  }
230 
231  void number_unsigned_long(unsigned long n) {
232  set_last_dim();
233  if (is_int_) {
234  values_i_.push_back(n);
235  } else {
236  values_r_.push_back(n);
237  }
238  incr_dim_size();
239  }
240 
242  if (0 == key_.size()) return;
243 
244  // redefinition or variables not allowed
245  if (vars_r_.find(key_) != vars_r_.end()
246  || vars_i_.find(key_) != vars_i_.end()) {
247  std::stringstream errorMsg;
248  errorMsg << "attempt to redefine variable: " << key_;
249  throw json_error(errorMsg.str());
250  }
251 
252  // transpose order of array values to column-major
253  if (is_int_) {
254  std::pair<std::vector<int>,
255  std::vector<size_t> > pair;
256  if (dims_.size() > 1) {
257  std::vector<int> cm_values_i(values_i_.size());
258  to_column_major(cm_values_i,values_i_,dims_);
259  pair = make_pair(cm_values_i, dims_);
260 
261  } else {
262  pair = make_pair(values_i_, dims_);
263  }
264  vars_i_[key_] = pair;
265  } else {
266  std::pair<std::vector<double>,
267  std::vector<size_t> > pair;
268  if (dims_.size() > 1) {
269  std::vector<double> cm_values_r(values_r_.size());
270  to_column_major(cm_values_r,values_r_,dims_);
271  pair = make_pair(cm_values_r, dims_);
272  } else {
273  pair = make_pair(values_r_, dims_);
274  }
275  vars_r_[key_] = pair;
276  }
277  }
278 
279  void incr_dim_size() {
280  if (dim_idx_ > 0) {
281  if (dims_unknown_[dim_idx_-1])
282  dims_[dim_idx_-1]++;
283  else
284  dims_verify_[dim_idx_-1]++;
285  }
286  }
287 
288  template <typename T>
289  void to_column_major(std::vector<T>& cm_vals, const std::vector<T>& rm_vals, const std::vector<size_t>& dims) {
290  for (size_t i = 0; i< rm_vals.size(); i++) {
291  size_t idx = convert_offset_rtl_2_ltr(i,dims);
292  cm_vals[idx] = rm_vals[i];
293  }
294  }
295 
296  void set_last_dim() {
297  if (dim_last_ > 0 && dim_idx_ < dim_last_) {
298  std::stringstream errorMsg;
299  errorMsg << "variable: " << key_ << ", error: non-rectangular array";
300  throw json_error(errorMsg.str());
301  }
302  dim_last_ = dim_idx_;
303  }
304 
305  // convert row-major offset to column-major offset
306  size_t convert_offset_rtl_2_ltr(size_t rtl_offset, const std::vector<size_t>& dims) {
307  size_t rtl_dsize = 1;
308  for (size_t i = 1; i < dims.size(); i++)
309  rtl_dsize *= dims[i];
310 
311  // array index should be valid, but check just in case
312  if (rtl_offset >= rtl_dsize*dims[0]) {
313  std::stringstream errorMsg;
314  errorMsg << "variable: " << key_ << ", unexpected error";
315  throw json_error(errorMsg.str());
316  }
317 
318  // calculate offset by working left-to-right to get array indices
319  // for row-major offset left-most dimensions are divided out
320  // for column-major offset successive dimensions are multiplied in
321  size_t rem = rtl_offset;
322  size_t ltr_offset = 0;
323  size_t ltr_dsize = 1;
324  for (size_t i = 0; i < dims.size()-1; i++) {
325  size_t idx = rem / rtl_dsize;
326  ltr_offset += idx * ltr_dsize;
327  rem = rem - idx * rtl_dsize;
328  rtl_dsize = rtl_dsize / dims[i+1];
329  ltr_dsize *= dims[i];
330  }
331  ltr_offset += rem * ltr_dsize; // for loop stops 1 early
332 
333  return ltr_offset;
334  }
335  };
336 
337  }
338 
339 }
340 
341 #endif
void end_object()
Handle the end of an object.
void start_object()
Handle the start of an object.
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 dims(const T &x, std::vector< int > &result)
Definition: dims.hpp:13
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–2014, Stan Development Team.