diff options
author | David Robillard <d@drobilla.net> | 2021-02-25 10:27:59 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2021-03-08 23:23:05 -0500 |
commit | c4821c8e6bf1f81c6ea31e11ebc0fc1666e9337b (patch) | |
tree | a62995534f5f606ac2f8bae22d525532b824cb5e /subprojects/exess/doc/c | |
parent | 6bcd18ae60482790b645a345f718e7099250f261 (diff) | |
download | serd-c4821c8e6bf1f81c6ea31e11ebc0fc1666e9337b.tar.gz serd-c4821c8e6bf1f81c6ea31e11ebc0fc1666e9337b.tar.bz2 serd-c4821c8e6bf1f81c6ea31e11ebc0fc1666e9337b.zip |
Add exess from git@gitlab.com:drobilla/exess.git 4638b1f
Diffstat (limited to 'subprojects/exess/doc/c')
-rw-r--r-- | subprojects/exess/doc/c/Doxyfile.in | 39 | ||||
-rw-r--r-- | subprojects/exess/doc/c/api/meson.build | 5 | ||||
-rw-r--r-- | subprojects/exess/doc/c/index.rst | 10 | ||||
-rw-r--r-- | subprojects/exess/doc/c/man/manlink.in | 1 | ||||
-rw-r--r-- | subprojects/exess/doc/c/man/meson.build | 122 | ||||
-rw-r--r-- | subprojects/exess/doc/c/meson.build | 53 | ||||
-rw-r--r-- | subprojects/exess/doc/c/overview.rst | 151 | ||||
-rw-r--r-- | subprojects/exess/doc/c/xml/meson.build | 12 |
8 files changed, 393 insertions, 0 deletions
diff --git a/subprojects/exess/doc/c/Doxyfile.in b/subprojects/exess/doc/c/Doxyfile.in new file mode 100644 index 00000000..9a768f89 --- /dev/null +++ b/subprojects/exess/doc/c/Doxyfile.in @@ -0,0 +1,39 @@ +PROJECT_NAME = Exess +PROJECT_BRIEF = "A library for reading and writing XSD datatypes" + +QUIET = YES +WARN_AS_ERROR = YES +WARN_IF_UNDOCUMENTED = NO +WARN_NO_PARAMDOC = NO + +JAVADOC_AUTOBRIEF = YES + +FULL_PATH_NAMES = NO +CASE_SENSE_NAMES = YES +HIDE_IN_BODY_DOCS = YES +REFERENCES_LINK_SOURCE = NO + +GENERATE_HTML = NO +GENERATE_LATEX = NO +GENERATE_XML = YES +XML_PROGRAMLISTING = NO +SHOW_FILES = NO + +ENABLE_PREPROCESSING = YES +SKIP_FUNCTION_MACROS = NO + +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +PREDEFINED = EXESS_API \ + EXESS_CONST_API \ + EXESS_CONST_FUNC= \ + EXESS_NONNULL= \ + EXESS_NULLABLE= \ + EXESS_PURE_API \ + EXESS_PURE_FUNC= \ + +RECURSIVE = YES +STRIP_FROM_PATH = @EXESS_SRCDIR@ +INPUT = @EXESS_SRCDIR@/include + +OUTPUT_DIRECTORY = @DOX_OUTPUT@ diff --git a/subprojects/exess/doc/c/api/meson.build b/subprojects/exess/doc/c/api/meson.build new file mode 100644 index 00000000..1a3d6f94 --- /dev/null +++ b/subprojects/exess/doc/c/api/meson.build @@ -0,0 +1,5 @@ +c_exess_rst = custom_target( + 'Exess C API Sphinx Input', + command: [dox_to_sphinx, '-f', '@INPUT0@', meson.current_build_dir()], + input: [c_index_xml] + c_rst_files, + output: 'exess.rst') diff --git a/subprojects/exess/doc/c/index.rst b/subprojects/exess/doc/c/index.rst new file mode 100644 index 00000000..396a2333 --- /dev/null +++ b/subprojects/exess/doc/c/index.rst @@ -0,0 +1,10 @@ +##### +Exess +##### + +.. include:: summary.rst + +.. toctree:: + + overview + api/exess diff --git a/subprojects/exess/doc/c/man/manlink.in b/subprojects/exess/doc/c/man/manlink.in new file mode 100644 index 00000000..95accb8a --- /dev/null +++ b/subprojects/exess/doc/c/man/manlink.in @@ -0,0 +1 @@ +.so @TARGET@ diff --git a/subprojects/exess/doc/c/man/meson.build b/subprojects/exess/doc/c/man/meson.build new file mode 100644 index 00000000..d2a31557 --- /dev/null +++ b/subprojects/exess/doc/c/man/meson.build @@ -0,0 +1,122 @@ +# Run Sphinx to generate group man pages + +# Group man pages generated by Sphinx +man_pages = [ + 'exess_base64.3', + 'exess_binary.3', + 'exess_boolean.3', + 'exess_coercion.3', + 'exess_byte.3', + 'exess_datatypes.3', + 'exess_date.3', + 'exess_datetime.3', + 'exess_decimal.3', + 'exess_double.3', + 'exess_duration.3', + 'exess_float.3', + 'exess_hex.3', + 'exess_int.3', + 'exess_long.3', + # 'exess_numbers.3', + 'exess_short.3', + 'exess_status.3', + 'exess_time.3', + 'exess_timezone.3', + 'exess_ubyte.3', + 'exess_uint.3', + 'exess_ulong.3', + 'exess_ushort.3', + 'exess_variant.3', +] + +# Run Sphinx to generate man pages +man_docs = custom_target( + 'man pages for exess', + command: [sphinx_build, '-M', 'man', + meson.current_build_dir() / '..', meson.current_build_dir() / '..', + '-E', '-q', '-t', 'man'], + input: [c_rst_files, c_exess_rst, c_index_xml], + output: man_pages, + build_by_default: true, + install: true, + install_dir: get_option('mandir') / 'man3') + + + +# message(man_docs.extract_all_objects()) + +# foreach man_page : man_pages +# install_man(man_docs[0])#meson.current_build_dir() / man_page) +# endforeach + +# "Links" from symbol names to corresponding page (one-line includes) +man_links = [ + ['ExessStatus.3', 'exess_status.3'], + ['ExessResult.3', 'exess_status.3'], + ['exess_strerror.3', 'exess_status.3'], + ['exess_read_decimal.3', 'exess_decimal.3'], + ['exess_write_decimal.3', 'exess_decimal.3'], + ['exess_read_double.3', 'exess_double.3'], + ['exess_write_double.3', 'exess_double.3'], + ['exess_read_float.3', 'exess_float.3'], + ['exess_write_float.3', 'exess_float.3'], + ['exess_read_boolean.3', 'exess_boolean.3'], + ['exess_write_boolean.3', 'exess_boolean.3'], + ['exess_read_long.3', 'exess_long.3'], + ['exess_write_long.3', 'exess_long.3'], + ['exess_read_int.3', 'exess_int.3'], + ['exess_write_int.3', 'exess_int.3'], + ['exess_read_short.3', 'exess_short.3'], + ['exess_write_short.3', 'exess_short.3'], + ['exess_read_byte.3', 'exess_byte.3'], + ['exess_write_byte.3', 'exess_byte.3'], + ['exess_read_ulong.3', 'exess_ulong.3'], + ['exess_write_ulong.3', 'exess_ulong.3'], + ['exess_read_uint.3', 'exess_uint.3'], + ['exess_write_uint.3', 'exess_uint.3'], + ['exess_read_ushort.3', 'exess_ushort.3'], + ['exess_write_ushort.3', 'exess_ushort.3'], + ['exess_read_ubyte.3', 'exess_ubyte.3'], + ['exess_write_ubyte.3', 'exess_ubyte.3'], + ['ExessDuration.3', 'exess_duration.3'], + ['exess_read_duration.3', 'exess_duration.3'], + ['exess_write_duration.3', 'exess_duration.3'], + ['ExessDateTime.3', 'exess_datetime.3'], + ['exess_read_datetime.3', 'exess_datetime.3'], + ['exess_write_datetime.3', 'exess_datetime.3'], + ['ExessTimezone.3', 'exess_timezone.3'], + ['ExessDate.3', 'exess_date.3'], + ['exess_read_date.3', 'exess_date.3'], + ['exess_write_date.3', 'exess_date.3'], + ['ExessTime.3', 'exess_time.3'], + ['exess_read_time.3', 'exess_time.3'], + ['exess_write_time.3', 'exess_time.3'], + ['ExessBlob.3', 'exess_binary.3'], + ['ExessDatatype.3', 'exess_datatypes.3'], + ['ExessValue.3', 'exess_variant.3'], + ['ExessVariant.3', 'exess_variant.3'], + ['exess_read_variant.3', 'exess_variant.3'], + ['exess_write_variant.3', 'exess_variant.3'], + ['exess_write_canonical.3', 'exess_variant.3'], + ['ExessCoercionFlag.3', 'exess_variant.3'], + ['ExessCoercionFlags.3', 'exess_variant.3'], + ['exess_coerce.3', 'exess_variant.3'], +] + +foreach man_link : man_links + link = man_link[0] + target = man_link[1] + + config = configuration_data() + config.set('TARGET', target) + + manlink = configure_file(configuration: config, + input: 'manlink.in', + output: link, + install: true, + install_dir: get_option('mandir') / 'man3') + + # message(target) + + # install_man(manlink) +endforeach diff --git a/subprojects/exess/doc/c/meson.build b/subprojects/exess/doc/c/meson.build new file mode 100644 index 00000000..64c02180 --- /dev/null +++ b/subprojects/exess/doc/c/meson.build @@ -0,0 +1,53 @@ +config = configuration_data() +config.set('EXESS_VERSION', meson.project_version()) + +conf_py = configure_file(configuration: config, + input: '../conf.py.in', + output: 'conf.py') + +configure_file(copy: true, input: '../summary.rst', output: 'summary.rst') + +c_rst_files = files( + 'index.rst', + 'overview.rst', +) + +foreach f : c_rst_files + configure_file(copy: true, input: f, output: '@PLAINNAME@') +endforeach + +subdir('xml') +subdir('api') + +custom_target( + 'Exess C API Documentation (singlehtml)', + command: [sphinx_build, '-M', 'singlehtml', + meson.current_build_dir(), meson.current_build_dir(), + '-E', '-q', '-t', 'singlehtml'], + input: [c_rst_files, c_exess_rst, c_index_xml], + output: 'singlehtml', + build_by_default: true, + install: true, + install_dir: docdir / 'exess-0') + +custom_target( + 'Exess C API Documentation (html)', + command: [sphinx_build, '-M', 'html', + meson.current_build_dir(), meson.current_build_dir(), + '-E', '-q', '-t', 'html'], + input: [c_rst_files, c_exess_rst, c_index_xml], + output: 'html', + build_by_default: true, + install: true, + install_dir: docdir / 'exess-0') + +# custom_target( +# 'man pages for exess', +# command: [sphinx_build, '-M', 'man', +# meson.current_build_dir(), meson.current_build_dir(), +# '-E', '-q', '-t', 'man'], +# input: [c_rst_files, c_exess_rst, c_index_xml], +# output: ['man/exess_base64.3'], +# build_by_default: true) + +subdir('man') diff --git a/subprojects/exess/doc/c/overview.rst b/subprojects/exess/doc/c/overview.rst new file mode 100644 index 00000000..1a2d3f6c --- /dev/null +++ b/subprojects/exess/doc/c/overview.rst @@ -0,0 +1,151 @@ +######## +Overview +######## + +.. default-domain:: c +.. highlight:: c + +The complete API is declared in ``exess.h``: + +.. code-block:: c + + #include <exess/exess.h> + +************** +Reading Values +************** + +Each supported type has a read function that takes a pointer to an output value, +and a string to read. +It reads the value after skipping any leading whitespace, +then returns an :struct:`ExessResult` with a ``status`` code and the ``count`` of characters read. +For example: + +.. code-block:: c + + int32_t value = 0; + ExessResult r = exess_read_int(&value, "1234"); + if (!r.status) { + fprintf(stderr, "Read %zu bytes as int %d\n", r.count, value); + } + +If there was a syntax error, +the status code indicates the specific problem. +If a value was read but didn't end at whitespace or the end of the string, +the status :enumerator:`EXESS_EXPECTED_END` is returned. +This indicates that there is trailing garbage in the string, +so the parse may not be complete or correct depending on the context. + + +************** +Writing Values +************** + +The corresponding write function takes a value to write, +a buffer size in bytes, and a buffer to write to. +It returns an :struct:`ExessResult`, +with a ``status`` code and the ``count`` of characters written, +not including the trailing null byte. + +For datatypes with a bounded length, +a constant like :var:`EXESS_MAX_INT_LENGTH` is the maximum length of the canonical representation of any value. +This can be used to allocate buffers statically or on the stack, +for example: + +.. code-block:: c + + char buf[EXESS_MAX_INT_LENGTH + 1] = {0}; + + ExessResult r = exess_write_int(1234, sizeof(buf), buf); + if (!r.status) { + printf("Write error: %s\n", exess_strerror(r.status)); + } + +****************** +Allocating Strings +****************** + +Exess doesn't do any allocation itself, +so the calling code is responsible for providing a large enough buffer for output. +The `count` returned by write functions can be used to determine the space required for a specific value. +If the write function is called with a null output buffer, +then this count is still returned as if a value were written. +This can be used to precisely allocate memory for the string, +taking care to allocate an extra byte for the null terminator. +For example: + +.. code-block:: c + + ExessResult r = exess_write_int(1234, 0, NULL); + char* str = (char*)calloc(r.count + 1, 1); + + r = exess_write_int(1234, r.count + 1, buf); + +Note that for some types, +this operation can be about as expensive as actually writing the value. +For example, it requires binary to decimal conversion for floating point numbers. +For ``float`` and ``double``, +since the length is bounded and relatively small, +it may be better to write immediately to a static buffer, +then copy the result to the final destination. + +******** +Variants +******** + +The fundamental read and write functions all have similar semantics, +but different type signatures since they use different value types. +:struct:`ExessVariant` is a tagged union that can hold any supported value, +allowing generic code to work with values of any type. + +Any value can be read with :func:`exess_read_variant` and written with :func:`exess_write_variant`, +which work similarly to the fundamental read and write functions, +except the read function takes an additional ``datatype`` parameter. +The expected datatype must be provided, +attempting to infer a datatype from the string content is not supported. + +Datatypes +========= + +:enum:`ExessDatatype` enumerates all of the supported variant datatypes. +The special value :enumerator:`EXESS_NOTHING` is used as a sentinel for unknown datatypes or other errors. + +If you have a datatype URI, then :func:`exess_datatype_from_uri()` can be used +to map it to a datatype. If the URI is not for a supported datatype, then it will return :enumerator:`EXESS_NOTHING`. + +Unbounded Numeric Types +======================= + +There are 6 unbounded numeric types: +decimal, integer, nonPositiveInteger, negativeInteger, nonNegativeInteger, and positiveInteger. +:struct:`ExessVariant` supports reading and writing these types, +but stores them in the largest corresponding native type: +``double``, ``int64_t``, or ``uint64_t``. +If the value doesn't fit in this type, +then :func:`exess_read_variant` will return an :enumerator:`EXESS_OUT_OF_RANGE` error. + +Writing Canonical Form +====================== + +Since values are always written in canonical form, +:struct:`ExessVariant` can be used as a generic mechanism to convert any string to canonical form: +simply read a value, +then write it. +If the value itself isn't required, +then :func:`exess_write_canonical` can be used to do this in a single step. +For example, this will print ``123``: + +.. code-block:: c + + char buf[4] = {0}; + + ExessResult r = exess_write_canonical(" +123", EXESS_INT, sizeof(buf), buf); + if (!r) { + printf("%s\n", buf); + } + +Note that it is better to use :func:`exess_write_canonical` if the value isn't required, +since it supports transforming some values outside the range of :struct:`ExessVariant`. +Specifically, +decimal and integer strings will be transformed directly, +avoiding conversion into values and the limits of the machine's numeric types. diff --git a/subprojects/exess/doc/c/xml/meson.build b/subprojects/exess/doc/c/xml/meson.build new file mode 100644 index 00000000..cfa726ed --- /dev/null +++ b/subprojects/exess/doc/c/xml/meson.build @@ -0,0 +1,12 @@ +config = configuration_data() +config.set('EXESS_SRCDIR', exess_src_root) +config.set('DOX_OUTPUT', meson.current_build_dir() / '..') + +c_doxyfile = configure_file(configuration: config, + input: '../Doxyfile.in', + output: 'Doxyfile') + +c_index_xml = custom_target('exess-c-index.xml', + command: [doxygen, '@INPUT0@'], + input: [c_doxyfile] + c_header_files, + output: 'index.xml') |