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/cpp | |
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/cpp')
-rw-r--r-- | subprojects/exess/doc/cpp/Doxyfile.in | 44 | ||||
-rw-r--r-- | subprojects/exess/doc/cpp/api/meson.build | 5 | ||||
-rw-r--r-- | subprojects/exess/doc/cpp/index.rst | 11 | ||||
-rw-r--r-- | subprojects/exess/doc/cpp/meson.build | 42 | ||||
-rw-r--r-- | subprojects/exess/doc/cpp/overview.rst | 151 | ||||
-rw-r--r-- | subprojects/exess/doc/cpp/xml/meson.build | 14 |
6 files changed, 267 insertions, 0 deletions
diff --git a/subprojects/exess/doc/cpp/Doxyfile.in b/subprojects/exess/doc/cpp/Doxyfile.in new file mode 100644 index 00000000..d254aa77 --- /dev/null +++ b/subprojects/exess/doc/cpp/Doxyfile.in @@ -0,0 +1,44 @@ +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 + +CASE_SENSE_NAMES = YES +EXCLUDE_SYMBOLS = exess::detail +EXTRACT_LOCAL_CLASSES = NO +EXTRACT_PRIVATE = NO +HIDE_IN_BODY_DOCS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_UNDOC_MEMBERS = 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 + +EXPAND_ONLY_PREDEF = YES +MACRO_EXPANSION = 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 \ + @EXESS_SRCDIR@/bindings/cpp/include + +OUTPUT_DIRECTORY = @DOX_OUTPUT@ diff --git a/subprojects/exess/doc/cpp/api/meson.build b/subprojects/exess/doc/cpp/api/meson.build new file mode 100644 index 00000000..6cdf4e04 --- /dev/null +++ b/subprojects/exess/doc/cpp/api/meson.build @@ -0,0 +1,5 @@ +cpp_exess_rst = custom_target( + 'Exess C++ API Sphinx Input', + command: [dox_to_sphinx, '-l', 'cpp', '-f', '@INPUT@', 'doc/cpp/api'], + input: cpp_index_xml, + output: 'exess.rst') diff --git a/subprojects/exess/doc/cpp/index.rst b/subprojects/exess/doc/cpp/index.rst new file mode 100644 index 00000000..a88d3007 --- /dev/null +++ b/subprojects/exess/doc/cpp/index.rst @@ -0,0 +1,11 @@ +##### +Exess +##### + +.. include:: summary.rst + +.. toctree:: + + overview + api/exesspp + api/exess diff --git a/subprojects/exess/doc/cpp/meson.build b/subprojects/exess/doc/cpp/meson.build new file mode 100644 index 00000000..27dc34c5 --- /dev/null +++ b/subprojects/exess/doc/cpp/meson.build @@ -0,0 +1,42 @@ +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') + +cpp_rst_files = files( + 'index.rst', + 'overview.rst', +) + +foreach f : cpp_rst_files + configure_file(copy: true, input: f, output: '@PLAINNAME@') +endforeach + +subdir('xml') +subdir('api') + +docs = 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: [cpp_rst_files, cpp_exess_rst, cpp_index_xml], + output: 'singlehtml', + build_by_default: true, + install: true, + install_dir: docdir / 'exessxx-0') + +docs = 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: [cpp_rst_files, cpp_exess_rst, cpp_index_xml], + output: 'html', + build_by_default: true, + install: true, + install_dir: docdir / 'exessxx-0') diff --git a/subprojects/exess/doc/cpp/overview.rst b/subprojects/exess/doc/cpp/overview.rst new file mode 100644 index 00000000..3e59a953 --- /dev/null +++ b/subprojects/exess/doc/cpp/overview.rst @@ -0,0 +1,151 @@ +######## +Overview +######## + +.. default-domain:: cpp +.. highlight:: cpp +.. namespace:: exess + +The complete API is declared in ``exess.hpp``: + +.. code-block:: cpp + + #include <exess/exess.hpp> + +************** +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:: cpp + + 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, +the `constexpr` function template :func:`max_length` returns 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:: cpp + + char buf[exess::max_length<int>() + 1] = {0}; + + exess::Result r = exess::write(1234, sizeof(buf), buf); + if (r.status != exess::Status::success) { + std::cerr << "Write error: " << exess::strerror(r.status) << "\n"; + } + +****************** +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:: cpp + + exess::Result r = exess::write(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:: cpp + + 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/cpp/xml/meson.build b/subprojects/exess/doc/cpp/xml/meson.build new file mode 100644 index 00000000..ee529bca --- /dev/null +++ b/subprojects/exess/doc/cpp/xml/meson.build @@ -0,0 +1,14 @@ +config = configuration_data() +config.set('EXESS_SRCDIR', exess_src_root) +config.set('DOX_OUTPUT', meson.current_build_dir() / '..') + +cpp_doxyfile = configure_file(configuration: config, + input: '../Doxyfile.in', + output: 'Doxyfile') + +cpp_index_xml = custom_target( + 'exess-cpp-index.xml', + command: [doxygen, '@INPUT0@'], + input: [cpp_doxyfile] + c_header_files + cpp_header_files, + output: 'index.xml') + |