aboutsummaryrefslogtreecommitdiffstats
path: root/prototypes/connections/pure-run.c
diff options
context:
space:
mode:
Diffstat (limited to 'prototypes/connections/pure-run.c')
-rw-r--r--prototypes/connections/pure-run.c48
1 files changed, 43 insertions, 5 deletions
diff --git a/prototypes/connections/pure-run.c b/prototypes/connections/pure-run.c
index e14e6ad..7f9f316 100644
--- a/prototypes/connections/pure-run.c
+++ b/prototypes/connections/pure-run.c
@@ -7,7 +7,8 @@
/* Test host for a verified module: reads commands from stdin and prints one
* JSON snapshot per command. Not a product interface.
* down NAME | up NAME | frame [N] | type NAME HEX|- | replace PATH | show
- * Text states and text views print as JSON strings; cursors as byte positions. */
+ * Text states and text views print as JSON strings; cursors as byte positions;
+ * lists as arrays of objects; indices as positions. A failed view is null. */
static const char *const fault_names[] = {"none", "divide", "non_finite", "clamp", "limit", "not_found", "encoding"};
static bool load(const char *path, PureModule *module) {
@@ -36,6 +37,36 @@ static bool json_span(void *context, PureSpan span) {
return true;
}
+/* A text view is collected first: it may fail after some bytes. */
+typedef struct { unsigned char bytes[1 << 16]; size_t used; bool fits; } Collected;
+
+static bool collect(void *context, PureSpan span) {
+ Collected *c = context;
+ c->fits = c->fits && span.size <= sizeof(c->bytes) - c->used;
+ if (c->fits && span.size) memcpy(c->bytes + c->used, span.data, span.size);
+ if (c->fits) c->used += span.size;
+ return true;
+}
+
+static void show_list(const PureModule *m, const PureList *list, const PureRecord *record) {
+ putchar('[');
+ for (size_t at = 0; at < pure_list_count(list); ++at) {
+ printf("%s{", at ? "," : "");
+ for (unsigned f = 0; f < record->count; ++f) {
+ PureCell cell = pure_list_get(list, at, f);
+ printf("%s\"%s\":", f ? "," : "", m->record_field_names[record->first + f]);
+ if (!m->record_field_text[record->first + f]) printf("%.17g", cell.num);
+ else {
+ putchar('"');
+ json_span(NULL, (PureSpan){cell.text, cell.size});
+ putchar('"');
+ }
+ }
+ putchar('}');
+ }
+ putchar(']');
+}
+
static void show(PureApp *app, const char *failure) {
const PureModule *m = app->module;
printf("{\"states\":{");
@@ -45,16 +76,23 @@ static void show(PureApp *app, const char *failure) {
putchar('"');
pure_draft_read(app->texts[i], 0, pure_draft_size(app->texts[i]), json_span, NULL);
putchar('"');
- } else printf("%.17g", app->values[i]);
+ } else if (m->state_type[i] == PURE_STATE_LIST) show_list(m, app->lists[i], &m->record[m->state_ref[i]]);
+ else printf("%.17g", app->values[i]);
}
printf("},\"views\":{");
for (uint32_t i = 0; i < m->views; ++i) {
printf("%s\"%s\":", i ? "," : "", m->view_names[i]);
double value;
+ static Collected text;
+ text.used = 0;
+ text.fits = true;
if (m->view_type[i] == PURE_VIEW_TEXT) {
- putchar('"');
- if (pure_app_view_text(app, i, json_span, NULL) != PURE_OK) printf("\\u0000failed");
- putchar('"');
+ if (pure_app_view_text(app, i, collect, &text) != PURE_OK || !text.fits) printf("null");
+ else {
+ putchar('"');
+ json_span(NULL, (PureSpan){text.bytes, text.used});
+ putchar('"');
+ }
} else if (pure_app_view(app, i, &value)) printf("%.17g", value);
else printf("null");
}