diff --git a/bshell.runtime/format/format.c b/bshell.runtime/format/format.c index ae56da4..e94d480 100644 --- a/bshell.runtime/format/format.c +++ b/bshell.runtime/format/format.c @@ -21,17 +21,10 @@ static void format_value_fallback(const fx_value *value, fx_stream *dest) enum bshell_status format_value_default(const fx_value *value, fx_stream *dest) { - if (fx_type_is_value_type(value->v_type)) { - format_value_fallback(value, dest); - return BSHELL_SUCCESS; - } - - fx_object *object = NULL; - fx_value_get_object(value, &object); - enum bshell_status status = format_object_table(object, dest); - if (status != BSHELL_SUCCESS) { - format_value_fallback(value, dest); - } + struct bshell_value_writer writer; + bshell_value_writer_init(&writer, dest); + bshell_value_writer_write(&writer, value); + bshell_value_writer_cleanup(&writer); return BSHELL_SUCCESS; } diff --git a/bshell.runtime/format/value-writer.c b/bshell.runtime/format/value-writer.c new file mode 100644 index 0000000..b626779 --- /dev/null +++ b/bshell.runtime/format/value-writer.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include + +static void initialise_table( + struct bshell_value_writer *w, + const fx_value *first_record) +{ + bshell_table_ctx_init(&w->w_table_ctx, w->w_dest); + const fx_type *ty = fx_type_get_by_id(first_record->v_type); + bshell_table_ctx_prepare_columns_from_format(&w->w_table_ctx, ty, NULL); + bshell_table_ctx_print_headers(&w->w_table_ctx); + w->w_table_initialised = true; +} + +static void write_iterable(struct bshell_value_writer *w, const fx_value *value) +{ + fx_array *array = NULL; + fx_value_get_object(value, &array); + + const fx_iterator *it = fx_iterator_begin(array); + fx_foreach(v, it) + { + bshell_value_writer_write(w, v); + } + fx_iterator_unref(it); +} + +static void write_string(struct bshell_value_writer *w, const fx_value *value) +{ + const char *str = NULL; + fx_value_get_cstr(value, &str); + fx_stream_write_cstr(w->w_dest, str, NULL); + fx_stream_write_char(w->w_dest, '\n'); +} + +static void write_value(struct bshell_value_writer *w, const fx_value *value) +{ + const fx_type *ty = fx_type_get_by_id(value->v_type); + if (fx_value_is_type(value, FX_TYPE_STRING)) { + write_string(w, value); + return; + } + + if (fx_type_get_interface(ty, FX_TYPE_ITERABLE)) { + write_iterable(w, value); + return; + } + + if (fx_type_is_value_type(value->v_type)) { + fx_value_to_string(value, w->w_dest, NULL); + fx_stream_write_char(w->w_dest, '\n'); + return; + } + + if (!w->w_table_initialised) { + initialise_table(w, value); + } + + bshell_table_ctx_print_record(&w->w_table_ctx, value); +} + +void bshell_value_writer_init(struct bshell_value_writer *w, fx_stream *dest) +{ + memset(w, 0x00, sizeof *w); + w->w_dest = dest; +} + +void bshell_value_writer_write( + struct bshell_value_writer *w, + const fx_value *value) +{ + write_value(w, value); +} + +void bshell_value_writer_cleanup(struct bshell_value_writer *w) +{ + if (w->w_table_initialised) { + bshell_table_ctx_cleanup(&w->w_table_ctx); + } + + w->w_table_initialised = false; +} diff --git a/bshell.runtime/include/bshell/format.h b/bshell.runtime/include/bshell/format.h index 929eca0..bb450f2 100644 --- a/bshell.runtime/include/bshell/format.h +++ b/bshell.runtime/include/bshell/format.h @@ -47,6 +47,12 @@ struct bshell_table_ctx { fx_stream *ctx_out; }; +struct bshell_value_writer { + struct bshell_table_ctx w_table_ctx; + bool w_table_initialised; + fx_stream *w_dest; +}; + extern enum bshell_status bshell_table_init(void); extern const struct bshell_table *bshell_table_get_for_type(const fx_type *ty); extern enum bshell_status format_object_table( @@ -74,4 +80,12 @@ extern enum bshell_status bshell_table_ctx_print_record( struct bshell_table_ctx *ctx, const fx_value *record); +extern void bshell_value_writer_init( + struct bshell_value_writer *w, + fx_stream *dest); +extern void bshell_value_writer_write( + struct bshell_value_writer *w, + const fx_value *value); +extern void bshell_value_writer_cleanup(struct bshell_value_writer *w); + #endif diff --git a/bshell.runtime/include/bshell/runtime/runtime.h b/bshell.runtime/include/bshell/runtime/runtime.h index 16c6284..1bb6aee 100644 --- a/bshell.runtime/include/bshell/runtime/runtime.h +++ b/bshell.runtime/include/bshell/runtime/runtime.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -15,6 +16,7 @@ struct bshell_runtime { struct bshell_runtime_scope *rt_global; fx_hashtable *rt_aliases; fx_queue rt_scope; + struct bshell_value_writer rt_writer; }; extern struct bshell_runtime *bshell_runtime_create(void); @@ -53,4 +55,10 @@ extern struct bshell_runtime_scope *bshell_runtime_get_parent_scope( struct bshell_runtime *rt, struct bshell_runtime_scope *scope); +extern void bshell_runtime_begin_output(struct bshell_runtime *rt); +extern void bshell_runtime_output_value( + struct bshell_runtime *rt, + const fx_value *value); +extern void bshell_runtime_end_output(struct bshell_runtime *rt); + #endif diff --git a/bshell.runtime/runtime/eval.c b/bshell.runtime/runtime/eval.c index 7415cbb..d10b707 100644 --- a/bshell.runtime/runtime/eval.c +++ b/bshell.runtime/runtime/eval.c @@ -353,10 +353,8 @@ static enum bshell_status eval_instruction( } int end_of_data = 0; - bool columns_initialised = false; fx_value record = FX_VALUE_EMPTY; - struct bshell_table_ctx table_ctx; - bshell_table_ctx_init(&table_ctx, fx_stdout); + bshell_runtime_begin_output(rt); while (1) { bstatus = bshell_pipeline_pump_record( pipeline, @@ -371,22 +369,11 @@ static enum bshell_status eval_instruction( continue; } - if (!columns_initialised) { - const fx_type *ty - = fx_type_get_by_id(record.v_type); - bshell_table_ctx_prepare_columns_from_format( - &table_ctx, - ty, - NULL); - bshell_table_ctx_print_headers(&table_ctx); - columns_initialised = true; - } - - bshell_table_ctx_print_record(&table_ctx, &record); + bshell_runtime_output_value(rt, &record); fx_value_unset(&record); } - bshell_table_ctx_cleanup(&table_ctx); + bshell_runtime_end_output(rt); bshell_pipeline_unref(pipeline); break; } diff --git a/bshell.runtime/runtime/output.c b/bshell.runtime/runtime/output.c new file mode 100644 index 0000000..b0b8c2a --- /dev/null +++ b/bshell.runtime/runtime/output.c @@ -0,0 +1,20 @@ +#include +#include +#include + +void bshell_runtime_begin_output(struct bshell_runtime *rt) +{ + bshell_value_writer_init(&rt->rt_writer, fx_stdout); +} + +void bshell_runtime_output_value( + struct bshell_runtime *rt, + const fx_value *value) +{ + bshell_value_writer_write(&rt->rt_writer, value); +} + +void bshell_runtime_end_output(struct bshell_runtime *rt) +{ + bshell_value_writer_cleanup(&rt->rt_writer); +}