return;
}
- private_f_fss_skip_past_combining_joiner(buffer, range, state);
+ // Skip past initial place holders so that the initial state of the range can be handled (F_complete_not_utf_eos and F_complete_not_utf_stop).
+ for (;; ++range->start) {
+
+ if (state->interrupt) {
+ state->interrupt((void *) state, 0);
+ if (F_status_set_fine(state->status) == F_interrupt) return;
+ }
+
+ if (range->start >= buffer.used) {
+ state->status = F_okay_eos;
+
+ return;
+ }
+
+ if (range->start > range->stop) {
+ state->status = F_okay_stop;
+
+ return;
+ }
+
+ if (buffer.string[range->start] != f_fss_placeholder_s.string[0]) break;
+ } // for
+
+ if (macro_f_utf_byte_width_is(buffer.string[range->start])) {
+ if (range->start + macro_f_utf_byte_width(buffer.string[range->start]) > buffer.used) {
+ state->status = F_status_set_error(F_complete_not_utf_eos);
+
+ f_fss_fail_utf(state);
+
+ return;
+ }
+
+ if (range->start + (macro_f_utf_byte_width(buffer.string[range->start]) - 1) > range->stop) {
+ state->status = F_status_set_error(F_complete_not_utf_stop);
+
+ f_fss_fail_utf(state);
+
+ return;
+ }
+ }
+
+ #define ___f_flag_last_combining___ 0x1
+ #define ___f_flag_last_joiner___ 0x2
+
+ uint8_t flag_f = 0x0;
+
+ for (;;) {
+
+ if (state->interrupt) {
+ state->interrupt((void *) state, 0);
+ if (F_status_set_fine(state->status) == F_interrupt) return;
+ }
+
+ if (range->start >= buffer.used) {
+ state->status = flag_f & ___f_flag_last_combining___
+ ? F_combarudoo
+ : flag_f & ___f_flag_last_joiner___
+ ? F_bound
+ : F_okay_eos;
+
+ return;
+ }
+
+ if (range->start > range->stop) {
+ state->status = flag_f & ___f_flag_last_combining___
+ ? F_combarudoo
+ : flag_f & ___f_flag_last_joiner___
+ ? F_bound
+ : F_okay_stop;
+
+ return;
+ }
+
+ if (buffer.string[range->start] == f_fss_eol_s.string[0]) {
+ state->status = F_okay_eol;
+
+ return;
+ }
+
+ if (buffer.string[range->start] == f_fss_placeholder_s.string[0]) {
+ ++range->start;
+
+ continue;
+ }
+
+ state->status = f_utf_is_combining(
+ buffer.string + range->start,
+ (range->stop - range->start) + 1 > buffer.used - range->start
+ ? buffer.used - range->start
+ : (range->stop - range->start) + 1
+ );
+
+ f_fss_fail_utf_to_false(state);
+
+ if (state->status == F_true) {
+ flag_f = ___f_flag_last_combining___;
+ }
+ else if (F_status_is_error_not(state->status)) {
+ state->status = f_utf_is_joiner(
+ buffer.string + range->start,
+ (range->stop - range->start) + 1 > buffer.used - range->start
+ ? buffer.used - range->start
+ : (range->stop - range->start) + 1
+ );
+
+ if (state->status == F_true) {
+ flag_f = ___f_flag_last_joiner___;
+ }
+ else {
+ f_fss_fail_utf_to_false(state);
+ }
+ }
+
+ if (state->status == F_false) break;
+ if (F_status_is_error(state->status)) return;
+
+ if (macro_f_utf_byte_width_is(buffer.string[range->start])) {
+ if (range->start + macro_f_utf_byte_width(buffer.string[range->start]) > buffer.used) {
+ state->status = F_status_set_error(F_complete_not_utf_eos);
+
+ f_fss_fail_utf(state);
+
+ return;
+ }
+
+ if (range->start + (macro_f_utf_byte_width(buffer.string[range->start]) - 1) > range->stop) {
+ state->status = F_status_set_error(F_complete_not_utf_stop);
+
+ f_fss_fail_utf(state);
+
+ return;
+ }
+ }
+
+ range->start += macro_f_utf_byte_width(buffer.string[range->start]);
+ } // for
+
+ state->status = flag_f & ___f_flag_last_combining___
+ ? F_combarudoo
+ : flag_f & ___f_flag_last_joiner___
+ ? F_bound
+ : F_okay;
+
+ #undef ___f_flag_last_combining___
+ #undef ___f_flag_last_joiner___
}
#endif // _di_f_fss_skip_past_combining_joiner_
}
#endif // !defined(_di_f_fss_count_slash_) || !defined(_di_f_fss_is_combining_joiner_)
-#if !defined(_di_f_fss_count_slash_) || !defined(_di_f_fss_skip_past_combining_joiner_)
- void private_f_fss_skip_past_combining_joiner(const f_string_static_t buffer, f_range_t * const range, f_state_t * const state) {
-
- // Skip past initial place holders.
- for (;; ++range->start) {
-
- if (state->interrupt) {
- state->interrupt((void *) state, 0);
- if (F_status_set_fine(state->status) == F_interrupt) return;
- }
-
- if (range->start >= buffer.used) {
- state->status = F_okay_eos;
-
- return;
- }
-
- if (range->start > range->stop) {
- state->status = F_okay_stop;
-
- return;
- }
-
- if (buffer.string[range->start] != f_fss_placeholder_s.string[0]) break;
- } // for
-
- if (macro_f_utf_byte_width_is(buffer.string[range->start])) {
- if (range->start + macro_f_utf_byte_width(buffer.string[range->start]) > buffer.used) {
- state->status = F_status_set_error(F_complete_not_utf_eos);
-
- f_fss_fail_utf(state);
-
- return;
- }
-
- if (range->start + (macro_f_utf_byte_width(buffer.string[range->start]) - 1) > range->stop) {
- state->status = F_status_set_error(F_complete_not_utf_stop);
-
- f_fss_fail_utf(state);
-
- return;
- }
- }
-
- #define ___f_flag_last_combining___ 0x1
- #define ___f_flag_last_joiner___ 0x2
-
- uint8_t flag_f = 0x0;
-
- for (;;) {
-
- if (state->interrupt) {
- state->interrupt((void *) state, 0);
- if (F_status_set_fine(state->status) == F_interrupt) return;
- }
-
- if (range->start >= buffer.used) {
- state->status = F_okay_eos;
-
- return;
- }
-
- if (range->start > range->stop) {
- state->status = F_okay_stop;
-
- return;
- }
-
- if (buffer.string[range->start] == f_fss_eol_s.string[0]) {
- state->status = F_okay_eol;
-
- return;
- }
-
- if (buffer.string[range->start] == f_fss_placeholder_s.string[0]) {
- ++range->start;
-
- continue;
- }
-
- state->status = f_utf_is_combining(
- buffer.string + range->start,
- (range->stop - range->start) + 1 > buffer.used - range->start
- ? buffer.used - range->start
- : (range->stop - range->start) + 1
- );
-
- f_fss_fail_utf_to_false(state);
-
- if (state->status == F_true) {
- flag_f = ___f_flag_last_combining___;
- }
- else if (F_status_is_error_not(state->status)) {
- state->status = f_utf_is_joiner(
- buffer.string + range->start,
- (range->stop - range->start) + 1 > buffer.used - range->start
- ? buffer.used - range->start
- : (range->stop - range->start) + 1
- );
-
- if (state->status == F_true) {
- flag_f = ___f_flag_last_joiner___;
- }
- else {
- f_fss_fail_utf_to_false(state);
- }
- }
-
- if (state->status == F_false) break;
- if (F_status_is_error(state->status)) return;
-
- if (macro_f_utf_byte_width_is(buffer.string[range->start])) {
- if (range->start + macro_f_utf_byte_width(buffer.string[range->start]) > buffer.used) {
- state->status = F_status_set_error(F_complete_not_utf_eos);
-
- f_fss_fail_utf(state);
-
- return;
- }
-
- if (range->start + (macro_f_utf_byte_width(buffer.string[range->start]) - 1) > range->stop) {
- state->status = F_status_set_error(F_complete_not_utf_stop);
-
- f_fss_fail_utf(state);
-
- return;
- }
- }
-
- range->start += macro_f_utf_byte_width(buffer.string[range->start]);
- } // for
-
- state->status = flag_f & ___f_flag_last_combining___
- ? F_combarudoo
- : flag_f & ___f_flag_last_joiner___
- ? F_bound
- : F_okay;
-
- #undef ___f_flag_last_combining___
- #undef ___f_flag_last_joiner___
- }
-#endif // !defined(_di_f_fss_count_slash_) || !defined(_di_f_fss_skip_past_combining_joiner_)
-
#if !defined(_di_f_fss_skip_past_space_) || !defined(_di_f_fss_skip_past_space_previous_)
void private_f_fss_skip_past_space_previous(const f_string_static_t buffer, f_range_t * const range, f_state_t * const state, f_number_unsigned_t * const previous) {
#define ___fl_flag_as_object___ 0x1
- #define ___fl_flag_has_combining___ 0x1
- #define ___fl_flag_has_combining_joiner___ 0x5
- #define ___fl_flag_has_eol___ 0x2
- #define ___fl_flag_has_joiner___ 0x4
- #define ___fl_flag_is_quoted___ 0x8
- #define ___fl_flag_is_commented___ 0x10
- #define ___fl_flag_save_character___ 0x20
- #define ___fl_flag_save_comment___ 0x40
- #define ___fl_flag_save_normal___ 0x80
- #define ___fl_flag_save_partial___ 0x100
- #define ___fl_flag_save_quote___ 0x200
- #define ___fl_flag_save_quote_character___ 0x220
- #define ___fl_flag_save_slash___ 0x400
- #define ___fl_flag_save_slash_quote___ 0x600
+ #define ___fl_flag_has_combining___ 0x1
+ #define ___fl_flag_has_combining_has_joiner___ 0x5
+ #define ___fl_flag_has_eol___ 0x2
+ #define ___fl_flag_has_joiner___ 0x4
+ #define ___fl_flag_is_quoted___ 0x8
+ #define ___fl_flag_is_commented___ 0x10
+ #define ___fl_flag_save_character___ 0x20
+ #define ___fl_flag_save_comment___ 0x40
+ #define ___fl_flag_save_normal___ 0x80
+ #define ___fl_flag_save_partial___ 0x100
+ #define ___fl_flag_save_partial_is_quoted___ 0x108
+ #define ___fl_flag_save_quote___ 0x200
+ #define ___fl_flag_save_quote_save_character___ 0x220
+ #define ___fl_flag_save_slash___ 0x400
+ #define ___fl_flag_save_slash_save_comment___ 0x440
+ #define ___fl_flag_save_slash_quote___ 0x600
+
+ // Handle has_combining, has_joiner, save_quote, save_character, save_comment, and save_partial.
+ #define ___fl_flag_reset_top___ 0x365
const f_number_unsigned_t input_start = range->start;
const f_number_unsigned_t used_start = destination->used;
else {
// The joined character must be considered a new, different, character.
- if (!(flag_fl & ___fl_flag_has_joiner___)) {
+ if (F_status_is_error_not(state->status) && state->status == F_combarudoo) {
f_utf_buffer_decrement(object, range, 1);
}
- flag_fl &= ~___fl_flag_has_combining_joiner___;
-
if (F_status_is_error_not(state->status)) {
partial.stop = range->start;
}
}
}
+
+ flag_fl &= ~___fl_flag_has_combining_has_joiner___;
}
else if (F_status_is_error_not(state->status)) {
range->start = input_start;
}
flag_fl |= ___fl_flag_save_normal___;
+ flag_fl &= ~___fl_flag_reset_top___;
if (object.string[range->start] == f_fss_slash_s.string[0]) {
item_first = partial.start = range->start++;
: ___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) {
+ if (object.string[range->start] == quote_char || (flag & ___fl_flag_as_object___) && item_first == input_start && 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);
+ // A quote following a slash must either be followed by space or an EOL to be valid for the slash escaping behavior.
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 {
- range->start = partial.stop;
- }
- }
- }
-
- if (flag_fl & ___fl_flag_has_combining_joiner___) {
- item_total = 0;
-
- f_fss_skip_past_combining_joiner(object, range, state);
-
- // 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 (F_status_is_error(state->status)) break;
-
- if (range->start > range->stop || range->start >= object.used) {
- flag_fl |= ___fl_flag_save_slash___;
-
- if (object.string[partial.stop] == quote_char) {
- flag_fl |= ___fl_flag_save_quote___;
- }
- else if (object.string[partial.stop] == f_fss_comment_s.string[0]) {
- flag_fl |= ___fl_flag_save_comment___;
- }
-
- break;
- }
+ else if (object.string[partial.stop] == quote_char || object.string[partial.stop] == f_fss_comment_s.string[0]) {
+ if (object.string[partial.stop] == quote_char) {
+ partial.stop = range->start++;
- range->start = partial.stop;
+ f_fss_skip_past_delimit(object, range, state);
+ if (F_status_is_error(state->status)) break;
- 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;
+ if (range->start > range->stop || range->start >= object.used) {
- flag_fl |= ___fl_flag_save_quote___;
+ // Slashes before a closing quote must escaped when there is a leading quote.
+ if (flag_fl & ___fl_flag_is_quoted___ && item_total) {
+ item_total *= 2;
+ }
- f_fss_skip_past_delimit(object, range, state);
- if (F_status_is_error(state->status)) break;
+ flag_fl |= ___fl_flag_save_slash_quote___;
- if (range->start > range->stop || range->start >= object.used) {
+ break;
+ }
- // Slashes before a closing quote must escaped when there is a leading quote.
- if (flag_fl & ___fl_flag_is_quoted___ && item_total) {
- item_total *= 2;
- }
+ // If any space is found after a quote after a slash, then this must be delimited and quote.
+ if (f_fss_is_space(object, *range, state) == F_false) {
+ if (F_status_is_error(state->status)) break;
- flag_fl |= ___fl_flag_save_slash___;
+ item_total = 0;
+ partial.stop = range->start;
+ flag_fl |= ___fl_flag_save_partial___;
+ }
+ else {
+ if (object.string[range->start] == f_fss_eol_s.string[0]) {
+ if (state->flag & f_fss_state_flag_eol_stop_e) {
+ flag_fl |= ___fl_flag_has_eol___;
+ }
+ else {
+ state->status = F_status_set_error(F_okay_eol);
+ }
- break;
- }
+ break;
+ }
- // If any space is found after a quote after a slash, then this must be delimited and quote.
- if (f_fss_is_space(object, *range, state) == F_false) {
- if (F_status_is_error(state->status)) break;
+ 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___;
+ }
+ else {
+ flag_fl |= ___fl_flag_save_slash_quote___;
+ range->start = partial.stop;
+ }
- item_total = 0;
- }
- else {
- if (object.string[range->start] == f_fss_eol_s.string[0]) {
- if (state->flag & f_fss_state_flag_eol_stop_e) {
- flag_fl |= ___fl_flag_has_eol___;
+ if (F_status_is_error(state->status)) break;
+ }
}
else {
- state->status = F_status_set_error(F_okay_eol);
+ item_total = 0;
+ partial.stop = range->start;
+ flag_fl |= ___fl_flag_save_slash_save_comment___;
}
-
- break;
}
-
- // TODO: Verify no combining joiners following space.
- flag_fl |= ___fl_flag_is_quoted___;
+ else {
+ range->start = partial.stop;
+ }
}
-
- flag_fl |= ___fl_flag_save_character___;
}
- else if (!(flag_fl & ___fl_flag_is_quoted___) && (flag & ___fl_flag_as_object___) && object.string[range->start] == f_fss_comment_s.string[0]) { // TODO: monitor if first character is found and if so, then skip over comment entirely.
- // TODO: Verify no combining joiners following.
- // FIXME: this block looks incorrect. Shouldn't comment b escaped?
- // Only the first slash needs to be escaped for a comment, and then only if not quote.
- if (item_first == input_start) {
- flag_fl |= ___fl_flag_is_commented___;
- }
+ if (flag_fl & ___fl_flag_has_combining_has_joiner___) {
+ item_total = 0;
- // item_total (slashes), 6 for reservations as described above.
- state->status = f_memory_array_increase_by(item_total + 6, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
- if (F_status_is_error(state->status)) break;
+ f_fss_skip_past_combining_joiner(object, range, state);
- for (i = 0; i < item_total; ++i) {
- destination->string[destination->used++] = f_fss_slash_s.string[0];
- } // for
+ // The joined character must be considered a new, different, character.
+ if (F_status_is_error_not(state->status) && state->status == F_combarudoo) {
+ f_utf_buffer_decrement(object, range, 1);
+ }
- destination->string[destination->used++] = object.string[range->start++];
- item_total = 0;
+ flag_fl |= ___fl_flag_save_partial___;
- continue;
- }
- else {
+ // TODO: how to handle incomplete combining/joiner at end of buffer or range?
+ if (F_status_is_error_not(state->status) && (range->start > range->stop || range->start >= object.used)) {
+ partial.stop = range->start >= object.used
+ ? object.used - 1
+ : range->stop;
- // 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;
+ break;
}
- else {
- // TODO: combining joiner check against space.
- if (object.string[range->start] == f_fss_eol_s.string[0]) {
- if (state->flag & f_fss_state_flag_eol_stop_e) {
- flag_fl |= ___fl_flag_has_eol___;
- }
- else {
- state->status = F_status_set_error(F_okay_eol);
- }
- break;
- }
+ partial.stop = range->start;
+ }
- flag_fl |= ___fl_flag_is_quoted___;
- }
+ if (F_status_is_error(state->status)) break;
- flag_fl |= ___fl_flag_save_character___;
+ range->start = partial.stop;
+
+ // A quote followed by a combining/joiner is not treated as a quote.
+ if (flag_fl & ___fl_flag_has_combining_has_joiner___) {
+ flag_fl &= ~___fl_flag_has_combining_has_joiner___;
}
if (flag_fl & ___fl_flag_save_character___) {
destination->used += width;
item_total = 0;
- flag_fl &= ~___fl_flag_save_quote_character___;
+ flag_fl &= ~___fl_flag_save_quote_save_character___;
}
flag_fl &= ~___fl_flag_save_normal___;
}
if (F_status_is_error(state->status)) break;
+
+ partial.start = 1;
+ partial.stop = 0;
}
}
else if ((flag_fl & ___fl_flag_save_normal___) && 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);
}
else if (flag_fl & ___fl_flag_save_comment___) {
destination->string[destination->used++] = f_fss_comment_s.string[0];
+ flag_fl |= ___fl_flag_is_commented___;
}
}
}
#undef ___fl_flag_as_object___
#undef ___fl_flag_has_combining___
- #undef ___fl_flag_has_combining_joiner___
+ #undef ___fl_flag_has_combining_has_joiner___
#undef ___fl_flag_has_eol___
#undef ___fl_flag_has_joiner___
#undef ___fl_flag_is_quoted___
#undef ___fl_flag_save_comment___
#undef ___fl_flag_save_normal___
#undef ___fl_flag_save_partial___
+ #undef ___fl_flag_save_partial_is_quoted___
#undef ___fl_flag_save_quote___
- #undef ___fl_flag_save_quote_character___
+ #undef ___fl_flag_save_quote_save_character___
#undef ___fl_flag_save_slash___
+ #undef ___fl_flag_save_slash_save_comment___
+ #undef ___fl_flag_save_slash_quote___
+
+ #undef ___fl_flag_reset_top___
}
#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_)