-
Notifications
You must be signed in to change notification settings - Fork 0
Runtime (C): expand ads_fmt_* family + add result mutators #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -93,23 +93,221 @@ void ads_fmt_departure_airport(ads_decode_result_t *r, ads_value_t *v) { push_st | |
| void ads_fmt_arrival_airport(ads_decode_result_t *r, ads_value_t *v) { push_string(r, v, "arrival_icao", "airport_destination", "ARR", "Destination"); } | ||
|
|
||
| void ads_fmt_unknown_arr(ads_decode_result_t *r, const char *const *values, size_t count) { | ||
| ads_fmt_unknown_arr_sep(r, values, count, ","); | ||
| } | ||
|
|
||
| void ads_fmt_unknown_arr_sep(ads_decode_result_t *r, const char *const *values, size_t count, const char *sep) { | ||
| if (!r || !values || count == 0) return; | ||
| if (!sep) sep = ","; | ||
| size_t sep_len = strlen(sep); | ||
| size_t total = 1; | ||
| for (size_t i = 0; i < count; i++) total += strlen(values[i] ? values[i] : "") + 1; | ||
| for (size_t i = 0; i < count; i++) total += strlen(values[i] ? values[i] : "") + sep_len; | ||
| char *joined = malloc(total); | ||
| if (!joined) return; | ||
| joined[0] = '\0'; | ||
| for (size_t i = 0; i < count; i++) { | ||
| if (i > 0) strcat(joined, ","); | ||
| if (i > 0) strcat(joined, sep); | ||
| strcat(joined, values[i] ? values[i] : ""); | ||
| } | ||
| ads_result_append_remaining(r, joined, sep); | ||
| free(joined); | ||
| } | ||
|
|
||
| void ads_fmt_unknown(ads_decode_result_t *r, const char *value) { | ||
| ads_result_append_remaining(r, value, ","); | ||
| } | ||
|
|
||
| void ads_fmt_unknown_sep(ads_decode_result_t *r, const char *value, const char *sep) { | ||
| ads_result_append_remaining(r, value, sep); | ||
| } | ||
|
|
||
| /* ─── Time-of-day helper ─────────────────────────────────────────────────── */ | ||
|
|
||
| char *ads_fmt_time_of_day_str(int64_t seconds) { | ||
| char *out = malloc(16); | ||
| if (!out) return NULL; | ||
| if (seconds >= 0 && seconds < 86400) { | ||
| int h = (int)(seconds / 3600); | ||
| int m = (int)((seconds % 3600) / 60); | ||
| int s = (int)(seconds % 60); | ||
| snprintf(out, 16, "%02d:%02d:%02d", h, m, s); | ||
| } else { | ||
| snprintf(out, 16, "%lld", (long long)seconds); | ||
| } | ||
| return out; | ||
| } | ||
|
Comment on lines
+126
to
+138
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Buffer too small for out-of-range integer values. When 🔧 Suggested fix char *ads_fmt_time_of_day_str(int64_t seconds) {
- char *out = malloc(16);
+ char *out = malloc(24); /* Room for longest int64 string + null */
if (!out) return NULL;
if (seconds >= 0 && seconds < 86400) {
int h = (int)(seconds / 3600);
int m = (int)((seconds % 3600) / 60);
int s = (int)(seconds % 60);
- snprintf(out, 16, "%02d:%02d:%02d", h, m, s);
+ snprintf(out, 24, "%02d:%02d:%02d", h, m, s);
} else {
- snprintf(out, 16, "%lld", (long long)seconds);
+ snprintf(out, 24, "%lld", (long long)seconds);
}
return out;
}🤖 Prompt for AI Agents |
||
|
|
||
| /* ─── Time-of-day formatters (value in seconds since midnight) ───────────── */ | ||
|
|
||
| static void push_tod(ads_decode_result_t *r, ads_value_t *v, const char *raw_key, | ||
| const char *kind, const char *code, const char *label) { | ||
| if (!v) return; | ||
| int64_t n = 0; | ||
| ads_value_as_int(v, &n); | ||
| cJSON_AddNumberToObject(r->raw, raw_key, (double)n); | ||
| char *display = ads_fmt_time_of_day_str(n); | ||
| push_item(r, kind, code, label, display ? display : ""); | ||
| free(display); | ||
| ads_value_free(v); | ||
| } | ||
|
|
||
| void ads_fmt_eta(ads_decode_result_t *r, ads_value_t *v) { | ||
| push_tod(r, v, "eta_time", "time", "ETA", "Estimated Time of Arrival"); | ||
| } | ||
| void ads_fmt_off(ads_decode_result_t *r, ads_value_t *v) { | ||
| push_tod(r, v, "off_time", "time", "OFF", "Takeoff Time"); | ||
| } | ||
| void ads_fmt_on(ads_decode_result_t *r, ads_value_t *v) { | ||
| push_tod(r, v, "on_time", "time", "ON", "Landing Time"); | ||
| } | ||
| void ads_fmt_in(ads_decode_result_t *r, ads_value_t *v) { | ||
| push_tod(r, v, "in_time", "time", "IN", "Arrival at Gate"); | ||
| } | ||
| void ads_fmt_out(ads_decode_result_t *r, ads_value_t *v) { | ||
| push_tod(r, v, "out_time", "time", "OUT", "Departure from Gate"); | ||
|
Comment on lines
+163
to
+167
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For OUT/IN time formatters, the TypeScript reference labels these items Useful? React with 👍 / 👎.
Comment on lines
+163
to
+167
|
||
| } | ||
|
|
||
| /* ─── Calendar formatters ────────────────────────────────────────────────── */ | ||
|
|
||
| static void push_int_item(ads_decode_result_t *r, ads_value_t *v, const char *raw_key, | ||
| const char *kind, const char *code, const char *label) { | ||
| if (!v) return; | ||
| int64_t n = 0; | ||
| ads_value_as_int(v, &n); | ||
| cJSON_AddNumberToObject(r->raw, raw_key, (double)n); | ||
| char buf[32]; | ||
| snprintf(buf, sizeof(buf), "%lld", (long long)n); | ||
| push_item(r, kind, code, label, buf); | ||
| ads_value_free(v); | ||
| } | ||
|
|
||
| void ads_fmt_day(ads_decode_result_t *r, ads_value_t *v) { push_int_item(r, v, "day", "day", "MSG_DAY", "Day of Month"); } | ||
| void ads_fmt_departure_day(ads_decode_result_t *r, ads_value_t *v) { push_int_item(r, v, "departure_day", "day", "DEP_DAY", "Departure Day"); } | ||
| void ads_fmt_arrival_day(ads_decode_result_t *r, ads_value_t *v) { push_int_item(r, v, "arrival_day", "day", "ARR_DAY", "Arrival Day"); } | ||
| void ads_fmt_month(ads_decode_result_t *r, ads_value_t *v) { push_int_item(r, v, "month", "month", "MSG_MONTH", "Month"); } | ||
|
|
||
|
|
||
| /* ─── Velocity / atmosphere formatters ───────────────────────────────────── */ | ||
|
|
||
| void ads_fmt_mach(ads_decode_result_t *r, ads_value_t *v) { push_numeric(r, v, "mach", "mach", "MACH", "Mach", ""); } | ||
| void ads_fmt_groundspeed(ads_decode_result_t *r, ads_value_t *v) { push_numeric(r, v, "groundspeed", "groundspeed", "GS", "Ground Speed", "knots"); } | ||
| void ads_fmt_airspeed(ads_decode_result_t *r, ads_value_t *v) { push_numeric(r, v, "airspeed", "airspeed", "IAS", "Indicated Airspeed", "knots"); } | ||
|
Comment on lines
+191
to
+193
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When hatches use these new velocity formatters, their formatted item shapes differ from Useful? React with 👍 / 👎. |
||
| void ads_fmt_temperature(ads_decode_result_t *r, ads_value_t *v) { push_numeric(r, v, "outside_air_temperature", "outside_air_temperature", "OATEMP", "Outside Air Temperature (C)", "degrees"); } | ||
| void ads_fmt_total_air_temp(ads_decode_result_t *r, ads_value_t *v) { push_numeric(r, v, "total_air_temperature", "total_air_temperature", "TATEMP", "Total Air Temperature (C)", "degrees"); } | ||
|
Comment on lines
+194
to
+195
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The TS Useful? React with 👍 / 👎.
Comment on lines
+191
to
+195
|
||
|
|
||
| /* ─── Fuel formatters ────────────────────────────────────────────────────── */ | ||
|
|
||
| void ads_fmt_current_fuel(ads_decode_result_t *r, ads_value_t *v) { push_numeric(r, v, "fuel_on_board", "fuel_on_board", "FOB", "Fuel On Board", ""); } | ||
| void ads_fmt_remaining_fuel(ads_decode_result_t *r, ads_value_t *v) { push_numeric(r, v, "fuel_remaining", "fuel_remaining", "FUEL_REM", "Fuel Remaining", ""); } | ||
|
|
||
|
|
||
| /* ─── Routing formatters ─────────────────────────────────────────────────── */ | ||
|
|
||
| void ads_fmt_alternate_airport(ads_decode_result_t *r, ads_value_t *v) { push_string(r, v, "alternate_icao", "icao", "ALT_DST", "Alternate Destination"); } | ||
| void ads_fmt_arrival_runway(ads_decode_result_t *r, ads_value_t *v) { push_string(r, v, "arrival_runway", "runway", "ARWY", "Arrival Runway"); } | ||
| void ads_fmt_alternate_runway(ads_decode_result_t *r, ads_value_t *v) { push_string(r, v, "alternate_runway", "runway", "ALT_RWY", "Alternate Runway"); } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For decoded alternate runways, the TypeScript formatter emits code Useful? React with 👍 / 👎. |
||
|
|
||
| /* ─── Event formatters ───────────────────────────────────────────────────── */ | ||
|
|
||
| void ads_fmt_state_change(ads_decode_result_t *r, const char *from, const char *to) { | ||
| if (!r || !from || !to) return; | ||
| cJSON *obj = cJSON_CreateObject(); | ||
| cJSON_AddStringToObject(obj, "from", from); | ||
| cJSON_AddStringToObject(obj, "to", to); | ||
| cJSON_AddItemToObject(r->raw, "state_change", obj); | ||
| char buf[128]; | ||
| snprintf(buf, sizeof(buf), "%s -> %s", from, to); | ||
| push_item(r, "state_change", "STATE_CHANGE", "State Change", buf); | ||
| } | ||
|
Comment on lines
+210
to
+219
|
||
|
|
||
| void ads_fmt_door_event(ads_decode_result_t *r, const char *door, const char *state) { | ||
| if (!r || !door || !state) return; | ||
| cJSON *obj = cJSON_CreateObject(); | ||
| cJSON_AddStringToObject(obj, "door", door); | ||
| cJSON_AddStringToObject(obj, "state", state); | ||
| cJSON_AddItemToObject(r->raw, "door_event", obj); | ||
| char buf[128]; | ||
| snprintf(buf, sizeof(buf), "%s %s", door, state); | ||
| push_item(r, "door_event", "DOOR", "Door Event", buf); | ||
| } | ||
|
|
||
| /* ─── Free-text formatters ───────────────────────────────────────────────── */ | ||
|
|
||
| void ads_fmt_text(ads_decode_result_t *r, const char *value) { | ||
| if (!r || !value) return; | ||
| cJSON_AddStringToObject(r->raw, "text", value); | ||
| push_item(r, "text", "TEXT", "Text Message", value); | ||
| } | ||
|
|
||
| /* ─── Diagnostic formatters ──────────────────────────────────────────────── */ | ||
|
|
||
| void ads_fmt_checksum(ads_decode_result_t *r, ads_value_t *v) { | ||
| if (!v) return; | ||
| int64_t n = 0; | ||
| ads_value_as_int(v, &n); | ||
| cJSON_AddNumberToObject(r->raw, "checksum", (double)n); | ||
| char buf[32]; | ||
| snprintf(buf, sizeof(buf), "%llx", (long long)n); | ||
| push_item(r, "checksum", "CKSUM", "Checksum", buf); | ||
|
Comment on lines
+248
to
+249
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For messages that include a checksum, the TypeScript formatter emits Useful? React with 👍 / 👎. |
||
| ads_value_free(v); | ||
|
Comment on lines
+242
to
+250
|
||
| } | ||
|
|
||
| void ads_fmt_checksum_algorithm(ads_decode_result_t *r, const char *value) { | ||
| if (!r || !value) return; | ||
| cJSON_AddStringToObject(r->raw, "checksum_algorithm", value); | ||
| push_item(r, "checksum_algorithm", "CKSUM_ALGO", "Checksum Algorithm", value); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When ARINC 702-style hatches call Useful? React with 👍 / 👎. |
||
| } | ||
|
Comment on lines
+253
to
+257
|
||
|
|
||
| /* ─── Generic structured-item push ───────────────────────────────────────── */ | ||
|
|
||
| void ads_fmt_push_item(ads_decode_result_t *r, const char *type, const char *code, | ||
| const char *label, const char *value) { | ||
| if (!r) return; | ||
| push_item(r, | ||
| type ? type : "unknown", | ||
| code ? code : "", | ||
| label ? label : "", | ||
| value ? value : ""); | ||
| } | ||
|
|
||
| /* ─── Result mutators (declared in ads_helpers.h) ────────────────────────── */ | ||
|
|
||
| void ads_result_set_description(ads_decode_result_t *r, const char *description) { | ||
| if (!r) return; | ||
| free(r->description); | ||
| r->description = description ? strdup(description) : NULL; | ||
| } | ||
|
Comment on lines
+273
to
+277
|
||
|
|
||
| void ads_result_set_remaining(ads_decode_result_t *r, const char *text) { | ||
| if (!r) return; | ||
| free(r->remaining); | ||
| r->remaining = text ? strdup(text) : NULL; | ||
| } | ||
|
|
||
| void ads_result_append_remaining(ads_decode_result_t *r, const char *text, const char *sep) { | ||
| if (!r || !text) return; | ||
| if (!sep) sep = ","; | ||
| if (r->remaining) { | ||
| size_t newlen = strlen(r->remaining) + 1 + strlen(joined) + 1; | ||
| size_t newlen = strlen(r->remaining) + strlen(sep) + strlen(text) + 1; | ||
| char *grown = malloc(newlen); | ||
| snprintf(grown, newlen, "%s,%s", r->remaining, joined); | ||
| if (!grown) return; | ||
| snprintf(grown, newlen, "%s%s%s", r->remaining, sep, text); | ||
| free(r->remaining); | ||
| r->remaining = grown; | ||
| } else { | ||
| r->remaining = strdup(joined); | ||
| r->remaining = strdup(text); | ||
| } | ||
|
Comment on lines
+279
to
297
|
||
| free(joined); | ||
| } | ||
|
|
||
| const char *ads_result_get_remaining(const ads_decode_result_t *r) { | ||
| return r ? r->remaining : NULL; | ||
| } | ||
|
|
||
| void ads_result_set_decode_level(ads_decode_result_t *r, ads_decode_level_t level) { | ||
| if (!r) return; | ||
| r->decode_level = level; | ||
| } | ||
|
|
||
| void ads_result_clear_items(ads_decode_result_t *r) { | ||
| if (!r) return; | ||
| cJSON_Delete(r->items); | ||
| r->items = cJSON_CreateArray(); | ||
| } | ||
|
Comment on lines
+309
to
313
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documentation overstates ownership scope.
The comment says "Every ads_fmt_*" takes ownership of
ads_value_t*, but severalads_fmt_*functions declared below don't acceptads_value_t*at all (e.g.,ads_fmt_state_change,ads_fmt_door_event,ads_fmt_text,ads_fmt_unknown*,ads_fmt_checksum_algorithm,ads_fmt_push_item). Consider clarifying:📝 Suggested wording
📝 Committable suggestion
🤖 Prompt for AI Agents