Always reset the original used length on error.
Reduce the number of return statements.
Add a check for the combining joiner characters after the `#`.
Remove inaccurate comment about depending on `f_utf_is_combining()` from parse function.
Utilize the `f_state_t` locally to perform the necessary operations.
This is not exposed to the caller to prevent **API** and **ABI** breakage.
Future versions of **FLL** (0.9+) are expected to pass the state via the function parameter.
Switch to the new practice of using flags to manage special internal states.
This no longer guesses success based on `ids.used` being non-zero.
Using the internal flags allows accurate handling.
Add comments to functions that need `f_state_t` so that future version of **FLL** can properly handle.
if (buffer.string[range->start]) break;
} // for
- if (range->start > range->stop) {
- return F_data_not;
- }
+ if (range->start > range->stop) return F_data_not;
+
+ f_status_t status = F_okay;
// The FLL Identifier is always at least 6 characters ("X-0000").
if (range->stop - range->start < 5) {
- // Increment until stop, while taking into consideration UTF-8 character widths.
- for (; range->start <= range->stop && range->start < buffer.used; ) {
-
- if (buffer.string[range->start] == f_string_eol_s.string[0]) {
- ++range->start;
-
- break;
- }
-
- range->start += macro_f_utf_byte_width(buffer.string[range->start]);
- } // for
-
- return F_found_not;
+ status = F_found_not;
}
- f_status_t status = F_okay;
-
- for (; range->start <= range->stop && range->start < buffer.used; ) {
-
- status = f_utf_is_whitespace(buffer.string + range->start, (range->stop - range->start) + 1, F_false);
+ if (status != F_found_not) {
- if (F_status_is_error(status)) {
- if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_complete_not_utf);
+ // Seek past initial white space.
+ for (; range->start <= range->stop && range->start < buffer.used; ) {
- return status;
- }
+ status = f_utf_is_whitespace(buffer.string + range->start, (range->stop - range->start) + 1, F_false);
- if (status == F_false) {
- if (!buffer.string[range->start]) {
- ++range->start;
+ if (F_status_is_error(status)) {
+ if (F_status_set_fine(status) == F_maybe) return F_status_set_error(F_complete_not_utf);
- continue;
+ return status;
}
- break;
- }
-
- if (buffer.string[range->start] == f_string_eol_s.string[0]) {
- ++range->start;
-
- return F_found_not;
- }
-
- range->start += macro_f_utf_byte_width(buffer.string[range->start]);
- } // for
-
- if (range->start > range->stop || range->start > buffer.used) return F_found_not;
+ if (status == F_false) {
+ if (!buffer.string[range->start]) {
+ ++range->start;
- if (range->stop - range->start < 5) {
+ continue;
+ }
- // Increment until stop, while taking into consideration UTF-8 character widths.
- for (; range->start <= range->stop && range->start < buffer.used; ) {
+ break;
+ }
if (buffer.string[range->start] == f_string_eol_s.string[0]) {
++range->start;
- break;
+ return F_found_not;
}
range->start += macro_f_utf_byte_width(buffer.string[range->start]);
} // for
- return F_found_not;
- }
-
- f_number_unsigned_t i = range->start;
-
- for (; range->start <= range->stop && range->start < buffer.used; ) {
-
- status = f_utf_is_word(buffer.string + range->start, (range->stop - range->start) + 1, F_true);
- if (F_status_is_error(status)) return status;
-
- if (status == F_false) {
- if (!buffer.string[range->start]) {
- ++range->start;
-
- continue;
- }
+ if (range->start > range->stop || range->start > buffer.used) return F_found_not;
- break;
+ // Check minimum required length (a difference of 5 represents the 6 minimum characters because start and stop are inclusive).
+ if (range->stop - range->start < 5) {
+ status = F_found_not;
}
+ }
- range->start += macro_f_utf_byte_width(buffer.string[range->start]);
- } // for
-
- if (range->start > range->stop || range->start >= buffer.used || buffer.string[range->start] != '-') {
+ if (status != F_found_not) {
+ f_number_unsigned_t i = range->start;
- // Increment until stop, while taking into consideration UTF-8 character widths.
+ // Only word characters are allowed on the left side of the dash.
for (; range->start <= range->stop && range->start < buffer.used; ) {
- if (buffer.string[range->start] == f_string_eol_s.string[0]) {
- ++range->start;
+ status = f_utf_is_word(buffer.string + range->start, (range->stop - range->start) + 1, F_true);
+ if (F_status_is_error(status)) return status;
+
+ if (status == F_false) {
+ if (!buffer.string[range->start]) {
+ ++range->start;
+
+ continue;
+ }
break;
}
range->start += macro_f_utf_byte_width(buffer.string[range->start]);
} // for
- return F_found_not;
- }
+ if (range->start > range->stop || range->start >= buffer.used || buffer.string[range->start] != f_string_ascii_minus_s.string[0]) {
+ status = F_found_not;
+ }
- {
- f_number_unsigned_t j = 0;
- f_char_t number[5] = { 0, 0, 0, 0, 0 };
+ if (status != F_found_not) {
+ f_number_unsigned_t j = 0;
+ f_char_t number[5] = { 0, 0, 0, 0, 0 };
- for (++range->start; range->start <= range->stop && range->start < buffer.used && j < 4; ++range->start, ++j) {
+ // Only 4 hexidecimal ASCII digits are allowed after the dash.
+ for (++range->start; range->start <= range->stop && range->start < buffer.used && j < 4; ++range->start, ++j) {
- // The hexidecimal representing the number may only be ASCII.
- if (macro_f_utf_byte_width_is(buffer.string[range->start])) {
+ // The hexidecimal representing the number may only be ASCII.
+ if (macro_f_utf_byte_width_is(buffer.string[range->start])) {
- // Increment until stop, while taking into consideration UTF-8 character widths.
- for (; range->start <= range->stop && range->start < buffer.used; ) {
+ // Increment until stop, while taking into consideration UTF-8 character widths.
+ for (; range->start <= range->stop && range->start < buffer.used; ) {
- if (buffer.string[range->start] == f_string_eol_s.string[0]) {
- ++range->start;
+ if (buffer.string[range->start] == f_string_eol_s.string[0]) {
+ ++range->start;
- break;
- }
+ break;
+ }
- range->start += macro_f_utf_byte_width(buffer.string[range->start]);
- } // for
+ range->start += macro_f_utf_byte_width(buffer.string[range->start]);
+ } // for
- if (id) {
- id->type = 0;
+ if (id) {
+ id->type = 0;
+ }
+
+ return F_found_not;
}
- return F_found_not;
- }
+ if ((uint16_t) (buffer.string[range->start] - f_string_ascii_a_s.string[0]) < 6 || (uint16_t) (buffer.string[range->start] - f_string_ascii_A_s.string[0]) < 6 || (uint16_t) (buffer.string[range->start] - f_string_ascii_0_s.string[0]) < 10) {
+ number[j] = buffer.string[range->start];
+ }
+ else {
+ if (!buffer.string[range->start]) continue;
- if ((uint16_t) (buffer.string[range->start] - 'a') < 6 || (uint16_t) (buffer.string[range->start] - 'A') < 6 || (uint16_t) (buffer.string[range->start] - '0') < 10) {
- number[j] = buffer.string[range->start];
- }
- else {
- if (!buffer.string[range->start]) continue;
+ break;
+ }
+ } // for
- break;
+ if (status != F_found_not) {
+ if (j == 4) {
+ if (id) {
+ id->type = strtol(number, 0, 16);
+ }
+ }
+ else {
+ status = F_found_not;
+ }
}
- } // for
- if (j == 4) {
- if (id) {
- id->type = strtol(number, 0, 16);
- }
- }
- else {
+ if (status != F_found_not) {
- // Increment until stop, while taking into consideration UTF-8 character widths.
- for (; range->start <= range->stop && range->start < buffer.used; ) {
+ // Skip past all NULLs.
+ for (; range->start <= range->stop && range->start < buffer.used; ++range->start) {
+ if (buffer.string[range->start]) break;
+ } // for
- if (buffer.string[range->start] == f_string_eol_s.string[0]) {
- ++range->start;
+ // The end of line, white space, or range stop point are the only valid stop points.
+ if (range->start <= range->stop) {
+ status = f_utf_is_whitespace(buffer.string + range->start, (range->stop - range->start) + 1, F_false);
- break;
- }
+ if (F_status_is_error(status)) {
+ if (id) {
+ id->type = 0;
+ }
- range->start += macro_f_utf_byte_width(buffer.string[range->start]);
- } // for
+ return status;
+ }
- if (id) {
- id->type = 0;
+ if (status == F_false) {
+ status = F_found_not;
+ }
+ }
}
- return F_found_not;
- }
- }
+ if (status != F_found_not) {
+ if (range->start <= range->stop && range->start < buffer.used && buffer.string[range->start] == f_string_eol_s.string[0]) {
+ ++range->start;
+ }
- // Skip past all NULLs.
- for (; range->start <= range->stop && range->start < buffer.used; ++range->start) {
- if (buffer.string[range->start]) break;
- } // for
+ // Copy the cached characters over.
+ if (id) {
+ for (f_number_unsigned_t j = i, i = 0; j <= range->stop && j < buffer.used; ++j) {
- // The end of line, whitespace, or range stop point are the only valid stop points.
- if (range->start <= range->stop) {
- status = f_utf_is_whitespace(buffer.string + range->start, (range->stop - range->start) + 1, F_false);
+ if (!buffer.string[j]) continue;
+ if (buffer.string[j] == f_string_ascii_minus_s.string[0]) break;
- if (F_status_is_error(status)) {
- if (id) {
- id->type = 0;
- }
+ id->name[i++] = buffer.string[j];
- return status;
- }
+ if (i > f_fll_id_name_length_d) {
+ status = F_found_not;
- if (status == F_false) {
+ break;
+ }
+ } // for
- // Increment until stop, while taking into consideration UTF-8 character widths.
- for (; range->start <= range->stop && range->start < buffer.used; ) {
+ id->used = i + 1;
- if (buffer.string[range->start] == f_string_eol_s.string[0]) {
- ++range->start;
+ if (id->used < f_fll_id_name_length_d) {
+ id->name[id->used] = 0;
+ }
+ else {
- break;
+ // The last byte must always be NULL (f_fll_id_name_max_length_d is always 1 byte longer).
+ id->name[f_fll_id_name_length_d] = 0;
+ }
}
-
- range->start += macro_f_utf_byte_width(buffer.string[range->start]);
- } // for
-
- if (id) {
- id->type = 0;
}
-
- return F_found_not;
}
}
- if (buffer.string[range->start] == f_string_eol_s.string[0]) {
- ++range->start;
- }
+ if (status == F_found_not) {
- if (id) {
- for (f_number_unsigned_t j = i, i = 0; j <= range->stop && j < buffer.used; ++j) {
+ // Increment until stop, while taking into consideration UTF-8 character widths.
+ for (; range->start <= range->stop && range->start < buffer.used; ) {
- if (!buffer.string[j]) continue;
- if (buffer.string[j] == '-') break;
+ if (buffer.string[range->start] == f_string_eol_s.string[0]) {
+ ++range->start;
- id->name[i++] = buffer.string[j];
- } // for
+ break;
+ }
- id->used = i + 1;
+ range->start += macro_f_utf_byte_width(buffer.string[range->start]);
+ } // for
- if (id->used < 64) {
- id->name[id->used] = 0;
- }
+ return F_found_not;
}
return F_found;
* F_parameter (with error bit) if a parameter is invalid.
* F_utf_not (with error bit) if character is an invalid UTF-8 character.
*
- * F_parameter (with error bit) from: f_utf_is_combining().
* F_parameter (with error bit) from: f_utf_is_whitespace().
* F_parameter (with error bit) from: f_utf_is_word().
*
- * @see f_utf_is_combining()
* @see f_utf_is_whitespace()
* @see f_utf_is_word()
*/
if (!range) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- // Skip past all NULLs.
- for (; range->start <= range->stop; ++range->start) {
- if (buffer.string[range->start]) break;
- }
+ // Future version will have this passed as a parameter.
+ f_state_t state = f_state_t_initialize;
- if (range->start > range->stop) return F_data_not;
+ f_fss_skip_past_delimit(buffer, range, &state);
+ if (F_status_is_error(state.status) || state.status == F_data_not) return state.status;
// The first character must be a '#'.
- if (buffer.string[range->start] != f_fss_pound_s.string[0]) {
-
- // Increment until stop, while taking into consideration UTF-8 character widths.
- for (; range->start <= range->stop; ) {
-
- if (buffer.string[range->start] == f_string_eol_s.string[0]) {
- ++range->start;
-
- break;
- }
-
- range->start += macro_f_utf_byte_width(buffer.string[range->start]);
- } // for
+ if (buffer.string[range->start] == f_fss_pound_s.string[0]) {
- if (ids) {
- ids->used = 0;
+ // A combining joiner after the '#' invalidates the '#'.
+ if (f_fss_is_combining_joiner(buffer, *range, &state) == F_true) {
+ state.status = F_skip;
}
+ else {
+ if (F_status_is_error(state.status)) return state.status;
- return F_found_not;
- }
-
- // Skip past all NULLs after the '#'.
- for (++range->start; range->start <= range->stop; ++range->start) {
- if (buffer.string[range->start]) break;
- }
-
- if (range->start > range->stop) {
- if (ids) {
- ids->used = 0;
+ range->start += f_fss_pound_s.used;
}
-
- return F_found_not;
+ }
+ else {
+ state.status = F_skip;
}
// The minimum requirement for a valid FLL/FSS Identifier for the entire line is 7 characters after the '#' ("# X-FFFF").
- if (range->stop - range->start < 6) {
-
- // Increment until stop, while taking into consideration UTF-8 character widths.
- for (; range->start <= range->stop; ) {
-
- if (buffer.string[range->start] == f_string_eol_s.string[0]) {
- ++range->start;
-
- break;
- }
+ if (state.status != F_skip) {
+ if (range->start > range->stop || range->start >= buffer.used || range->stop - range->start < 6) state.status = F_skip;
+ }
- range->start += macro_f_utf_byte_width(buffer.string[range->start]);
- } // for
+ if (state.status != F_skip) {
+ state.status = f_utf_is_whitespace(buffer.string + range->start, (range->stop - range->start) + 1, F_false);
- if (ids) {
- ids->used = 0;
+ if (F_status_is_error(state.status)) {
+ return F_status_set_fine(state.status) == F_maybe
+ ? F_status_set_error(F_complete_not_utf)
+ : state.status;
}
- return F_found_not;
+ if (state.status == F_false) state.status = F_skip;
}
- f_status_t status = f_utf_is_whitespace(buffer.string + range->start, (range->stop - range->start) + 1, F_false);
-
- if (F_status_is_error(status)) return (F_status_set_fine(status) == F_maybe) ? F_status_set_error(F_complete_not_utf) : status;
-
- if (status == F_false) {
-
- // Increment until stop, while taking into consideration UTF-8 character widths.
- for (; range->start <= range->stop; ) {
-
- if (buffer.string[range->start] == f_string_eol_s.string[0]) {
- ++range->start;
-
- break;
- }
-
- range->start += macro_f_utf_byte_width(buffer.string[range->start]);
- } // for
+ const f_number_unsigned_t original = ids ? ids->used : 0;
- return F_found_not;
- }
+ if (state.status == F_skip || buffer.string[range->start] == f_string_eol_s.string[0]) {
+ if (state.status == F_skip) {
+ f_fss_seek_to_eol(buffer, range, &state);
+ if (F_status_is_error(state.status)) return state.status;
+ }
- if (buffer.string[range->start] == f_string_eol_s.string[0]) {
- ++range->start;
+ if (state.status != F_data_not && range->start <= range->stop && range->start < buffer.used) {
+ ++range->start;
+ }
if (ids) {
- ids->used = 0;
+ ids->used = original;
}
return F_found_not;
}
- // in order to determine if a valid FLL Identifier represents a valid FSS identifier, the data must be saved.
+ #define ___fll_flag_has_found___ 0x1
+ #define ___fll_flag_has_fss___ 0x2
+
+ // In order to determine if a valid FLL Identifier represents a valid FSS identifier, the data must be saved.
f_fll_id_t id = f_fll_id_t_initialize;
- uint8_t found_fss = F_false;
+ uint8_t fll_flag = 0x0;
do {
if (ids && ids->used + 1 > ids->size) {
- status = f_memory_array_increase(F_fss_default_allocation_step_small_d, sizeof(f_fll_id_t), (void **) &ids->array, &ids->used, &ids->size);
+ state.status = f_memory_array_increase_by(F_fss_default_allocation_step_small_d, sizeof(f_fll_id_t), (void **) &ids->array, &ids->used, &ids->size);
}
- if (F_status_is_error_not(status)) {
- status = f_parse_dynamic_partial_fll_identify(buffer, range, ids ? &ids->array[ids->used] : &id);
+ if (F_status_is_error_not(state.status)) {
+ state.status = f_parse_dynamic_partial_fll_identify(buffer, range, ids ? &ids->array[ids->used] : &id);
}
- if (F_status_is_error(status) || (status == F_found_not && !found_fss)) {
+ if (F_status_is_error(state.status)) {
if (ids) {
- ids->used = 0;
+ ids->used = original;
}
- return status;
+ return state.status;
}
- if (!found_fss) {
- if (ids) {
- if (ids->used && ids->array[ids->used - 1].used == 3 && ids->array[ids->used - 1].name[0] == f_fss_f_s.string[0] && ids->array[ids->used - 1].name[0] == f_fss_s_s.string[0] && ids->array[ids->used - 1].name[0] == f_fss_s_s.string[0]) {
- found_fss = F_true;
- }
+ if (state.status == F_found_not) {
+ fll_flag = 0;
+
+ break;
+ }
+
+ if (state.status == F_found) {
+ if (!fll_flag) {
+ fll_flag |= ___fll_flag_has_found___;
}
- else {
- if (id.used == 3 && id.name[0] == f_fss_f_s.string[0] && id.name[0] == f_fss_s_s.string[0] && id.name[0] == f_fss_s_s.string[0]) {
- found_fss = F_true;
+
+ // At least one FLL identifier must have "FSS".
+ if (!(fll_flag & ___fll_flag_has_fss___)) {
+ if (ids) {
+ if (ids->used && ids->array[ids->used - 1].used == 3 && ids->array[ids->used - 1].name[0] == f_fss_f_s.string[0] && ids->array[ids->used - 1].name[1] == ids->array[ids->used - 1].name[2] == f_fss_s_s.string[0]) {
+ fll_flag |= ___fll_flag_has_fss___;
+ }
+ }
+ else {
+ if (id.used == 3 && id.name[0] == f_fss_f_s.string[0] && id.name[1] == id.name[2] == f_fss_s_s.string[0]) {
+ fll_flag |= ___fll_flag_has_fss___;
+ }
}
}
- }
- if (ids) {
- status = f_memory_array_increase(F_fss_default_allocation_step_small_d, sizeof(f_fll_id_t), (void **) &ids->array, &ids->used, &ids->size);
+ if (ids) {
+ state.status = f_memory_array_increase(F_fss_default_allocation_step_small_d, sizeof(f_fll_id_t), (void **) &ids->array, &ids->used, &ids->size);
- if (F_status_is_error(status)) {
- if (ids) {
- ids->used = 0;
+ if (F_status_is_error(state.status)) {
+ if (ids) {
+ ids->used = original;
+ }
+
+ return state.status;
}
- return status;
+ ++ids->used;
}
-
- ++ids->used;
}
} while (range->start <= range->stop);
+ if (fll_flag) return fll_flag & ___fll_flag_has_fss___
+ ? F_found
+ : F_maybe;
+
+ #undef ___fll_flag_has_found___
+ #undef ___fll_flag_has_fss___
+
if (ids) {
- if (ids->used) return found_fss ? F_found : F_maybe;
+ ids->used = original;
}
- else if (id.used) return found_fss ? F_found : F_maybe;
return F_found_not;
}
if (!values) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- if (!buffer.used) return F_data_not;
- if (!objects.used) return F_data_not;
- if (!contents.used) return F_data_not;
+ if (!buffer.used || !objects.used || !contents.used) return F_data_not;
f_status_t status = F_okay;
if (!values) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- if (!buffer.used) return F_data_not;
- if (!objects.used) return F_data_not;
- if (!contents.used) return F_data_not;
+ if (!buffer.used || !objects.used || !contents.used) return F_data_not;
f_status_t status = F_okay;
f_ranges_t *content = 0;
if (!values) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- if (!buffer.used) return F_data_not;
- if (!objects.used) return F_data_not;
- if (!contents.used) return F_data_not;
+ if (!buffer.used || !objects.used || !contents.used) return F_data_not;
f_status_t status = F_okay;
f_string_dynamic_t name = f_string_dynamic_t_initialize;
if (!values) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- if (!buffer.used) return F_data_not;
- if (!objects.used) return F_data_not;
- if (!contents.used) return F_data_not;
+ if (!buffer.used || !objects.used || !contents.used) return F_data_not;
f_status_t status = F_okay;
if (!values) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- if (!buffer.used) return F_data_not;
- if (!objects.used) return F_data_not;
- if (!contents.used) return F_data_not;
+ if (!buffer.used || !objects.used || !contents.used) return F_data_not;
f_status_t status = F_okay;
if (!values) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- if (!buffer.used) return F_data_not;
- if (!objects.used) return F_data_not;
- if (!contents.used) return F_data_not;
+ if (!buffer.used || !objects.used || !contents.used) return F_data_not;
f_status_t status = F_okay;
f_string_dynamic_t name = f_string_dynamic_t_initialize;
if (!values) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- if (!buffer.used) return F_data_not;
- if (!objects.used) return F_data_not;
- if (!contents.used) return F_data_not;
+ if (!buffer.used || !objects.used || !contents.used) return F_data_not;
f_status_t status = F_okay;
f_string_dynamic_t name = f_string_dynamic_t_initialize;
if (!values) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- if (!buffer.used) return F_data_not;
- if (!objects.used) return F_data_not;
- if (!contents.used) return F_data_not;
+ if (!buffer.used || !objects.used || !contents.used) return F_data_not;
f_status_t status = F_okay;
if (!values) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- if (!buffer.used) return F_data_not;
- if (!objects.used) return F_data_not;
- if (!contents.used) return F_data_not;
+ if (!buffer.used || !objects.used || !contents.used) return F_data_not;
f_status_t status = F_okay;
if (!values) return F_status_set_error(F_parameter);
#endif // _di_level_2_parameter_checking_
- if (!buffer.used) return F_data_not;
- if (!objects.used) return F_data_not;
- if (!contents.used) return F_data_not;
+ if (!buffer.used || !objects.used || !contents.used) return F_data_not;
f_status_t status = F_okay;
*
* See the f_parse_dynamic_partial_fll_identify() function for details on individual FLL/FSS Identifier processing.
*
+ * This function needs f_state_t as a parameter in future implementations.
+ *
* @param buffer
* The string to process.
* @param range
*
* F_complete_not_utf (with error bit) if character is an incomplete UTF-8 fragment.
*
+ * Errors (with error bit) from: f_fss_is_combining_joiner().
+ * Errors (with error bit) from: f_fss_seek_to_eol().
+ * Errors (with error bit) from: f_fss_skip_past_delimit().
* Errors (with error bit) from: f_memory_array_increase().
* Errors (with error bit) from: f_utf_is_whitespace().
* Errors (with error bit) from: f_parse_dynamic_partial_fll_identify().
*
+ * @see f_fss_is_combining_joiner()
+ * @see f_fss_seek_to_eol()
+ * @see f_fss_skip_past_delimit()
* @see f_memory_array_increase()
* @see f_utf_is_whitespace()
* @see f_parse_dynamic_partial_fll_identify()
*
* This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
*
+ * This function needs f_state_t as a parameter in future implementations.
+ *
* @param buffer
* The buffer to read from.
* @param objects
*
* This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
*
+ * This function needs f_state_t as a parameter in future implementations.
+ *
* @param buffer
* The buffer to read from.
* @param objects
*
* This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
*
+ * This function needs f_state_t as a parameter in future implementations.
+ *
* @param buffer
* The buffer to read from.
* @param objects
*
* This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
*
+ * This function needs f_state_t as a parameter in future implementations.
+ *
* @param buffer
* The buffer to read from.
* @param objects
*
* This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
*
+ * This function needs f_state_t as a parameter in future implementations.
+ *
* @param buffer
* The buffer to read from.
* @param objects
*
* This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
*
+ * This function needs f_state_t as a parameter in future implementations.
+ *
* @param buffer
* The buffer to read from.
* @param objects
*
* This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
*
+ * This function needs f_state_t as a parameter in future implementations.
+ *
* @param buffer
* The buffer to read from.
* @param objects
*
* This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
*
+ * This function needs f_state_t as a parameter in future implementations.
+ *
* @param buffer
* The buffer to read from.
* @param objects
*
* This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
*
+ * This function needs f_state_t as a parameter in future implementations.
+ *
* @param buffer
* The buffer to read from.
* @param objects
*
* This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
*
+ * This function needs f_state_t as a parameter in future implementations.
+ *
* @param buffer
* The buffer to read from.
* @param objects