nvObj_t *nv_add_object(const char_t *token) // add an object to the body using a token { nvObj_t *nv = nv_body; for (uint8_t i=0; i<NV_BODY_LEN; i++) { if (nv->valuetype != TYPE_EMPTY) { if ((nv = nv->nx) == NULL) return(NULL); // not supposed to find a NULL; here for safety continue; } // load the index from the token or die trying if ((nv->index = nv_get_index((const char_t *)"",token)) == NO_MATCH) { return (NULL);} nv_get_nvObj(nv); // populate the object from the index return (nv); } return (NULL); }
static stat_t _text_parser_kernal(char_t *str, nvObj_t *nv) { char_t *rd, *wr; // read and write pointers // char_t separators[] = {"="}; // STRICT: only separator allowed is = sign char_t separators[] = {" =:|\t"}; // RELAXED: any separator someone might use // pre-process and normalize the string // nv_reset_nv(nv); // initialize config object nv_copy_string(nv, str); // make a copy for eventual reporting if (*str == '$') str++; // ignore leading $ for (rd = wr = str; *rd != NUL; rd++, wr++) { *wr = tolower(*rd); // convert string to lower case if (*rd == ',') { *wr = *(++rd);} // skip over commas } *wr = NUL; // terminate the string // parse fields into the nv struct nv->valuetype = TYPE_NULL; if ((rd = strpbrk(str, separators)) == NULL) { // no value part strncpy(nv->token, str, TOKEN_LEN); } else { *rd = NUL; // terminate at end of name strncpy(nv->token, str, TOKEN_LEN); str = ++rd; nv->value = strtof(str, &rd); // rd used as end pointer if (rd != str) { nv->valuetype = TYPE_FLOAT; } } // validate and post-process the token if ((nv->index = nv_get_index((const char_t *)"", nv->token)) == NO_MATCH) { // get index or fail it return (STAT_UNRECOGNIZED_NAME); } strcpy_P(nv->group, cfgArray[nv->index].group); // capture the group string if there is one // see if you need to strip the token if (nv->group[0] != NUL) { wr = nv->token; rd = nv->token + strlen(nv->group); while (*rd != NUL) { *(wr)++ = *(rd)++;} *wr = NUL; } return (STAT_OK); }
// ASSUMES A RAM STRING. If you need to post a FLASH string use pstr2str to convert it to a RAM string nvObj_t *nv_add_string(const char_t *token, const char_t *string) // add a string object to the body { nvObj_t *nv = nv_body; for (uint8_t i=0; i<NV_BODY_LEN; i++) { if (nv->valuetype != TYPE_EMPTY) { if ((nv = nv->nx) == NULL) return(NULL); // not supposed to find a NULL; here for safety continue; } strncpy(nv->token, token, TOKEN_LEN); if (nv_copy_string(nv, string) != STAT_OK) return (NULL); nv->index = nv_get_index((const char_t *)"", nv->token); nv->valuetype = TYPE_STRING; return (nv); } return (NULL); }
static stat_t _json_parser_kernal(char *str) { stat_t status; int8_t depth; nvObj_t *nv = nv_reset_nv_list(); // get a fresh nvObj list char group[GROUP_LEN+1] = {""}; // group identifier - starts as NUL int8_t i = NV_BODY_LEN; ritorno(_normalize_json_string(str, JSON_OUTPUT_STRING_MAX)); // return if error // parse the JSON command into the nv body do { if (--i == 0) { return (STAT_JSON_TOO_MANY_PAIRS); } // length error // if ((status = _get_nv_pair_strict(nv, &str, &depth)) > STAT_EAGAIN) { // erred out if ((status = _get_nv_pair(nv, &str, &depth)) > STAT_EAGAIN) { // erred out return (status); } // propagate the group from previous NV pair (if relevant) if (group[0] != NUL) { strncpy(nv->group, group, GROUP_LEN); // copy the parent's group to this child } // validate the token and get the index if ((nv->index = nv_get_index(nv->group, nv->token)) == NO_MATCH) { nv->valuetype = TYPE_NULL; return (STAT_UNRECOGNIZED_NAME); } if ((nv_index_is_group(nv->index)) && (nv_group_is_prefixed(nv->token))) { strncpy(group, nv->token, GROUP_LEN); // record the group ID } if ((nv = nv->nx) == NULL) return (STAT_JSON_TOO_MANY_PAIRS);// Not supposed to encounter a NULL } while (status != STAT_OK); // breaks when parsing is complete // execute the command nv = nv_body; if (nv->valuetype == TYPE_NULL){ // means GET the value ritorno(nv_get(nv)); // ritorno returns w/status on any errors } else { cm_parse_clear(*nv->stringp); // parse Gcode and clear alarms if M30 or M2 is found ritorno(cm_is_alarmed()); // return error status if in alarm, shutdown or panic ritorno(nv_set(nv)); // set value or call a function (e.g. gcode) nv_persist(nv); } return (STAT_OK); // only successful commands exit through this point }