diff --git a/TinyG2/gcode_parser.cpp b/TinyG2/gcode_parser.cpp index ad455e25..9796c540 100755 --- a/TinyG2/gcode_parser.cpp +++ b/TinyG2/gcode_parser.cpp @@ -180,7 +180,7 @@ static stat_t _get_next_gcode_word(char **pstr, char *letter, float *value) // get-value general case char *end; - *value = strtod(*pstr, &end); + *value = strtof(*pstr, &end); if(end == *pstr) { return(STAT_BAD_NUMBER_FORMAT); } // more robust test then checking for value=0; *pstr = end; return (STAT_OK); // pointer points to next character after the word diff --git a/TinyG2/json_parser.cpp b/TinyG2/json_parser.cpp index 5bfffc02..58738924 100755 --- a/TinyG2/json_parser.cpp +++ b/TinyG2/json_parser.cpp @@ -1,8 +1,8 @@ /* * json_parser.cpp - JSON parser for TinyG - * Part of TinyG2 project + * This file is part of the TinyG2 project * - * Copyright (c) 2011 - 2013 Alden S. Hart Jr. + * Copyright (c) 2011 - 2013 Alden S. Hart, Jr. * * This file ("the software") is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2 as published by the @@ -81,7 +81,7 @@ static stat_t _normalize_json_string(char_t *str, uint16_t size); * - returns the status and the JSON response string * * Separation of concerns - * js_json_parser() is the only exposed part. It does parsing, display, and status reports. + * json_parser() is the only exposed part. It does parsing, display, and status reports. * _get_nv_pair() only does parsing and syntax; no semantic validation or group handling * _json_parser_kernal() does index validation and group handling and executes sets and gets * in an application agnostic way. It should work for other apps than TinyG @@ -91,15 +91,15 @@ void json_parser(char_t *str) { stat_t status = _json_parser_kernal(str); cmd_print_list(status, TEXT_NO_PRINT, JSON_RESPONSE_FORMAT); - sr_request_status_report(SR_IMMEDIATE_REQUEST);// generate an incremental status report if there are gcode model changes + sr_request_status_report(SR_IMMEDIATE_REQUEST); // generate incremental status report to show any changes } static stat_t _json_parser_kernal(char_t *str) { stat_t status; int8_t depth; - cmdObj_t *cmd = cmd_reset_list(); - char_t group[CMD_GROUP_LEN+1] = {""}; // group identifier - starts as NUL + cmdObj_t *cmd = cmd_reset_list(); // get a fresh cmdObj list + char_t group[CMD_GROUP_LEN+1] = {""}; // group identifier - starts as NUL int8_t i = CMD_BODY_LEN; ritorno(_normalize_json_string(str, JSON_OUTPUT_STRING_MAX)); // return if error @@ -126,13 +126,13 @@ static stat_t _json_parser_kernal(char_t *str) // execute the command cmd = cmd_body; - if (cmd->objtype == TYPE_NULL){ // means GET the value - ritorno(cmd_get(cmd)); // ritorno returns w/status on any errors + if (cmd->objtype == TYPE_NULL){ // means GET the value + ritorno(cmd_get(cmd)); // ritorno returns w/status on any errors } else { - ritorno(cmd_set(cmd)); // set value or call a function (e.g. gcode) + ritorno(cmd_set(cmd)); // set value or call a function (e.g. gcode) cmd_persist(cmd); } - return (STAT_OK); // only successful commands exit through this point + return (STAT_OK); // only successful commands exit through this point } /* @@ -188,19 +188,19 @@ static stat_t _get_nv_pair_strict(cmdObj_t *cmd, char_t **pstr, int8_t *depth) char_t *tmp; char_t terminators[] = {"},"}; - cmd_reset_obj(cmd); // wipes the object and sets the depth + cmd_reset_obj(cmd); // wipes the object and sets the depth // --- Process name part --- // find leading and trailing name quotes and set pointers. if ((*pstr = strchr(*pstr, '\"')) == NULL) { return (STAT_JSON_SYNTAX_ERROR);} if ((tmp = strchr(++(*pstr), '\"')) == NULL) { return (STAT_JSON_SYNTAX_ERROR);} *tmp = NUL; - strncpy(cmd->token, *pstr, CMD_TOKEN_LEN); // copy the string to the token + strncpy(cmd->token, *pstr, CMD_TOKEN_LEN); // copy the string to the token // --- Process value part --- (organized from most to least frequently encountered) *pstr = ++tmp; if ((*pstr = strchr(*pstr, ':')) == NULL) return (STAT_JSON_SYNTAX_ERROR); - (*pstr)++; // advance to start of value field + (*pstr)++; // advance to start of value field // nulls (gets) if ((**pstr == 'n') || ((**pstr == '\"') && (*(*pstr+1) == '\"'))) { // process null value @@ -216,12 +216,12 @@ static stat_t _get_nv_pair_strict(cmdObj_t *cmd, char_t **pstr, int8_t *depth) // object parent } else if (**pstr == '{') { cmd->objtype = TYPE_PARENT; -// *depth += 1; // cmd_reset_obj() sets the next object's level so this is redundant +// *depth += 1; // cmd_reset_obj() sets the next object's level so this is redundant (*pstr)++; - return(STAT_EAGAIN); // signal that there is more to parse + return(STAT_EAGAIN); // signal that there is more to parse // strings - } else if (**pstr == '\"') { // value is a string + } else if (**pstr == '\"') { // value is a string (*pstr)++; cmd->objtype = TYPE_STRING; if ((tmp = strchr(*pstr, '\"')) == NULL) { return (STAT_JSON_SYNTAX_ERROR);} // find the end of the string @@ -240,24 +240,24 @@ static stat_t _get_nv_pair_strict(cmdObj_t *cmd, char_t **pstr, int8_t *depth) // arrays } else if (**pstr == '[') { cmd->objtype = TYPE_ARRAY; - ritorno(cmd_copy_string(cmd, *pstr)); // copy array into string for error displays - return (STAT_INPUT_VALUE_UNSUPPORTED); // return error as the parser doesn't do input arrays yet + ritorno(cmd_copy_string(cmd, *pstr)); // copy array into string for error displays + return (STAT_INPUT_VALUE_UNSUPPORTED); // return error as the parser doesn't do input arrays yet // general error condition - } else { return (STAT_JSON_SYNTAX_ERROR); } // ill-formed JSON + } else { return (STAT_JSON_SYNTAX_ERROR); } // ill-formed JSON // process comma separators and end curlies if ((*pstr = strpbrk(*pstr, terminators)) == NULL) { // advance to terminator or err out return (STAT_JSON_SYNTAX_ERROR); } if (**pstr == '}') { - *depth -= 1; // pop up a nesting level - (*pstr)++; // advance to comma or whatever follows + *depth -= 1; // pop up a nesting level + (*pstr)++; // advance to comma or whatever follows } - if (**pstr == ',') { return (STAT_EAGAIN);} // signal that there is more to parse + if (**pstr == ',') { return (STAT_EAGAIN);} // signal that there is more to parse (*pstr)++; - return (STAT_OK); // signal that parsing is complete + return (STAT_OK); // signal that parsing is complete } /**************************************************************************** @@ -290,9 +290,6 @@ static stat_t _get_nv_pair_strict(cmdObj_t *cmd, char_t **pstr, int8_t *depth) * - If a JSON object is empty represent it as {} * --- OR --- * - If a JSON object is empty omit the object altogether (no curlies) - * - * Note: TYPE_FLOAT_UNITS is used to convert a value back to inches mode for display - * that was previously converted to MM mode for internal operations. */ #define BUFFER_MARGIN 8 // safety margin to avoid buffer overruns during footer checksum generation @@ -307,59 +304,58 @@ uint16_t json_serialize(cmdObj_t *cmd, char_t *out_buf, uint16_t size) *str++ = '{'; // write opening curly - while (true) { - if (cmd->objtype != TYPE_EMPTY) { - if (need_a_comma) { *str++ = ',';} - need_a_comma = true; - str += sprintf((char *)str, "\"%s\":", cmd->token); + while (true) { + if (cmd->objtype != TYPE_EMPTY) { + if (need_a_comma) { *str++ = ',';} + need_a_comma = true; + str += sprintf((char *)str, "\"%s\":", cmd->token); - // check for illegal float values - if (cmd->objtype == TYPE_FLOAT) { - if (isnan((double)cmd->value) || isinf((double)cmd->value)) { cmd->value = 0;} - } + // check for illegal float values + if (cmd->objtype == TYPE_FLOAT) { + if (isnan((double)cmd->value) || isinf((double)cmd->value)) { cmd->value = 0;} + } - // serialize output value - if (cmd->objtype == TYPE_NULL) { str += (char_t)sprintf((char *)str, "\"\"");} // Note that that "" is NOT null. - else if (cmd->objtype == TYPE_INTEGER) { - str += (char_t)sprintf((char *)str, "%1.0f", (double)cmd->value); - } - else if (cmd->objtype == TYPE_STRING) { str += (char_t)sprintf((char *)str, "\"%s\"",(char *)*cmd->stringp);} - else if (cmd->objtype == TYPE_ARRAY) { str += (char_t)sprintf((char *)str, "[%s]", (char *)*cmd->stringp);} - else if (cmd->objtype == TYPE_FLOAT) { - if (cmd->precision == 0) { str += (char_t)sprintf((char *)str, "%0.0f", (double)cmd->value);} - else if (cmd->precision == 1) { str += (char_t)sprintf((char *)str, "%0.1f", (double)cmd->value);} - else if (cmd->precision == 2) { str += (char_t)sprintf((char *)str, "%0.2f", (double)cmd->value);} - else if (cmd->precision == 3) { str += (char_t)sprintf((char *)str, "%0.3f", (double)cmd->value);} - else if (cmd->precision == 4) { str += (char_t)sprintf((char *)str, "%0.4f", (double)cmd->value);} - else { str += (char_t)sprintf((char *)str, "%f", (double)cmd->value);} - } - else if (cmd->objtype == TYPE_BOOL) { - if (fp_FALSE(cmd->value)) { str += sprintf((char *)str, "false");} - else { str += (char_t)sprintf((char *)str, "true"); } - } - if (cmd->objtype == TYPE_PARENT) { - *str++ = '{'; - need_a_comma = false; - } - } - if (str >= str_max) { return (-1);} // signal buffer overrun - if ((cmd = cmd->nx) == NULL) { break;} // end of the list - - while (cmd->depth < prev_depth--) { // iterate the closing curlies - need_a_comma = true; - *str++ = '}'; + // serialize output value + if (cmd->objtype == TYPE_NULL) { str += (char_t)sprintf((char *)str, "\"\"");} // Note that that "" is NOT null. + else if (cmd->objtype == TYPE_INTEGER) { + str += (char_t)sprintf((char *)str, "%1.0f", (double)cmd->value); + } + else if (cmd->objtype == TYPE_STRING) { str += (char_t)sprintf((char *)str, "\"%s\"",(char *)*cmd->stringp);} + else if (cmd->objtype == TYPE_ARRAY) { str += (char_t)sprintf((char *)str, "[%s]", (char *)*cmd->stringp);} + else if (cmd->objtype == TYPE_FLOAT) { + if (cmd->precision == 0) { str += (char_t)sprintf((char *)str, "%0.0f", (double)cmd->value);} + else if (cmd->precision == 1) { str += (char_t)sprintf((char *)str, "%0.1f", (double)cmd->value);} + else if (cmd->precision == 2) { str += (char_t)sprintf((char *)str, "%0.2f", (double)cmd->value);} + else if (cmd->precision == 3) { str += (char_t)sprintf((char *)str, "%0.3f", (double)cmd->value);} + else if (cmd->precision == 4) { str += (char_t)sprintf((char *)str, "%0.4f", (double)cmd->value);} + else { str += (char_t)sprintf((char *)str, "%f", (double)cmd->value);} + } + else if (cmd->objtype == TYPE_BOOL) { + if (fp_FALSE(cmd->value)) { str += sprintf((char *)str, "false");} + else { str += (char_t)sprintf((char *)str, "true"); } + } + if (cmd->objtype == TYPE_PARENT) { + *str++ = '{'; + need_a_comma = false; } - prev_depth = cmd->depth; } + if (str >= str_max) { return (-1);} // signal buffer overrun + if ((cmd = cmd->nx) == NULL) { break;} // end of the list - // closing curlies and NEWLINE - while (prev_depth-- > initial_depth) { *str++ = '}';} + while (cmd->depth < prev_depth--) { // iterate the closing curlies + need_a_comma = true; + *str++ = '}'; + } + prev_depth = cmd->depth; + } + + // closing curlies and NEWLINE + while (prev_depth-- > initial_depth) { *str++ = '}';} str += sprintf((char *)str, "}\n"); // using sprintf for this last one ensures a NUL termination if (str > out_buf + size) { return (-1);} return (str - out_buf); } - /* * json_print_object() - serialize and print the cmdObj array directly (w/o header & footer) * @@ -387,7 +383,7 @@ void json_print_list(stat_t status, uint8_t flags) } /* - * json_print_response() - JSON responses with headers, footers and observes JSON verbosity + * json_print_response() - JSON responses with headers, footers and observing JSON verbosity * * A footer is returned for every setting except $jv=0 * @@ -416,7 +412,7 @@ void json_print_response(uint8_t status) cmd_reset_list(); cmd_add_string((const char_t *)"err", escape_string(cs.in_buf, cs.saved_buf)); - } else if (cm.machine_state != MACHINE_INITIALIZING) { // always do full echo during startup + } else if (cm.machine_state != MACHINE_INITIALIZING) { // always do full echo during startup uint8_t cmd_type; do { if ((cmd_type = cmd_get_type(cmd)) == CMD_TYPE_NULL) break; @@ -426,17 +422,17 @@ void json_print_response(uint8_t status) cmd->objtype = TYPE_EMPTY; } - //+++++ } else if (cmd_type == CMD_TYPE_CONFIG) { // kill config echo if not enabled - //fix me if (js.echo_json_configs == false) { - // cmd->objtype = TYPE_EMPTY; - // } +//+++++ } else if (cmd_type == CMD_TYPE_CONFIG) { // kill config echo if not enabled +//fix me if (js.echo_json_configs == false) { +// cmd->objtype = TYPE_EMPTY; +// } - } else if (cmd_type == CMD_TYPE_MESSAGE) { // kill message echo if not enabled + } else if (cmd_type == CMD_TYPE_MESSAGE) { // kill message echo if not enabled if (js.echo_json_messages == false) { cmd->objtype = TYPE_EMPTY; } - } else if (cmd_type == CMD_TYPE_LINENUM) { // kill line number echo if not enabled + } else if (cmd_type == CMD_TYPE_LINENUM) { // kill line number echo if not enabled if ((js.echo_json_linenum == false) || (fp_ZERO(cmd->value))) { // do not report line# 0 cmd->objtype = TYPE_EMPTY; } @@ -456,7 +452,7 @@ void json_print_response(uint8_t status) cs.linelen = 0; // reset linelen so it's only reported once cmd_copy_string(cmd, footer_string); // link string to cmd object - // cmd->depth = 0; // footer 'f' is a peer to response 'r' (hard wired to 0) +// cmd->depth = 0; // footer 'f' is a peer to response 'r' (hard wired to 0) cmd->depth = js.json_footer_depth; // 0=footer is peer to response 'r', 1=child of response 'r' cmd->objtype = TYPE_ARRAY; strcpy(cmd->token, "f"); // terminate the list @@ -528,8 +524,7 @@ void js_print_ej(cmdObj_t *cmd) { text_print_ui8(cmd, fmt_ej);} void js_print_jv(cmdObj_t *cmd) { text_print_ui8(cmd, fmt_jv);} void js_print_fs(cmdObj_t *cmd) { text_print_ui8(cmd, fmt_fs);} -#endif // __TEXT_MODE - +#endif // __TEXT_MODE /**************************************************************************** @@ -538,16 +533,16 @@ void js_print_fs(cmdObj_t *cmd) { text_print_ui8(cmd, fmt_fs);} #if defined (__UNIT_TESTS) && defined (__UNIT_TEST_JSON) -void _test_parser(void); -void _test_serialize(void); -cmdObj_t * _reset_array(void); -cmdObj_t * _add_parent(cmdObj_t *cmd, char_t *token); -cmdObj_t * _add_string(cmdObj_t *cmd, char_t *token, char_t *string); -cmdObj_t * _add_integer(cmdObj_t *cmd, char_t *token, uint32_t integer); -cmdObj_t * _add_empty(cmdObj_t *cmd); -cmdObj_t * _add_array(cmdObj_t *cmd, char_t *footer); -char_t * _clr(char_t *buf); -void _printit(void); +static void _test_parser(void); +static void _test_serialize(void); +static cmdObj_t * _reset_array(void); +static cmdObj_t * _add_parent(cmdObj_t *cmd, char_t *token); +static cmdObj_t * _add_string(cmdObj_t *cmd, char_t *token, char_t *string); +static cmdObj_t * _add_integer(cmdObj_t *cmd, char_t *token, uint32_t integer); +static cmdObj_t * _add_empty(cmdObj_t *cmd); +static cmdObj_t * _add_array(cmdObj_t *cmd, char_t *footer); +static char_t * _clr(char_t *buf); +static void _printit(void); #define ARRAY_LEN 8 cmdObj_t cmd_array[ARRAY_LEN]; @@ -558,75 +553,75 @@ void js_unit_tests() _test_serialize(); } -void _test_serialize() -{ - cmdObj_t *cmd = cmd_array; -// printf("\n\nJSON serialization tests\n"); - - // null list - _reset_array(); - js_serialize_json(cmd_array, kc.out_buf); - _printit(); - - // parent with a null child - cmd = _reset_array(); - cmd = _add_parent(cmd, "r"); - js_serialize_json(cmd_array, kc.out_buf); - _printit(); - - // single string element (message) - cmd = _reset_array(); - cmd = _add_string(cmd, "msg", "test message"); - js_serialize_json(cmd_array, kc.out_buf); - _printit(); - - // string element and an integer element - cmd = _reset_array(); - cmd = _add_string(cmd, "msg", "test message"); - cmd = _add_integer(cmd, "answer", 42); - js_serialize_json(cmd_array, kc.out_buf); - _printit(); - - // parent with a string and an integer element - cmd = _reset_array(); - cmd = _add_parent(cmd, "r"); - cmd = _add_string(cmd, "msg", "test message"); - cmd = _add_integer(cmd, "answer", 42); - js_serialize_json(cmd_array, kc.out_buf); - _printit(); - - // parent with a null child followed by a final level 0 element (footer) - cmd = _reset_array(); - cmd = _add_parent(cmd, "r"); - cmd = _add_empty(cmd); - cmd = _add_string(cmd, "f", "[1,0,12,1234]"); // fake out a footer - cmd->pv->depth = 0; - js_serialize_json(cmd_array, kc.out_buf); - _printit(); - - // parent with a single element child followed by empties folowed by a final level 0 element - cmd = _reset_array(); - cmd = _add_parent(cmd, "r"); - cmd = _add_integer(cmd, "answer", 42); - cmd = _add_empty(cmd); - cmd = _add_empty(cmd); - cmd = _add_string(cmd, "f", "[1,0,12,1234]"); // fake out a footer - cmd->pv->depth = 0; - js_serialize_json(cmd_array, kc.out_buf); - _printit(); - - // response object parent with no children w/footer - cmd_reset_list(); // works with the header/body/footer list - _add_array(cmd, "1,0,12,1234"); // fake out a footer - js_serialize_json(cmd_header, kc.out_buf); - _printit(); - - // response parent with one element w/footer - cmd_reset_list(); // works with the header/body/footer list - cmd_add_string("msg", "test message"); - _add_array(cmd, "1,0,12,1234"); // fake out a footer - js_serialize_json(cmd_header, kc.out_buf); - _printit(); +static void _test_serialize() +{ + cmdObj_t *cmd = cmd_array; +// printf("\n\nJSON serialization tests\n"); + + // null list + _reset_array(); + json_serialize(cmd_array, cs.out_buf, sizeof(cs.out_buf)); + _printit(); + + // parent with a null child + cmd = _reset_array(); + cmd = _add_parent(cmd, (char_t *)"r"); + json_serialize(cmd_array, cs.out_buf, sizeof(cs.out_buf)); + _printit(); + + // single string element (message) + cmd = _reset_array(); + cmd = _add_string(cmd, (char_t *)"msg", (char_t *)"test message"); + json_serialize(cmd_array, cs.out_buf, sizeof(cs.out_buf)); + _printit(); + + // string element and an integer element + cmd = _reset_array(); + cmd = _add_string(cmd, (char_t *)"msg", (char_t *)"test message"); + cmd = _add_integer(cmd, (char_t *)"answer", 42); + json_serialize(cmd_array, cs.out_buf, sizeof(cs.out_buf)); + _printit(); + + // parent with a string and an integer element + cmd = _reset_array(); + cmd = _add_parent(cmd, (char_t *)"r"); + cmd = _add_string(cmd, (char_t *)"msg", (char_t *)"test message"); + cmd = _add_integer(cmd, (char_t *)"answer", 42); + json_serialize(cmd_array, cs.out_buf, sizeof(cs.out_buf)); + _printit(); + + // parent with a null child followed by a final level 0 element (footer) + cmd = _reset_array(); + cmd = _add_parent(cmd, (char_t *)"r"); + cmd = _add_empty(cmd); + cmd = _add_string(cmd, (char_t *)"f", (char_t *)"[1,0,12,1234]"); // fake out a footer + cmd->pv->depth = 0; + json_serialize(cmd_array, cs.out_buf, sizeof(cs.out_buf)); + _printit(); + + // parent with a single element child followed by empties folowed by a final level 0 element + cmd = _reset_array(); + cmd = _add_parent(cmd, (char_t *)"r"); + cmd = _add_integer(cmd, (char_t *)"answer", 42); + cmd = _add_empty(cmd); + cmd = _add_empty(cmd); + cmd = _add_string(cmd, (char_t *)"f", (char_t *)"[1,0,12,1234]"); // fake out a footer + cmd->pv->depth = 0; + json_serialize(cmd_array, cs.out_buf, sizeof(cs.out_buf)); + _printit(); + + // response object parent with no children w/footer + cmd_reset_list(); // works with the header/body/footer list + _add_array(cmd, (char_t *)"1,0,12,1234"); // fake out a footer + json_serialize(cmd_header, cs.out_buf, sizeof(cs.out_buf)); + _printit(); + + // response parent with one element w/footer + cmd_reset_list(); // works with the header/body/footer list + cmd_add_string((char_t *)"msg", (char_t *)"test message"); + _add_array(cmd, (char_t *)"1,0,12,1234"); // fake out a footer + json_serialize(cmd_header, cs.out_buf, sizeof(cs.out_buf)); + _printit(); } static char_t * _clr(char_t *buf) @@ -639,7 +634,7 @@ static char_t * _clr(char_t *buf) static void _printit(void) { -// printf("%s", kc.out_buf); +// printf("%s", cs.out_buf); } static cmdObj_t * _reset_array() @@ -702,39 +697,39 @@ static cmdObj_t * _add_array(cmdObj_t *cmd, char_t *array_string) static void _test_parser() { -// tip: breakpoint the js_json_parser return (STAT_OK) and examine the js[] array +// tip: breakpoint the json_parser return (STAT_OK) and examine the js[] array // success cases // single NV pair cases - js_json_parser("{\"config_version\":null}\n"); // simple null test - js_json_parser("{\"config_profile\":true}\n"); // simple true test - js_json_parser("{\"prompt\":false}\n"); // simple false test - js_json_parser("{\"gcode\":\"g0 x3 y4 z5.5 (comment line)\"}\n");// string test w/comment - js_json_parser("{\"x_feedrate\":1200}\n"); // numeric test - js_json_parser("{\"y_feedrate\":-1456}\n"); // numeric test + json_parser((char_t *)"{\"config_version\":null}\n"); // simple null test + json_parser((char_t *)"{\"config_profile\":true}\n"); // simple true test + json_parser((char_t *)"{\"prompt\":false}\n"); // simple false test + json_parser((char_t *)"{\"gcode\":\"g0 x3 y4 z5.5 (comment line)\"}\n");// string test w/comment + json_parser((char_t *)"{\"x_feedrate\":1200}\n"); // numeric test + json_parser((char_t *)"{\"y_feedrate\":-1456}\n"); // numeric test - js_json_parser("{\"Z_velocity_maximum\":null}\n"); // axis w/null - js_json_parser("{\"m1_microsteps\":null}\n"); // motor w/null - js_json_parser("{\"2mi\":8}\n"); // motor token w/null - js_json_parser("{\"no-token\":12345}\n"); // non-token w/number + json_parser((char_t *)"{\"Z_velocity_maximum\":null}\n"); // axis w/null + json_parser((char_t *)"{\"m1_microsteps\":null}\n"); // motor w/null + json_parser((char_t *)"{\"2mi\":8}\n"); // motor token w/null + json_parser((char_t *)"{\"no-token\":12345}\n"); // non-token w/number // multi-pair cases tabs here V - js_json_parser("{\"firmware_version\":329.26, \"config_version\":0.93}\n"); - js_json_parser("{\"1mi\":8, \"2mi\":8,\"3mi\":8,\"4mi\":8}\n"); // 4 elements + json_parser((char_t *)"{\"firmware_version\":329.26, \"config_version\":0.93}\n"); + json_parser((char_t *)"{\"1mi\":8, \"2mi\":8,\"3mi\":8,\"4mi\":8}\n"); // 4 elements // parent / child cases - js_json_parser("{\"status_report\":{\"ln\":true, \"x_pos\":true, \"y_pos\":true, \"z_pos\":true}}\n"); - js_json_parser("{\"parent_case1\":{\"child_null\":null}}\n"); // parent w/single child - js_json_parser("{\"parent_case2\":{\"child_num\":23456}}\n"); // parent w/single child - js_json_parser("{\"parent_case3\":{\"child_str\":\"stringdata\"}}\n");// parent w/single child + json_parser((char_t *)"{\"status_report\":{\"ln\":true, \"x_pos\":true, \"y_pos\":true, \"z_pos\":true}}\n"); + json_parser((char_t *)"{\"parent_case1\":{\"child_null\":null}}\n"); // parent w/single child + json_parser((char_t *)"{\"parent_case2\":{\"child_num\":23456}}\n"); // parent w/single child + json_parser((char_t *)"{\"parent_case3\":{\"child_str\":\"stringdata\"}}\n");// parent w/single child // error cases - js_json_parser("{\"err_1\":36000x\n}"); // illegal number - js_json_parser("{\"err_2\":\"text\n}"); // no string termination - js_json_parser("{\"err_3\":\"12345\",}\n"); // bad } termination - js_json_parser("{\"err_4\":\"12345\"\n"); // no } termination + json_parser((char_t *)"{\"err_1\":36000x\n}"); // illegal number + json_parser((char_t *)"{\"err_2\":\"text\n}"); // no string termination + json_parser((char_t *)"{\"err_3\":\"12345\",}\n"); // bad } termination + json_parser((char_t *)"{\"err_4\":\"12345\"\n"); // no } termination } diff --git a/TinyG2/json_parser.h b/TinyG2/json_parser.h index 2b9273ee..8b01b80b 100755 --- a/TinyG2/json_parser.h +++ b/TinyG2/json_parser.h @@ -1,8 +1,8 @@ /* - * json_parser.h - JSON parser and JSON support - * This file is part of the TinyG2 project + * json_parser.h - JSON parser and JSON support for TinyG + * This file is part of the TinyG project * - * Copyright (c) 2011 - 2013 Alden S. Hart Jr. + * Copyright (c) 2011 - 2013 Alden S. Hart, Jr. * * This file ("the software") is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2 as published by the @@ -102,23 +102,6 @@ stat_t json_set_jv(cmdObj_t *cmd); #endif // __TEXT_MODE - - -/* -// for now there is only one JSON array in use - the footer -// if you add these make sure there are no collisions w/present or past numbers - -#define FOOTER_REVISION 1 -#define JSON_OUTPUT_STRING_MAX (OUTPUT_BUFFER_LEN) -#define JSON_MAX_DEPTH 4 - -void json_parser(char_t *str); -uint16_t json_serialize(cmdObj_t *cmd, char_t *out_buf, uint16_t size); -void json_print_object(cmdObj_t *cmd); -void json_print_response(uint8_t status); -void json_print_list(stat_t status, uint8_t flags); -*/ - /* unit test setup */ //#define __UNIT_TEST_JSON // uncomment to enable JSON unit tests diff --git a/TinyG2/text_parser.cpp b/TinyG2/text_parser.cpp index f5205d1a..66062081 100755 --- a/TinyG2/text_parser.cpp +++ b/TinyG2/text_parser.cpp @@ -114,7 +114,7 @@ static stat_t _text_parser_kernal(char_t *str, cmdObj_t *cmd) *rd = NUL; // terminate at end of name strncpy(cmd->token, str, CMD_TOKEN_LEN); str = ++rd; - cmd->value = strtod(str, &rd); // rd used as end pointer + cmd->value = strtof(str, &rd); // rd used as end pointer if (rd != str) { cmd->objtype = TYPE_FLOAT; } diff --git a/TinyG2/tinyg2.h b/TinyG2/tinyg2.h index 875001ff..de9716a7 100755 --- a/TinyG2/tinyg2.h +++ b/TinyG2/tinyg2.h @@ -35,7 +35,7 @@ #include "MotatePins.h" -#define TINYG_FIRMWARE_BUILD 020.08 // Alignment changes to help.cpp +#define TINYG_FIRMWARE_BUILD 020.09 // Alignment changes to json_parser #define TINYG_FIRMWARE_VERSION 0.8 // firmware major version #define TINYG_HARDWARE_PLATFORM 2 // hardware platform indicator (2 = Native Arduino Due) #define TINYG_HARDWARE_VERSION 1 // hardware platform revision number diff --git a/TinyG2/util.cpp b/TinyG2/util.cpp index 3f502e86..5ebc44af 100755 --- a/TinyG2/util.cpp +++ b/TinyG2/util.cpp @@ -213,7 +213,7 @@ uint8_t read_float(char *buf, uint8_t *i, float *float_ptr) char *start = buf + *i; char *end; - *float_ptr = strtod(start, &end); + *float_ptr = strtof(start, &end); if(end == start) { return(false); }