void nv_get_nvObj(nvObj_t *nv) { if (nv->index >= nv_index_max()) { return; } // sanity index_t tmp = nv->index; nv_reset_nv(nv); nv->index = tmp; strcpy_P(nv->token, cfgArray[nv->index].token); // token field is always terminated strcpy_P(nv->group, cfgArray[nv->index].group); // group field is always terminated // special processing for system groups and stripping tokens for groups if (nv->group[0] != NUL) { if (GET_TABLE_BYTE(flags) & F_NOSTRIP) { nv->group[0] = NUL; } else { strcpy(nv->token, &nv->token[strlen(nv->group)]); // strip group from the token } } ((fptrCmd)GET_TABLE_WORD(get))(nv); // populate the value }
static stat_t _get_nv_pair(nvObj_t *nv, char **pstr, int8_t *depth) { uint8_t i; char *tmp; char leaders[] = {"{,\""}; // open curly, quote and leading comma char separators[] = {":\""}; // colon and quote char terminators[] = {"},\""}; // close curly, comma and quote char value[] = {"{\".-+"}; // open curly, quote, period, minus and plus nv_reset_nv(nv); // wipes the object and sets the depth // --- Process name part --- // Find, terminate and set pointers for the name. Allow for leading and trailing name quotes. char * name = *pstr; for (i=0; true; i++, (*pstr)++) { if (strchr(leaders, (int)**pstr) == NULL) { // find leading character of name name = (*pstr)++; break; } if (i == MAX_PAD_CHARS) return (STAT_JSON_SYNTAX_ERROR); } // Find the end of name, NUL terminate and copy token for (i=0; true; i++, (*pstr)++) { if (strchr(separators, (int)**pstr) != NULL) { *(*pstr)++ = NUL; strncpy(nv->token, name, TOKEN_LEN+1); // copy the string to the token break; } if (i == MAX_NAME_CHARS) return (STAT_JSON_SYNTAX_ERROR); } // --- Process value part --- (organized from most to least frequently encountered) // Find the start of the value part for (i=0; true; i++, (*pstr)++) { if (isalnum((int)**pstr)) break; if (strchr(value, (int)**pstr) != NULL) break; if (i == MAX_PAD_CHARS) return (STAT_JSON_SYNTAX_ERROR); } // nulls (gets) if ((**pstr == 'n') || ((**pstr == '\"') && (*(*pstr+1) == '\"'))) { // process null value nv->valuetype = TYPE_NULL; nv->value = TYPE_NULL; // numbers } else if (isdigit(**pstr) || (**pstr == '-')) {// value is a number nv->value = (float)strtod(*pstr, &tmp); // tmp is the end pointer if(tmp == *pstr) { return (STAT_BAD_NUMBER_FORMAT);} nv->valuetype = TYPE_FLOAT; // object parent } else if (**pstr == '{') { nv->valuetype = TYPE_PARENT; // *depth += 1; // nv_reset_nv() 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)++; nv->valuetype = TYPE_STRING; if ((tmp = strchr(*pstr, '\"')) == NULL) { return (STAT_JSON_SYNTAX_ERROR);} // find the end of the string *tmp = NUL; // if string begins with 0x it might be data, needs to be at least 3 chars long if( strlen(*pstr)>=3 && (*pstr)[0]=='0' && (*pstr)[1]=='x') { uint32_t *v = (uint32_t*)&nv->value; *v = strtoul((const char *)*pstr, 0L, 0); nv->valuetype = TYPE_DATA; } else { ritorno(nv_copy_string(nv, *pstr)); } *pstr = ++tmp; // boolean true/false } else if (**pstr == 't') { nv->valuetype = TYPE_BOOL; nv->value = true; } else if (**pstr == 'f') { nv->valuetype = TYPE_BOOL; nv->value = false; // arrays } else if (**pstr == '[') { nv->valuetype = TYPE_ARRAY; ritorno(nv_copy_string(nv, *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 }