00001 #include <assert.h>
00002 #include <string.h>
00003 #include "../csm/csm_all.h"
00004 #include <options/options.h>
00005
00006 #include <json-c/json.h>
00007 #include <json-c/json_object_private.h>
00008
00009 void jo_write_as_matlab(JO jo, FILE*out);
00010
00011 void jo_write_as_matrix(JO jo, FILE*out);
00012 void jo_write_as_column_vector(JO jo, FILE* out);
00013
00014 void jo_write_as_cell_array(JO jo, FILE* out);
00015 int jo_is_numeric_matrix(JO jo);
00016 int jo_is_numeric_array(JO jo);
00017 void jo_write_as_matlab_object(JO jo, FILE*out);
00018
00019
00020 const char * banner =
00021 "Converts JSON stream to Matlab file. \n"
00022 "There are three usages: \n"
00023 " 1) with only one parameter, \n"
00024 " $ json2matlab dir/mydata.json \n"
00025 " creates a Matlab function 'mydata' inside the file 'dir/mydata.m' \n"
00026 " 2) with two parameters, \n"
00027 " $ json2matlab dir/mydata.json dir/out.m \n"
00028 " creates a Matlab function 'out' inside the file 'dir/out.m'. \n"
00029 " 3) otherwise, use the options switches. \n"
00030 " \n"
00031 " By default it creates a complete script of the kind:\n"
00032 " \n"
00033 " function res = function_name()\n"
00034 " res = \n"
00035 " { ...}\n"
00036 " \n"
00037 " If complete_script is set to 0, it just outputs the meat: \n"
00038 " \n"
00039 " { ...}\n"
00040 " \n";
00041
00042
00043 int main(int argc, const char * argv[]) {
00044 sm_set_program_name(argv[0]);
00045
00046 const char * input_filename;
00047 const char * out_filename;
00048 const char * function;
00049 int complete_script;
00050 int debug;
00051
00052 options_banner(banner);
00053
00054 struct option* ops = options_allocate(8);
00055 options_string(ops, "in", &input_filename, "stdin", "input file (JSON)");
00056 options_string(ops, "out", &out_filename, "stdout", "output file (MATLAB)");
00057 options_string(ops, "function", &function, "", "Matlab function name (if empty, use basename of out)");
00058 options_int(ops, "complete_script", &complete_script, 1, "Write complete script 'function res = ...'");
00059 options_int(ops, "debug", &debug, 1, "Shows debug information");
00060
00061 if(argc == 2 && (argv[1][0] != '-')) {
00062
00063 input_filename = argv[1]; int len = strlen(input_filename) + 4;
00064 char base[len], no_suffix[len], out[len];
00065 my_no_suffix(input_filename, no_suffix);
00066 sprintf(out, "%s.m", no_suffix);
00067 my_basename_no_suffix(input_filename, base);
00068 out_filename = my_strdup(out);
00069 function = my_strdup(base);
00070 } else if(argc == 3 && (argv[1][0] != '-') && (argv[2][0] != '-')) {
00071 input_filename = argv[1];
00072 out_filename = argv[2];
00073 } else {
00074
00075 if(!options_parse_args(ops, argc, argv))
00076 return -1;
00077 }
00078
00079 sm_debug_write(debug);
00080
00081 if(!strcmp(function,"")) {
00082 int len = strlen(out_filename) + 4;
00083 char base[len];
00084 my_basename_no_suffix(out_filename, base);
00085 function = my_strdup(base);
00086 }
00087
00088
00089 FILE * out = open_file_for_writing(out_filename);
00090 if(!out) return -2;
00091
00092 FILE * in = open_file_for_reading(input_filename);
00093 if(!in) return -3;
00094
00095 if(complete_script) {
00096 fprintf(out, "function res = %s\n", function);
00097 fprintf(out, " res = ... \n");
00098 }
00099 fprintf(out, " { ... \n\t");
00100
00101 JO jo;
00102 int i = 0;
00103 while((jo = json_read_stream(in))) {
00104 if(i>0) fprintf(out, ", ...\n\t");
00105 jo_write_as_matlab(jo, out);
00106 jo_free(jo);
00107 i++;
00108 }
00109
00110 fprintf(out, "... \n }; \n");
00111 return 0;
00112 }
00113
00114
00115 void jo_write_as_matlab(JO jo, FILE*out) {
00116 if(!jo) { fprintf(out, "NaN"); return; }
00117
00118 switch(json_object_get_type(jo)) {
00119 case json_type_null:
00120 fprintf(out, "NaN");
00121 return;
00122
00123 case json_type_boolean:
00124 fprintf(out, json_object_get_boolean(jo) ? "true" : "false" );
00125 return;
00126
00127 case json_type_int:
00128 fprintf(out, "%d", json_object_get_int(jo));
00129 return;
00130
00131 case json_type_double:
00132 fprintf(out, "%lg", json_object_get_double(jo));
00133 return;
00134
00135 case json_type_object:
00136 jo_write_as_matlab_object(jo, out);
00137 return;
00138
00139 case json_type_array:
00140 if(jo_is_numeric_matrix(jo))
00141 jo_write_as_matrix(jo, out);
00142 else
00143 if(jo_is_numeric_array(jo))
00144 jo_write_as_column_vector(jo, out);
00145 else
00146 jo_write_as_cell_array(jo, out);
00147 return;
00148
00149 case json_type_string:
00150 fprintf(out, "'");
00151 const char* s = json_object_get_string(jo);
00152 while(*s) {
00153 if(*s==39)
00154 fputc('"', out);
00155 else
00156 fputc(*s, out);
00157 s++;
00158 }
00159
00160 fprintf(out, "'");
00161 return;
00162 }
00163
00164
00165 }
00166
00167
00168
00169 void jo_write_as_matlab_object(JO jo, FILE*out) {
00170 int i=0;
00171 struct json_object_iter iter;
00172 fprintf(out, "struct(");
00173
00174 json_object_object_foreachC(jo, iter) {
00175 if(i) fprintf(out, ", ... \n\t ");
00176 fprintf(out, "'%s', ", iter.key);
00177
00178 enum json_type t = json_object_get_type(iter.val);
00179 if( (t == json_type_array) && (!jo_is_numeric_matrix(iter.val)) && (!jo_is_numeric_array(iter.val))) {
00180 fprintf(out, "{");
00181 jo_write_as_matlab(iter.val, out);
00182 fprintf(out, "}");
00183 } else if(t == json_type_object) {
00184 fprintf(out, "{ ");
00185 jo_write_as_matlab(iter.val, out);
00186 fprintf(out, " }");
00187 } else jo_write_as_matlab(iter.val, out);
00188
00189 i++;
00190 }
00191 fprintf(out, ")");
00192 }
00193
00194
00195 int jo_is_numeric_matrix(JO jo) {
00196
00197 if(!jo) return 0;
00198 if(json_object_get_type(jo) != json_type_array) return 0;
00199 int len = json_object_array_length(jo);
00200 int ncolumns = -1;
00201 for(int i=0;i<len;i++){
00202 JO row = json_object_array_get_idx(jo, i);
00203 if(!jo_is_numeric_array(row)) return 0;
00204 if(i==0)
00205 ncolumns = json_object_array_length(row);
00206 else
00207 if(ncolumns != json_object_array_length(row))
00208 return 0;
00209 }
00210 if(ncolumns==0) return 0;
00211 return 1;
00212 }
00213
00214 int jo_is_numeric_array(JO jo) {
00215
00216 if(!jo) return 0;
00217 if(json_object_get_type(jo) != json_type_array) return 0;
00218 int len = json_object_array_length(jo);
00219 for(int i=0;i<len;i++){
00220 JO elem = json_object_array_get_idx(jo, i);
00221
00222
00223
00224 if(elem==0)
00225 continue;
00226
00227 switch(json_object_get_type(elem)) {
00228 case json_type_null:
00229 case json_type_boolean:
00230 case json_type_int:
00231 case json_type_double:
00232 continue;
00233 default:
00234 return 0;
00235 }
00236 }
00237 return 1;
00238 }
00239
00240 void jo_write_as_matrix(JO jo, FILE*out) {
00241
00242 assert(json_object_get_type(jo) == json_type_array);
00243 fprintf(out, "[");
00244 int len = json_object_array_length(jo);
00245 for(int i=0;i<len;i++){
00246 if(i>0) fprintf(out, "; ");
00247 JO row = json_object_array_get_idx(jo, i);
00248 int n = json_object_array_length(row);
00249 for(int j=0;j<n;j++) {
00250 if(j>0) fprintf(out, ", ");
00251 jo_write_as_matlab(json_object_array_get_idx(row, j), out);
00252 }
00253 }
00254 fprintf(out, "]");
00255 }
00256
00257 void jo_write_as_column_vector(JO jo, FILE* out) {
00258
00259 assert(json_object_get_type(jo) == json_type_array);
00260 fprintf(out, "[");
00261 int len = json_object_array_length(jo);
00262 for(int i=0;i<len;i++){
00263 if(i>0) fprintf(out, "; ");
00264 JO elem = json_object_array_get_idx(jo, i);
00265 jo_write_as_matlab(elem, out);
00266 }
00267 fprintf(out, "]");
00268 }
00269
00270 void jo_write_as_cell_array(JO jo, FILE* out) {
00271 assert(json_object_get_type(jo) == json_type_array);
00272 int len = json_object_array_length(jo);
00273 if(len==0) {
00274 fprintf(out, "{}");
00275 return;
00276 } else {
00277 fprintf(out, "{ ");
00278 for(int i=0;i<len;i++){
00279 if(i>0) fprintf(out, ", ");
00280 JO elem = json_object_array_get_idx(jo, i);
00281 jo_write_as_matlab(elem, out);
00282 }
00283 fprintf(out, "}");
00284 }
00285
00286 }