Add prepend functionality to all write programs.
- for FSS-0000 (Basic) and FSS-0001 (Extended), this does nothing.
- for FSS-0002 (Basic List) and FSS-0003 (Extended List), this prepends the start of multi-line content with some whitespace.
Begin working on the FSS-0003 (Extended List) write functions and programs.
- At this time, the extended list write is only implemented partially.
- I will focus on the recursive aspects later.
Add the "complete" processing to the basic list content (and now extended list content) write functions.
- Includes updates to the newline handling as appropriate.
Update documentation comments.
#define f_fss_extended_open ' '
#define f_fss_extended_next ' '
#define f_fss_extended_close f_string_eol[0]
- #define f_fss_list_terminator f_string_eol[0]
#define f_fss_basic_list_open ':'
+ #define f_fss_basic_list_open_end f_string_eol[0]
#define f_fss_basic_list_close f_string_eol[0]
#define f_fss_extended_list_open '{'
+ #define f_fss_extended_list_open_end f_string_eol[0]
#define f_fss_extended_list_close '}'
#define f_fss_extended_list_close_end f_string_eol[0]
#define f_fss_type_header_open '#'
* @param content
* The string to write as (does not stop at NULLS, they are ignored and not written).
* @param complete
- * If f_fss_complete_none, then only the object name is written.
- * If f_fss_complete_partial, this will write any appropriate open and close aspects of this object, except for the final newline.
- * If f_fss_complete_full, this will write any appropriate open and close aspects of this object, including the final newline.
+ * If f_fss_complete_none, then only the content is written.
+ * If f_fss_complete_next, then the content followed by any appropriate "next" character separating one content from the next, if applicable.
+ * If f_fss_complete_end, then the content followed by any appropriate "end" character designating the last content for some object, printing final newline, if applicable.
+ * If f_fss_complete_partial, this will write any appropriate open and close aspects of this content, except for the final newline.
+ * If f_fss_complete_full, this will write any appropriate open and close aspects of this content, including the final newline.
* @param range
* The start/stop location within the content string to write as an content.
* @param destination
destination->string[destination->used++] = f_fss_basic_list_open;
if (complete == f_fss_complete_full) {
- destination->string[destination->used++] = f_fss_eol;
+ destination->string[destination->used++] = f_fss_basic_list_open_end;
}
}
}
destination->string[destination->used++] = f_fss_basic_list_open;
- destination->string[destination->used++] = f_fss_eol;
+
+ if (complete == f_fss_complete_full) {
+ destination->string[destination->used++] = f_fss_basic_list_open_end;
+ }
}
if (range->start > range->stop) {
#endif // _di_fl_fss_basic_list_object_write_
#ifndef _di_fl_fss_basic_list_content_write_
- f_return_status fl_fss_basic_list_content_write(const f_string_static_t content, f_string_range_t *range, f_string_dynamic_t *destination) {
+ f_return_status fl_fss_basic_list_content_write(const f_string_static_t content, const uint8_t complete, const f_string_static_t prepend, f_string_range_t *range, f_string_dynamic_t *destination) {
#ifndef _di_level_1_parameter_checking_
if (!range) return F_status_set_error(F_parameter);
if (!destination) return F_status_set_error(F_parameter);
fl_macro_fss_skip_past_delimit_placeholders(content, (*range));
- if (range->start > range->stop) {
- status = F_data_not_stop;
- }
- else if (range->start >= content.used) {
- status = F_data_not_eos;
- }
+ if (range->start > range->stop || range->start >= content.used) {
+ if (complete == f_fss_complete_full || complete == f_fss_complete_end) {
+ status = private_fl_fss_destination_increase(destination);
+ if (F_status_is_error(status)) return status;
- if (status == F_data_not_stop || status == F_data_not_eos) {
- return status;
+ destination->string[destination->used++] = f_fss_basic_list_close;
+ }
+
+ if (range->start > range->stop) {
+ return F_data_not_stop;
+ }
+
+ return F_data_not_eos;
}
- // ensure that there is room for a slash delimit and possibly the end of line character.
+ // ensure that there is room for a slash delimit and possibly the end of content character.
status = private_fl_fss_destination_increase_by(destination->used + (range->stop - range->start) + 2, destination);
if (F_status_is_error(status)) return status;
bool is_comment = F_false;
bool has_graph = F_false;
+ bool do_prepend = F_true;
f_string_length_t i = 0;
f_string_length_t slash_count = 0;
if (content.string[range->start] == f_fss_delimit_slash && !is_comment) {
slash_count = 1;
+ if (do_prepend) {
+ status = private_fl_fss_destination_prepend(prepend, destination);
+ if (F_status_is_error(status)) break;
+
+ do_prepend = F_false;
+ }
+
destination->string[destination->used++] = content.string[range->start];
has_graph = F_true;
status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
for (; range->start <= range->stop && range->start < content.used; range->start++) {
start = range->start;
status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
while (range->start < content.used && range->start <= range->stop) {
- if (content.string[range->start] == f_fss_eol) break;
+ if (content.string[range->start] == f_fss_eol) {
+ do_prepend = F_true;
+ break;
+ }
status = f_fss_is_space(content, *range);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
if (status == F_false) break;
status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
} // while
+ if (F_status_is_error(status)) break;
+
if (content.string[range->start] == f_fss_eol || range->start >= content.used || range->start > range->stop) {
- // increase by total slashes + 1, along with the basic list open.
- status = private_fl_fss_destination_increase_by(slash_count + 2, destination);
- if (F_status_is_error(status)) return status;
+ // increase by total slashes + 1, along with the basic list open and possible newline.
+ status = private_fl_fss_destination_increase_by(slash_count + 3, destination);
+ if (F_status_is_error(status)) break;
while (slash_count--) {
destination->string[destination->used++] = f_fss_delimit_slash;
}
else {
status = private_fl_fss_destination_increase(destination);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
}
destination->string[destination->used++] = f_fss_basic_list_open;
+
+ if (content.string[range->start] == f_fss_eol) {
+ destination->string[destination->used++] = f_fss_eol;
+ }
+
range->start = start + 1;
continue;
}
if (content.string[range->start] == f_fss_eol) break;
status = f_fss_is_space(content, *range);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
if (status == F_false) break;
status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
} // while
+ if (F_status_is_error(status)) break;
+
+ if (do_prepend) {
+ status = private_fl_fss_destination_prepend(prepend, destination);
+ if (F_status_is_error(status)) break;
+
+ do_prepend = F_false;
+ }
+
if (content.string[range->start] == f_fss_eol || range->start >= content.used || range->start > range->stop) {
+ if (content.string[range->start] == f_fss_eol) {
+ do_prepend = F_true;
+ }
- // increase by slash and basic list open.
- status = private_fl_fss_destination_increase_by(2, destination);
- if (F_status_is_error(status)) return status;
+ // increase by slash and basic list open and possible newline.
+ status = private_fl_fss_destination_increase_by(3, destination);
+ if (F_status_is_error(status)) break;
destination->string[destination->used++] = f_fss_delimit_slash;
has_graph = F_false;
}
else {
status = private_fl_fss_destination_increase(destination);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
}
destination->string[destination->used++] = f_fss_basic_list_open;
+
+ if (content.string[range->start] == f_fss_eol) {
+ destination->string[destination->used++] = f_fss_eol;
+ }
+
range->start = start + 1;
continue;
}
has_graph = F_true;
}
else if (F_status_is_error(status)) {
- return status;
+ break;
}
if (content.string[range->start] != f_fss_delimit_placeholder) {
+ if (do_prepend) {
+ status = private_fl_fss_destination_prepend(prepend, destination);
+ if (F_status_is_error(status)) break;
+
+ do_prepend = F_false;
+ }
+
+ if (content.string[range->start] == f_fss_eol) {
+ do_prepend = F_true;
+ }
+
width = f_macro_utf_byte_width(content.string[range->start]);
status = private_fl_fss_destination_increase_by(width, destination);
}
status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
} // while
+ if (F_status_is_error(status)) {
+ destination->used = used_start;
+ return status;
+ }
+
+ if (complete == f_fss_complete_full || complete == f_fss_complete_end) {
+ status = private_fl_fss_destination_increase(destination);
+ if (F_status_is_error(status)) return status;
+
+ destination->string[destination->used++] = f_fss_basic_list_close;
+ }
+
if (range->start > range->stop) {
return F_none_stop;
}
*
* @param content
* The string to write as (does not stop at NULLS, they are ignored and not written).
+ * @param complete
+ * If f_fss_complete_none, then only the content is written.
+ * If f_fss_complete_next, then the content followed by any appropriate "next" character separating one content from the next, if applicable.
+ * If f_fss_complete_end, then the content followed by any appropriate "end" character designating the last content for some object, printing final newline, if applicable.
+ * If f_fss_complete_partial, this will write any appropriate open and close aspects of this content, except for the final newline.
+ * If f_fss_complete_full, this will write any appropriate open and close aspects of this content, including the final newline.
+ * @param prepend
+ * A string of whitespace to prepend at the start of each line.
+ * This should only be whitespace, anything else could product invalid content.
+ * Set prepend.used to 0 to not use.
* @param range
* The start/stop location within the content string to write as an content.
* @param destination
* Errors (with error bit) from: f_utf_buffer_increment().
*/
#ifndef _di_fl_fss_basic_list_content_write_
- extern f_return_status fl_fss_basic_list_content_write(const f_string_static_t content, f_string_range_t *range, f_string_dynamic_t *destination);
+ extern f_return_status fl_fss_basic_list_content_write(const f_string_static_t content, const uint8_t complete, const f_string_static_t prepend, f_string_range_t *range, f_string_dynamic_t *destination);
#endif // _di_fl_fss_basic_list_content_write_
#ifdef __cplusplus
* If 0, then double quotes are auto-inserted, when required.
* Otherwise, this is the type of quote to wrap the object in when writing.
* @param complete
- * If f_fss_complete_none, then only the object name is written.
- * If f_fss_complete_partial, this will write any appropriate open and close aspects of this object, except for the final newline.
- * If f_fss_complete_full, this will write any appropriate open and close aspects of this object, including the final newline.
+ * If f_fss_complete_none, then only the content is written.
+ * If f_fss_complete_next, then the content followed by any appropriate "next" character separating one content from the next, if applicable.
+ * If f_fss_complete_end, then the content followed by any appropriate "end" character designating the last content for some object, printing final newline, if applicable.
+ * If f_fss_complete_partial, this will write any appropriate open and close aspects of this content, except for the final newline.
+ * If f_fss_complete_full, this will write any appropriate open and close aspects of this content, including the final newline.
* @param range
* The start/stop location within the content string to write as an content.
* @param destination
#endif // _di_fl_fss_extended_list_content_read_
#ifndef _di_fl_fss_extended_list_object_write_
- f_return_status fl_fss_extended_list_object_write(const f_string_static_t object, f_string_range_t *range, f_string_dynamic_t *destination) {
+ f_return_status fl_fss_extended_list_object_write(const f_string_static_t object, const uint8_t complete, f_string_range_t *range, f_string_dynamic_t *destination) {
#ifndef _di_level_1_parameter_checking_
if (!destination) return F_status_set_error(F_parameter);
#endif // _di_level_1_parameter_checking_
f_status_t status = F_none;
- f_string_range_t buffer_position = f_string_range_t_initialize;
- f_string_length_t start_position = f_string_t_initialize;
- f_string_length_t size_allocate = 0;
- f_string_length_t start_buffer = 0;
+ fl_macro_fss_skip_past_delimit_placeholders(object, (*range));
- fl_macro_fss_skip_past_delimit_placeholders(object, (*range))
-
- if (range->start > range->stop) return F_data_not_stop;
- else if (range->start >= object.used) return F_data_not_eos;
+ if (range->start > range->stop) {
+ status = F_data_not_stop;
+ }
+ else if (range->start >= object.used) {
+ status = F_data_not_eos;
+ }
- start_position = range->start;
+ if (status == F_data_not_stop || status == F_data_not_eos) {
+ if (complete == f_fss_complete_partial || complete == f_fss_complete_full) {
+ const f_status_t status_allocation = private_fl_fss_destination_increase_by(2, destination);
+ if (F_status_is_error(status_allocation)) return status_allocation;
- // add an additional 2 to ensure that there is room for the slash delimit and the object open character.
- size_allocate = destination->used + (range->stop - range->start) + 2 + f_fss_default_allocation_step;
+ destination->string[destination->used++] = f_fss_extended_list_open;
- if (size_allocate > destination->size) {
- f_macro_string_dynamic_t_resize(status, (*destination), size_allocate);
+ if (complete == f_fss_complete_full) {
+ destination->string[destination->used++] = f_fss_extended_list_open_end;
+ }
+ }
- if (F_status_is_error(status)) return status;
+ return status;
}
- buffer_position.start = destination->used;
- buffer_position.stop = destination->used;
+ // ensure that there is room for a slash delimit, the object open character, and the end of line character.
+ status = private_fl_fss_destination_increase_by(destination->used + (range->stop - range->start) + 3, destination);
+ if (F_status_is_error(status)) return status;
+
+ const f_string_length_t input_start = range->start;
+ const f_string_length_t used_start = destination->used;
+
+ f_string_length_t i = 0;
+ f_string_length_t slash_count = 0;
+ f_string_range_t range_next = f_string_range_t_initialize;
+
+ bool ends_on_space = F_false;
+
+ uint8_t width = 0;
+
+ // find the first graph character.
while (range->start <= range->stop && range->start < object.used) {
if (object.string[range->start] == f_fss_comment) {
- // comments are not allowed and this format has no way of "wrapping" a comment.
- return F_status_set_error(FL_fss_found_comment);
- }
- else if ((status = f_fss_is_graph(object, *range)) == F_true) {
+
+ // when a comment is found, escape it.
+ status = private_fl_fss_destination_increase(destination);
+ if (F_status_is_error(status)) break;
+
+ destination->string[destination->used++] = f_fss_delimit_slash;
break;
}
- else if (F_status_is_error(status)) {
- return status;
- }
+ status = f_fss_is_graph(object, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_true) break;
+
+ // objects will not have leading whitespaces, but having this does not result in an invalid object, so just write the provided spaces.
if (object.string[range->start] != f_fss_delimit_placeholder) {
- destination->string[buffer_position.stop] = object.string[range->start];
- buffer_position.stop++;
+ if (object.string[range->start] == f_fss_eol) {
+ status = F_status_set_error(F_none_eol);
+ break;
+ }
+
+ status = f_fss_is_space(object, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_true) {
+ width = f_macro_utf_byte_width(object.string[range->start]);
+
+ status = private_fl_fss_destination_increase_by(width, destination);
+ if (F_status_is_error(status)) break;
+
+ for (i = 0; i < width; i++) {
+ destination->string[destination->used++] = object.string[range->start + i];
+ } // for
+ }
}
status = f_utf_buffer_increment(object, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
} // while
+ if (F_status_is_error(status)) {
+ destination->used = used_start;
+ return status;
+ }
+
while (range->start <= range->stop && range->start < object.used) {
if (object.string[range->start] == f_fss_delimit_slash) {
- f_string_length_t slash_count = 1;
-
- destination->string[buffer_position.stop] = object.string[range->start];
- buffer_position.stop++;
-
- status = f_utf_buffer_increment(object, range, 1);
- if (F_status_is_error(status)) return status;
+ slash_count = 1;
- while (range->start <= range->stop && range->start < object.used) {
+ for (range->start++; range->start <= range->stop && range->start < object.used; range->start++) {
if (object.string[range->start] == f_fss_delimit_placeholder) {
- status = f_utf_buffer_increment(object, range, 1);
- if (F_status_is_error(status)) return status;
-
continue;
} else if (object.string[range->start] != f_fss_delimit_slash) {
break;
}
- destination->string[buffer_position.stop] = object.string[range->start];
- buffer_position.stop++;
-
- status = f_utf_buffer_increment(object, range, 1);
- if (F_status_is_error(status)) return status;
-
slash_count++;
- } // while
+ } // for
+
+ if (F_status_is_error(status)) break;
if (range->start > range->stop || range->start >= object.used) {
- size_allocate += slash_count;
- if (size_allocate > destination->size) {
- f_macro_string_dynamic_t_resize(status, (*destination), size_allocate + f_fss_default_allocation_step);
- if (F_status_is_error(status)) return status;
- }
+ // slashes at the end of the object must be delimited to avoid delimiting the object close character.
+ slash_count *= 2;
+ }
- while (slash_count > 0) {
- destination->string[buffer_position.stop] = f_fss_delimit_slash;
- buffer_position.stop++;
- slash_count--;
- } // while
+ status = private_fl_fss_destination_increase_by(slash_count, destination);
+ if (F_status_is_error(status)) break;
+ while (slash_count--) {
+ destination->string[destination->used++] = f_fss_delimit_slash;
+ } // while
+
+ if (range->start > range->stop || range->start >= object.used) {
+ ends_on_space = F_false;
break;
}
}
- else if (object.string[range->start] == f_string_eol[0]) {
- if (buffer_position.stop == buffer_position.start) return F_data_not_eol;
-
- break;
- }
if (object.string[range->start] != f_fss_delimit_placeholder) {
- destination->string[buffer_position.stop] = object.string[range->start];
- buffer_position.stop++;
+ if (object.string[range->start] == f_fss_eol) {
+ status = F_status_set_error(F_none_eol);
+ break;
+ }
+
+ status = f_fss_is_space(object, *range);
+ if (F_status_is_error(status)) break;
+
+ ends_on_space = status == F_true;
+
+ width = f_macro_utf_byte_width(object.string[range->start]);
+
+ status = private_fl_fss_destination_increase_by(width, destination);
+ if (F_status_is_error(status)) break;
+
+ for (i = 0; i < width; i++) {
+ destination->string[destination->used++] = object.string[range->start + i];
+ } // for
}
status = f_utf_buffer_increment(object, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
} // while
- destination->string[buffer_position.stop] = f_fss_extended_list_open;
- destination->string[buffer_position.stop + 1] = f_string_eol[0];
- destination->used = buffer_position.stop + 2;
+ if (F_status_is_error(status)) {
+ destination->used = used_start;
+ return status;
+ }
+
+ if (complete == f_fss_complete_partial || complete == f_fss_complete_full) {
+ status = private_fl_fss_destination_increase_by(3, destination);
- if (range->start > range->stop) return F_none_stop;
- else if (range->start >= object.used) return F_none_eos;
+ if (F_status_is_error(status)) {
+ destination->used = used_start;
+ return status;
+ }
+
+ if (!ends_on_space) {
+ destination->string[destination->used++] = f_fss_space;
+ }
+
+ destination->string[destination->used++] = f_fss_extended_list_open;
+
+ if (complete == f_fss_complete_full) {
+ destination->string[destination->used++] = f_fss_extended_list_open_end;
+ }
+ }
+
+ if (range->start > range->stop) {
+ return F_none_stop;
+ }
+
+ if (range->start >= object.used) {
+ return F_none_eos;
+ }
return F_none;
}
#endif // _di_fl_fss_extended_list_object_write_
#ifndef _di_fl_fss_extended_list_content_write_
- f_return_status fl_fss_extended_list_content_write(const f_string_static_t content, f_string_range_t *range, f_string_dynamic_t *destination) {
+ f_return_status fl_fss_extended_list_content_write(const f_string_static_t content, const uint8_t complete, const f_string_static_t prepend, f_string_range_t *range, f_string_dynamic_t *destination) {
#ifndef _di_level_1_parameter_checking_
+ if (!range) return F_status_set_error(F_parameter);
if (!destination) return F_status_set_error(F_parameter);
#endif // _di_level_1_parameter_checking_
- // @todo
- /*
f_status_t status = F_none;
- bool is_comment = F_false;
- bool has_graph = F_false;
-
- f_string_range_t buffer_position = f_string_range_t_initialize;
- f_string_length_t start_position = f_string_t_initialize;
- f_string_length_t size_allocate = 0;
- fl_macro_fss_skip_past_delimit_placeholders(content, (*range))
+ fl_macro_fss_skip_past_delimit_placeholders(content, (*range));
- if (range->start > range->stop) return F_data_not_stop;
- else if (range->start >= content.used) return F_data_not_eos;
+ if (range->start > range->stop || range->start >= content.used) {
+ if (complete == f_fss_complete_full || complete == f_fss_complete_end) {
+ status = private_fl_fss_destination_increase_by(2, destination);
+ if (F_status_is_error(status)) return status;
- start_position = range->start;
+ destination->string[destination->used++] = f_fss_extended_list_close;
+ destination->string[destination->used++] = f_fss_extended_list_close_end;
+ }
- // add an additional 2 to ensure that there is room for the slash delimit and the content open character.
- size_allocate = destination->used + (range->stop - range->start) + 2 + f_fss_default_allocation_step;
+ if (range->start > range->stop) {
+ return F_data_not_stop;
+ }
- if (size_allocate > destination->size) {
- f_macro_string_dynamic_t_resize(status, (*destination), size_allocate);
- if (F_status_is_error(status)) return status;
+ return F_data_not_eos;
}
- buffer_position.start = destination->used;
- buffer_position.stop = destination->used;
+ // ensure that there is room for a slash delimit and possibly the end of content characters.
+ status = private_fl_fss_destination_increase_by(destination->used + (range->stop - range->start) + 3, destination);
+ if (F_status_is_error(status)) return status;
+
+ const f_string_length_t input_start = range->start;
+ const f_string_length_t used_start = destination->used;
+
+ bool is_comment = F_false;
+ bool ends_on_eol = F_false;
+ bool has_graph = F_false;
+ bool do_prepend = F_true;
+
+ f_string_length_t i = 0;
+ f_string_length_t slash_count = 0;
+ f_string_length_t start = 0;
+
+ uint8_t width = 0;
while (range->start <= range->stop && range->start < content.used) {
if (content.string[range->start] == f_fss_delimit_slash && !is_comment) {
- f_string_length_t slash_count = 1;
+ slash_count = 1;
- destination->string[buffer_position.stop] = content.string[range->start];
- buffer_position.stop++;
+ if (do_prepend) {
+ status = private_fl_fss_destination_prepend(prepend, destination);
+ if (F_status_is_error(status)) break;
+ do_prepend = F_false;
+ }
+
+ destination->string[destination->used++] = content.string[range->start];
has_graph = F_true;
+
status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
- while (range->start <= range->stop && range->start < content.used) {
+ for (; range->start <= range->stop && range->start < content.used; range->start++) {
if (content.string[range->start] == f_fss_delimit_placeholder) {
- status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
-
continue;
}
else if (content.string[range->start] != f_fss_delimit_slash) {
break;
}
- destination->string[buffer_position.stop] = content.string[range->start];
- buffer_position.stop++;
-
- status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
-
+ destination->string[destination->used++] = f_fss_delimit_slash;
slash_count++;
- } // while
+ } // for
if (content.string[range->start] == f_fss_extended_list_open) {
- f_string_length_t start = range->start;
+ start = range->start;
status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
while (range->start < content.used && range->start <= range->stop) {
- if (content.string[range->start] == f_string_eol[0] || (status = f_fss_is_graph(content, *range)) == F_true) {
+ if (content.string[range->start] == f_fss_eol) {
+ do_prepend = F_true;
break;
}
- if (F_status_is_error(status)) return status;
+ status = f_fss_is_space(content, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) break;
status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
} // while
- if (content.string[range->start] == f_string_eol[0] || range->start >= content.used || range->start > range->stop) {
- size_allocate += slash_count + 1;
+ if (F_status_is_error(status)) break;
- if (size_allocate > destination->size) {
- f_macro_string_dynamic_t_resize(status, (*destination), size_allocate + f_fss_default_allocation_step);
- if (F_status_is_error(status)) return status;
- }
+ if (content.string[range->start] == f_fss_eol || range->start >= content.used || range->start > range->stop) {
- while (slash_count > 0) {
- destination->string[buffer_position.stop] = f_fss_delimit_slash;
- buffer_position.stop++;
- slash_count--;
+ // increase by total slashes + 1, along with the extended list open and possible newline.
+ status = private_fl_fss_destination_increase_by(slash_count + 3, destination);
+ if (F_status_is_error(status)) break;
+
+ while (slash_count--) {
+ destination->string[destination->used++] = f_fss_delimit_slash;
} // while
- destination->string[buffer_position.stop] = f_fss_delimit_slash;
- buffer_position.stop++;
+ destination->string[destination->used++] = f_fss_delimit_slash;
has_graph = F_false;
is_comment = F_false;
}
+ else {
+ status = private_fl_fss_destination_increase(destination);
+ if (F_status_is_error(status)) break;
+ }
+
+ destination->string[destination->used++] = f_fss_extended_list_open;
+
+ if (content.string[range->start] == f_fss_eol) {
+ destination->string[destination->used++] = f_fss_eol;
+ ends_on_eol = F_true;
+ }
+ else {
+ ends_on_eol = F_false;
+ }
- destination->string[buffer_position.stop] = f_fss_extended_list_open;
- buffer_position.stop++;
range->start = start + 1;
continue;
}
}
else if (content.string[range->start] == f_fss_extended_list_open && !is_comment) {
- f_string_length_t start = range->start;
-
+ start = range->start++;
has_graph = F_true;
- status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
-
while (range->start < content.used && range->start <= range->stop) {
- if (content.string[range->start] == f_string_eol[0] || (status = f_fss_is_graph(content, *range)) == F_true) {
- break;
- }
+ if (content.string[range->start] == f_fss_eol) break;
- if (F_status_is_error(status)) return status;
+ status = f_fss_is_space(content, *range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) break;
status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
} // while
- if (content.string[range->start] == f_string_eol[0] || range->start >= content.used || range->start > range->stop) {
- size_allocate++;
+ if (F_status_is_error(status)) break;
- if (size_allocate > destination->size) {
- f_macro_string_dynamic_t_resize(status, (*destination), size_allocate + f_fss_default_allocation_step);
+ if (do_prepend) {
+ status = private_fl_fss_destination_prepend(prepend, destination);
+ if (F_status_is_error(status)) break;
- if (F_status_is_error(status)) return status;
+ do_prepend = F_false;
+ }
+
+ if (content.string[range->start] == f_fss_eol || range->start >= content.used || range->start > range->stop) {
+ if (content.string[range->start] == f_fss_eol) {
+ do_prepend = F_true;
}
- destination->string[buffer_position.stop] = f_fss_delimit_slash;
- buffer_position.stop++;
+ // increase by slash and extended list open and possible newline.
+ status = private_fl_fss_destination_increase_by(3, destination);
+ if (F_status_is_error(status)) break;
+
+ destination->string[destination->used++] = f_fss_delimit_slash;
has_graph = F_false;
is_comment = F_false;
}
+ else {
+ status = private_fl_fss_destination_increase(destination);
+ if (F_status_is_error(status)) break;
+ }
+
+ destination->string[destination->used++] = f_fss_extended_list_open;
+
+ if (content.string[range->start] == f_fss_eol) {
+ destination->string[destination->used++] = f_fss_eol;
+ ends_on_eol = F_true;
+ }
+ else {
+ ends_on_eol = F_false;
+ }
- destination->string[buffer_position.stop] = f_fss_extended_list_open;
- buffer_position.stop++;
range->start = start + 1;
continue;
}
else if (content.string[range->start] == f_fss_comment && !has_graph) {
is_comment = F_true;
}
- else if (content.string[range->start] == f_string_eol[0]) {
+ else if (content.string[range->start] == f_fss_eol) {
has_graph = F_false;
is_comment = F_false;
}
has_graph = F_true;
}
else if (F_status_is_error(status)) {
- return status;
+ break;
}
if (content.string[range->start] != f_fss_delimit_placeholder) {
- destination->string[buffer_position.stop] = content.string[range->start];
- buffer_position.stop++;
+ if (do_prepend) {
+ status = private_fl_fss_destination_prepend(prepend, destination);
+ if (F_status_is_error(status)) break;
+
+ do_prepend = F_false;
+ }
+
+ if (content.string[range->start] == f_fss_eol) {
+ do_prepend = F_true;
+ ends_on_eol = F_true;
+ }
+ else {
+ ends_on_eol = F_false;
+ }
+
+ width = f_macro_utf_byte_width(content.string[range->start]);
+
+ status = private_fl_fss_destination_increase_by(width, destination);
+ if (F_status_is_error(status)) break;
+
+ for (i = 0; i < width; i++) {
+ destination->string[destination->used++] = content.string[range->start + i];
+ } // for
}
status = f_utf_buffer_increment(content, range, 1);
- if (F_status_is_error(status)) return status;
+ if (F_status_is_error(status)) break;
} // while
- destination->string[buffer_position.stop] = f_string_eol[0];
- destination->used = buffer_position.stop + 1;
+ if (F_status_is_error(status)) {
+ destination->used = used_start;
+ return status;
+ }
- if (range->start > range->stop) return F_none_stop;
- else if (range->start >= content.used) return F_none_eos;
- */
+ if (complete == f_fss_complete_full || complete == f_fss_complete_end) {
+ status = private_fl_fss_destination_increase_by(3, destination);
+ if (F_status_is_error(status)) return status;
+
+ if (!ends_on_eol) {
+ destination->string[destination->used++] = f_fss_eol;
+ }
+
+ destination->string[destination->used++] = f_fss_extended_list_close;
+ destination->string[destination->used++] = f_fss_extended_list_close_end;
+ }
+
+ if (range->start > range->stop) {
+ return F_none_stop;
+ }
+
+ if (range->start >= content.used) {
+ return F_none_eos;
+ }
return F_none;
}
*
* @param object
* The string to write as (does not stop at NULLS, they are ignored and not written).
+ * @param complete
+ * If f_fss_complete_none, then only the object name is written.
+ * If f_fss_complete_partial, this will write any appropriate open and close aspects of this object.
+ * If f_fss_complete_full, this will write any appropriate open and close aspects of this object.
* @param range
* The start/stop location within the object string to write as an object.
* @param destination
* F_none_stop on success after reaching stopping point .
* F_incomplete_utf (with error bit) is returned on failure to read/process a UTF-8 character due to the character being potentially incomplete.
* F_memory_reallocation (with error bit) on reallocation error.
+ * F_none_eol (with error bit) after reaching an EOL, which is not supported by the standard.
* F_parameter (with error bit) if a parameter is invalid.
* F_utf (with error bit) is returned on failure to read/process a UTF-8 character.
*
* Errors (with error bit) from: f_utf_buffer_increment().
*/
#ifndef _di_fl_fss_extended_list_object_write_
- extern f_return_status fl_fss_extended_list_object_write(const f_string_static_t object, f_string_range_t *range, f_string_dynamic_t *destination);
+ extern f_return_status fl_fss_extended_list_object_write(const f_string_static_t object, const uint8_t complete, f_string_range_t *range, f_string_dynamic_t *destination);
#endif // _di_fl_fss_extended_list_object_write_
/**
*
* @param content
* The string to write as (does not stop at NULLS, they are ignored and not written).
+ * @param complete
+ * If f_fss_complete_none, then only the content is written.
+ * If f_fss_complete_next, then the content followed by any appropriate "next" character separating one content from the next, if applicable.
+ * If f_fss_complete_end, then the content followed by any appropriate "end" character designating the last content for some object, printing final newline, if applicable.
+ * If f_fss_complete_partial, this will write any appropriate open and close aspects of this content, except for the final newline.
+ * If f_fss_complete_full, this will write any appropriate open and close aspects of this content, including the final newline.
+ * @param prepend
+ * A string of whitespace to prepend at the start of each line.
+ * This should only be whitespace, anything else could product invalid content.
+ * Set prepend.used to 0 to not use.
* @param range
* The start/stop location within the content string to write as an content.
* @param destination
* Errors (with error bit) from: f_utf_buffer_increment().
*/
#ifndef _di_fl_fss_extended_list_content_write_
- extern f_return_status fl_fss_extended_list_content_write(const f_string_static_t content, f_string_range_t *range, f_string_dynamic_t *destination);
+ extern f_return_status fl_fss_extended_list_content_write(const f_string_static_t content, const uint8_t complete, const f_string_static_t prepend, f_string_range_t *range, f_string_dynamic_t *destination);
#endif // _di_fl_fss_extended_list_content_write_
#ifdef __cplusplus
}
#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_)
-#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_)
+#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) || !defined(_di_fl_fss_extended_list_object_write_) || !defined(_di_fl_fss_extended_list_content_write_)
f_return_status private_fl_fss_destination_increase(f_string_dynamic_t *destination) {
f_status_t status = F_none;
return status;
}
-#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_)
+#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) || !defined(_di_fl_fss_extended_list_object_write_) || !defined(_di_fl_fss_extended_list_content_write_)
-#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_)
+#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) || !defined(_di_fl_fss_extended_list_object_write_) || !defined(_di_fl_fss_extended_list_content_write_)
f_return_status private_fl_fss_destination_increase_by(const f_string_length_t amount, f_string_dynamic_t *destination) {
f_status_t status = F_none;
return status;
}
-#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_)
+#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) || !defined(_di_fl_fss_extended_list_object_write_) || !defined(_di_fl_fss_extended_list_content_write_)
+
+#if !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_list_content_write_)
+ f_return_status private_fl_fss_destination_prepend(const f_string_static_t prepend, f_string_dynamic_t *destination) {
+
+ if (!prepend.used) {
+ return F_none;
+ }
+
+ if (prepend.used) {
+ f_status_t status = private_fl_fss_destination_increase_by(prepend.used, destination);
+ if (F_status_is_error(status)) return status;
+ }
+
+ for (f_string_length_t i = 0; i < prepend.used; i++) {
+ destination->string[destination->used++] = prepend.string[i];
+ } // for
+
+ return F_none;
+ }
+#endif // !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_list_content_write_)
#ifdef __cplusplus
} // extern "C"
* @see fl_fss_basic_object_write()
* @see fl_fss_basic_content_write()
* @see fl_fss_basic_list_object_write()
+ * @see fl_fss_basic_list_content_write()
* @see fl_fss_extended_object_write()
* @see fl_fss_extended_content_write()
+ * @see fl_fss_extended_list_object_write()
+ * @see fl_fss_extended_list_content_write()
*/
-#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_)
+#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) || !defined(_di_fl_fss_extended_list_object_write_) || !defined(_di_fl_fss_extended_list_content_write_)
extern f_return_status private_fl_fss_destination_increase(f_string_dynamic_t *destination) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_)
+#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) || !defined(_di_fl_fss_extended_list_object_write_) || !defined(_di_fl_fss_extended_list_content_write_)
/**
* Increase the size of destination buffer by the given amount, but only if necessary.
* @see fl_fss_basic_object_write()
* @see fl_fss_basic_content_write()
* @see fl_fss_basic_list_object_write()
+ * @see fl_fss_basic_list_content_write()
* @see fl_fss_extended_object_write()
* @see fl_fss_extended_content_write()
+ * @see fl_fss_extended_list_object_write()
+ * @see fl_fss_extended_list_content_write()
*/
-#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_)
- f_return_status private_fl_fss_destination_increase_by(const f_string_length_t amount, f_string_dynamic_t *destination);
-#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_)
+#if !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) || !defined(_di_fl_fss_extended_list_object_write_) || !defined(_di_fl_fss_extended_list_content_write_)
+ f_return_status private_fl_fss_destination_increase_by(const f_string_length_t amount, f_string_dynamic_t *destination) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_basic_content_write_) || !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_write_) || !defined(_di_fl_fss_extended_list_object_write_) || !defined(_di_fl_fss_extended_list_content_write_)
+
+/**
+ * Prepend the given string onto the destination buffer, allocating space as necessary
+ *
+ * @param prepend
+ * A string to prepend at the start of each line, such as spaces.
+ * Set prepend.used to 0 to not use.
+ * @param destination
+ * The destination buffer to prepend to.
+ *
+ * @return
+ * F_none on success.
+ * F_memory_reallocation (with error bit) on reallocation error.
+ * F_string_too_large (with error bit) if appended string length is too large to store in the destination.
+ *
+ * @see fl_fss_basic_list_content_write()
+ * @see fl_fss_extended_list_content_write()
+ */
+#if !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_list_content_write_)
+ f_return_status private_fl_fss_destination_prepend(const f_string_static_t prepend, f_string_dynamic_t *destination) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fl_fss_basic_list_content_write_) || !defined(_di_fl_fss_extended_list_content_write_)
#ifdef __cplusplus
} // extern "C"
#endif // _di_fll_fss_basic_list_read_
#ifndef _di_fll_fss_basic_list_write_
- f_return_status fll_fss_basic_list_write(const f_string_static_t object, const f_string_statics_t contents, f_string_dynamic_t *destination) {
+ f_return_status fll_fss_basic_list_write(const f_string_static_t object, const f_string_statics_t contents, const f_string_static_t contents_prepend, f_string_dynamic_t *destination) {
#ifndef _di_level_2_parameter_checking_
if (!destination) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
range.start = 0;
range.stop = contents.array[0].used - 1;
- status = fl_fss_basic_list_content_write(contents.array[0], &range, destination);
+ status = fl_fss_basic_list_content_write(contents.array[0], f_fss_complete_full, contents_prepend, &range, destination);
}
}
* A string representing the object.
* @param contents
* An array of strings representing multiple content to write.
+ * @param contents_prepend
+ * A string to prepend at the start of each line in contents, such as spaces.
+ * Set prepend.used to 0 to not use.
* @param buffer
* The buffer to write to.
*
* Errors (with error bit) from: fl_string_dynamic_size_increase().
*/
#ifndef _di_fll_fss_basic_list_write_
- extern f_return_status fll_fss_basic_list_write(const f_string_static_t object, const f_string_statics_t contents, f_string_dynamic_t *buffer);
+ extern f_return_status fll_fss_basic_list_write(const f_string_static_t object, const f_string_statics_t contents, const f_string_static_t contents_prepend, f_string_dynamic_t *buffer);
#endif // _di_fll_fss_basic_list_write_
#ifdef __cplusplus
printf("%c", f_string_eol[0]);
fll_program_print_help_option(file, context, fss_basic_list_write_short_file, fss_basic_list_write_long_file, f_console_symbol_short_enable, f_console_symbol_long_enable, " Specify a file to send output to.");
- fll_program_print_help_option(file, context, fss_basic_list_write_short_content, fss_basic_list_write_long_content, f_console_symbol_short_enable, f_console_symbol_long_enable, "The content to output.");
+ fll_program_print_help_option(file, context, fss_basic_list_write_short_content, fss_basic_list_write_long_content, f_console_symbol_short_enable, f_console_symbol_long_enable, "The Content to output.");
fll_program_print_help_option(file, context, fss_basic_list_write_short_double, fss_basic_list_write_long_double, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use double quotes (default).");
- fll_program_print_help_option(file, context, fss_basic_list_write_short_object, fss_basic_list_write_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " The object to output.");
- fll_program_print_help_option(file, context, fss_basic_list_write_short_partial, fss_basic_list_write_long_partial, f_console_symbol_short_enable, f_console_symbol_long_enable, "Do not output end of object/content character.");
+ fll_program_print_help_option(file, context, fss_basic_list_write_short_object, fss_basic_list_write_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " The Object to output.");
+ fll_program_print_help_option(file, context, fss_basic_list_write_short_partial, fss_basic_list_write_long_partial, f_console_symbol_short_enable, f_console_symbol_long_enable, "Do not output end of Object/Content character.");
+ fll_program_print_help_option(file, context, fss_basic_list_write_short_prepend, fss_basic_list_write_long_prepend, f_console_symbol_short_enable, f_console_symbol_long_enable, "Prepend the given whitespace characters to the start of each multi-line Content.");
fll_program_print_help_option(file, context, fss_basic_list_write_short_single, fss_basic_list_write_long_single, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use single quotes.");
fll_program_print_help_usage(file, context, fss_basic_list_write_name, "");
}
}
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_basic_list_write_parameter_prepend].result == f_console_result_found) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_basic_list_write_parameter_prepend].result == f_console_result_additional) {
+ const f_string_length_t index = data->parameters[fss_basic_list_write_parameter_prepend].additional.array[data->parameters[fss_basic_list_write_parameter_prepend].additional.used - 1];
+ const f_string_length_t length = strnlen(arguments.argv[index], f_console_length_size);
+
+ if (length) {
+ f_string_range_t range = f_macro_string_range_t_initialize(length);
+
+ data->prepend.string = arguments.argv[index];
+ data->prepend.used = length;
+ data->prepend.size = length;
+
+ for (; range.start < length; range.start++) {
+
+ status = f_fss_is_space(data->prepend, range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' must only contain whitespace.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ break;
+ }
+ } // for
+ }
+ else {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_list_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' must not be an empty string.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+ }
+
f_fss_quote_t quote = f_fss_delimit_quote_double;
if (F_status_is_error_not(status)) {
#define fss_basic_list_write_short_double "d"
#define fss_basic_list_write_short_object "o"
#define fss_basic_list_write_short_partial "p"
+ #define fss_basic_list_write_short_prepend "P"
#define fss_basic_list_write_short_single "s"
#define fss_basic_list_write_long_file "file"
#define fss_basic_list_write_long_double "double"
#define fss_basic_list_write_long_object "object"
#define fss_basic_list_write_long_partial "partial"
+ #define fss_basic_list_write_long_prepend "prepend"
#define fss_basic_list_write_long_single "single"
enum {
fss_basic_list_write_parameter_double,
fss_basic_list_write_parameter_object,
fss_basic_list_write_parameter_partial,
+ fss_basic_list_write_parameter_prepend,
fss_basic_list_write_parameter_single,
};
f_console_parameter_t_initialize(fss_basic_list_write_short_double, fss_basic_list_write_long_double, 0, 0, f_console_type_normal), \
f_console_parameter_t_initialize(fss_basic_list_write_short_object, fss_basic_list_write_long_object, 0, 1, f_console_type_normal), \
f_console_parameter_t_initialize(fss_basic_list_write_short_partial, fss_basic_list_write_long_partial, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_basic_list_write_short_prepend, fss_basic_list_write_long_prepend, 0, 1, f_console_type_normal), \
f_console_parameter_t_initialize(fss_basic_list_write_short_single, fss_basic_list_write_long_single, 0, 0, f_console_type_normal), \
}
- #define fss_basic_list_write_total_parameters 15
+ #define fss_basic_list_write_total_parameters 16
#endif // _di_fss_basic_list_write_defines_
#ifndef _di_fss_basic_list_write_data_t_
f_file_t output;
fll_error_print_t error;
+ f_string_static_t prepend;
f_color_context_t context;
} fss_basic_list_write_data_t;
F_false, \
f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
fll_error_print_t_initialize, \
+ f_string_static_t_initialize, \
f_color_context_t_initialize, \
}
#endif // _di_fss_basic_list_write_data_t_
range.stop = 0;
}
- status = fl_fss_basic_list_object_write(*object, content ? f_fss_complete_full : f_fss_complete_partial, &range, buffer);
+ status = fl_fss_basic_list_object_write(*object, content ? f_fss_complete_full : f_fss_complete_none, &range, buffer);
if (F_status_set_fine(status) == F_none_eol) {
fss_basic_list_write_error_parameter_unsupported_eol_print(data);
range.start = 0;
range.stop = content->used - 1;
- status = fl_fss_basic_list_content_write(*content, &range, buffer);
+ status = fl_fss_basic_list_content_write(*content, object ? f_fss_complete_full : f_fss_complete_none, data.prepend, &range, buffer);
if (F_status_is_error(status)) {
fll_error_print(data.error, F_status_set_fine(status), "fl_fss_basic_list_content_write", F_true);
}
}
+ if (!object || !content) {
+ status = fl_string_append(f_string_eol, 1, buffer);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_string_append", F_true);
+ return status;
+ }
+ }
+
f_print_dynamic(output.stream, *buffer);
buffer->used = 0;
printf("%c", f_string_eol[0]);
fll_program_print_help_option(file, context, fss_basic_write_short_file, fss_basic_write_long_file, f_console_symbol_short_enable, f_console_symbol_long_enable, " Specify a file to send output to.");
- fll_program_print_help_option(file, context, fss_basic_write_short_content, fss_basic_write_long_content, f_console_symbol_short_enable, f_console_symbol_long_enable, "The content to output.");
+ fll_program_print_help_option(file, context, fss_basic_write_short_content, fss_basic_write_long_content, f_console_symbol_short_enable, f_console_symbol_long_enable, "The Content to output.");
fll_program_print_help_option(file, context, fss_basic_write_short_double, fss_basic_write_long_double, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use double quotes (default).");
- fll_program_print_help_option(file, context, fss_basic_write_short_object, fss_basic_write_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " The object to output.");
- fll_program_print_help_option(file, context, fss_basic_write_short_partial, fss_basic_write_long_partial, f_console_symbol_short_enable, f_console_symbol_long_enable, "Do not output end of object/content character.");
+ fll_program_print_help_option(file, context, fss_basic_write_short_object, fss_basic_write_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " The Object to output.");
+ fll_program_print_help_option(file, context, fss_basic_write_short_partial, fss_basic_write_long_partial, f_console_symbol_short_enable, f_console_symbol_long_enable, "Do not output end of Object/Content character.");
+ fll_program_print_help_option(file, context, fss_basic_write_short_prepend, fss_basic_write_long_prepend, f_console_symbol_short_enable, f_console_symbol_long_enable, "Prepend the given whitespace characters to the start of each multi-line Content.");
fll_program_print_help_option(file, context, fss_basic_write_short_single, fss_basic_write_long_single, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use single quotes.");
fll_program_print_help_usage(file, context, fss_basic_write_name, "");
printf("%c", f_string_eol[0]);
+ printf(" The FSS-0000 (Basic) specification does not support multi-line Content, therefore the parameter '");
+ fl_color_print(f_type_output, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_prepend);
+ printf("' does nothing.%c", f_string_eol[0]);
+
+ printf("%c", f_string_eol[0]);
+
return F_none;
}
#endif // _di_fss_basic_write_print_help_
}
}
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_basic_write_parameter_prepend].result == f_console_result_found) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_basic_write_parameter_prepend].result == f_console_result_additional) {
+ const f_string_length_t index = data->parameters[fss_basic_write_parameter_prepend].additional.array[data->parameters[fss_basic_write_parameter_prepend].additional.used - 1];
+ const f_string_length_t length = strnlen(arguments.argv[index], f_console_length_size);
+
+ // Even though this standard does not utilize this parameter, provide the validation for consistency.
+ if (length) {
+ f_string_range_t range = f_macro_string_range_t_initialize(length);
+ const f_string_static_t prepend = f_macro_string_static_t_initialize(arguments.argv[index], length);
+
+ for (; range.start < length; range.start++) {
+
+ status = f_fss_is_space(prepend, range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' must only contain whitespace.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ break;
+ }
+ } // for
+ }
+ else {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_basic_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' must not be an empty string.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+ }
+
f_fss_quote_t quote = f_fss_delimit_quote_double;
if (F_status_is_error_not(status)) {
#define fss_basic_write_short_double "d"
#define fss_basic_write_short_object "o"
#define fss_basic_write_short_partial "p"
+ #define fss_basic_write_short_prepend "P"
#define fss_basic_write_short_single "s"
#define fss_basic_write_long_file "file"
#define fss_basic_write_long_double "double"
#define fss_basic_write_long_object "object"
#define fss_basic_write_long_partial "partial"
+ #define fss_basic_write_long_prepend "prepend"
#define fss_basic_write_long_single "single"
enum {
fss_basic_write_parameter_double,
fss_basic_write_parameter_object,
fss_basic_write_parameter_partial,
+ fss_basic_write_parameter_prepend,
fss_basic_write_parameter_single,
};
f_console_parameter_t_initialize(fss_basic_write_short_double, fss_basic_write_long_double, 0, 0, f_console_type_normal), \
f_console_parameter_t_initialize(fss_basic_write_short_object, fss_basic_write_long_object, 0, 1, f_console_type_normal), \
f_console_parameter_t_initialize(fss_basic_write_short_partial, fss_basic_write_long_partial, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_basic_write_short_prepend, fss_basic_write_long_prepend, 0, 1, f_console_type_normal), \
f_console_parameter_t_initialize(fss_basic_write_short_single, fss_basic_write_long_single, 0, 0, f_console_type_normal), \
}
- #define fss_basic_write_total_parameters 15
+ #define fss_basic_write_total_parameters 16
#endif // _di_fss_basic_write_defines_
#ifndef _di_fss_basic_write_data_
range.stop = 0;
}
- status = fl_fss_basic_object_write(*object, quote, content ? f_fss_complete_full : f_fss_complete_partial, &range, buffer);
+ status = fl_fss_basic_object_write(*object, quote, content ? f_fss_complete_full : f_fss_complete_none, &range, buffer);
if (F_status_set_fine(status) == F_none_eol) {
fss_basic_write_error_parameter_unsupported_eol_print(data);
range.stop = 0;
}
- status = fl_fss_basic_content_write(*content, object ? f_fss_complete_full : f_fss_complete_partial, &range, buffer);
+ status = fl_fss_basic_content_write(*content, object ? f_fss_complete_full : f_fss_complete_none, &range, buffer);
if (F_status_set_fine(status) == F_none_eol) {
fss_basic_write_error_parameter_unsupported_eol_print(data);
return status;
}
}
- else {
- // objects in this standard do not have EOL, so add an EOL for printing purposes when there is no desired content.
+
+ if (!object || !content) {
status = fl_string_append(f_string_eol, 1, buffer);
if (F_status_is_error(status)) {
--- /dev/null
+#include "fss_extended_list_write.h"
+#include "private-fss_extended_list_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_extended_list_write_print_help_
+ f_return_status fss_extended_list_write_print_help(const f_file_t file, const f_color_context_t context) {
+
+ fll_program_print_help_header(file, context, fss_extended_list_write_name_long, fss_extended_list_write_version);
+
+ fll_program_print_help_option(file, context, f_console_standard_short_help, f_console_standard_long_help, f_console_symbol_short_enable, f_console_symbol_long_enable, " Print this help message.");
+ fll_program_print_help_option(file, context, f_console_standard_short_dark, f_console_standard_long_dark, f_console_symbol_short_disable, f_console_symbol_long_disable, " Output using colors that show up better on dark backgrounds.");
+ fll_program_print_help_option(file, context, f_console_standard_short_light, f_console_standard_long_light, f_console_symbol_short_disable, f_console_symbol_long_disable, " Output using colors that show up better on light backgrounds.");
+ fll_program_print_help_option(file, context, f_console_standard_short_no_color, f_console_standard_long_no_color, f_console_symbol_short_disable, f_console_symbol_long_disable, "Do not output in color.");
+ fll_program_print_help_option(file, context, f_console_standard_short_quiet, f_console_standard_long_quiet, f_console_symbol_short_disable, f_console_symbol_long_disable, " Decrease verbosity beyond normal output.");
+ fll_program_print_help_option(file, context, f_console_standard_short_normal, f_console_standard_long_normal, f_console_symbol_short_disable, f_console_symbol_long_disable, " Set verbosity to normal output.");
+ fll_program_print_help_option(file, context, f_console_standard_short_verbose, f_console_standard_long_verbose, f_console_symbol_short_disable, f_console_symbol_long_disable, " Increase verbosity beyond normal output.");
+ fll_program_print_help_option(file, context, f_console_standard_short_debug, f_console_standard_long_debug, f_console_symbol_short_disable, f_console_symbol_long_disable, " Enable debugging, inceasing verbosity beyond normal output.");
+ fll_program_print_help_option(file, context, f_console_standard_short_version, f_console_standard_long_version, f_console_symbol_short_disable, f_console_symbol_long_disable, " Print only the version number.");
+
+ printf("%c", f_string_eol[0]);
+
+ fll_program_print_help_option(file, context, fss_extended_list_write_short_file, fss_extended_list_write_long_file, f_console_symbol_short_enable, f_console_symbol_long_enable, " Specify a file to send output to.");
+ fll_program_print_help_option(file, context, fss_extended_list_write_short_content, fss_extended_list_write_long_content, f_console_symbol_short_enable, f_console_symbol_long_enable, "The Content to output.");
+ fll_program_print_help_option(file, context, fss_extended_list_write_short_double, fss_extended_list_write_long_double, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use double quotes (default).");
+ fll_program_print_help_option(file, context, fss_extended_list_write_short_object, fss_extended_list_write_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " The Object to output.");
+ fll_program_print_help_option(file, context, fss_extended_list_write_short_partial, fss_extended_list_write_long_partial, f_console_symbol_short_enable, f_console_symbol_long_enable, "Do not output end of Object/Content character.");
+ fll_program_print_help_option(file, context, fss_extended_list_write_short_prepend, fss_extended_list_write_long_prepend, f_console_symbol_short_enable, f_console_symbol_long_enable, "Prepend the given whitespace characters to the start of each multi-line Content.");
+ fll_program_print_help_option(file, context, fss_extended_list_write_short_single, fss_extended_list_write_long_single, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use single quotes.");
+
+ fll_program_print_help_usage(file, context, fss_extended_list_write_name, "");
+
+ printf(" The pipe uses the NULL character '");
+ fl_color_print(f_type_output, context.set.notable, "\\0");
+ printf("' (");
+ fl_color_print(f_type_output, context.set.notable, "U+0000");
+ printf(") to designate the start of a Content and uses the Form Feed character '");
+ fl_color_print(f_type_output, context.set.notable, "\\f");
+ printf("' (");
+ fl_color_print(f_type_output, context.set.notable, "U+000C");
+ printf(") to designate the end of the last Content.%c", f_string_eol[0]);
+ printf(" For the pipe, an Object is terminated by either a NULL character '");
+ fl_color_print(f_type_output, context.set.notable, "\\0");
+ printf("' (");
+ fl_color_print(f_type_output, context.set.notable, "U+0000");
+ printf(") or a Form Feed character '");
+ fl_color_print(f_type_output, context.set.notable, "\\f");
+ printf("' (");
+ fl_color_print(f_type_output, context.set.notable, "U+000C");
+ printf(").%c", f_string_eol[0]);
+ printf(" The end of the pipe represents the end of any Object or Content.%c", f_string_eol[0]);
+
+ printf("%c", f_string_eol[0]);
+
+ printf(" The FSS-0002 (Basic List) specification does not support quoted names, therefore the parameters '");
+ fl_color_print(f_type_output, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_single);
+ printf("' and '");
+ fl_color_print(f_type_output, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_double);
+ printf("' do nothing.%c", f_string_eol[0]);
+
+ printf("%c", f_string_eol[0]);
+
+ return F_none;
+ }
+#endif // _di_fss_extended_list_write_print_help_
+
+#ifndef _di_fss_extended_list_write_main_
+ f_return_status fss_extended_list_write_main(const f_console_arguments_t arguments, fss_extended_list_write_data_t *data) {
+ f_status_t status = F_none;
+
+ {
+ const f_console_parameters_t parameters = f_macro_console_parameters_t_initialize(data->parameters, fss_extended_list_write_total_parameters);
+
+ {
+ f_console_parameter_id_t ids[3] = { fss_extended_list_write_parameter_no_color, fss_extended_list_write_parameter_light, fss_extended_list_write_parameter_dark };
+ const f_console_parameter_ids_t choices = f_macro_console_parameter_ids_t_initialize(ids, 3);
+
+ status = fll_program_parameter_process(arguments, parameters, choices, F_true, &data->remaining, &data->context);
+
+ data->error.context = data->context.set.error;
+ data->error.notable = data->context.set.notable;
+
+ if (F_status_is_error(status)) {
+ fss_extended_list_write_delete_data(data);
+ return F_status_set_error(status);
+ }
+ }
+
+ // Identify priority of verbosity related parameters.
+ {
+ f_console_parameter_id_t ids[4] = { fss_extended_list_write_parameter_verbosity_quiet, fss_extended_list_write_parameter_verbosity_normal, fss_extended_list_write_parameter_verbosity_verbose, fss_extended_list_write_parameter_verbosity_debug };
+ f_console_parameter_id_t choice = 0;
+ const f_console_parameter_ids_t choices = f_macro_console_parameter_ids_t_initialize(ids, 4);
+
+ status = f_console_parameter_prioritize_right(parameters, choices, &choice);
+
+ if (F_status_is_error(status)) {
+ fss_extended_list_write_delete_data(data);
+ return status;
+ }
+
+ if (choice == fss_extended_list_write_parameter_verbosity_quiet) {
+ data->error.verbosity = f_console_verbosity_quiet;
+ }
+ else if (choice == fss_extended_list_write_parameter_verbosity_normal) {
+ data->error.verbosity = f_console_verbosity_normal;
+ }
+ else if (choice == fss_extended_list_write_parameter_verbosity_verbose) {
+ data->error.verbosity = f_console_verbosity_verbose;
+ }
+ else if (choice == fss_extended_list_write_parameter_verbosity_debug) {
+ data->error.verbosity = f_console_verbosity_debug;
+ }
+ }
+
+ status = F_none;
+ }
+
+ if (data->parameters[fss_extended_list_write_parameter_help].result == f_console_result_found) {
+ fss_extended_list_write_print_help(data->output, data->context);
+
+ fss_extended_list_write_delete_data(data);
+ return status;
+ }
+
+ if (data->parameters[fss_extended_list_write_parameter_version].result == f_console_result_found) {
+ fll_program_print_version(data->output, fss_extended_list_write_version);
+
+ fss_extended_list_write_delete_data(data);
+ return status;
+ }
+
+ f_file_t output = f_file_t_initialize;
+
+ output.id = f_type_descriptor_output;
+ output.stream = f_type_output;
+ output.flag = f_file_flag_create | f_file_flag_write_only | f_file_flag_append;
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_extended_list_write_parameter_file].result == f_console_result_additional) {
+ if (data->parameters[fss_extended_list_write_parameter_file].additional.used > 1) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_file);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' may only be specified once.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ else {
+ const f_string_length_t location = data->parameters[fss_extended_list_write_parameter_file].additional.array[0];
+
+ output.id = -1;
+ output.stream = 0;
+ status = f_file_stream_open(arguments.argv[location], 0, &output);
+
+ if (F_status_is_error(status)) {
+ fll_error_file_print(data->error, F_status_set_fine(status), "f_file_stream_open", F_true, arguments.argv[location], "open", fll_error_file_type_file);
+ }
+ }
+ }
+ else if (data->parameters[fss_extended_list_write_parameter_file].result == f_console_result_found) {
+ fss_extended_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_extended_list_write_long_file);
+ status = F_status_set_error(F_parameter);
+ }
+ }
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_extended_list_write_parameter_object].locations.used || data->parameters[fss_extended_list_write_parameter_content].locations.used) {
+ if (data->parameters[fss_extended_list_write_parameter_object].locations.used) {
+ if (data->parameters[fss_extended_list_write_parameter_object].locations.used != data->parameters[fss_extended_list_write_parameter_object].additional.used) {
+ fss_extended_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_extended_list_write_long_object);
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_extended_list_write_parameter_content].locations.used != data->parameters[fss_extended_list_write_parameter_content].additional.used) {
+ fss_extended_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_extended_list_write_long_content);
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_extended_list_write_parameter_object].locations.used != data->parameters[fss_extended_list_write_parameter_content].locations.used && data->parameters[fss_extended_list_write_parameter_partial].result == f_console_result_none) {
+ fss_extended_list_write_error_parameter_same_times_print(*data);
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_extended_list_write_parameter_content].locations.used && data->parameters[fss_extended_list_write_parameter_partial].locations.used) {
+ if (data->parameters[fss_extended_list_write_parameter_content].result == f_console_result_additional) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_partial);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter only allows either the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_object);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter or the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_content);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter, but not both.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_extended_list_write_parameter_content].result == f_console_result_additional) {
+ f_array_length_t location_object = 0;
+ f_array_length_t location_content = 0;
+ f_array_length_t location_sub_object = 0;
+ f_array_length_t location_sub_content = 0;
+
+ for (f_array_length_t i = 0; i < data->parameters[fss_extended_list_write_parameter_object].locations.used; i++) {
+ location_object = data->parameters[fss_extended_list_write_parameter_object].locations.array[i];
+ location_content = data->parameters[fss_extended_list_write_parameter_content].locations.array[i];
+ location_sub_object = data->parameters[fss_extended_list_write_parameter_object].locations_sub.array[i];
+ location_sub_content = data->parameters[fss_extended_list_write_parameter_content].locations_sub.array[i];
+
+ if (location_object > location_content || location_object == location_content && location_sub_object > location_sub_content) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sEach ", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_object);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter must be specified before a '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_content);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ break;
+ }
+ } // for
+ }
+ }
+ }
+ else if (data->parameters[fss_extended_list_write_parameter_content].locations.used) {
+ if (data->parameters[fss_extended_list_write_parameter_content].locations.used != data->parameters[fss_extended_list_write_parameter_content].additional.used) {
+ fss_extended_list_write_error_parameter_value_missing_print(*data, f_console_symbol_long_enable, fss_extended_list_write_long_content);
+ status = F_status_set_error(F_parameter);
+ }
+ else if (!data->parameters[fss_extended_list_write_parameter_partial].locations.used) {
+ fss_extended_list_write_error_parameter_same_times_print(*data);
+ status = F_status_set_error(F_parameter);
+ }
+ }
+ }
+ else if (!data->process_pipe) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThis requires either piped data or the use of the '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_object);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter with the '");
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_content);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+
+ if (F_status_is_error_not(status) && data->process_pipe) {
+ if (data->parameters[fss_extended_list_write_parameter_partial].result == f_console_result_found) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_partial);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' parameter cannot be used when processing a pipe.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+ }
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_extended_list_write_parameter_prepend].result == f_console_result_found) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_extended_list_write_parameter_prepend].result == f_console_result_additional) {
+ const f_string_length_t index = data->parameters[fss_extended_list_write_parameter_prepend].additional.array[data->parameters[fss_extended_list_write_parameter_prepend].additional.used - 1];
+ const f_string_length_t length = strnlen(arguments.argv[index], f_console_length_size);
+
+ if (length) {
+ f_string_range_t range = f_macro_string_range_t_initialize(length);
+
+ data->prepend.string = arguments.argv[index];
+ data->prepend.used = length;
+ data->prepend.size = length;
+
+ for (; range.start < length; range.start++) {
+
+ status = f_fss_is_space(data->prepend, range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' must only contain whitespace.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ break;
+ }
+ } // for
+ }
+ else {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' must not be an empty string.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+ }
+
+ f_fss_quote_t quote = f_fss_delimit_quote_double;
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_extended_list_write_parameter_double].result == f_console_result_found) {
+ if (data->parameters[fss_extended_list_write_parameter_single].result == f_console_result_found) {
+ if (data->parameters[fss_extended_list_write_parameter_double].location < data->parameters[fss_extended_list_write_parameter_single].location) {
+ quote = f_fss_delimit_quote_single;
+ }
+ }
+ }
+ else if (data->parameters[fss_extended_list_write_parameter_single].result == f_console_result_found) {
+ quote = f_fss_delimit_quote_single;
+ }
+ }
+
+ f_string_dynamic_t buffer = f_string_dynamic_t_initialize;
+ f_string_dynamic_t object = f_string_dynamic_t_initialize;
+ f_string_dynamic_t content = f_string_dynamic_t_initialize;
+
+ if (F_status_is_error_not(status)) {
+ f_string_dynamic_t escaped = f_string_dynamic_t_initialize;
+
+ if (data->process_pipe) {
+ status = fss_extended_list_write_process_pipe(*data, output, quote, &buffer);
+
+ if (F_status_is_error(status)) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "input pipe");
+ fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]);
+ }
+ }
+ }
+
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_extended_list_write_parameter_partial].result == f_console_result_found) {
+
+ if (data->parameters[fss_extended_list_write_parameter_object].result == f_console_result_additional) {
+ for (f_array_length_t i = 0; i < data->parameters[fss_extended_list_write_parameter_object].additional.used; i++) {
+
+ object.string = arguments.argv[data->parameters[fss_extended_list_write_parameter_object].additional.array[i]];
+ object.used = strnlen(object.string, f_console_length_size);
+ object.size = object.used;
+
+ status = fss_extended_list_write_process(*data, output, quote, &object, 0, &buffer);
+ if (F_status_is_error(status)) break;
+ } // for
+ }
+ else {
+ for (f_array_length_t i = 0; i < data->parameters[fss_extended_list_write_parameter_content].additional.used; i++) {
+
+ content.string = arguments.argv[data->parameters[fss_extended_list_write_parameter_content].additional.array[i]];
+ content.used = strnlen(content.string, f_console_length_size);
+ content.size = content.used;
+
+ status = fss_extended_list_write_process(*data, output, quote, 0, &content, &buffer);
+ if (F_status_is_error(status)) break;
+ } // for
+ }
+ }
+ else {
+ for (f_array_length_t i = 0; i < data->parameters[fss_extended_list_write_parameter_object].additional.used; i++) {
+
+ object.string = arguments.argv[data->parameters[fss_extended_list_write_parameter_object].additional.array[i]];
+ object.used = strnlen(object.string, f_console_length_size);
+ object.size = object.used;
+
+ content.string = arguments.argv[data->parameters[fss_extended_list_write_parameter_content].additional.array[i]];
+ content.used = strnlen(content.string, f_console_length_size);
+ content.size = content.used;
+
+ status = fss_extended_list_write_process(*data, output, quote, &object, &content, &buffer);
+ if (F_status_is_error(status)) break;
+ } // for
+ }
+
+ if (F_status_is_error(status)) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sWhile processing the ", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "input arguments");
+ fl_color_print(data->error.to.stream, data->context.set.error, ".%c", f_string_eol[0]);
+ }
+ }
+ else if (data->error.verbosity != f_console_verbosity_quiet && data->parameters[fss_extended_list_write_parameter_file].result == f_console_result_none) {
+ // ensure there is always a newline at the end, unless in quiet mode.
+ fprintf(f_type_output, "%c", f_string_eol[0]);
+ }
+ }
+
+ f_macro_string_dynamic_t_delete_simple(escaped);
+
+ // object and content, though being a "dynamic" type, is being used statically, so clear them up to avoid invalid free().
+ object.string = 0;
+ object.used = 0;
+ object.size = 0;
+
+ content.string = 0;
+ content.used = 0;
+ content.size = 0;
+ }
+
+ if (data->parameters[fss_extended_list_write_parameter_file].result == f_console_result_additional) {
+ if (output.id != -1) {
+ f_file_stream_close(F_true, &output);
+ }
+ }
+
+ // ensure a newline is always put at the end of the program execution, unless in quiet mode.
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ if (F_status_is_error(status)) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ }
+ }
+
+ f_macro_string_dynamic_t_delete_simple(buffer);
+ f_macro_string_dynamic_t_delete_simple(object);
+ f_macro_string_dynamic_t_delete_simple(content);
+ fss_extended_list_write_delete_data(data);
+ return status;
+ }
+#endif // _di_fss_extended_list_write_main_
+
+#ifndef _di_fss_extended_list_write_delete_data_
+ f_return_status fss_extended_list_write_delete_data(fss_extended_list_write_data_t *data) {
+
+ for (f_string_length_t i = 0; i < fss_extended_list_write_total_parameters; i++) {
+ f_macro_string_lengths_t_delete_simple(data->parameters[i].locations);
+ f_macro_string_lengths_t_delete_simple(data->parameters[i].locations_sub);
+ f_macro_string_lengths_t_delete_simple(data->parameters[i].additional);
+ } // for
+
+ f_macro_string_lengths_t_delete_simple(data->remaining);
+
+ f_macro_color_context_t_delete_simple(data->context);
+
+ return F_none;
+ }
+#endif // _di_fss_extended_list_write_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * This program provides fss basic list write functionality.
+ */
+#ifndef _fss_extended_list_write_h
+
+// libc includes
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// fll-0 includes
+#include <level_0/type.h>
+#include <level_0/status.h>
+#include <level_0/memory.h>
+#include <level_0/string.h>
+#include <level_0/utf.h>
+#include <level_0/console.h>
+#include <level_0/file.h>
+#include <level_0/pipe.h>
+#include <level_0/print.h>
+
+// fll-1 includes
+#include <level_1/color.h>
+#include <level_1/console.h>
+#include <level_1/fss_extended_list.h>
+#include <level_1/status.h>
+#include <level_1/string.h>
+
+// fll-2 includes
+#include <level_2/error.h>
+#include <level_2/fss_status.h>
+#include <level_2/program.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_extended_list_write_version_
+ #define fss_extended_list_write_major_version "0"
+ #define fss_extended_list_write_minor_version "5"
+ #define fss_extended_list_write_micro_version "1"
+ #define fss_extended_list_write_version fss_extended_list_write_major_version "." fss_extended_list_write_minor_version "." fss_extended_list_write_micro_version
+#endif // _di_fss_extended_list_write_version_
+
+#ifndef _di_fss_extended_list_write_name_
+ #define fss_extended_list_write_name "fss_extended_list_write"
+ #define fss_extended_list_write_name_long "FSS Basic List Write"
+#endif // _di_fss_extended_list_write_name_
+
+#ifndef _di_fss_extended_list_write_defines_
+ #define fss_extended_list_write_pipe_content_start '\0'
+ #define fss_extended_list_write_pipe_content_end '\f'
+
+ #define fss_extended_list_write_short_file "f"
+ #define fss_extended_list_write_short_content "c"
+ #define fss_extended_list_write_short_double "d"
+ #define fss_extended_list_write_short_object "o"
+ #define fss_extended_list_write_short_partial "p"
+ #define fss_extended_list_write_short_prepend "P"
+ #define fss_extended_list_write_short_single "s"
+
+ #define fss_extended_list_write_long_file "file"
+ #define fss_extended_list_write_long_content "content"
+ #define fss_extended_list_write_long_double "double"
+ #define fss_extended_list_write_long_object "object"
+ #define fss_extended_list_write_long_partial "partial"
+ #define fss_extended_list_write_long_prepend "prepend"
+ #define fss_extended_list_write_long_single "single"
+
+ enum {
+ fss_extended_list_write_parameter_help,
+ fss_extended_list_write_parameter_light,
+ fss_extended_list_write_parameter_dark,
+ fss_extended_list_write_parameter_no_color,
+ fss_extended_list_write_parameter_verbosity_quiet,
+ fss_extended_list_write_parameter_verbosity_normal,
+ fss_extended_list_write_parameter_verbosity_verbose,
+ fss_extended_list_write_parameter_verbosity_debug,
+ fss_extended_list_write_parameter_version,
+
+ fss_extended_list_write_parameter_file,
+ fss_extended_list_write_parameter_content,
+ fss_extended_list_write_parameter_double,
+ fss_extended_list_write_parameter_object,
+ fss_extended_list_write_parameter_partial,
+ fss_extended_list_write_parameter_prepend,
+ fss_extended_list_write_parameter_single,
+ };
+
+ #define fss_extended_list_write_console_parameter_t_initialize \
+ { \
+ f_console_parameter_t_initialize(f_console_standard_short_help, f_console_standard_long_help, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(f_console_standard_short_light, f_console_standard_long_light, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_dark, f_console_standard_long_dark, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_no_color, f_console_standard_long_no_color, 0, F_false, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_quiet, f_console_standard_long_quiet, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_normal, f_console_standard_long_normal, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_verbose, f_console_standard_long_verbose, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_debug, f_console_standard_long_debug, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(f_console_standard_short_version, f_console_standard_long_version, 0, 0, f_console_type_inverse), \
+ f_console_parameter_t_initialize(fss_extended_list_write_short_file, fss_extended_list_write_long_file, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_extended_list_write_short_content, fss_extended_list_write_long_content, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_extended_list_write_short_double, fss_extended_list_write_long_double, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_extended_list_write_short_object, fss_extended_list_write_long_object, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_extended_list_write_short_partial, fss_extended_list_write_long_partial, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_extended_list_write_short_prepend, fss_extended_list_write_long_prepend, 0, 1, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_extended_list_write_short_single, fss_extended_list_write_long_single, 0, 0, f_console_type_normal), \
+ }
+
+ #define fss_extended_list_write_total_parameters 16
+#endif // _di_fss_extended_list_write_defines_
+
+#ifndef _di_fss_extended_list_write_data_t_
+ typedef struct {
+ f_console_parameter_t parameters[fss_extended_list_write_total_parameters];
+
+ f_string_lengths_t remaining;
+ bool process_pipe;
+
+ f_file_t output;
+ fll_error_print_t error;
+ f_string_static_t prepend;
+
+ f_color_context_t context;
+ } fss_extended_list_write_data_t;
+
+ #define fss_extended_list_write_data_t_initialize \
+ { \
+ fss_extended_list_write_console_parameter_t_initialize, \
+ f_string_lengths_t_initialize, \
+ F_false, \
+ f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
+ fll_error_print_t_initialize, \
+ f_string_static_t_initialize, \
+ f_color_context_t_initialize, \
+ }
+#endif // _di_fss_extended_list_write_data_t_
+
+/**
+ * Print help.
+ *
+ * @param file
+ * The file to print to.
+ * @param context
+ * The color context settings.
+ *
+ * @return
+ * F_none on success.
+ */
+#ifndef _di_fss_extended_list_write_print_help_
+ extern f_return_status fss_extended_list_write_print_help(const f_file_t file, const f_color_context_t context);
+#endif // _di_fss_extended_list_write_print_help_
+
+/**
+ * Execute main program.
+ *
+ * Be sure to call fss_extended_list_write_delete_data() after executing this.
+ *
+ * @param arguments
+ * The parameters passed to the process.
+ * @param data
+ * The program data.
+ *
+ * @return
+ * F_none on success.
+ *
+ * Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_extended_list_write_delete_data()
+ */
+#ifndef _di_fss_extended_list_write_main_
+ extern f_return_status fss_extended_list_write_main(const f_console_arguments_t arguments, fss_extended_list_write_data_t *data);
+#endif // _di_fss_extended_list_write_main_
+
+/**
+ * Deallocate data.
+ *
+ * Be sure to call this after executing fss_extended_list_write_main().
+ *
+ * @param data
+ * The program data.
+ *
+ * @return
+ * F_none on success.
+ *
+ * Status codes (with error bit) are returned on any problem.
+ *
+ * @see fss_extended_list_write_main()
+ */
+#ifndef _di_fss_extended_list_write_delete_data_
+ extern f_return_status fss_extended_list_write_delete_data(fss_extended_list_write_data_t *data);
+#endif // _di_fss_extended_list_write_delete_data_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _fss_extended_list_write_h
--- /dev/null
+#include "fss_extended_list_write.h"
+
+int main(const unsigned long argc, const f_string_t *argv) {
+ const f_console_arguments_t arguments = { argc, argv };
+ fss_extended_list_write_data_t data = fss_extended_list_write_data_t_initialize;
+
+ if (f_pipe_input_exists()) {
+ data.process_pipe = F_true;
+ }
+
+ if (F_status_is_error(fss_extended_list_write_main(arguments, &data))) {
+ return 1;
+ }
+
+ return 0;
+}
--- /dev/null
+#include "fss_extended_list_write.h"
+#include "private-fss_extended_list_write.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_fss_extended_list_write_error_parameter_same_times_print_
+ void fss_extended_list_write_error_parameter_same_times_print(const fss_extended_list_write_data_t data) {
+
+ if (data.error.verbosity == f_console_verbosity_quiet) {
+ return;
+ }
+
+ fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data.error.to.stream, data.context.set.error, "%sMust specify both the '", fll_error_print_error);
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_object);
+ fl_color_print(data.error.to.stream, data.context.set.error, "' parameter and the '");
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_content);
+ fl_color_print(data.error.to.stream, data.context.set.error, "' parameter the same number of times when not specifying the ");
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_list_write_long_partial);
+ fl_color_print(data.error.to.stream, data.context.set.error, "' parameter.%c", f_string_eol[0]);
+ }
+#endif // _di_fss_extended_list_write_error_parameter_same_times_print_
+
+#ifndef _di_fss_extended_list_write_error_parameter_unsupported_eol_print_
+ void fss_extended_list_write_error_parameter_unsupported_eol_print(const fss_extended_list_write_data_t data) {
+
+ if (data.error.verbosity == f_console_verbosity_quiet) {
+ return;
+ }
+
+ fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard does not support end of line character '", fll_error_print_error);
+ fl_color_print(data.error.to.stream, data.context.set.notable, "\\n");
+ fl_color_print(data.error.to.stream, data.context.set.error, "' in objects.%c", f_string_eol[0]);
+ }
+#endif // _di_fss_extended_list_write_error_parameter_unsupported_eol_print_
+
+#ifndef _di_fss_extended_list_write_error_parameter_value_missing_print_
+ void fss_extended_list_write_error_parameter_value_missing_print(const fss_extended_list_write_data_t data, const f_string_t symbol, const f_string_t parameter) {
+
+ if (data.error.verbosity == f_console_verbosity_quiet) {
+ return;
+ }
+
+ fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data.error.to.stream, data.context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data.error.to.stream, data.context.set.notable, "%s%s", symbol, parameter);
+ fl_color_print(data.error.to.stream, data.context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]);
+ }
+#endif // _di_fss_extended_list_write_error_parameter_value_missing_print_
+
+#ifndef _di_fss_extended_list_write_process_
+ f_return_status fss_extended_list_write_process(const fss_extended_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, f_string_dynamic_t *buffer) {
+ f_status_t status = F_none;
+
+ f_string_range_t range = f_string_range_t_initialize;
+
+ if (object) {
+ if (object->used) {
+ range.start = 0;
+ range.stop = object->used - 1;
+ }
+ else {
+ range.start = 1;
+ range.stop = 0;
+ }
+
+ status = fl_fss_extended_list_object_write(*object, content ? f_fss_complete_full : f_fss_complete_none, &range, buffer);
+
+ if (F_status_set_fine(status) == F_none_eol) {
+ fss_extended_list_write_error_parameter_unsupported_eol_print(data);
+
+ return F_status_set_error(F_unsupported);
+ }
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_fss_extended_list_object_write", F_true);
+ return status;
+ }
+ }
+
+ if (content && content->used) {
+ range.start = 0;
+ range.stop = content->used - 1;
+
+ status = fl_fss_extended_list_content_write(*content, object ? f_fss_complete_full : f_fss_complete_none, data.prepend, &range, buffer);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_fss_extended_list_content_write", F_true);
+ return status;
+ }
+ }
+
+ if (!object || !content) {
+ status = fl_string_append(f_string_eol, 1, buffer);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_string_append", F_true);
+ return status;
+ }
+ }
+
+ f_print_dynamic(output.stream, *buffer);
+
+ buffer->used = 0;
+ return status;
+ }
+#endif // _di_fss_extended_list_write_process_
+
+#ifndef _di_fss_extended_list_write_process_pipe_
+ f_return_status fss_extended_list_write_process_pipe(const fss_extended_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) {
+ f_status_t status = F_none;
+ f_status_t status_pipe = F_none;
+
+ f_file_t input = f_file_t_initialize;
+
+ input.id = f_type_descriptor_input;
+ input.size_read = 2048;
+
+ f_string_length_t total = 0;
+ f_string_length_t previous = 0;
+ f_string_range_t range = f_string_range_t_initialize;
+
+ f_string_dynamic_t block = f_string_dynamic_t_initialize;
+ f_string_dynamic_t object = f_string_dynamic_t_initialize;
+ f_string_dynamic_t content = f_string_dynamic_t_initialize;
+
+ // 0x0 = start new object/content set, 0x1 = processing object, 0x2 = processing content, 0x3 = end object/content set.
+ uint8_t state = 0;
+
+ for (;;) {
+
+ if (range.start > range.stop) {
+ if (status_pipe == F_none_eof) break;
+
+ block.used = 0;
+
+ status_pipe = f_file_read_block(input, &block);
+
+ if (F_status_is_error(status_pipe)) {
+ fll_error_print(data.error, F_status_set_fine(status_pipe), "f_file_read_block", F_true);
+
+ status_pipe = F_status_set_error(F_pipe);
+ break;
+ }
+
+ if (!block.used) break;
+
+ range.start = 0;
+ range.stop = block.used - 1;
+ }
+
+ if (!state || state == 0x1) {
+ if (!state) {
+ object.used = 0;
+ content.used = 0;
+
+ state = 0x1;
+ }
+
+ if (object.used + block.used > object.size) {
+ status = fl_string_dynamic_size_increase(block.used, &object);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_size_increase", F_true);
+ break;
+ }
+ }
+
+ for (; range.start <= range.stop; range.start++) {
+
+ if (block.string[range.start] == fss_extended_list_write_pipe_content_start) {
+ state = 0x2;
+ range.start++;
+ break;
+ }
+
+ if (block.string[range.start] == fss_extended_list_write_pipe_content_end) {
+ state = 0x3;
+ range.start++;
+ break;
+ }
+
+ object.string[object.used++] = block.string[range.start];
+ } // for
+
+ if (F_status_is_error(status)) break;
+
+ // if the start of content was not found, then fetch the next block.
+ if (state == 0x1) continue;
+
+ // if the end of the current block is reached, fetch the next block.
+ if (range.start > range.stop) continue;
+ }
+
+ if (state == 0x2) {
+ if (range.start <= range.stop) {
+ total = (range.stop - range.start) + 1;
+ }
+ else {
+ total = 0;
+ }
+
+ if (total) {
+ if (content.used + total > content.size) {
+ status = fl_string_dynamic_size_increase(total, &content);
+
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_size_increase", F_true);
+ break;
+ }
+ }
+
+ for (; range.start <= range.stop; range.start++) {
+
+ if (block.string[range.start] == fss_extended_list_write_pipe_content_start) {
+ if (data.error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data.error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data.error.to.stream, data.context.set.error, "%sThis standard only supports one content per object.%c", fll_error_print_error, f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_unsupported);
+ break;
+ }
+
+ if (block.string[range.start] == fss_extended_list_write_pipe_content_end) {
+ state = 0x3;
+ range.start++;
+ break;
+ }
+
+ content.string[content.used++] = block.string[range.start];
+ } // for
+
+ if (F_status_is_error(status)) break;
+ }
+ else {
+ state = 0x3;
+ }
+ }
+
+ if (state == 0x3) {
+ status = fss_extended_list_write_process(data, output, quote, &object, &content, buffer);
+ if (F_status_is_error(status)) break;
+
+ state = 0;
+ }
+ } // for
+
+ // if the pipe ended before finishing, then attempt to wrap up.
+ if (F_status_is_error_not(status) && status_pipe == F_none_eof && state) {
+ status = fss_extended_list_write_process(data, output, quote, &object, &content, buffer);
+ }
+
+ f_macro_string_dynamic_t_delete_simple(block);
+ f_macro_string_dynamic_t_delete_simple(object);
+ f_macro_string_dynamic_t_delete_simple(content);
+ return status;
+ }
+#endif // _di_fss_extended_list_write_process_pipe_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 3
+ *
+ * Project: FSS
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ */
+#ifndef _PRIVATE_fss_extended_list_write_h
+#define _PRIVATE_fss_extended_list_write_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Print an message about the object and content parameters not being specified the same number of times.
+ *
+ * @param data
+ * The program data.
+ *
+ * @return
+ * F_none on success.
+ * F_failure (with error bit) for any othe failure.
+ */
+#ifndef _di_fss_extended_list_write_error_parameter_same_times_print_
+ void fss_extended_list_write_error_parameter_same_times_print(const fss_extended_list_write_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_extended_list_write_error_parameter_same_times_print_
+
+/**
+ * Print an message about a parameter EOL being unsupported.
+ *
+ * @param data
+ * The program data.
+ *
+ * @return
+ * F_none on success.
+ * F_failure (with error bit) for any othe failure.
+ */
+#ifndef _di_fss_extended_list_write_error_parameter_unsupported_eol_print_
+ void fss_extended_list_write_error_parameter_unsupported_eol_print(const fss_extended_list_write_data_t data) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_extended_list_write_error_parameter_unsupported_eol_print_
+
+/**
+ * Print an message about a parameter missing a value.
+ *
+ * @param data
+ * The program data.
+ * @param symbol
+ * The console symbol, such as "--" in "--help".
+ * @param parameter
+ * The parameter name, such as "help" in "--help".
+ *
+ * @return
+ * F_none on success.
+ * F_failure (with error bit) for any othe failure.
+ */
+#ifndef _di_fss_extended_list_write_error_parameter_value_missing_print_
+ void fss_extended_list_write_error_parameter_value_missing_print(const fss_extended_list_write_data_t data, const f_string_t symbol, const f_string_t parameter) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_extended_list_write_error_parameter_value_missing_print_
+
+/**
+ * Process a given object and content, printing the FSS if valid or an error if invalid.
+ *
+ * @param data
+ * The program data.
+ * @param output
+ * The file to output to.
+ * @param quote
+ * The quote character to use.
+ * This is either single our double quote.
+ * @param object
+ * The object to validate and print.
+ * @param content
+ * The content to escape and print.
+ * @param buffer
+ * The buffer array used as a cache to construct the output before printing.
+ *
+ * @return
+ * F_none on success.
+ * F_failure (with error bit) for any othe failure.
+ */
+#ifndef _di_fss_extended_list_write_process_
+ extern f_return_status fss_extended_list_write_process(const fss_extended_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, const f_string_static_t *object, const f_string_static_t *content, f_string_dynamic_t *buffer) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_extended_list_write_process_
+
+/**
+ * Process the pipe, reading from the pipe and writing to the output.
+ *
+ * @param data
+ * The program data.
+ * @param output
+ * The file to output to.
+ * @param quote
+ * The quote character to use.
+ * This is either single our double quote.
+ * @param buffer
+ * The buffer array used as a cache to construct the output before printing.
+ *
+ * @return
+ * F_none on success.
+ * F_failure (with error bit) for any othe failure.
+ */
+#ifndef _di_fss_extended_list_write_process_pipe_
+ extern f_return_status fss_extended_list_write_process_pipe(const fss_extended_list_write_data_t data, const f_file_t output, const f_fss_quote_t quote, f_string_dynamic_t *buffer) f_gcc_attribute_visibility_internal;
+#endif // _di_fss_extended_list_write_process_pipe_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_fss_extended_list_write_h
--- /dev/null
+# fss-0000
+
--- /dev/null
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_string
+f_utf
+f_color
+f_console
+f_directory
+f_environment
+f_file
+f_fss
+f_pipe
+f_print
+fl_color
+fl_console
+fl_conversion
+fl_fss
+fl_status
+fl_string
+fll_error
+fll_execute
+fll_file
+fll_fss
+fll_program
--- /dev/null
+# fss-0001
+
+project_name fss_extended_list_write
+
+version_major 0
+version_minor 5
+version_micro 1
+version_target major
+
+environment
+
+process_pre
+process_post
+
+modes individual level monolithic
+modes_default individual
+
+build_compiler gcc
+build_indexer ar
+build_language c
+build_libraries -lc
+build_libraries-individual -lfll_program -lfll_fss -lfll_file -lfl_directory -lfll_execute -lfl_environment -lf_signal -lf_path -lfll_error -lfl_string -lfl_status -lfl_fss -lfl_conversion -lfl_console -lf_conversion -lfl_color -lf_print -lf_pipe -lf_fss -lf_file -lf_environment -lf_directory -lf_console -lf_utf -lf_memory
+build_libraries-level -lfll_2 -lfll_1 -lfll_0
+build_libraries-monolithic -lfll
+build_sources_library fss_extended_list_write.c private-fss_extended_list_write.c
+build_sources_program main.c
+build_sources_headers fss_extended_list_write.h
+build_sources_script
+build_sources_setting
+build_script yes
+build_shared yes
+build_static yes
+
+path_headers level_3
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+path_sources
+path_standard yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines_all
+defines_static
+defines_shared
+
+flags_all -z now -g -fdiagnostics-color=always
+flags_shared
+flags_static
+flags_library -fPIC
+flags_program -fPIE
printf("%c", f_string_eol[0]);
fll_program_print_help_option(file, context, fss_extended_write_short_file, fss_extended_write_long_file, f_console_symbol_short_enable, f_console_symbol_long_enable, " Specify a file to send output to.");
- fll_program_print_help_option(file, context, fss_extended_write_short_content, fss_extended_write_long_content, f_console_symbol_short_enable, f_console_symbol_long_enable, "The content to output.");
+ fll_program_print_help_option(file, context, fss_extended_write_short_content, fss_extended_write_long_content, f_console_symbol_short_enable, f_console_symbol_long_enable, "The Content to output.");
fll_program_print_help_option(file, context, fss_extended_write_short_double, fss_extended_write_long_double, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use double quotes (default).");
- fll_program_print_help_option(file, context, fss_extended_write_short_object, fss_extended_write_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " The object to output.");
- fll_program_print_help_option(file, context, fss_extended_write_short_partial, fss_extended_write_long_partial, f_console_symbol_short_enable, f_console_symbol_long_enable, "Do not output end of object/content character.");
+ fll_program_print_help_option(file, context, fss_extended_write_short_object, fss_extended_write_long_object, f_console_symbol_short_enable, f_console_symbol_long_enable, " The Object to output.");
+ fll_program_print_help_option(file, context, fss_extended_write_short_partial, fss_extended_write_long_partial, f_console_symbol_short_enable, f_console_symbol_long_enable, "Do not output end of Object/Content character.");
+ fll_program_print_help_option(file, context, fss_extended_write_short_prepend, fss_extended_write_long_prepend, f_console_symbol_short_enable, f_console_symbol_long_enable, "Prepend the given whitespace characters to the start of each multi-line Content.");
fll_program_print_help_option(file, context, fss_extended_write_short_single, fss_extended_write_long_single, f_console_symbol_short_enable, f_console_symbol_long_enable, " Use single quotes.");
fll_program_print_help_usage(file, context, fss_extended_write_name, "");
printf("%c", f_string_eol[0]);
+ printf(" The FSS-0001 (Extended) specification does not support multi-line Content, therefore the parameter '");
+ fl_color_print(f_type_output, context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_prepend);
+ printf("' does nothing.%c", f_string_eol[0]);
+
+ printf("%c", f_string_eol[0]);
+
return F_none;
}
#endif // _di_fss_extended_write_print_help_
}
}
+ if (F_status_is_error_not(status)) {
+ if (data->parameters[fss_extended_write_parameter_prepend].result == f_console_result_found) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' was specified, but no value was given.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ else if (data->parameters[fss_extended_write_parameter_prepend].result == f_console_result_additional) {
+ const f_string_length_t index = data->parameters[fss_extended_write_parameter_prepend].additional.array[data->parameters[fss_extended_write_parameter_prepend].additional.used - 1];
+ const f_string_length_t length = strnlen(arguments.argv[index], f_console_length_size);
+
+ // Even though this standard does not utilize this parameter, provide the validation for consistency.
+ if (length) {
+ f_string_range_t range = f_macro_string_range_t_initialize(length);
+ const f_string_static_t prepend = f_macro_string_static_t_initialize(arguments.argv[index], length);
+
+ for (; range.start < length; range.start++) {
+
+ status = f_fss_is_space(prepend, range);
+ if (F_status_is_error(status)) break;
+
+ if (status == F_false) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' must only contain whitespace.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ break;
+ }
+ } // for
+ }
+ else {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data->error.to.stream, "%c", f_string_eol[0]);
+ fl_color_print(data->error.to.stream, data->context.set.error, "%sThe value for the parameter '", fll_error_print_error);
+ fl_color_print(data->error.to.stream, data->context.set.notable, "%s%s", f_console_symbol_long_enable, fss_extended_write_long_prepend);
+ fl_color_print(data->error.to.stream, data->context.set.error, "' must not be an empty string.%c", f_string_eol[0]);
+ }
+
+ status = F_status_set_error(F_parameter);
+ }
+ }
+ }
+
f_fss_quote_t quote = f_fss_delimit_quote_double;
if (F_status_is_error_not(status)) {
fll_error_print(data->error, F_status_set_fine(status), "fl_string_dynamics_size_increase", F_true);
}
else {
- for (f_array_length_t i = 0; i < data->parameters[fss_extended_write_parameter_content].additional.used; i++) {
+ f_array_length_t i = 0;
+
+ for (; i < data->parameters[fss_extended_write_parameter_content].additional.used; i++) {
contents.array[contents.used].string = arguments.argv[data->parameters[fss_extended_write_parameter_content].additional.array[i]];
contents.array[contents.used].used = strnlen(contents.array[contents.used].string, f_console_length_size);
} // for
status = fss_extended_write_process(*data, output, quote, 0, &contents, &buffer);
+
+ // clear the contents array of the static strings to avoid deallocation attempts on static variables.
+ for (; i < data->parameters[fss_extended_write_parameter_content].additional.used; i++) {
+ contents.array[contents.used].string = 0;
+ contents.array[contents.used].used = 0;
+ contents.array[contents.used].size = 0;
+ } // for
+
+ contents.used = 0;
+ contents.size = 0;
}
}
}
#define fss_extended_write_short_double "d"
#define fss_extended_write_short_object "o"
#define fss_extended_write_short_partial "p"
+ #define fss_extended_write_short_prepend "P"
#define fss_extended_write_short_single "s"
#define fss_extended_write_long_file "file"
#define fss_extended_write_long_double "double"
#define fss_extended_write_long_object "object"
#define fss_extended_write_long_partial "partial"
+ #define fss_extended_write_long_prepend "prepend"
#define fss_extended_write_long_single "single"
enum {
fss_extended_write_parameter_double,
fss_extended_write_parameter_object,
fss_extended_write_parameter_partial,
+ fss_extended_write_parameter_prepend,
fss_extended_write_parameter_single,
};
f_console_parameter_t_initialize(fss_extended_write_short_double, fss_extended_write_long_double, 0, 0, f_console_type_normal), \
f_console_parameter_t_initialize(fss_extended_write_short_object, fss_extended_write_long_object, 0, 1, f_console_type_normal), \
f_console_parameter_t_initialize(fss_extended_write_short_partial, fss_extended_write_long_partial, 0, 0, f_console_type_normal), \
+ f_console_parameter_t_initialize(fss_extended_write_short_prepend, fss_extended_write_long_prepend, 0, 1, f_console_type_normal), \
f_console_parameter_t_initialize(fss_extended_write_short_single, fss_extended_write_long_single, 0, 0, f_console_type_normal), \
}
- #define fss_extended_write_total_parameters 15
+ #define fss_extended_write_total_parameters 16
#endif // _di_fss_extended_write_defines_
#ifndef _di_fss_extended_write_data_t_
f_file_t output;
fll_error_print_t error;
+ f_string_static_t prepend;
f_color_context_t context;
} fss_extended_write_data_t;
F_false, \
f_macro_file_t_initialize(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \
fll_error_print_t_initialize, \
+ f_string_static_t_initialize, \
f_color_context_t_initialize, \
}
#endif // _di_fss_extended_write_data_t_
range.stop = 0;
}
- status = fl_fss_extended_object_write(*object, quote, contents && contents->used ? f_fss_complete_full : f_fss_complete_partial, &range, buffer);
+ status = fl_fss_extended_object_write(*object, quote, contents && contents->used ? f_fss_complete_full : f_fss_complete_none, &range, buffer);
if (F_status_set_fine(status) == F_none_eol) {
fss_extended_write_error_parameter_unsupported_eol_print(data);
}
} // for
}
- else {
- // objects in this standard do not have EOL, so add an EOL for printing purposes when there is no desired content.
- status = fl_string_append(f_string_eol, 1, buffer);
+ }
+ else if (!object) {
+ status = fl_string_append(f_string_eol, 1, buffer);
- if (F_status_is_error(status)) {
- fll_error_print(data.error, F_status_set_fine(status), "fl_string_append", F_true);
- return status;
- }
+ if (F_status_is_error(status)) {
+ fll_error_print(data.error, F_status_set_fine(status), "fl_string_append", F_true);
+ return status;
}
}