static const char * match_hfdte_record(const char *p, struct tm *tm) { int mday = 0, mon = 0, year = 0; p = match_literal(p, "HFDTE"); if (!p) return 0; p = match_n_digits(p, 2, &mday); p = match_n_digits(p, 2, &mon); p = match_n_digits(p, 2, &year); p = match_literal(p, "\r\n"); if (!p) return 0; tm->tm_year = year + 2000 - 1900; tm->tm_mon = mon - 1; tm->tm_mday = mday; return p; }
static void flytec_pbrwps(flytec_t *flytec) { flytec_puts_nmea(flytec, "PBRWPS,"); flytec_expectc(flytec, XOFF); char line[128]; while (flytec_gets_nmea(flytec, line, sizeof line)) { const char *p = line; p = match_literal(p, "PBRWPS,"); int lat_deg = 0, lat_min = 0, lat_mmin = 0; p = match_n_digits(p, 2, &lat_deg); p = match_n_digits(p, 2, &lat_min); p = match_char(p, '.'); p = match_n_digits(p, 3, &lat_mmin); p = match_char(p, ','); char lat_hemi = '\0'; p = match_one_of(p, "NS", &lat_hemi); p = match_char(p, ','); int lon_deg = 0, lon_min = 0, lon_mmin = 0; p = match_n_digits(p, 3, &lon_deg); p = match_n_digits(p, 2, &lon_min); p = match_char(p, '.'); p = match_n_digits(p, 3, &lon_mmin); p = match_char(p, ','); char lon_hemi = '\0'; p = match_one_of(p, "EW", &lon_hemi); p = match_char(p, ','); char *name = 0; p = match_string_until(p, ',', 1, 0); p = match_string_until(p, ',', 1, &name); int ele = 0; p = match_unsigned(p, &ele); p = match_eos(p); if (p) { waypoint *w = waypt_new(); w->latitude = lat_deg + lat_min / 60.0 + lat_mmin / 60000.0; if (lat_hemi == 'S') w->latitude = -w->latitude; w->longitude = lon_deg + lon_min / 60.0 + lon_mmin / 60000.0; if (lon_hemi == 'W') w->longitude = -w->longitude; w->altitude = ele; w->shortname = rstrip(name); waypt_add(w); } else { free(name); } } flytec_expectc(flytec, XON); }
snp_t *snp_new(const char *p) { snp_t *snp = alloc(sizeof(snp_t)); p = match_literal(p, "PBRSNP,"); p = match_string_until(p, ',', 1, &snp->instrument_id); p = match_string_until(p, ',', 1, &snp->pilot_name); p = match_unsigned(p, &snp->serial_number); p = match_char(p, ','); p = match_string_until(p, '\0', 0, &snp->software_version); p = match_eos(p); if (!p) { snp_delete(snp); return 0; } return snp; }
static void flytec_pbrrts(flytec_t *flytec) { flytec_puts_nmea(flytec, "PBRRTS,"); flytec_expectc(flytec, XOFF); route_head *route = 0; char line[128]; while (flytec_gets_nmea(flytec, line, sizeof line)) { const char *p = line; p = match_literal(p, "PBRRTS,"); int index = 0, count = 0, routepoint_index = 0; p = match_unsigned(p, &index); p = match_char(p, ','); p = match_unsigned(p, &count); p = match_char(p, ','); p = match_unsigned(p, &routepoint_index); p = match_char(p, ','); if (!p) continue; if (routepoint_index == 0) { char *name = 0; p = match_string_until(p, '\0', 0, &name); p = match_eos(p); if (p) { route = route_head_alloc(); route->rte_num = index + 1; route->rte_name = rstrip(name); route_add_head(route); } else { free(name); } } else { char *name = 0; p = match_string_until(p, ',', 1, 0); p = match_string_until(p, '\0', 0, &name); p = match_eos(p); if (p) { const waypoint *w = find_waypt_by_name(rstrip(name)); if (w) route_add_wpt(route, waypt_dupe(w)); } free(name); } } flytec_expectc(flytec, XON); }
static track_t * track_new(const char *p) { track_t *track = xmalloc(sizeof(track_t)); memset(track, 0, sizeof *track); p = match_literal(p, "PBRTL,"); p = match_unsigned(p, &track->count); p = match_char(p, ','); p = match_unsigned(p, &track->index); p = match_char(p, ','); struct tm tm; memset(&tm, 0, sizeof tm); p = match_unsigned(p, &tm.tm_mday); p = match_char(p, '.'); p = match_unsigned(p, &tm.tm_mon); p = match_char(p, '.'); p = match_unsigned(p, &tm.tm_year); p = match_char(p, ','); p = match_unsigned(p, &tm.tm_hour); p = match_char(p, ':'); p = match_unsigned(p, &tm.tm_min); p = match_char(p, ':'); p = match_unsigned(p, &tm.tm_sec); p = match_char(p, ','); int duration_hour = 0, duration_min = 0, duration_sec = 0; p = match_unsigned(p, &duration_hour); p = match_char(p, ':'); p = match_unsigned(p, &duration_min); p = match_char(p, ':'); p = match_unsigned(p, &duration_sec); p = match_eos(p); if (!p) { track_delete(track); return 0; } tm.tm_mon -= 1; tm.tm_year += 2000 - 1900; track->date = DATE_NEW(tm); track->time = mktime(&tm); if (track->time == (time_t) -1) DIE("mktime", errno); track->duration = 3600 * duration_hour + 60 * duration_min + duration_sec; return track; }
ssize_t spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t num_values, void **end, uint32_t flags) { uint8_t *json_end = json + size; enum spdk_json_val_type containers[SPDK_JSON_MAX_NESTING_DEPTH]; size_t con_value[SPDK_JSON_MAX_NESTING_DEPTH]; enum spdk_json_val_type con_type = SPDK_JSON_VAL_INVALID; bool trailing_comma = false; size_t depth = 0; /* index into containers */ size_t cur_value = 0; /* index into values */ size_t con_start_value; uint8_t *data = json; uint8_t *new_data; int rc; const struct json_literal *lit; enum { STATE_VALUE, /* initial state */ STATE_VALUE_SEPARATOR, /* value separator (comma) */ STATE_NAME, /* "name": value */ STATE_NAME_SEPARATOR, /* colon */ STATE_END, /* parsed the complete value, so only whitespace is valid */ } state = STATE_VALUE; #define ADD_VALUE(t, val_start_ptr, val_end_ptr) \ if (values && cur_value < num_values) { \ values[cur_value].type = t; \ values[cur_value].start = val_start_ptr; \ values[cur_value].len = val_end_ptr - val_start_ptr; \ } \ cur_value++ while (data < json_end) { uint8_t c = *data; switch (c) { case ' ': case '\t': case '\r': case '\n': /* Whitespace is allowed between any tokens. */ data++; break; case 't': case 'f': case 'n': /* true, false, or null */ if (state != STATE_VALUE) return SPDK_JSON_PARSE_INVALID; lit = &g_json_literals[(c >> 3) & 3]; /* See comment above g_json_literals[] */ assert(lit->str[0] == c); rc = match_literal(data, json_end, lit->str, lit->len); if (rc < 0) return rc; ADD_VALUE(lit->type, data, data + rc); data += rc; state = depth ? STATE_VALUE_SEPARATOR : STATE_END; trailing_comma = false; break; case '"': if (state != STATE_VALUE && state != STATE_NAME) return SPDK_JSON_PARSE_INVALID; rc = json_decode_string(data, json_end, &new_data, flags); if (rc < 0) return rc; /* * Start is data + 1 to skip initial quote. * Length is data + rc - 1 to skip both quotes. */ ADD_VALUE(state == STATE_VALUE ? SPDK_JSON_VAL_STRING : SPDK_JSON_VAL_NAME, data + 1, data + rc - 1); data = new_data; if (state == STATE_NAME) { state = STATE_NAME_SEPARATOR; } else { state = depth ? STATE_VALUE_SEPARATOR : STATE_END; } trailing_comma = false; break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (state != STATE_VALUE) return SPDK_JSON_PARSE_INVALID; rc = json_valid_number(data, json_end); if (rc < 0) return rc; ADD_VALUE(SPDK_JSON_VAL_NUMBER, data, data + rc); data += rc; state = depth ? STATE_VALUE_SEPARATOR : STATE_END; trailing_comma = false; break; case '{': case '[': if (state != STATE_VALUE) return SPDK_JSON_PARSE_INVALID; if (depth == SPDK_JSON_MAX_NESTING_DEPTH) { return SPDK_JSON_PARSE_MAX_DEPTH_EXCEEDED; } if (c == '{') { con_type = SPDK_JSON_VAL_OBJECT_BEGIN; state = STATE_NAME; } else { con_type = SPDK_JSON_VAL_ARRAY_BEGIN; state = STATE_VALUE; } con_value[depth] = cur_value; containers[depth++] = con_type; ADD_VALUE(con_type, data, data + 1); data++; trailing_comma = false; break; case '}': case ']': if (trailing_comma) return SPDK_JSON_PARSE_INVALID; if (depth == 0) return SPDK_JSON_PARSE_INVALID; con_type = containers[--depth]; con_start_value = con_value[depth]; if (values && con_start_value < num_values) { values[con_start_value].len = cur_value - con_start_value - 1; } if (c == '}') { if (state != STATE_NAME && state != STATE_VALUE_SEPARATOR) { return SPDK_JSON_PARSE_INVALID; } if (con_type != SPDK_JSON_VAL_OBJECT_BEGIN) { return SPDK_JSON_PARSE_INVALID; } ADD_VALUE(SPDK_JSON_VAL_OBJECT_END, data, data + 1); } else { if (state != STATE_VALUE && state != STATE_VALUE_SEPARATOR) { return SPDK_JSON_PARSE_INVALID; } if (con_type != SPDK_JSON_VAL_ARRAY_BEGIN) { return SPDK_JSON_PARSE_INVALID; } ADD_VALUE(SPDK_JSON_VAL_ARRAY_END, data, data + 1); } con_type = depth == 0 ? SPDK_JSON_VAL_INVALID : containers[depth - 1]; data++; state = depth ? STATE_VALUE_SEPARATOR : STATE_END; trailing_comma = false; break; case ',': if (state != STATE_VALUE_SEPARATOR) return SPDK_JSON_PARSE_INVALID; data++; assert(con_type == SPDK_JSON_VAL_ARRAY_BEGIN || con_type == SPDK_JSON_VAL_OBJECT_BEGIN); state = con_type == SPDK_JSON_VAL_ARRAY_BEGIN ? STATE_VALUE : STATE_NAME; trailing_comma = true; break; case ':': if (state != STATE_NAME_SEPARATOR) return SPDK_JSON_PARSE_INVALID; data++; state = STATE_VALUE; break; case '/': if (!(flags & SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS)) { return SPDK_JSON_PARSE_INVALID; } rc = json_valid_comment(data, json_end); if (rc < 0) return rc; /* Skip over comment */ data += rc; break; default: return SPDK_JSON_PARSE_INVALID; } if (state == STATE_END) { break; } } if (state == STATE_END) { /* Skip trailing whitespace */ while (data < json_end) { uint8_t c = *data; if (c == ' ' || c == '\t' || c == '\r' || c == '\n') { data++; } else { break; } } /* * These asserts are just for sanity checking - they are guaranteed by the allowed * state transitions. */ assert(depth == 0); assert(trailing_comma == false); assert(data <= json_end); if (end) { *end = data; } return cur_value; } /* Invalid end state - ran out of data */ if (end) { *end = data; } return SPDK_JSON_PARSE_INCOMPLETE; }
static match_result match_null(const char* begin, const char* end, token_kind& kind, std::size_t& length) { kind = token_kind::null; return match_literal(begin, end, "null", length); }
static match_result match_false(const char* begin, const char* end, token_kind& kind, std::size_t& length) { kind = token_kind::boolean; return match_literal(begin, end, "false", length); }