26 #if defined (HAVE_CONFIG_H)
37 #if defined (HAVE_RAPIDJSON)
38 # include <rapidjson/document.h>
39 # include <rapidjson/error/en.h>
44 #if defined (HAVE_RAPIDJSON)
47 decode (
const rapidjson::Value& val,
48 const octave::make_valid_name_options *options);
65 decode_number (
const rapidjson::Value& val)
69 else if (val.IsInt ())
71 else if (val.IsUint64 ())
73 else if (val.IsInt64 ())
75 else if (val.IsDouble ())
78 error (
"jsondecode: unidentified type");
97 decode_object (
const rapidjson::Value& val,
98 const octave::make_valid_name_options *options)
102 for (
const auto& pair : val.GetObject ())
106 std::string varname = pair.name.GetString ();
107 if (options !=
nullptr)
109 retval.
assign (varname, decode (pair.value, options));
131 decode_numeric_array (
const rapidjson::Value& val)
135 for (
const auto&
elem : val.GetArray ())
137 : decode_number (
elem).double_value ();
156 decode_boolean_array (
const rapidjson::Value& val)
160 for (
const auto&
elem : val.GetArray ())
161 retval(index++) =
elem.GetBool ();
190 decode_string_and_mixed_array (
const rapidjson::Value& val,
191 const octave::make_valid_name_options *options)
195 for (
const auto&
elem : val.GetArray ())
196 retval(index++) = decode (
elem, options);
226 decode_object_array (
const rapidjson::Value& val,
227 const octave::make_valid_name_options *options)
229 Cell struct_cell = decode_string_and_mixed_array (val, options).cell_value ();
230 string_vector field_names = struct_cell(0).scalar_map_value ().fieldnames ();
232 bool same_field_names =
true;
235 != struct_cell(i).scalar_map_value ().fieldnames ().std_list ())
237 same_field_names =
false;
241 if (same_field_names)
246 if (field_names.
numel ())
248 Cell value (struct_array_dims);
252 value(k) = struct_cell(k).scalar_map_value ()
253 .getfield (field_names(i));
254 struct_array.
assign (field_names(i), value);
258 struct_array.
resize (struct_array_dims,
true);
292 decode_array_of_arrays (
const rapidjson::Value& val,
293 const octave::make_valid_name_options *options)
296 Cell cell = decode_string_and_mixed_array (val, options).cell_value ();
299 bool is_bool = cell(0).is_bool_matrix ();
300 bool is_struct = cell(0).isstruct ();
301 string_vector field_names = is_struct ? cell(0).map_value ().fieldnames ()
310 if (cell(i).iscell ())
313 if (cell(i).dims () != sub_array_dims || sub_array_dims ==
dim_vector ())
317 if (cell(i).is_bool_matrix () != is_bool)
320 if (cell(i).isstruct () != is_struct)
323 if (is_struct && (field_names.
std_list ()
324 != cell(i).map_value ().fieldnames ().std_list ()))
330 array_dims.
resize (sub_array_ndims + 1);
331 array_dims(0) = cell_numel;
332 for (
auto i = 1; i < sub_array_ndims + 1; i++)
333 array_dims(i) = sub_array_dims(i-1);
340 if (field_names.
numel ())
342 Cell value (array_dims);
351 Cell sub_array_value = cell(k).map_value ()
352 .getfield (field_names(j));
354 value(k + i * cell_numel) = sub_array_value(i);
356 struct_array.
assign (field_names(j), value);
360 struct_array.
resize(array_dims,
true);
373 NDArray sub_array_value = cell(k).array_value ();
375 array(k + i * cell_numel) = sub_array_value(i);
402 decode_array (
const rapidjson::Value& val,
403 const octave::make_valid_name_options *options)
410 rapidjson::Type array_type = val[0].GetType ();
412 bool same_type =
true;
413 bool is_numeric =
true;
414 for (
const auto&
elem : val.GetArray ())
416 rapidjson::Type current_elem_type =
elem.GetType ();
417 if (is_numeric && ! (current_elem_type == rapidjson::kNullType
418 || current_elem_type == rapidjson::kNumberType))
420 if (same_type && (current_elem_type != array_type))
422 if (! ((current_elem_type == rapidjson::kTrueType
423 && array_type == rapidjson::kFalseType)
424 || (current_elem_type == rapidjson::kFalseType
425 && array_type == rapidjson::kTrueType)))
430 return decode_numeric_array (val);
432 if (same_type && (array_type != rapidjson::kStringType))
434 if (array_type == rapidjson::kTrueType
435 || array_type == rapidjson::kFalseType)
436 return decode_boolean_array (val);
437 else if (array_type == rapidjson::kObjectType)
438 return decode_object_array (val, options);
439 else if (array_type == rapidjson::kArrayType)
440 return decode_array_of_arrays (val, options);
442 error (
"jsondecode: unidentified type");
445 return decode_string_and_mixed_array (val, options);
465 decode (
const rapidjson::Value& val,
466 const octave::make_valid_name_options *options)
469 return val.GetBool ();
470 else if (val.IsNumber ())
471 return decode_number (val);
472 else if (val.IsString ())
473 return val.GetString ();
474 else if (val.IsObject ())
475 return decode_object (val, options);
476 else if (val.IsNull ())
478 else if (val.IsArray ())
479 return decode_array (val, options);
481 error (
"jsondecode: unidentified type");
486 DEFUN (jsondecode, args, ,
587 #if defined (HAVE_RAPIDJSON)
589 int nargin = args.length ();
596 bool use_makeValidName =
true;
598 for (
auto i = 1; i < nargin; i = i + 2)
600 std::string parameter = args(i).xstring_value (
"jsondecode: "
601 "option argument must be a string");
604 use_makeValidName = args(i + 1).xbool_value (
"jsondecode: "
605 "'makeValidName' value must be a bool");
608 make_valid_name_params.
append (args.slice(i, 2));
615 unwind_action del_opts ([options] (
void) {
if (options)
delete options; });
617 if (! args(0).is_string ())
618 error (
"jsondecode: JSON_TXT must be a character string");
620 std::string json = args(0).string_value ();
621 rapidjson::Document
d;
627 d.Parse <rapidjson::kParseNanAndInfFlag> (json.c_str ());
629 if (
d.HasParseError ())
630 error (
"jsondecode: parse error at offset %u: %s\n",
631 static_cast<unsigned int> (
d.GetErrorOffset ()) + 1,
632 rapidjson::GetParseError_En (
d.GetParseError ()));
634 return decode (
d, options);
638 octave_unused_parameter (args);
OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type numel(void) const
Number of elements in the array.
OCTARRAY_OVERRIDABLE_FUNC_API const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
OCTARRAY_OVERRIDABLE_FUNC_API int ndims(void) const
Size of the specified dimension.
Vector representing the dimensions (size) of an Array.
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
void resize(int n, int fill_value=0)
void chop_trailing_singletons(void)
Helper class for make_valid_name function calls.
void resize(const dim_vector &dv, bool fill=false)
void assign(const std::string &k, const Cell &val)
void assign(const std::string &k, const octave_value &val)
octave_value_list & append(const octave_value &val)
octave_idx_type numel(void) const
std::list< std::string > std_list(void) const
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
OCTINTERP_API void print_usage(void)
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
void error(const char *fmt,...)
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
class OCTAVE_API boolNDArray
OCTAVE_API bool strcmpi(const T &str_a, const T &str_b)
True if strings are the same, ignoring case.
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
bool make_valid_name(std::string &str, const make_valid_name_options &options)
Modify str to be a valid variable name.