static uint8_t _text_parser(char *str, cmdObj_t *cmd) { char *ptr_rd, *ptr_wr; // read and write pointers char separators[] = {" =:|\t"}; // any separator someone might use // string pre-processing cmd_reset_obj(cmd); // initialize config object if (*str == '$') str++; // ignore leading $ for (ptr_rd = ptr_wr = str; *ptr_rd!=NUL; ptr_rd++, ptr_wr++) { *ptr_wr = tolower(*ptr_rd); // convert string to lower case if (*ptr_rd==',') { *ptr_wr = *(++ptr_rd); // skip over comma } } *ptr_wr = NUL; // field processing cmd->type = TYPE_NULL; if ((ptr_rd = strpbrk(str, separators)) == NULL) { // no value part strncpy(cmd->token, str, CMD_TOKEN_LEN); } else { *ptr_rd = NUL; // terminate at end of name strncpy(cmd->token, str, CMD_TOKEN_LEN); str = ++ptr_rd; cmd->value = strtod(str, &ptr_rd); // ptr_rd used as end pointer if (ptr_rd != str) { cmd->type = TYPE_FLOAT; } } if ((cmd->index = cmd_get_index("",cmd->token)) == NO_MATCH) { return (SC_UNRECOGNIZED_COMMAND); } return (SC_OK); }
/* * _get_nv_pair_strict() - get the next name-value pair w/strict JSON rules * * Parse the next statement and populate the command object (cmdObj). * * Leaves string pointer (str) on the first character following the object. * Which is the character just past the ',' separator if it's a multi-valued * object or the terminating NUL if single object or the last in a multi. * * Keeps track of tree depth and closing braces as much as it has to. * If this were to be extended to track multiple parents or more than two * levels deep it would have to track closing curlies - which it does not. * * ASSUMES INPUT STRING HAS FIRST BEEN NORMALIZED BY _normalize_json_string() * * If a group prefix is passed in it will be pre-pended to any name parsed * to form a token string. For example, if "x" is provided as a group and * "fr" is found in the name string the parser will search for "xfr"in the * cfgArray. */ static stat_t _get_nv_pair_strict(cmdObj_t *cmd, char **pstr, int8_t *depth) { char *tmp; char terminators[] = {"},"}; 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 // --- Process value part --- (organized from most to least encountered) *pstr = ++tmp; if ((*pstr = strchr(*pstr, ':')) == NULL) return (STAT_JSON_SYNTAX_ERROR); (*pstr)++; // advance to start of value field // nulls (gets) if ((**pstr == 'n') || ((**pstr == '\"') && (*(*pstr+1) == '\"'))) { // process null value cmd->objtype = TYPE_NULL; cmd->value = TYPE_NULL; // numbers } else if (isdigit(**pstr) || (**pstr == '-')) {// value is a number cmd->value = strtod(*pstr, &tmp); // tmp is the end pointer if(tmp == *pstr) { return (STAT_BAD_NUMBER_FORMAT);} cmd->objtype = TYPE_FLOAT; // object parent } else if (**pstr == '{') { cmd->objtype = TYPE_PARENT; // *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 // strings } 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 *tmp = NUL; ritorno(cmd_copy_string(cmd, *pstr)); *pstr = ++tmp; // boolean true/false } else if (**pstr == 't') { cmd->objtype = TYPE_BOOL; cmd->value = true; } else if (**pstr == 'f') { cmd->objtype = TYPE_BOOL; cmd->value = false; // 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 // general error condition } 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 } if (**pstr == ',') { return (STAT_EAGAIN);} // signal that there is more to parse (*pstr)++; return (STAT_OK); // signal that parsing is complete }