f_fss_count_slash(buffer, range, &slash_count, state);
+ if (state->status == F_combarudoo || state->status == F_bound) {
+ f_fss_skip_past_combining_joiner(buffer, range, state);
+ if (F_status_is_error(state->status)) return;
+
+ continue;
+ }
+
if (F_status_is_error(state->status)) return;
- if (state->status == F_combarudoo || state->status == F_bound) continue;
if (range->start >= buffer.used) {
found->stop = buffer.used - 1;
// This check sets the state status, which is then used by the condition below.
if (f_fss_is_space(buffer, *range, state) == F_true) {
- if (state->status == F_control && buffer.string[range->start] == f_fss_eol_s.string[0]) {
+ if (buffer.string[range->start] == f_fss_eol_s.string[0]) {
// The EOL is immediately valid and is not to be checked for combining/joiners.
state->status = F_true;
#define ___fl_flag_as_object___ 0x1
- #define ___fl_flag_do_handle___ 0x1
+ #define ___fl_flag_do_handle___ 0x1
+ #define ___fl_flag_has_combining___ 0x2
+ #define ___fl_flag_has_combining_joiner___ 0xa
+ #define ___fl_flag_has_increased___ 0x4
+ #define ___fl_flag_has_joiner___ 0x8
+ #define ___fl_flag_is_quoted___ 0x10
+ #define ___fl_flag_is_commented___ 0x20
+ #define ___fl_flag_save_partial___ 0x40
const f_number_unsigned_t input_start = range->start;
const f_number_unsigned_t used_start = destination->used;
- uint8_t quoted_is = F_false;
uint8_t commented = F_false;
uint8_t width = 0;
uint8_t flag_fl = 0x0;
if (F_status_is_error_not(state->status)) {
if (f_fss_is_combining_joiner(object, *range, state) == F_true) {
+ flag_fl |= state->status == F_combarudoo
+ ? ___fl_flag_has_combining___
+ : ___fl_flag_has_joiner___;
+
f_fss_skip_past_combining_joiner(object, range, state);
if (F_status_is_error_not(state->status)) {
- partial.start = input_start;
- partial.stop = range->start;
+ if (range->start > range->stop || range->start >= object.used) {
+ partial.stop = range->start;
+ }
+ else {
- state->status = f_memory_array_increase_by(width, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
- }
+ // The joined character must be considered a new, different, character.
+ if (!(flag_fl & ___fl_flag_has_joiner___)) {
+ f_utf_buffer_decrement(object, range, 1);
+ }
- if (F_status_is_error_not(state->status)) {
- state->status = f_string_dynamic_partial_append_nulless(object, partial, destination);
- }
+ flag_fl &= ~___fl_flag_has_combining_joiner___;
- if (F_status_is_error_not(state->status)) {
- state->status = f_utf_buffer_increment(object, range, 1);
+ if (F_status_is_error_not(state->status)) {
+ partial.stop = range->start;
+
+ state->status = f_memory_array_increase_by((partial.stop - partial.start) + 4, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+ }
+
+ if (F_status_is_error_not(state->status)) {
+ state->status = f_string_dynamic_partial_append_nulless(object, partial, destination);
+ }
+ }
}
}
else if (F_status_is_error_not(state->status)) {
range->start = input_start;
if (object.string[input_start] == quote_char) {
- quoted_is = F_true;
+ flag_fl |= ___fl_flag_is_quoted___;
}
else {
- commented = F_true;
+ flag_fl |= ___fl_flag_is_commented___;
}
}
}
- if (F_status_is_error(state->status)) return;
+ if (F_status_is_error(state->status)) {
+ destination->used = used_start;
+
+ return;
+ }
}
for (; range->start <= range->stop && range->start < object.used; ) {
flag_fl |= ___fl_flag_do_handle___;
if (object.string[range->start] == f_fss_slash_s.string[0]) {
- // TODO: Verify no combining joiners following.
item_first = partial.start = range->start++;
item_total = 1;
f_fss_count_slash(object, range, &item_total, state);
- if (F_status_is_error(state->status)) return;
+ if (F_status_is_error(state->status)) break;
+ // End of string or end of buffer can only happen when only slashes and delimit place holders are found.
if (range->start > range->stop || range->start >= object.used) {
+ partial.stop = range->start;
+ flag_fl |= ___fl_flag_save_partial___;
- // Slashes before the final quote must be escaped when quoted, add the delimit slashes.
- if (quoted_is) {
+ // Slashes at end of line must be escaped when there is a quote.
+ if (flag_fl & ___fl_flag_is_quoted___) {
+ item_total *= 2;
+ }
- // If this is the first quote, then only a single delimit slash is needed.
- if (item_first == input_start) {
- state->status = f_memory_array_increase(state->step_large, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
- if (F_status_is_error(state->status)) break;
+ break;
+ }
- destination->string[destination->used++] = f_fss_slash_s.string[0];
+ if (object.string[range->start] == f_fss_eol_s.string[0]) {
+ state->status = F_status_set_error(F_okay_eol);
+
+ break;
+ }
+
+ // Found a combining/joiner, so the slashes do not escape anything.
+ if (state->status == F_combarudoo || state->status == F_bound) {
+ flag_fl |= state->status == F_combarudoo
+ ? ___fl_flag_has_combining___
+ : ___fl_flag_has_joiner___;
+ }
+ else {
+ if (object.string[range->start] == quote_char || (flag & ___fl_flag_as_object___) && object.string[range->start] == f_fss_comment_s.string[0] || f_fss_is_space(object, *range, state) == F_true) {
+ partial.stop = range->start++;
+
+ f_fss_skip_past_delimit(object, range, state);
+
+ if (F_status_is_error_not(state->status) && f_fss_is_combining_joiner(object, *range, state) == F_true) {
+ flag_fl |= state->status == F_combarudoo
+ ? ___fl_flag_has_combining___
+ : ___fl_flag_has_joiner___;
}
else {
- state->status = f_memory_array_increase_by(item_total, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
- if (F_status_is_error(state->status)) break;
-
- for (i = 0; i < item_total; ++i) {
- destination->string[destination->used++] = f_fss_slash_s.string[0];
- } // for
+ range->start = partial.stop;
}
}
+ }
- state->status = f_memory_array_increase_by(item_total, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
- if (F_status_is_error(state->status)) break;
+ if (flag_fl & ___fl_flag_has_combining_joiner___) {
+ item_total = 0;
- for (i = 0; i < item_total; ++i) {
- destination->string[destination->used++] = f_fss_slash_s.string[0];
- } // for
+ f_fss_skip_past_combining_joiner(object, range, state);
- break;
+ // The joined character must be considered a new, different, character.
+ if (F_status_is_error_not(state->status) && !(flag_fl & ___fl_flag_has_joiner___)) {
+ f_utf_buffer_decrement(object, range, 1);
+ }
}
- if (object.string[range->start] == f_fss_eol_s.string[0]) {
- state->status = F_status_set_error(F_okay_eol);
+ if (F_status_is_error(state->status) || range->start > range->stop || range->start >= object.used) break;
- break;
- }
+ range->start = partial.stop;
- if (object.string[range->start] == quote_char) {
- // TODO: Verify no combining joiners following.
- item_first = range->start++;
+ if (flag_fl & ___fl_flag_has_combining_joiner___) {
+ flag_fl |= ___fl_flag_save_partial___;
+ flag_fl &= ~___fl_flag_has_combining_joiner___;
+ }
+ else if (object.string[range->start] == quote_char) {
+ ++range->start;
f_fss_skip_past_delimit(object, range, state);
if (F_status_is_error(state->status)) break;
if (range->start > range->stop || range->start >= object.used) {
- state->status = f_memory_array_increase_by(item_total + 1, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+ state->status = f_memory_array_increase_by(item_total + 3, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
if (F_status_is_error(state->status)) break;
- for (i = 0; i < item_total; ++i) {
+ for (i = 0; i < item_total; ++i) { // TODO: what is the correct number of slashes?
destination->string[destination->used++] = f_fss_slash_s.string[0];
} // for
destination->string[destination->used++] = quote_char;
+ item_total = 0;
break;
}
if (F_status_is_error(state->status)) break;
}
else {
+ // TODO: Verify no combining joiners following.
if (object.string[range->start] == f_fss_eol_s.string[0]) {
state->status = F_status_set_error(F_okay_eol);
break;
}
- quoted_is = F_true;
+ flag_fl |= ___fl_flag_is_quoted___;
- state->status = f_memory_array_increase_by(item_total + 1, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+ state->status = f_memory_array_increase_by(item_total + 3, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
if (F_status_is_error(state->status)) break;
// Add the slashes that delimit the slashes.
width = macro_f_utf_byte_width(object.string[range->start]);
- state->status = f_memory_array_increase_by(item_total + width + 1, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+ state->status = f_memory_array_increase_by(item_total + width + 3, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
if (F_status_is_error(state->status)) break;
for (i = 0; i < item_total; ++i) {
memcpy(destination->string + destination->used, object.string + range->start, width);
destination->used += width;
+ item_total = 0;
}
else if ((flag & ___fl_flag_as_object___) && object.string[range->start] == f_fss_comment_s.string[0]) {
// TODO: Verify no combining joiners following.
commented = F_true;
}
- state->status = f_memory_array_increase_by(item_total + 1, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+ state->status = f_memory_array_increase_by(item_total + 3, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
if (F_status_is_error(state->status)) break;
for (i = 0; i < item_total; ++i) {
} // for
destination->string[destination->used++] = object.string[range->start++];
+ item_total = 0;
continue;
}
else {
- // If any space is found, then this must be quote.
+ // If any space is found, then this must be quoted.
if (f_fss_is_space(object, *range, state) == F_false) {
if (F_status_is_error(state->status)) break;
}
else {
+ // TODO: combining joiner check against space.
if (object.string[range->start] == f_fss_eol_s.string[0]) {
state->status = F_status_set_error(F_okay_eol);
break;
}
- quoted_is = F_true;
+ flag_fl |= ___fl_flag_is_quoted___;
}
width = macro_f_utf_byte_width(object.string[range->start]);
- state->status = f_memory_array_increase_by(item_total + width, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+ state->status = f_memory_array_increase_by(item_total + width + 3, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
if (F_status_is_error(state->status)) break;
// There is nothing to delimit, so all slashes should be printed as is.
memcpy(destination->string + destination->used, object.string + range->start, width);
destination->used += width;
+ item_total = 0;
}
flag_fl &= ~___fl_flag_do_handle___;
}
else if (object.string[range->start] == quote_char) {
// TODO: Verify no combining joiners following.
- item_first = range->start++;
+ item_first = partial.start = range->start++;
f_fss_skip_past_delimit(object, range, state);
- if (F_status_is_error(state->status)) return;
+ if (F_status_is_error(state->status)) break;
if (range->start > range->stop || range->start >= object.used) {
state->status = f_memory_array_increase(state->step_large, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
destination->string[destination->used++] = f_fss_slash_s.string[0];
- quoted_is = F_true;
+ flag_fl |= ___fl_flag_is_quoted___;
}
width = macro_f_utf_byte_width(object.string[range->start]);
- state->status = f_memory_array_increase_by(width + 1, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+ state->status = f_memory_array_increase_by(width + 3, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
if (F_status_is_error(state->status)) break;
destination->string[destination->used++] = quote_char;
break;
}
- if (flag_fl & ___fl_flag_do_handle___ && object.string[range->start] != f_fss_placeholder_s.string[0]) {
- if (!quoted_is) {
+ if (flag_fl & ___fl_flag_save_partial___) {
+ flag_fl &= ~___fl_flag_save_partial___;
+
+ if (partial.start <= partial.stop) {
+ state->status = f_memory_array_increase_by((partial.stop - partial.start) + 4, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+
+ if (F_status_is_error_not(state->status)) {
+ state->status = f_string_dynamic_partial_append_nulless(object, partial, destination);
+ }
+
+ if (F_status_is_error(state->status)) break;
+ }
+ }
+ else if ((flag_fl & ___fl_flag_do_handle___) && object.string[range->start] != f_fss_placeholder_s.string[0]) {
+ if (!(flag_fl & ___fl_flag_is_quoted___)) {
if (object.string[range->start] == f_string_ascii_quote_double_s.string[0] || object.string[range->start] == f_string_ascii_quote_single_s.string[0] || object.string[range->start] == f_string_ascii_grave_s.string[0]) {
// TODO: Verify no combining joiners following.
item_first = range->start++;
f_fss_skip_past_delimit(object, range, state);
- if (F_status_is_error(state->status)) return;
+ if (F_status_is_error(state->status)) break;
if (range->start > range->stop || range->start >= object.used || object.string[range->start] == object.string[item_first]) {
- quoted_is = F_true;
+ flag_fl |= ___fl_flag_is_quoted___;
}
else if (f_fss_is_space(object, *range, state) == F_true) {
- quoted_is = F_true;
+ flag_fl |= ___fl_flag_is_quoted___;
}
else if (F_status_is_error(state->status)) {
break;
if (F_status_is_error(state->status)) break;
}
else {
- quoted_is = F_true;
+ flag_fl |= ___fl_flag_is_quoted___;
}
}
width = macro_f_utf_byte_width(object.string[range->start]);
- state->status = f_memory_array_increase_by(width, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+ state->status = f_memory_array_increase_by(width + 3, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
if (F_status_is_error(state->status)) break;
memcpy(destination->string + destination->used, object.string + range->start, width);
if (F_status_is_error(state->status)) break;
} // for
- if (F_status_is_error(state->status)) {
- destination->used = used_start;
+ if (F_status_is_error_not(state->status) && (flag_fl & ___fl_flag_save_partial___)) {
+ if (range->start > range->stop || range->start >= object.used) {
+ if (partial.start <= partial.stop) {
+ state->status = f_memory_array_increase_by((partial.stop - partial.start) + 4, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
- return;
+ if (F_status_is_error_not(state->status)) {
+ flag_fl |= ___fl_flag_has_increased___;
+
+ state->status = f_string_dynamic_partial_append_nulless(object, partial, destination);
+ }
+ }
+ }
}
- if (quoted_is) {
- state->status = f_memory_array_increase_by(state->step_small + 2, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+ if (F_status_is_error_not(state->status) && (flag_fl & ___fl_flag_is_quoted___) && !(flag_fl & ___fl_flag_has_increased___)) {
+ state->status = f_memory_array_increase_by(state->step_small + 3, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
+ }
- if (F_status_is_error(state->status)) {
- destination->used = used_start;
+ if (F_status_is_error(state->status)) {
+ destination->used = used_start;
- return;
- }
+ return;
+ }
+ if (flag_fl & ___fl_flag_is_quoted___) {
destination->string[used_start] = quote_char;
destination->string[destination->used++] = quote_char;
- // The start quote may or may not need to be delimited in this case.
+ // The start quote may or may not need to be delimited in this case. // TODO: save start quote position? Review this logic.
if (destination->string[input_start] == quote_char) {
- // TODO: Verify no combining joiners following.
for (i = input_start + macro_f_utf_byte_width(object.string[input_start]); i <= range->stop && i < object.used; i += macro_f_utf_byte_width(object.string[i])) {
if (state->interrupt) {
#undef ___fl_flag_as_object___
#undef ___fl_flag_do_handle___
+ #undef ___fl_flag_has_combining___
+ #undef ___fl_flag_has_combining_joiner___
+ #undef ___fl_flag_has_increased___
+ #undef ___fl_flag_has_joiner___
+ #undef ___fl_flag_is_quoted___
+ #undef ___fl_flag_is_commented___
+ #undef ___fl_flag_save_partial___
}
#endif // !defined(_di_fl_fss_basic_content_read_) || !defined(_di_fl_fss_basic_object_write_) || !defined(_di_fl_fss_extended_object_write_) || !defined(_di_fl_fss_extended_content_read_) || !defined(_di_fl_fss_extended_content_write_) || !defined(_di_fl_fss_payload_header_map_)