Example #1
0
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);
}
Example #2
0
// 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);
}
Example #3
0
void json_print_response(uint8_t status)
{
#ifdef __SILENCE_JSON_RESPONSES
	return;
#endif

	if (js.json_verbosity == JV_SILENT) {				    // silent means no responses
        return;
    }
	if (js.json_verbosity == JV_EXCEPTIONS)	{				// cutout for JV_EXCEPTIONS mode
		if (status == STAT_OK) {
			if (cm.machine_state != MACHINE_INITIALIZING) {	// always do full echo during startup
				return;
            }
        }
    }

	// Body processing
	nvObj_t *nv = nv_body;
	if (status == STAT_JSON_SYNTAX_ERROR) {
		nv_reset_nv_list();
		nv_add_string((const char *)"err", escape_string(cs.bufp, cs.saved_buf));

	} else if (cm.machine_state != MACHINE_INITIALIZING) {	// always do full echo during startup
		uint8_t nv_type;
		do {
			if ((nv_type = nv_get_type(nv)) == NV_TYPE_NULL) break;

			if (nv_type == NV_TYPE_GCODE) {
				if (js.echo_json_gcode_block == false) {	// kill command echo if not enabled
					nv->valuetype = TYPE_EMPTY;
				}

//++++		} else if (nv_type == NV_TYPE_CONFIG) {			// kill config echo if not enabled
//fix me		if (js.echo_json_configs == false) {
//					nv->valuetype = TYPE_EMPTY;
//				}

			} else if (nv_type == NV_TYPE_MESSAGE) {		// kill message echo if not enabled
				if (js.echo_json_messages == false) {
					nv->valuetype = TYPE_EMPTY;
				}

			} else if (nv_type == NV_TYPE_LINENUM) {		// kill line number echo if not enabled
				if ((js.echo_json_linenum == false) || (fp_ZERO(nv->value))) { // do not report line# 0
					nv->valuetype = TYPE_EMPTY;
				}
			}
		} while ((nv = nv->nx) != NULL);
	}

	// Footer processing
	while(nv->valuetype != TYPE_EMPTY) {					// find a free nvObj at end of the list...
		if ((nv = nv->nx) == NULL) {						// oops! No free nvObj!
			rpt_exception(STAT_JSON_TOO_LONG, "json_print"); // report this as an exception
			return;
		}
	}
	char footer_string[NV_FOOTER_LEN];

    // in xio.cpp:xio.readline the CR||LF read from the host is not appended to the string.
    // to ensure that the correct number of bytes are reported back to the host we add a +1 to
    // cs.linelen so that the number of bytes received matches the number of bytes reported
    sprintf((char *)footer_string, "%d,%d,%d", 1, status, cs.linelen + 1);
    cs.linelen = 0;										    // reset linelen so it's only reported once

//	if (xio.enable_window_mode) {							// 2 footer styles are supported...
//		sprintf((char *)footer_string, "%d,%d,%d", 2, status, xio_get_window_slots());	//...windowing
//	} else {
//		sprintf((char *)footer_string, "%d,%d,%d", 1, status, cs.linelen);				//...streaming
//		cs.linelen = 0;										// reset linelen so it's only reported once
//	}

	nv_copy_string(nv, footer_string);						// link string to nv object
	nv->depth = 0;											// footer 'f' is a peer to response 'r' (hard wired to 0)
	nv->valuetype = TYPE_ARRAY;								// declare it as an array
	strcpy(nv->token, "f");									// set it to Footer
	nv->nx = NULL;											// terminate the list

	// serialize the JSON response and print it if there were no errors
	if (json_serialize(nv_header, cs.out_buf, sizeof(cs.out_buf)) >= 0) {
		fprintf(stderr, "%s", cs.out_buf);
	}
}
Example #4
0
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
}
Example #5
0
stat_t gc_get_gc(nvObj_t *nv)
{
	ritorno(nv_copy_string(nv, cs.saved_buf));
	nv->valuetype = TYPE_STRING;
	return (STAT_OK);
}