*
* This is auto-included by iki.h and should not need to be explicitly included.
*/
-#ifndef _F_iki_h
-#define _F_iki_h
-
-// libc includes
-#include <stdio.h>
-#include <sys/stat.h>
-
-// fll-0 includes
-#include <level_0/status.h>
-#include <level_0/string.h>
-#include <level_0/type.h>
+#ifndef _F_iki_common_h
+#define _F_iki_common_h
#ifdef __cplusplus
extern "C" {
#endif
+/**
+ * IKI-specific syntax.
+ */
+#ifndef _di_f_iki_syntax_
+ #define f_iki_syntax_separator ':'
+ #define f_iki_syntax_placeholder 0
+ #define f_iki_syntax_quote_double '"'
+ #define f_iki_syntax_quote_single '\''
+ #define f_iki_syntax_slash '\\'
+#endif //_di_f_iki_syntax_
+
#ifndef _di_iki_vocabulary_0000_
#define iki_vocabulary_0000_emphasis "emphasis"
#define iki_vocabulary_0000_code "code"
#endif // _di_iki_vocabulary_0000_
#ifndef _di_iki_vocabulary_0001_
- #define iki_vocabulary_0001_variable "var"
+ #define iki_vocabulary_0001_define "define"
+ #define iki_vocabulary_0001_parameter "parameter"
- #define iki_vocabulary_0001_variable_length 3
+ #define iki_vocabulary_0001_define_length 6
+ #define iki_vocabulary_0001_parameter_length 9
#endif // _di_iki_vocabulary_0001_
/**
#define f_macro_iki_contents_adjust(status, content, new_length) f_macro_string_rangess_adjust(status, content, new_length)
#endif // _di_iki_contents_
+/**
+ * Provide a default allocation step.
+ *
+ * For a UTF-8 friendly allocation step, set to at least 4.
+ */
+#ifndef _di_f_iki_default_allocation_step_
+ #define f_iki_default_allocation_step 4
+#endif // _di_f_iki_default_allocation_step_
+
+/**
+ * Reallocate delimits array if necessary for appending a new delimit.
+ *
+ * status: The return status to use.
+ * delimits: The delimit array to conditionally reallocate.
+ */
+#ifndef _di_f_macro_iki_allocate_delimits_if_necessary_
+ #define f_macro_iki_allocate_delimits_if_necessary(status, delimits) \
+ status = F_none; \
+ if (delimits.used + 1 > delimits.size) { \
+ if (delimits.used + f_iki_default_allocation_step > f_string_length_size) { \
+ if (delimits.used + 1 > f_string_length_size) { \
+ status = F_status_set_error(F_string_too_large); \
+ } \
+ else { \
+ f_macro_string_lengths_resize(status, delimits, delimits.size + 1); \
+ } \
+ } \
+ else { \
+ f_macro_string_lengths_resize(status, delimits, delimits.size + f_iki_default_allocation_step); \
+ } \
+ }
+#endif // _di_f_macro_iki_allocate_delimits_if_necessary_
+
+/**
+ * Reallocate delimits array if necessary for appending a new ranges.
+ *
+ * status: The return status to use.
+ * ranges: The delimit array to conditionally reallocate.
+ */
+#ifndef _di_f_macro_iki_allocate_ranges_if_necessary_
+ #define f_macro_iki_allocate_ranges_if_necessary(status, ranges) \
+ status = F_none; \
+ if (ranges.used + 1 > ranges.size) { \
+ if (ranges.used + f_iki_default_allocation_step > f_string_length_size) { \
+ if (ranges.used + 1 > f_string_length_size) { \
+ status = F_status_set_error(F_string_too_large); \
+ } \
+ else { \
+ f_macro_string_ranges_resize(status, ranges, ranges.size + 1); \
+ } \
+ } \
+ else { \
+ f_macro_string_ranges_resize(status, ranges, ranges.size + f_iki_default_allocation_step); \
+ } \
+ }
+#endif // _di_f_macro_iki_allocate_ranges_if_necessary_
+
+/**
+ * Determine what the max width is based on the buffer and the range.
+ *
+ * buffer: (A pointer) The buffer to determine width against.
+ * range: (A pointer) The range within that buffer to determine against.
+ * width_max: The determined width max.
+ */
+#ifndef _di_f_macro_iki_determine_width_max_
+ #define f_macro_iki_determine_width_max(buffer, range, width_max) \
+ width_max = (range->stop - range->start) + 1; \
+ if (width_max > buffer->used - range->start) { \
+ width_max = buffer->used - range->start; \
+ }
+#endif // _di_f_macro_iki_determine_width_max_
+/**
+ * Seek until whitespace is found.
+ *
+ * status: The return status to use.
+ * buffer: (A pointer) The buffer to seek through.
+ * range: (A pointer) The range within that buffer to seek through.
+ */
+#ifndef _di_f_macro_iki_seek_whitespace_
+ #define f_macro_iki_seek_whitespace(status, buffer, range, width_max) \
+ while (range->start <= range->stop && range->start < buffer->used) { \
+ f_macro_iki_determine_width_max(buffer, range, width_max); \
+ status = f_utf_is_whitespace(buffer->string + range->start, width_max); \
+ if (status == F_true) break; \
+ else if (F_status_is_error(status)) break; \
+ status = f_utf_buffer_increment(*buffer, range, 1); \
+ if (F_status_is_error(status)) break; \
+ }
+#endif // _di_f_macro_iki_seek_whitespace_
+
+/**
+ * Skip past all delimit placeholders.
+ *
+ * status: The return status to use.
+ * buffer: (A pointer) The buffer to skip through.
+ * range: (A pointer) The range within that buffer to skip through.
+ */
+#ifndef _di_f_macro_iki_skip_past_delimit_placeholders_
+ #define f_macro_iki_skip_past_delimit_placeholders(status, buffer, range) \
+ do { \
+ status = f_utf_buffer_increment(*buffer, range, 1); \
+ } while (F_status_is_fine(status) && buffer->string[range->start] == f_iki_syntax_placeholder);
+#endif // _di_f_macro_iki_skip_past_delimit_placeholders_
+
#ifdef __cplusplus
} // extern "C"
#endif
-#endif // _F_iki_h
+#endif // _F_iki_common_h
extern "C" {
#endif
+#ifndef _di_f_iki_read_
+ f_return_status f_iki_read(f_string_static *buffer, f_string_range *range, f_iki_vocabulary *vocabulary, f_iki_content *content) {
+ #ifndef _di_level_1_parameter_checking_
+ if (buffer == 0) return F_status_set_error(F_parameter);
+ if (range == 0) return F_status_set_error(F_parameter);
+ if (vocabulary == 0) return F_status_set_error(F_parameter);
+ if (content == 0) return F_status_set_error(F_parameter);
+ if (buffer->used == 0) return F_status_set_error(F_parameter);
+ if (range->start > range->stop) return F_status_set_error(F_parameter);
+ if (range->start >= buffer->used) return F_status_set_error(F_parameter);
+ #endif // _di_level_1_parameter_checking_
+
+ f_status status = F_none;
+
+ f_string_length width_max = 0;
+
+ if (width_max > buffer->used - range->start) {
+ width_max = buffer->used - range->start;
+ }
+
+ // skip past all initial non-word, non-dash, and non-plus.
+ while (range->start <= range->stop && range->start < buffer->used) {
+
+ if (buffer->string[range->start] != f_iki_syntax_placeholder) {
+ f_macro_iki_determine_width_max(buffer, range, width_max);
+
+ status = f_utf_is_word_dash_plus(buffer->string + range->start, width_max);
+ if (F_status_is_error(status)) return status;
+
+ if (status == F_true) break;
+ }
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) return status;
+ } // while
+
+ if (range->start > range->stop) {
+ return F_data_not_stop;
+ }
+ else if (range->start >= buffer->used) {
+ return F_data_not_eos;
+ }
+
+ f_string_range found_vocabulary = f_string_range_initialize;
+ f_string_length found_content = 0;
+
+ found_vocabulary.start = range->start;
+
+ f_string_length vocabulary_slash_first = range->start;
+
+ uint8_t quote = 0;
+
+ bool vocabulary_delimited = F_false;
+
+ // delimits must only be applied once a valid object is found.
+ f_string_lengths delimits = f_string_lengths_initialize;
+
+ do {
+ // find the start and end of the vocabulary name.
+ while (range->start <= range->stop && range->start < buffer->used) {
+ if (buffer->string[range->start] == f_iki_syntax_placeholder) {
+ range->start++;
+ continue;
+ }
+
+ if (buffer->string[range->start] == f_iki_syntax_separator) {
+ if (range->start == found_vocabulary.start) {
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ break;
+ }
+
+ vocabulary_delimited = F_false;
+ found_vocabulary.stop = range->start - 1;
+
+ f_macro_iki_skip_past_delimit_placeholders(status, buffer, range);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ // found a valid vocabulary name.
+ if (buffer->string[range->start] == f_iki_syntax_quote_single || buffer->string[range->start] == f_iki_syntax_quote_double) {
+ quote = buffer->string[range->start];
+ break;
+ }
+
+ // this is not a valid vocabulary name so seek until a whitespace to prepare for the next main loop pass.
+ f_macro_iki_seek_whitespace(status, buffer, range, width_max);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ break;
+ }
+ else if (buffer->string[range->start] == f_iki_syntax_slash) {
+ bool separator_found = F_false;
+
+ vocabulary_slash_first = range->start;
+
+ // the slash only needs to be delimited if it were to otherwise be a valid vocabulary name.
+ while (range->start <= range->stop && range->start < buffer->used) {
+ if (buffer->string[range->start] == f_iki_syntax_placeholder) {
+ range->start++;
+ continue;
+ }
+
+ if (separator_found) {
+ if (buffer->string[range->start] == f_iki_syntax_quote_single || buffer->string[range->start] == f_iki_syntax_quote_double) {
+ vocabulary_delimited = F_true;
+
+ quote = buffer->string[range->start];
+ range->start++;
+ break;
+ }
+ else {
+ range->start = vocabulary_slash_first;
+
+ // this is not a valid vocabulary name so seek until a whitespace to prepare for the next main loop pass.
+ f_macro_iki_seek_whitespace(status, buffer, range, width_max);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ break;
+ }
+ }
+ else if (buffer->string[range->start] == f_iki_syntax_separator) {
+ separator_found = F_true;
+ }
+ else {
+ range->start = vocabulary_slash_first;
+
+ // this is not a valid vocabulary name so seek until a whitespace to prepare for the next main loop pass.
+ f_macro_iki_seek_whitespace(status, buffer, range, width_max);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ break;
+ }
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+ } // while
+ }
+ else {
+ f_macro_iki_determine_width_max(buffer, range, width_max);
+
+ status = f_utf_is_word_dash_plus(buffer->string + range->start, width_max);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ if (status == F_false) {
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ break;
+ }
+ }
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+ } // while
+
+ // process potentially valid content.
+ if (quote) {
+ found_content = range->start;
+
+ while (range->start <= range->stop && range->start < buffer->used) {
+ if (buffer->string[range->start] == f_iki_syntax_placeholder) {
+ range->start++;
+ continue;
+ }
+
+ if (buffer->string[range->start] == quote) {
+ // this is a valid vocabulary name and content, but if it is delimited, save the delimit and ignore.
+ if (vocabulary_delimited) {
+ f_macro_iki_allocate_delimits_if_necessary(status, delimits);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ delimits.array[delimits.used] = vocabulary_slash_first;
+ delimits.used++;
+
+ vocabulary_delimited = F_false;
+ quote = 0;
+
+ range->start++;
+
+ // skip past all initial non-word, non-dash, and non-plus.
+ while (range->start <= range->stop && range->start < buffer->used) {
+ if (buffer->string[range->start] == f_iki_syntax_placeholder) {
+ range->start++;
+ continue;
+ }
+
+ f_macro_iki_determine_width_max(buffer, range, width_max);
+
+ status = f_utf_is_word_dash_plus(buffer->string + range->start, width_max);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ if (status == F_true) break;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+ } // while
+
+ found_vocabulary.start = range->start;
+ }
+ else {
+ f_macro_iki_allocate_ranges_if_necessary(status, (*vocabulary));
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ f_macro_iki_allocate_ranges_if_necessary(status, (*content));
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ vocabulary->array[vocabulary->used].start = found_vocabulary.start;
+ vocabulary->array[vocabulary->used].stop = found_vocabulary.stop;
+ vocabulary->used++;
+
+ content->array[content->used].start = found_content;
+ content->array[content->used].stop = range->start - 1;
+ content->used++;
+
+ for (f_array_length i = 0; i < delimits.used; i++) {
+ buffer->string[delimits.array[i]] = f_iki_syntax_placeholder;
+ } // for
+
+ f_macro_string_lengths_delete(status, delimits);
+ if (F_status_is_error(status)) return status;
+
+ range->start++;
+
+ if (range->start > range->stop) {
+ return F_none_stop;
+ }
+
+ if (range->start >= buffer->used) {
+ return F_none_eos;
+ }
+
+ return F_none;
+ }
+ }
+ else if (buffer->string[range->start] == f_iki_syntax_slash) {
+ f_string_length content_slash_first = range->start;
+ f_array_length content_slash_total = 1;
+
+ while (range->start <= range->stop && range->start < buffer->used) {
+ if (buffer->string[range->start] == f_iki_syntax_placeholder) {
+ range->start++;
+ continue;
+ }
+
+ if (buffer->string[range->start] == quote) {
+ f_array_length content_slash_delimits = content_slash_total / 2;
+ f_string_range content_range = f_string_range_initialize;
+ f_array_length i = 0;
+
+ if (content_slash_total % 2) {
+ content_slash_delimits++;
+ }
+
+ if (delimits.used + content_slash_delimits > delimits.size) {
+ if (delimits.used + content_slash_delimits > f_string_length_size) {
+ status = F_status_set_error(F_string_too_large);
+ }
+ else {
+ f_macro_string_lengths_resize(status, delimits, delimits.used + content_slash_delimits);
+ }
+
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+ }
+
+ content_range.start = content_slash_first;
+ content_range.stop = range->stop;
+
+ while (i < content_slash_delimits) {
+ if (buffer->string[content_range.start] == f_iki_syntax_slash) {
+ delimits.array[delimits.used] = content_range.start;
+ delimits.used++;
+
+ i++;
+ }
+
+ status = f_utf_buffer_increment(*buffer, (&content_range), 1);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+ } // while
+
+ // valid content's ending quote is not delimited, save and return.
+ if (content_slash_total % 2 == 0) {
+
+ // this is a valid vocabulary name and content, but if it is delimited, save the delimit and ignore.
+ if (vocabulary_delimited) {
+ f_macro_iki_allocate_delimits_if_necessary(status, delimits);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ delimits.array[delimits.used] = vocabulary_slash_first;
+ delimits.used++;
+
+ vocabulary_delimited = F_false;
+ quote = 0;
+
+ range->start++;
+
+ // skip past all initial non-word, non-dash, and non-plus.
+ while (range->start <= range->stop && range->start < buffer->used) {
+ if (buffer->string[range->start] == f_iki_syntax_placeholder) {
+ range->start++;
+ continue;
+ }
+
+ f_macro_iki_determine_width_max(buffer, range, width_max);
+
+ status = f_utf_is_word_dash_plus(buffer->string + range->start, width_max);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ if (status == F_true) break;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+ } // while
+
+ found_vocabulary.start = range->start;
+ }
+ else {
+ f_macro_iki_allocate_ranges_if_necessary(status, (*vocabulary));
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ f_macro_iki_allocate_ranges_if_necessary(status, (*content));
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ vocabulary->array[vocabulary->used].start = found_vocabulary.start;
+ vocabulary->array[vocabulary->used].stop = found_vocabulary.stop;
+ vocabulary->used++;
+
+ content->array[content->used].start = found_content;
+ content->array[content->used].stop = range->start - 1;
+ content->used++;
+
+ for (f_array_length i = 0; i < delimits.used; i++) {
+ buffer->string[delimits.array[i]] = f_iki_syntax_placeholder;
+ } // for
+
+ f_macro_string_lengths_delete(status, delimits);
+ if (F_status_is_error(status)) return status;
+
+ range->start++;
+
+ if (range->start > range->stop) {
+ return F_none_stop;
+ }
+
+ if (range->start >= buffer->used) {
+ return F_none_eos;
+ }
+
+ return F_none;
+ }
+ }
+
+ break;
+ }
+ else if (buffer->string[range->start] != f_iki_syntax_slash) {
+ range->start++;
+ break;
+ }
+
+ content_slash_total++;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+ } // while
+ }
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+ } // while
+ }
+ else {
+ vocabulary_delimited = F_false;
+
+ // skip past all initial non-word, non-dash, and non-plus.
+ while (range->start <= range->stop && range->start < buffer->used) {
+ if (buffer->string[range->start] == f_iki_syntax_placeholder) {
+ range->start++;
+ continue;
+ }
+
+ f_macro_iki_determine_width_max(buffer, range, width_max);
+
+ status = f_utf_is_word_dash_plus(buffer->string + range->start, width_max);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+
+ if (status == F_true) break;
+
+ status = f_utf_buffer_increment(*buffer, range, 1);
+ if (F_status_is_error(status)) {
+ f_macro_string_lengths_delete(status, delimits);
+ return status;
+ }
+ } // while
+
+ found_vocabulary.start = range->start;
+ }
+ } while (range->start <= range->stop && range->start < buffer->used);
+
+ f_macro_string_lengths_delete(status, delimits);
+ if (F_status_is_error(status)) return status;
+
+ if (range->start > range->stop) {
+ return F_data_not_stop;
+ }
+
+ return F_data_not_eos;
+ }
+#endif // _di_f_iki_read_
#ifdef __cplusplus
} // extern "C"
* Provides a Wiki-Like syntax meant to be much simpler.
*
* This simpler Wiki-Like syntax, called Iki, focuses just on simply adding context.
- * The context itself is not explicitly define but a few common standards are provided.
- *
- * The example syntax:
- * - url:"http:// a b c/"
- * - code:" code goes here"
- * - quote:"This is a quote"
- * - var:"some_variable_name"
- * - emphasis:"This text is important"
- *
- * Which is: (word character, no whitespace, '-', '_', and '+')(colon ':')(quote, either single (') or double ("))(anything goes and closing quotes must be escaped)(closing quote, must match openening quote)
- *
- * Escaping only needs to be done like these three cases:
- * 1) escaping main syntax:
- * - url\:"http:// a b c/"
- * - after the first '\:', every '\' is a literal '\'.
- * - url\\\\\:"http:// a b c/" would be read as: 'url\\\\:"http:// a b c/"'.
- * 2) escaping the quoted part, but only for the closing quote that matches the opening quote:
- * - quote:"This is a \"quote\""
- * - There is no way to know the terminating quote so all quotes matching the opening quote inside must be escaped.
- * - emphasis:"\"This is some Text with a slash before quote: \\\"" would be read as: emphasis, with value: "This is some Text with a slash before quote: \".
- * - Create this as a new FSS format, FSS-Text (FSS-000D).
- *
- * IKI-0000 (Basic) provides the following vocabulary:
- * - emphasis: Providing emphasis on text, such as bold.
- * - code: Representing code (formatting preserved or otherwise presented literally).
- * - quote: Representing quoted text.
- * - uri: Representing a URI (This is a superset of URL and URN).
- * - url: Representing a URL.
- * - urn: Representing a URN.
- * - var: Representing a variable name.
- *
- * IKI-0001 (Variable) provides the following vocabulary:
- * - var: Representing a variable name.
- *
- * This is intended to also be used by FSS-Iki_Text (FSS-000D), which focuses on the format and not the context.
- * Wherease, IKI-0000 (Basic) represents the vocabulary and its respective context.
- * Therefore an FSS-000D may have any IKI-???? format within it.
- *
- * A format header such as "# fss-000d iki-0001\n" would represent an IKI format of IKI-0001 (Variable).
+ * The context itself is not explicitly defined but a few common standards are provided.
*/
#ifndef _F_iki_h
#define _F_iki_h
// fll-0 includes
#include <level_0/status.h>
+#include <level_0/memory.h>
#include <level_0/string.h>
#include <level_0/type.h>
+#include <level_0/utf.h>
+
+// fll-0 iki includes
+#include <level_0/iki-common.h>
#ifdef __cplusplus
extern "C" {
#endif
+/**
+ * Read a single iki Vocabulary and Content.
+ *
+ * This does not verify if the vocabulary name is known.
+ * This only finds a complete vocabulary name and content.
+ *
+ * @param buffer
+ * The string to process.
+ * @param range
+ * The start/stop location within the buffer to be processed.
+ * The start location will be updated as the buffer is being processed.
+ * The start location will represent where the read stopped on return.
+ * A start location past the stop location or buffer used means that the entire range was processed.
+ * @param vocabulary
+ * The vocabulary name list to store the found vocabulary name.
+ * @param content
+ * The content list to store the content associated with the found vocabulary name.
+ *
+ * @return
+ * F_none on success and an IKI vocabulary name was found.
+ * F_none_stop on success and an IKI vocabulary name was found and stop point was reached.
+ * F_none_eos on success and an IKI vocabulary name was found and end of string was reached.
+ * F_data_not_eos on success and EOS was reached, but there were no IKI vocabularie names found.
+ * F_data_not_stop on success and stop point was reached, but there were no IKI vocabularie names found.
+ * F_memory_reallocation (with error bit) on memory reallocation error.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_string_too_large (with error bit) if a string length is too large to store in the buffer.
+ */
+#ifndef _di_f_iki_read_
+ extern f_return_status f_iki_read(f_string_static *buffer, f_string_range *range, f_iki_vocabulary *vocabulary, f_iki_content *content);
+#endif // _di_f_iki_read_
+
#ifdef __cplusplus
} // extern "C"
#endif