*
* Values of f_fss_payload_write_*_e:
* - none: No write flag set.
+ * - base_2: Convert number to string using base 2.
+ * - base_8: Convert number to string using base 8.
+ * - base_10: Convert number to string using base 10.
+ * - base_12: Convert number to string using base 12.
+ * - base_16: Convert number to string using base 16.
* - comment_header: Print the header comment for the Simple Packet, "# fss-000f\n".
* - header_content: Print the header content.
* - header_object: Print the header object, "header:\n".
#ifndef _di_f_fss_payload_write_e_
enum {
f_fss_payload_write_none_e = 0x0,
- f_fss_payload_write_comment_header_e = 0x1,
- f_fss_payload_write_header_content_e = 0x2,
- f_fss_payload_write_header_object_e = 0x4,
- f_fss_payload_write_payload_object_e = 0x8,
- f_fss_payload_write_signature_content_e = 0x10,
- f_fss_payload_write_signature_object_e = 0x20,
+ f_fss_payload_write_base_2_e = 0x1,
+ f_fss_payload_write_base_8_e = 0x2,
+ f_fss_payload_write_base_10_e = 0x4,
+ f_fss_payload_write_base_12_e = 0x8,
+ f_fss_payload_write_base_16_e = 0x10,
+ f_fss_payload_write_comment_header_e = 0x20,
+ f_fss_payload_write_header_content_e = 0x40,
+ f_fss_payload_write_header_object_e = 0x80,
+ f_fss_payload_write_payload_object_e = 0x100,
+ f_fss_payload_write_signature_content_e = 0x200,
+ f_fss_payload_write_signature_object_e = 0x400,
}; // enum
#endif // _di_f_fss_payload_write_e_
/**
- * FSS Simple Packet strings.
+ * FSS Payload strings.
*
* f_fss_payload_*_s:
- * - header_comment: The header comment string for Simple Packet (FSS-000E).
+ * - header_comment: The header comment string for Payload (FSS-000E).
* - header_object: The header object.
* - payload_object: The payload object.
* - signature_object: The signature object.
*/
#ifndef _di_f_fss_payload_s_
- #define F_fss_payload_comment_header_s "# fss-000e"
+ #define F_fss_payload_comment_header_s "# fss-000e\n"
#define F_fss_payload_object_header_s "header:\n"
#define F_fss_payload_object_payload_s "payload:\n"
#define F_fss_payload_object_signature_s "signature:\n"
#ifndef _di_level_1_parameter_checking_
if (!state) return;
- if (!destination) {
+ if (!destination || !state->data) {
state->status = F_status_set_error(F_parameter);
+ if (state->handle) {
+ state->handle((void * const) state, 0);
+ }
+
return;
}
#endif // _di_level_1_parameter_checking_
+ f_fss_payload_header_write_state_t * const data = (f_fss_payload_header_write_state_t *) state->data;
+ f_fss_payload_header_write_internal_t internal = macro_f_fss_payload_header_write_internal_t_initialize_2(destination, destination->used);
+
+ if (!data->cache) {
+ state->status = F_status_set_error(F_parameter);
+
+ if (state->handle) {
+ state->handle((void * const) state, 0);
+ }
+
+ return;
+ }
+
+ // Pre-allocate as much as possible to reduce memory reallocation chances, using 'j'.
+ {
+ internal.j = 0;
+
+ if (state->code & f_fss_payload_write_comment_header_e) {
+ internal.j += f_fss_payload_comment_header_s.used + 1;
+ }
+
+ if (state->code & f_fss_payload_write_header_object_e) {
+ internal.j += f_fss_payload_object_header_s.used + 1;
+ }
+
+ // This uses step large to at least do something for header content.
+ if (state->code & f_fss_payload_write_header_content_e) {
+ internal.j += state->step_large + headers.used + 1;
+ }
+
+ if (state->code & f_fss_payload_write_signature_object_e) {
+ internal.j += f_fss_payload_object_signature_s.used + 1;
+ }
+
+ // This uses step large to at least do something for signature content.
+ if ((state->code & f_fss_payload_write_signature_content_e) && signatures) {
+ internal.j += state->step_large + signatures->used + 1;
+ }
+
+ if (state->code & f_fss_payload_write_payload_object_e) {
+ internal.j += f_fss_payload_object_payload_s.used + 1;
+ }
+
+ state->status = f_memory_array_increase_by(internal.j + 1, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+
+ internal.j = 0;
+
+ if (F_status_is_error(state->status)) {
+ if (state->handle) {
+ state->handle((void * const) state, (void * const) &internal);
+
+ if (F_status_is_error(state->status)) {
+ destination->used = internal.original;
+
+ return;
+ }
+ }
+ else {
+ destination->used = internal.original;
+
+ return;
+ }
+ }
+ }
+
if (state->code & f_fss_payload_write_comment_header_e) {
- // @todo flag for writing "# fss-000c"
+ internal.step = f_fss_payload_write_comment_header_e;
+
+ state->status = f_string_dynamic_append(f_fss_payload_comment_header_s, destination);
+
+ if (F_status_is_error(state->status)) {
+ if (state->handle) {
+ state->handle((void * const) state, (void * const) &internal);
+
+ if (F_status_is_error(state->status)) {
+ destination->used = internal.original;
+
+ return;
+ }
+ }
+ else {
+ destination->used = internal.original;
+
+ return;
+ }
+ }
}
if (state->code & f_fss_payload_write_header_object_e) {
- // @todo flag for writing "header:"
+ internal.step = f_fss_payload_write_header_object_e;
+
+ state->status = f_string_dynamic_append(f_fss_payload_object_header_s, destination);
+
+ if (F_status_is_error(state->status)) {
+ if (state->handle) {
+ state->handle((void * const) state, (void * const) &internal);
+
+ if (F_status_is_error(state->status)) {
+ destination->used = internal.original;
+
+ return;
+ }
+ }
+ else {
+ destination->used = internal.original;
+
+ return;
+ }
+ }
}
-/*
if (state->code & f_fss_payload_write_header_content_e) {
- for (f_number_unsigned_t i = 0; i < headers.used ; ++i) {
+ internal.step = f_fss_payload_write_header_content_e;
- switch () {
- f_abstruse_none_e:
- f_abstruse_void_e:
- f_abstruse_voids_e:
- f_abstruse_strings_e:
- break;
+ f_string_static_t string_static = f_string_static_t_initialize;
- f_abstruse_signed_e:
- f_abstruse_unsigned_e:
- // @todo
- break;
+ for (; internal.i < headers.used ; ++internal.i) {
- f_abstruse_int8s_e:
- f_abstruse_int16s_e:
- f_abstruse_int32s_e:
- f_abstruse_int64s_e:
- f_abstruse_signeds_e:
- // @todo
- break;
+ if (state->interrupt) {
+ state->interrupt((void * const) state, (void * const) &internal);
+ if (F_status_set_fine(state->status) == F_interrupt) return;
+ }
- f_abstruse_uint8s_e:
- f_abstruse_uint16s_e:
- f_abstruse_uint32s_e:
- f_abstruse_uint64s_e:
- f_abstruse_unsigneds_e:
- // @todo
- break;
+ if (!headers.array[internal.i].key.used) continue;
- f_abstruse_string_e:
- f_abstruse_strings_e:
- // @todo
- break;
+ internal.range.start = 0;
+ internal.range.stop = headers.array[internal.i].key.used - 1;
+ data->cache->used = 0;
- f_abstruse_dynamic_e:
- f_abstruse_dynamics_e:
- // @todo
- break;
+ // Pre-allocate space for the key, value (using step_large), separator space, EOL, and terminating NULL if necessary.
+ state->status = f_memory_array_increase_by(headers.array[internal.i].key.used + state->step_large + 3, sizeof(f_char_t), (void **) &data->cache->string, &data->cache->used, &data->cache->size);
- f_abstruse_map_e:
- f_abstruse_maps_e:
- // @todo
- break;
+ if (F_status_is_error_not(state->status)) {
+ data->cache->string[data->cache->used++] = f_fss_extended_open_s.string[0];
- f_abstruse_map_multi_e:
- f_abstruse_map_multis_e:
- // @todo
- break;
+ private_fl_fss_basic_write(F_true, headers.array[internal.i].key, 0, &internal.range, data->cache, state, (void * const) &internal);
+ }
- f_abstruse_quantity_e:
- f_abstruse_quantitys_e:
- // @todo
- break;
+ if (F_status_is_error_not(state->status)) {
+ switch (headers.array[internal.i].value.type) {
+ case f_abstruse_none_e:
+ case f_abstruse_void_e:
+ case f_abstruse_voids_e:
+ break;
+
+ case f_abstruse_signed_e:
+ data->cache->used = 0;
+
+ state->status = f_conversion_number_signed_to_string(headers.array[internal.i].value.is.a_signed, data->conversion, data->cache);
+
+ break;
+
+ case f_abstruse_unsigned_e:
+ data->cache->used = 0;
+
+ state->status = f_conversion_number_unsigned_to_string(headers.array[internal.i].value.is.a_unsigned, data->conversion, data->cache);
+
+ break;
+
+ case f_abstruse_int8s_e:
+ case f_abstruse_int16s_e:
+ case f_abstruse_int32s_e:
+ case f_abstruse_int64s_e:
+ case f_abstruse_signeds_e:
+ // @todo
+ break;
+
+ case f_abstruse_uint8s_e:
+ case f_abstruse_uint16s_e:
+ case f_abstruse_uint32s_e:
+ case f_abstruse_uint64s_e:
+ case f_abstruse_unsigneds_e:
+ // @todo
+ break;
+
+ case f_abstruse_string_e:
+ string_static.string = headers.array[internal.i].value.is.a_string;
+ string_static.used = strnlen(headers.array[internal.i].value.is.a_string, F_string_t_size_d);
+
+ internal.range.start = 0;
+ internal.range.stop = string_static.used;
+
+ private_fl_fss_basic_write(F_false, string_static, 0, &internal.range, data->cache, state, (void * const) &internal);
+
+ if (F_status_is_error(state->status)) {
+ destination->used = internal.original;
+ }
+
+ case f_abstruse_strings_e:
+ // @todo
+ break;
+
+ case f_abstruse_dynamic_e:
+ case f_abstruse_dynamics_e:
+ // @todo
+ break;
+
+ case f_abstruse_map_e:
+ case f_abstruse_maps_e:
+ // @todo
+ break;
+
+ case f_abstruse_map_multi_e:
+ case f_abstruse_map_multis_e:
+ // @todo
+ break;
+
+ case f_abstruse_quantity_e:
+ case f_abstruse_quantitys_e:
+ // @todo
+ break;
+
+ case f_abstruse_range_e:
+ case f_abstruse_ranges_e:
+ // @todo
+ break;
+
+ case f_abstruse_triple_e:
+ case f_abstruse_triples_e:
+ // @todo
+ break;
+
+ default:
+ break;
+ }
+ }
- f_abstruse_range_e:
- f_abstruse_ranges_e:
- // @todo
- break;
+ if (F_status_is_error_not(state->status)) {
+ if (data->cache->used) {
- f_abstruse_triple_e:
- f_abstruse_triples_e:
- // @todo
- break;
+ // Pre-allocate space for the built string and terminating NULL if necessary.
+ state->status = f_memory_array_increase_by(data->cache->used + 1, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+
+ if (F_status_is_error_not(state->status)) {
+ state->status = f_string_dynamic_append(*data->cache, destination);
+ }
+ }
+ }
+
+ if (F_status_is_error(state->status)) {
+ if (state->handle) {
+ state->handle((void * const) state, (void * const) &internal);
+
+ if (F_status_is_error(state->status)) {
+ destination->used = internal.original;
+
+ return;
+ }
+ }
+ else {
+ destination->used = internal.original;
+
+ return;
+ }
}
} // for
}
if (state->code & f_fss_payload_write_signature_object_e) {
- // @todo flag for writing "signature:"
+ internal.step = f_fss_payload_write_signature_object_e;
+
+ state->status = f_string_dynamic_append(f_fss_payload_object_signature_s, destination);
+
+ if (F_status_is_error(state->status)) {
+ if (state->handle) {
+ state->handle((void * const) state, (void * const) &internal);
+
+ if (F_status_is_error(state->status)) {
+ destination->used = internal.original;
+
+ return;
+ }
+ }
+ else {
+ destination->used = internal.original;
+
+ return;
+ }
+ }
}
if ((state->code & f_fss_payload_write_signature_content_e) && !signatures) {
- for (f_number_unsigned_t i = 0; i < signatures->used ; ++i) {
+ internal.step = f_fss_payload_write_signature_content_e;
+
+ for (internal.i = 0; internal.i < signatures->used ; ++internal.i) {
+
+ if (state->interrupt) {
+ state->interrupt((void * const) state, (void * const) &internal);
+ if (F_status_set_fine(state->status) == F_interrupt) return;
+ }
- switch () {
- f_abstruse_none_e:
- f_abstruse_void_e:
- f_abstruse_voids_e:
- f_abstruse_strings_e:
+ switch (signatures->array[internal.i].value.type) {
+ case f_abstruse_none_e:
+ case f_abstruse_void_e:
+ case f_abstruse_voids_e:
break;
- f_abstruse_signed_e:
- f_abstruse_unsigned_e:
+ case f_abstruse_signed_e:
+ case f_abstruse_unsigned_e:
// @todo
break;
- f_abstruse_int8s_e:
- f_abstruse_int16s_e:
- f_abstruse_int32s_e:
- f_abstruse_int64s_e:
- f_abstruse_signeds_e:
+ case f_abstruse_int8s_e:
+ case f_abstruse_int16s_e:
+ case f_abstruse_int32s_e:
+ case f_abstruse_int64s_e:
+ case f_abstruse_signeds_e:
// @todo
break;
- f_abstruse_uint8s_e:
- f_abstruse_uint16s_e:
- f_abstruse_uint32s_e:
- f_abstruse_uint64s_e:
- f_abstruse_unsigneds_e:
+ case f_abstruse_uint8s_e:
+ case f_abstruse_uint16s_e:
+ case f_abstruse_uint32s_e:
+ case f_abstruse_uint64s_e:
+ case f_abstruse_unsigneds_e:
// @todo
break;
- f_abstruse_string_e:
- f_abstruse_strings_e:
+ case f_abstruse_string_e:
+ case f_abstruse_strings_e:
// @todo
break;
- f_abstruse_dynamic_e:
- f_abstruse_dynamics_e:
+ case f_abstruse_dynamic_e:
+ case f_abstruse_dynamics_e:
// @todo
break;
- f_abstruse_map_e:
- f_abstruse_maps_e:
+ case f_abstruse_map_e:
+ case f_abstruse_maps_e:
// @todo
break;
- f_abstruse_map_multi_e:
- f_abstruse_map_multis_e:
+ case f_abstruse_map_multi_e:
+ case f_abstruse_map_multis_e:
// @todo
break;
- f_abstruse_quantity_e:
- f_abstruse_quantitys_e:
+ case f_abstruse_quantity_e:
+ case f_abstruse_quantitys_e:
// @todo
break;
- f_abstruse_range_e:
- f_abstruse_ranges_e:
+ case f_abstruse_range_e:
+ case f_abstruse_ranges_e:
// @todo
break;
- f_abstruse_triple_e:
- f_abstruse_triples_e:
+ case f_abstruse_triple_e:
+ case f_abstruse_triples_e:
// @todo
break;
+
+ default:
+ break;
}
} // for
}
-*/
+
if (state->code & f_fss_payload_write_payload_object_e) {
- // @todo flag for writing "payload:"
+ internal.step = f_fss_payload_write_payload_object_e;
+
+ state->status = f_string_dynamic_append(f_fss_payload_object_payload_s, destination);
+
+ if (F_status_is_error(state->status)) {
+ if (state->handle) {
+ state->handle((void * const) state, (void * const) &internal);
+
+ if (F_status_is_error(state->status)) {
+ destination->used = internal.original;
+
+ return;
+ }
+ }
+ else {
+ destination->used = internal.original;
+
+ return;
+ }
+ }
}
state->status = F_okay;
#include <fll/level_0/string.h>
#include <fll/level_0/utf.h>
#include <fll/level_0/abstruse.h>
+#include <fll/level_0/conversion.h>
#include <fll/level_0/fss.h>
// FLL-1 includes.
extern "C" {
#endif
+/**
+ * An internal structure for the fss_payload_header_write() passed to callbacks.
+ *
+ * Properties:
+ * - step: The current step.
+ * - i: A counter used for the "headers" and "signatures" outer arrays.
+ * - j: A counter used for the inner loop or for pre-allocation counting.
+ * - conversion: The conversion data.
+ * - destination: The destination string being written to.
+ * - original: The original destination used length.
+ */
+#ifndef _di_f_fss_payload_header_write_internal_t_
+ typedef struct {
+ uint16_t step;
+ f_number_unsigned_t i;
+ f_number_unsigned_t j;
+ f_string_range_t range;
+ f_conversion_data_t conversion;
+
+ f_string_dynamic_t * const destination;
+ const f_number_unsigned_t original;
+ } f_fss_payload_header_write_internal_t;
+
+ #define f_fss_payload_header_write_internal_t_initialize { \
+ 0, \
+ 0, \
+ 0, \
+ f_string_range_t_initialize, \
+ f_conversion_data_base_10_c, \
+ 0, \
+ 0, \
+ }
+
+ #define macro_f_fss_payload_header_write_internal_t_initialize_1(step, i, j, range, conversion, destination, original) { \
+ step, \
+ i, \
+ j, \
+ range, \
+ conversion, \
+ destination, \
+ original, \
+ }
+
+ #define macro_f_fss_payload_header_write_internal_t_initialize_2(destination, original) { \
+ 0, \
+ 0, \
+ 0, \
+ f_string_range_t_initialize, \
+ f_conversion_data_base_10_c, \
+ destination, \
+ original, \
+ }
+#endif // _di_f_fss_payload_header_write_internal_t_
+
+/**
+ * A state structure for passing data to fss_payload_header_write().
+ *
+ * Properties:
+ * - conversion: The conversion data.
+ * - cache: A string cache to use (generally required to be not NULL).
+ */
+#ifndef _di_f_fss_payload_header_write_state_t_
+ typedef struct {
+ f_conversion_data_t conversion;
+
+ f_string_dynamic_t *cache;
+ } f_fss_payload_header_write_state_t;
+
+ #define f_fss_payload_header_write_state_t_initialize { \
+ f_conversion_data_base_10_c, \
+ 0, \
+ }
+
+ #define macro_f_fss_payload_header_write_state_t_initialize_1(conversion, destination) { \
+ conversion, \
+ destination, \
+ }
+
+ #define macro_f_fss_payload_header_write_state_t_initialize_2(destination) { \
+ f_conversion_data_base_10_c, \
+ destination, \
+ }
+#endif // _di_f_fss_payload_header_write_state_t_
+
// @todo fl_fss_payload_header_read() to build an array of f_abstruse for the headers?
/**
* The string in which the resulting header is appended to.
* Must not be NULL.
* @param state
- * @todo update this as appropriate after implementing this function.
* A state for providing flags and handling interrupts during long running operations.
- * There is no state.handle().
+ * The state.handle() is optionally allowed.
* There is no "callbacks" structure.
- * There is no data structure passed to these functions.
+ * The data is required and set to f_fss_payload_header_write_state_t.
+ * The data.cache must not be NULL.
+ *
+ * The optional state->handle() is called on error and the handler may alter the status to not have an error bit step to prevent returning except for when there is an invalid parameter passed to this function.
+ * The second parameter is a f_fss_payload_header_write_internal_t.
+ * The second parameter to state->handle() is NULL on invalid paramter passed to this function.
*
* When state.interrupt() returns, only F_interrupt and F_interrupt_not are processed.
* Error bit designates an error but must be passed along with F_interrupt.
* All other statuses are ignored.
+ * The second parameter is a f_fss_payload_header_write_internal_t.
*
* Must not be NULL.
*