diff options
Diffstat (limited to 'subprojects/exess/include/exess/exess.h')
-rw-r--r-- | subprojects/exess/include/exess/exess.h | 1633 |
1 files changed, 1633 insertions, 0 deletions
diff --git a/subprojects/exess/include/exess/exess.h b/subprojects/exess/include/exess/exess.h new file mode 100644 index 00000000..f327eb2e --- /dev/null +++ b/subprojects/exess/include/exess/exess.h @@ -0,0 +1,1633 @@ +/* + Copyright 2021 David Robillard <d@drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef EXESS_EXESS_H +#define EXESS_EXESS_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#if defined(_WIN32) && !defined(EXESS_STATIC) && defined(EXESS_INTERNAL) +# define EXESS_API __declspec(dllexport) +#elif defined(_WIN32) && !defined(EXESS_STATIC) +# define EXESS_API __declspec(dllimport) +#elif defined(__GNUC__) +# define EXESS_API __attribute__((visibility("default"))) +#else +# define EXESS_API +#endif + +#ifdef __GNUC__ +# define EXESS_PURE_FUNC __attribute__((pure)) +# define EXESS_CONST_FUNC __attribute__((const)) +#else +# define EXESS_PURE_FUNC +# define EXESS_CONST_FUNC +#endif + +#if defined(__clang__) && __clang_major__ >= 7 +# define EXESS_NONNULL _Nonnull +# define EXESS_NULLABLE _Nullable +#else +# define EXESS_NONNULL +# define EXESS_NULLABLE +#endif + +// Pure API functions have no observable side-effects +#define EXESS_PURE_API \ + EXESS_API \ + EXESS_PURE_FUNC + +// Const API functions are pure, and read no memory other than their parameters +#define EXESS_CONST_API \ + EXESS_API \ + EXESS_CONST_FUNC + +#ifdef __cplusplus +extern "C" { +#endif + +/** + @defgroup exess Exess C API + This is the complete public C API of exess. + @{ +*/ + +/// The base URI of XML Schema, `http://www.w3.org/2001/XMLSchema#` +#define EXESS_XSD_URI "http://www.w3.org/2001/XMLSchema#" + +/** + @defgroup exess_status Status + + Status codes and return values used for error handling. + + Success and various specific errors are reported by an integer status code, + which can be converted to a string to produce friendly error messages. + Reading and writing functions return a "result", which has a status code + along with a count of bytes read or written. + + @{ +*/ + +/// Status code to describe errors or other relevant situations +typedef enum { + EXESS_SUCCESS, ///< Success + EXESS_EXPECTED_END, ///< Expected end of value + EXESS_EXPECTED_BOOLEAN, ///< Expected "false", "true", "0" or "1" + EXESS_EXPECTED_INTEGER, ///< Expected an integer value + EXESS_EXPECTED_DURATION, ///< Expected a duration starting with 'P' + EXESS_EXPECTED_SIGN, ///< Expected '-' or '+' + EXESS_EXPECTED_DIGIT, ///< Expected a digit + EXESS_EXPECTED_COLON, ///< Expected ':' + EXESS_EXPECTED_DASH, ///< Expected '-' + EXESS_EXPECTED_TIME_SEP, ///< Expected 'T' + EXESS_EXPECTED_TIME_TAG, ///< Expected 'H', 'M', or 'S' + EXESS_EXPECTED_DATE_TAG, ///< Expected 'Y', 'M', or 'D' + EXESS_EXPECTED_HEX, ///< Expected a hexadecimal character + EXESS_EXPECTED_BASE64, ///< Expected a base64 character + EXESS_BAD_ORDER, ///< Invalid field order + EXESS_BAD_VALUE, ///< Invalid value + EXESS_OUT_OF_RANGE, ///< Value out of range for datatype + EXESS_NO_SPACE, ///< Insufficient space + EXESS_WOULD_REDUCE_PRECISION, ///< Precision reducing coercion required + EXESS_WOULD_ROUND, ///< Rounding coercion required + EXESS_WOULD_TRUNCATE, ///< Truncating coercion required + EXESS_UNSUPPORTED, ///< Unsupported value +} ExessStatus; + +/** + Result returned from a read or write function. + + This combines a status code with a byte offset, so it can be used to + determine how many characters were read or written, or what error occurred + at what character offset. +*/ +typedef struct { + ExessStatus status; ///< Status code + size_t count; ///< Number of bytes read or written, excluding null +} ExessResult; + +/** + Return a string describing a status code in plain English. + + The returned string is always one sentence, with an uppercase first + character, and no trailing period. +*/ +EXESS_CONST_API +const char* EXESS_NONNULL +exess_strerror(ExessStatus status); + +/** + @} + @defgroup exess_numbers Numbers + Datatypes for numbers + @{ +*/ + +/** + @defgroup exess_decimal Decimal + + An xsd:decimal is a decimal number of arbitrary precision, but this + implementation only supports values that fit in a `double`. + + Unlike xsd:double, xsd:decimal is written in numeric form, never in + scientific notation. Special infinity and NaN values are not supported. + Note that the xsd:decimal representation for some numbers is very long, so + xsd:double may be a better choice for values in a wide range. + + Canonical form has no leading "+" sign, and at most 1 leading or trailing + zero such that there is at least 1 digit on either side of the decimal + point, like "12.34", "-1.0", and "0.0". + + Non-canonical form allows a leading "+", any number of leading and trailing + zeros, any number of digits (including zero) on either side of the point, + and does not require a decimal point, like "+1", "01", "-.5", "4.", and + "42". + + @{ +*/ + +/// The maximum length of an xsd:decimal string from exess_write_decimal(), 327 +#define EXESS_MAX_DECIMAL_LENGTH 327 + +/** + Read an xsd:decimal string after any leading whitespace. + + Values beyond the range of `decimal` will produce `-INF` or `INF`, and + return an error because these are not valid decimal values. + + @param out Set to the parsed value, or NaN on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_decimal(double* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:decimal string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_decimal(double value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_double Double + + An xsd:double is an IEEE-754 64-bit floating point number, written in + scientific notation. + + Canonical form has no leading "+" sign, at most 1 leading or trailing zero + such that there is at least 1 digit on either side of the decimal point, and + always has an exponent, like "12.34E56", "-1.0E-2", and "-0.0E0". The + special values negative infinity, positive infinity, and not-a-number are + written "-INF", "INF", and "NaN", respectively. + + Non-canonical form allows a leading "+", any number of leading and trailing + zeros, any number of digits (including zero) on either side of the point, + and does not require an exponent or decimal point, like "+1E3", "1E+3", + ".5E3", "4.2", and "42". + + @{ +*/ + +/// The maximum length of a canonical xsd:double string, 24 +#define EXESS_MAX_DOUBLE_LENGTH 24 + +/** + Read an xsd:double string after any leading whitespace. + + Values beyond the range of `double` will produce `-INF` or `INF`. + + @param out Set to the parsed value, or `NAN` on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_double(double* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:double string. + + Any `double` value is supported. Reading the resulting string with + exess_read_double() will produce exactly `value`, except the extra bits in + NaNs are not preserved. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output and `status` #EXESS_SUCCESS, + or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_double(double value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_float Float + + An xsd:float is an IEEE-754 32-bit floating point number, written in + scientific notation. + + The lexical form is the same as xsd:double, the only difference is that the + value space of xsd:float is smaller. See @ref exess_double for details. + + @{ +*/ + +/// The maximum length of a canonical xsd:float string, 15 +#define EXESS_MAX_FLOAT_LENGTH 15 + +/** + Read an xsd:float string after any leading whitespace. + + Values beyond the range of `float` will produce `-INF` or `INF`. + + @param out Set to the parsed value, or `NAN` on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_float(float* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:float string. + + Any `float` value is supported. Reading the resulting string with + exess_read_float() will produce exactly `value`, except the extra bits in + NaNs are not preserved. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_float(float value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_boolean Boolean + + An xsd:boolean has only two possible values, canonically written as "false" + and "true". The non-canonical forms "0" and "1" are also supported. + + @{ +*/ + +/// The maximum length of a canonical xsd:boolean string, 5 +#define EXESS_MAX_BOOLEAN_LENGTH 5 + +/** + Read an xsd:boolean string after any leading whitespace. + + @param out Set to the parsed value, or false on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_boolean(bool* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:boolean string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_boolean(bool value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_long Long + + An xsd:long is a signed 64-bit integer, written in decimal. + + Values range from -9223372036854775808 to 9223372036854775807 inclusive. + + Canonical form has no leading "+" sign and no leading zeros (except for the + number "0"), like "-1", "0", and "1234". + + Non-canonical form allows a leading "+" and any number of leading zeros, + like "01" and "+0001234". + + @{ +*/ + +/// The maximum length of a canonical xsd:long string, 20 +#define EXESS_MAX_LONG_LENGTH 20 + +/** + Read an xsd:long string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_long(int64_t* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:long string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_long(int64_t value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_int Int + + An xsd:int is a signed 32-bit integer. + + Values range from -2147483648 to 2147483647 inclusive. + + The lexical form is the same as xsd:long, the only difference is that the + value space of xsd:int is smaller. See @ref exess_long for details. + + @{ +*/ + +/// The maximum length of a canonical xsd:int string, 11 +#define EXESS_MAX_INT_LENGTH 11 + +/** + Read an xsd:int string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_int(int32_t* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:int string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_int(int32_t value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_short Short + + An xsd:short is a signed 16-bit integer. + + Values range from -32768 to 32767 inclusive. + + The lexical form is the same as xsd:long, the only difference is that the + value space of xsd:short is smaller. See @ref exess_long for details. + + @{ +*/ + +/// The maximum length of a canonical xsd:short string, 6 +#define EXESS_MAX_SHORT_LENGTH 6 + +/** + Read an xsd:short string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_short(int16_t* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:short string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_short(int16_t value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_byte Byte + + An xsd:byte is a signed 8-bit integer. + + Values range from -128 to 127 inclusive. + + The lexical form is the same as xsd:long, the only difference is that the + value space of xsd:byte is smaller. See @ref exess_long for details. + + @{ +*/ + +/// The maximum length of a canonical xsd:byte string, 4 +#define EXESS_MAX_BYTE_LENGTH 4 + +/** + Read an xsd:byte string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_byte(int8_t* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:byte string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_byte(int8_t value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_ulong Unsigned Long + + An xsd:unsignedLong is an unsigned 64-bit integer, written in decimal. + + Values range from 0 to 18446744073709551615 inclusive. + + Canonical form has no leading "+" sign and no leading zeros (except for the + number "0"), like "0", and "1234". + + Non-canonical form allows any number of leading zeros, like "01" and + "0001234". + + @{ +*/ + +/// The maximum length of a canonical xsd:unsignedLong string, 20 +#define EXESS_MAX_ULONG_LENGTH 20 + +/** + Read an xsd:unsignedLong string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_ulong(uint64_t* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:unsignedLong string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_ulong(uint64_t value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_uint Unsigned Int + + An xsd:unsignedInt is an unsigned 32-bit integer. + + Values range from 0 to 4294967295 inclusive. + + The lexical form is the same as xsd:unsignedLong, the only difference is + that the value space of xsd:unsignedInt is smaller. See @ref exess_ulong + for details. + + @{ +*/ + +/// The maximum length of a canonical xsd:unsignedInt string, 10 +#define EXESS_MAX_UINT_LENGTH 10 + +/** + Read an xsd:unsignedInt string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_uint(uint32_t* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:unsignedInt string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_uint(uint32_t value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_ushort Unsigned Short + + An xsd:unsignedShort is an unsigned 16-bit integer. + + Values range from 0 to 65535 inclusive. + + The lexical form is the same as xsd:unsignedLong, the only difference is + that the value space of xsd:unsignedShort is smaller. See @ref exess_ulong + for details. + + @{ +*/ + +/// The maximum length of a canonical xsd:unsignedShort string, 5 +#define EXESS_MAX_USHORT_LENGTH 5 + +/** + Read an xsd:unsignedShort string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_ushort(uint16_t* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:unsignedShort string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_ushort(uint16_t value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_ubyte Unsigned Byte + + An xsd:unsignedByte is an unsigned 8-bit integer. Values range from 0 to + 255 inclusive. + + The lexical form is the same as xsd:unsignedLong, the only difference is + that the value space of xsd:unsignedByte is smaller. See @ref exess_ulong + for details. + + @{ +*/ + +/// The maximum length of a canonical xsd:unsignedByte string, 3 +#define EXESS_MAX_UBYTE_LENGTH 3 + +/** + Read an xsd:unsignedByte string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_ubyte(uint8_t* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:unsignedByte string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_ubyte(uint8_t value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @} + @defgroup exess_time_and_date Time and Date + Datatypes for dates, times, and durations of time. + @{ +*/ + +/** + @defgroup exess_duration Duration + + An xsd:duration is a positive or negative duration of time, written in ISO + 8601 format like "PnYnMnDTnHnMnS" where each "n" is a number and fields may + be omitted if they are zero. + + All numbers must be integers, except for seconds which may be a decimal. If + seconds is a decimal, then at least one digit must follow the decimal point. + A negative duration is written with "-" as the first character, for example + "-P60D". + + Canonical form omits all zero fields and writes no leading or trailing + zeros, except for the zero duration which is written "P0Y", for example + "P1DT2H", "PT30M", or "PT4.5S". + + Non-canonical form allows zero fields, leading zeros, and for seconds to be + written as a decimal even if it is integer, for example "P06D", "PT7.0S", or + "P0Y0M01DT06H00M00S". + + @{ +*/ + +/// The maximum length of an xsd:duration string from exess_write_duration(), 41 +#define EXESS_MAX_DURATION_LENGTH 41 + +/** + A duration of time (xsd:duration value). + + To save space and to simplify arithmetic, this representation only stores + two values: integer months, and decimal seconds (to nanosecond precision). + These values are converted to and from the other fields during writing and + reading. Years and months are stored as months, and days, hours, minutes, + and seconds are stored as seconds. + + The sign of all members must match, so a negative duration has all + non-positive members, and a positive duration has all non-negative members. +*/ +typedef struct { + int32_t months; + int32_t seconds; + int32_t nanoseconds; +} ExessDuration; + +/** + Read an xsd:duration string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_duration(ExessDuration* EXESS_NONNULL out, + const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:duration string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return #EXESS_SUCCESS on success, #EXESS_NO_SPACE if the buffer is too + small, or #EXESS_BAD_VALUE if the value is invalid. +*/ +EXESS_API +ExessResult +exess_write_duration(ExessDuration value, + size_t buf_size, + char* EXESS_NULLABLE buf); +/** + @} + @defgroup exess_datetime Datetime + + An xsd:datetime is a date and time in either UTC or local time. + + Strings have the form YYYY-MM-DDTHH:MM:SS with at least 4 year digits + (negative or positive), and all other fields positive two-digit integers + except seconds which may be a decimal, for example "2001-02-03T12:13:14.56". + Nanosecond precision is supported. + + A local datetime has no suffix, a datetime with a time zone is always in + UTC, and is written with a "Z" suffix, for example 2001-02-03T12:13:14Z. + + Canonical form only includes a decimal point if the number of seconds is not + an integer. + + This implementation supports up to nanosecond resolution. + + @{ +*/ + +/// The maximum length of an xsd:dateTime string from exess_write_datetime(), 32 +#define EXESS_MAX_DATETIME_LENGTH 32 + +/** + A date and time (xsd:dateTime value). + + This representation follows the syntax, except the UTC flag is stored + between the date and time for more efficient packing. +*/ +typedef struct { + int16_t year; ///< Year: any positive or negative value + uint8_t month; ///< Month: [1, 12] + uint8_t day; ///< Day: [1, 31] + uint8_t is_utc; ///< True if this is UTC (not local) time + uint8_t hour; ///< Hour: [0, 23] + uint8_t minute; ///< Minute: [0, 59] + uint8_t second; ///< Second: [0, 59] + uint32_t nanosecond; ///< Nanosecond: [0, 999999999] +} ExessDateTime; + +/** + Add a duration to a datetime. + + This advances or rewinds the datetime by the given duration, depending on + whether the duration is positive or negative. + + If underflow or overflow occur, then this will return an infinite value. A + positive infinity has all fields at maximum, and a negative infinity has all + fields at minimum, except `is_utc` which is preserved from the input (so + infinities are comparable with the values they came from). Since 0 and 255 + are never valid months, these can be tested for by checking if the year and + month are `INT16_MIN` and 0, or `INT16_MAX` and `INT8_MAX`. + + @return `s + d`, or an infinite past or infinite future if underflow or + overflow occurs. +*/ +EXESS_CONST_API +ExessDateTime +exess_add_datetime_duration(ExessDateTime s, ExessDuration d); + +/** + Read an xsd:dateTime string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_datetime(ExessDateTime* EXESS_NONNULL out, + const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:datetime string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return #EXESS_SUCCESS on success, #EXESS_NO_SPACE if the buffer is too + small, or #EXESS_BAD_VALUE if the value is invalid. +*/ +EXESS_API +ExessResult +exess_write_datetime(ExessDateTime value, + size_t buf_size, + char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_timezone Timezones + + Date and time values can have a timezone qualifier suffix. Note that + timezone is not a datatype, one only exists as a part of another value. + + Canonical form starts with a sign, followed by two-digit hour and minute + offsets separated by a colon, like "-06:00" and "+02:30". The zero offset, + UTC, is written "Z". + + Non-canonical form also allows writing UTC as "-00:00" or "+00:00". + + This implementation only supports a resolution of 15 minutes, that is, only + offsets at 0, 15, 30, and 45 minutes within an hour. + + @{ +*/ + +/// A time zone offset for a date or time value +typedef struct { + int8_t quarter_hours; ///< Offset in quarter hours: [-56, 56] +} ExessTimezone; + +/// Sentinel value for local time, `INT8_MAX` +#define EXESS_LOCAL INT8_MAX + +/** + @} + @defgroup exess_date Date + An xsd:date is a year, month, and day, with optional timezone. + @{ +*/ + +/// The maximum length of an xsd:date string from exess_write_date(), 18 +#define EXESS_MAX_DATE_LENGTH 18 + +/// Date (xsd:date) +typedef struct { + int16_t year; + uint8_t month; + uint8_t day; + ExessTimezone zone; +} ExessDate; + +/** + Read an xsd:date string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_date(ExessDate* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:date string. + + The output is always in canonical form, like `2001-04-12` or + `-2001-10-26+02:00`. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return #EXESS_SUCCESS on success, #EXESS_NO_SPACE if the buffer is too + small, or #EXESS_BAD_VALUE if the value is invalid. +*/ +EXESS_API +ExessResult +exess_write_date(ExessDate value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_time Time + + An xsd:time is a time of day, with optional timezone. + + @{ +*/ + +/// The maximum length of an xsd:time string from exess_write_time(), 24 +#define EXESS_MAX_TIME_LENGTH 24 + +/// Time (xsd:time) +typedef struct { + ExessTimezone zone; ///< Time zone + uint8_t hour; ///< Hour: [0, 23] + uint8_t minute; ///< Minute: [0, 59] + uint8_t second; ///< Second: [0, 59] + uint32_t nanosecond; ///< Nanosecond: [0, 999999999] +} ExessTime; + +/** + Read an xsd:time string after any leading whitespace. + + @param out Set to the parsed value, or zero on error. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_time(ExessTime* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:time string. + + The output is always in canonical form, like "12:15" or "02:00Z". + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return #EXESS_SUCCESS on success, #EXESS_NO_SPACE if the buffer is too + small, or #EXESS_BAD_VALUE if the value is invalid. +*/ +EXESS_API +ExessResult +exess_write_time(ExessTime value, size_t buf_size, char* EXESS_NULLABLE buf); + +/** + @} + @} + @defgroup exess_binary Binary + Datatypes for arbitrary binary data. + @{ +*/ + +typedef struct { + size_t size; + void* EXESS_NULLABLE data; +} ExessBlob; + +/** + @defgroup exess_base64 Base64 + An xsd:base64Binary is arbitrary binary data in base64 encoding. + @{ +*/ + +/** + Return the maximum number of bytes required to decode `length` bytes of + base64. + + The returned value is an upper bound which is only exact for canonical + strings. + + @param length The number of input (text) bytes to decode. + @return The size of a decoded value in bytes. +*/ +EXESS_CONST_API +size_t +exess_base64_decoded_size(size_t length); + +/** + Read a binary value from a base64 string. + + Canonical syntax is a multiple of 4 base64 characters, with either 1 or 2 + trailing "=" characters as necessary, like "Zm9vYg==", with no whitespace. + All whitespace is skipped when reading. + + The caller must allocate a large enough buffer to read the value, otherwise + an #EXESS_NO_SPACE error will be returned. The required space can be + calculated with exess_base64_decoded_size(). + + When this is called, the output blob must have the size of the available + buffer in bytes, and a pointer to the buffer. On return, the size will be + set to the exact size of the decoded data, which may be smaller than the + initial available size. Only these first bytes are written, the rest of the + buffer is not modified. + + @param out The blob to set to the decoded binary data. + @param str String to parse. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_base64(ExessBlob* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:base64Binary string. + + The data is always written in canonical form, as a multiple of 4 characters + with no whitespace and 1 or 2 trailing "=" characters as padding if + necessary. + + @param data_size The size of `data` in bytes. + @param data Data to write to a string. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_base64(size_t data_size, + const void* EXESS_NONNULL data, + size_t buf_size, + char* EXESS_NULLABLE buf); + +/** + @} + @defgroup exess_hex Hex + An xsd:hexBinary is arbitrary binary data in hexadecimal encoding. + @{ +*/ + +/** + Return the maximum number of bytes required to decode `length` bytes of hex. + + The returned value is an upper bound which is only exact for canonical + strings. + + @param length The number of input (text) bytes to decode. + @return The size of a decoded value in bytes. +*/ +EXESS_CONST_API +size_t +exess_hex_decoded_size(size_t length); + +/** + Read a binary value from a hex string. + + Canonical syntax is an even number of uppercase hexadecimal digits with no + whitespace, like "666F6F". Lowercase hexadecimal is also supported, and all + whitespace is skipped when reading. + + The caller must allocate a large enough buffer to read the value, otherwise + an #EXESS_NO_SPACE error will be returned. The required space can be + calculated with exess_hex_decoded_size(). + + When this is called, the output blob must have the size of the available + buffer in bytes, and a pointer to the buffer. On return, the size will be + set to the exact size of the decoded data, which may be smaller than the + initial available size. Only these first bytes are written, the rest of the + buffer is not modified. + + @param out The blob to set to the decoded binary data. + @param str String to parse. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_hex(ExessBlob* EXESS_NONNULL out, const char* EXESS_NONNULL str); + +/** + Write a canonical xsd:hexBinary string. + + The data is always written in canonical form, as an even number of uppercase + hexadecimal digits with no whitespace. + + @param data_size The size of `data` in bytes. + @param data Data to write to a string. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_hex(size_t data_size, + const void* EXESS_NONNULL data, + size_t buf_size, + char* EXESS_NULLABLE buf); + +/** + @} + @} + @defgroup exess_datatypes Datatypes + Runtime integer tags for supported datatypes with conversion to/from URIs. + @{ +*/ + +typedef enum { + EXESS_NOTHING, ///< Sentinel for unknown datatypes or errors + EXESS_BOOLEAN, ///< xsd:boolean (see @ref exess_boolean) + EXESS_DECIMAL, ///< xsd:decimal (see @ref exess_decimal) + EXESS_DOUBLE, ///< xsd:double (see @ref exess_double) + EXESS_FLOAT, ///< xsd:float (see @ref exess_float) + EXESS_INTEGER, ///< xsd:integer (see @ref exess_long) + EXESS_NON_POSITIVE_INTEGER, ///< xsd:nonPositiveInteger (see @ref exess_long) + EXESS_NEGATIVE_INTEGER, ///< xsd:negativeInteger (see @ref exess_long) + EXESS_LONG, ///< xsd:long (see @ref exess_long) + EXESS_INT, ///< xsd:integer (see @ref exess_int) + EXESS_SHORT, ///< xsd:short (see @ref exess_short) + EXESS_BYTE, ///< xsd:byte (see @ref exess_byte) + EXESS_NON_NEGATIVE_INTEGER, ///< xsd:nonNegativeInteger (see @ref exess_ulong) + EXESS_ULONG, ///< xsd:unsignedLong (see @ref exess_ulong) + EXESS_UINT, ///< xsd:unsignedInt (see @ref exess_uint) + EXESS_USHORT, ///< xsd:unsignedShort (see @ref exess_ushort) + EXESS_UBYTE, ///< xsd:unsignedByte (see @ref exess_ubyte) + EXESS_POSITIVE_INTEGER, ///< xsd:positiveInteger (see @ref exess_ulong) + EXESS_DURATION, ///< xsd:duration (see @ref exess_duration) + EXESS_DATETIME, ///< xsd:dateTime (see @ref exess_datetime) + EXESS_TIME, ///< xsd:time (see @ref exess_time) + EXESS_DATE, ///< xsd:date (see @ref exess_date) + EXESS_HEX, ///< xsd:hexBinary (see @ref exess_hex) + EXESS_BASE64, ///< xsd:base64Binary (see @ref exess_base64) +} ExessDatatype; + +/** + Return the URI for a supported datatype. + + This only returns URIs that start with + `http://www.w3.org/2001/XMLSchema#`. + + @param datatype Datatype tag. + @return The URI of the datatype, or null for #EXESS_NOTHING. +*/ +EXESS_CONST_API +const char* EXESS_NULLABLE +exess_datatype_uri(ExessDatatype datatype); + +/** + Return the datatype tag for a datatype URI. + + @return A datatype tag, or #EXESS_NOTHING if the URI is not a supported + datatype. +*/ +EXESS_PURE_API +ExessDatatype +exess_datatype_from_uri(const char* EXESS_NONNULL uri); + +/** + Return whether a datatype has an upper bound on value sizes. + + This returns true for all datatypes except #EXESS_DECIMAL, #EXESS_INTEGER + and its half-bounded subtypes #EXESS_NON_POSITIVE_INTEGER, + #EXESS_NEGATIVE_INTEGER, #EXESS_NON_NEGATIVE_INTEGER, and + #EXESS_POSITIVE_INTEGER, and the binary types #EXESS_HEX and #EXESS_BASE64. + + For bounded datatypes, the maximum length of the string representation is + available in `exess_max_lengths` array, or as static constants like + #EXESS_MAX_INT_LENGTH. + + @return True if values of the given datatype have a maximum size. +*/ +EXESS_CONST_API +bool +exess_datatype_is_bounded(ExessDatatype datatype); + +/** + @} + @defgroup exess_variant Variant + An ExessVariant is a tagged union that can hold any supported datatype. + @{ +*/ + +typedef union { + ExessStatus as_status; + ExessBlob as_blob; + bool as_bool; + double as_double; + float as_float; + int64_t as_long; + int32_t as_int; + int16_t as_short; + int8_t as_byte; + uint64_t as_ulong; + uint32_t as_uint; + uint16_t as_ushort; + uint8_t as_ubyte; + ExessDuration as_duration; + ExessDateTime as_datetime; + ExessTime as_time; + ExessDate as_date; +} ExessValue; + +/** + Any supported value. + + A variant is either nothing, or a value of a specific supported type. The + nothing variant has datatype #EXESS_NOTHING. + + The value fields (everything other than datatype) are stored in an anonymous + union, only the field corresponding to the datatype is active. This should + not be used for type punning, use exess_coerce() for that instead. +*/ +typedef struct { + ExessDatatype datatype; + ExessValue value; +} ExessVariant; + +/** + @defgroup exess_variant_constructors Constructors + @{ +*/ + +/// Return a nothing (null) variant, with a status code to signal errors +EXESS_CONST_API +ExessVariant +exess_make_nothing(ExessStatus status); + +/// Return a boolean variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_boolean(bool value); + +/// Return a decimal variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_decimal(double value); + +/// Return a double variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_double(double value); + +/// Return a float variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_float(float value); + +/// Return a long variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_long(int64_t value); + +/// Return an int variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_int(int32_t value); + +/// Return a short variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_short(int16_t value); + +/// Return a byte variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_byte(int8_t value); + +/// Return a ulong variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_ulong(uint64_t value); + +/// Return a uint variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_uint(uint32_t value); + +/// Return a ushort variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_ushort(uint16_t value); + +/// Return a ubyte variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_ubyte(uint8_t value); + +/// Return a duration variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_duration(ExessDuration value); + +/// Return a datetime variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_datetime(ExessDateTime value); + +/// Return a time variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_time(ExessTime value); + +/// Return a date variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_date(ExessDate value); + +/// Return a hex binary variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_hex(ExessBlob value); + +/// Return a base64 binary variant with the given value +EXESS_CONST_API +ExessVariant +exess_make_base64(ExessBlob value); + +/** + @} + @defgroup exess_variant_accessors Accessors + @{ +*/ + +/** + Return the status of a variant. + + This returns #EXESS_SUCCESS for any valid value, or the stored status for a + #EXESS_NOTHING variant. +*/ +EXESS_PURE_API +ExessStatus +exess_get_status(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a boolean, otherwise null +EXESS_PURE_API +const bool* EXESS_NULLABLE +exess_get_boolean(const ExessVariant* EXESS_NONNULL variant); + +/** + Return a pointer to the value if `variant` is a double, otherwise null. + + This will also access the value for #EXESS_DECIMAL. +*/ +EXESS_PURE_API +const double* EXESS_NULLABLE +exess_get_double(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a float, otherwise null +EXESS_PURE_API +const float* EXESS_NULLABLE +exess_get_float(const ExessVariant* EXESS_NONNULL variant); + +/** + Return a pointer to the value if `variant` is a long, otherwise null. + + This will also access the value for #EXESS_INTEGER, + #EXESS_NON_POSITIVE_INTEGER, and #EXESS_NEGATIVE_INTEGER. +*/ +EXESS_PURE_API +const int64_t* EXESS_NULLABLE +exess_get_long(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is an int, otherwise null +EXESS_PURE_API +const int32_t* EXESS_NULLABLE +exess_get_int(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a short, otherwise null +EXESS_PURE_API +const int16_t* EXESS_NULLABLE +exess_get_short(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a byte, otherwise null +EXESS_PURE_API +const int8_t* EXESS_NULLABLE +exess_get_byte(const ExessVariant* EXESS_NONNULL variant); + +/** + Return a pointer to the value if `variant` is a ulong, otherwise null. + + This will also access the value for #EXESS_NON_NEGATIVE_INTEGER and + #EXESS_POSITIVE_INTEGER. +*/ +EXESS_PURE_API +const uint64_t* EXESS_NULLABLE +exess_get_ulong(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a uint, otherwise null +EXESS_PURE_API +const uint32_t* EXESS_NULLABLE +exess_get_uint(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a ushort, otherwise null +EXESS_PURE_API +const uint16_t* EXESS_NULLABLE +exess_get_ushort(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a ubyte, otherwise null +EXESS_PURE_API +const uint8_t* EXESS_NULLABLE +exess_get_ubyte(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a duration, otherwise null +EXESS_PURE_API +const ExessDuration* EXESS_NULLABLE +exess_get_duration(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a datetime, otherwise null +EXESS_PURE_API +const ExessDateTime* EXESS_NULLABLE +exess_get_datetime(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a time, otherwise null +EXESS_PURE_API +const ExessTime* EXESS_NULLABLE +exess_get_time(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a date, otherwise null +EXESS_PURE_API +const ExessDate* EXESS_NULLABLE +exess_get_date(const ExessVariant* EXESS_NONNULL variant); + +/// Return a pointer to the value if `variant` is a date, otherwise null +EXESS_PURE_API +const ExessBlob* EXESS_NULLABLE +exess_get_blob(const ExessVariant* EXESS_NONNULL variant); + +/** + @} +*/ + +// + +/** + Read any supported datatype from a string. + + For reading binary blobs from base64 or hex, the `as_blob` field of `out` + must have the size of the available buffer in bytes, and a pointer to the + buffer. On return, the size will be set to the exact size of the decoded + data, which may be smaller than the initial available size. Only these + first bytes are written, the rest of the buffer is not modified. + + @param out Set to the parsed value, or nothing on error. + @param datatype The datatype to read the string as. + @param str String input. + @return The `count` of characters read, and a `status` code. +*/ +EXESS_API +ExessResult +exess_read_variant(ExessVariant* EXESS_NONNULL out, + ExessDatatype datatype, + const char* EXESS_NONNULL str); + +/** + Write any supported xsd datatype to a canonical string. + + @param value Value to write. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and `status` + #EXESS_SUCCESS, or #EXESS_NO_SPACE if the buffer is too small. +*/ +EXESS_API +ExessResult +exess_write_variant(ExessVariant value, + size_t buf_size, + char* EXESS_NULLABLE buf); + +/** + Rewrite a supported xsd datatype in canonical form. + + @param value Input value string. + @param datatype Datatype of value. + @param buf_size The size of `buf` in bytes. + @param buf Output buffer, or null to only measure. + + @return The `count` of characters in the output, and a `status` code. The + status may be an error from reading or writing, but the `count` always + refers to the number of characters written. +*/ +EXESS_API +ExessResult +exess_write_canonical(const char* EXESS_NONNULL value, + ExessDatatype datatype, + size_t buf_size, + char* EXESS_NULLABLE buf); + +/** + @defgroup exess_coercion Datatype coercion + + Values can be converted between some datatypes using exess_coerce(). This is + particularly useful for reducing the number of datatypes that the application + needs to explicitly handle. + + @{ +*/ + +/** + Coercion flags. + + These values are ORed together to enable different kinds of lossy conversion + in exess_coerce(). +*/ +typedef enum { + /** + Only do lossless datatype coercions. + + A lossless coercion is when the value has been perfectly preserved in the + target datatype, and coercing it back will result in the same value. + + For some datatype combinations this will always be the case, for example + from short to long. For others it will depend on the value, for example + only the numbers 0 and 1 coerce to boolean without loss. + */ + EXESS_LOSSLESS = 0u, + + /** + Allow datatype coercions that reduce the precision of values. + + This allows coercions that are lossy only in terms of precision, so the + resulting value is approximately equal to the original value. + Specifically, this allows coercing double to float. + */ + EXESS_REDUCE_PRECISION = 1u << 0u, + + /** + Allow datatype coercions that round to the nearest integer. + + This allows coercing floating point numbers to integers by rounding to the + nearest integer, with halfway cases rounding towards even (the default + IEEE-754 rounding order). + */ + EXESS_ROUND = 1u << 1u, + + /** + Allow datatype coercions that truncate significant parts of values. + + This allows coercions that lose data beyond simple precision loss. + Specifically, this allows coercing any number to boolean, datetime to + date, and datetime to time. + */ + EXESS_TRUNCATE = 1u << 2u, +} ExessCoercionFlag; + +/// Bitwise OR of #ExessCoercionFlag values +typedef uint32_t ExessCoercionFlags; + +/** + Coerce a value to another datatype if possible. + + @param value Value to coerce. + + @param datatype Datatype to convert to. + + @param coercions Enabled coercion flags. If this is #EXESS_LOSSLESS (zero), + then #EXESS_SUCCESS is only returned if the resulting value can be coerced + back to the original type without any loss of data. Otherwise, the lossy + coercions enabled by the set bits will be attempted. + + @return #EXESS_SUCCESS on successful conversion, #EXESS_OUT_OF_RANGE if the + value is outside the range of the target type, + #EXESS_WOULD_REDUCE_PRECISION, #EXESS_WOULD_ROUND, or #EXESS_WOULD_TRUNCATE + if the required coercion is not enabled, or #EXESS_UNSUPPORTED if conversion + between the types is not supported at all. +*/ +EXESS_API +ExessVariant +exess_coerce(ExessVariant value, + ExessDatatype datatype, + ExessCoercionFlags coercions); + +/** + @} + @} +*/ + +/** + The maximum length of the string representation of datatypes. + + For datatypes that do not have such a bound, the value is zero. +*/ +static const size_t exess_max_lengths[] = { + 0, // Unknown + EXESS_MAX_BOOLEAN_LENGTH, + 0, // decimal + EXESS_MAX_DOUBLE_LENGTH, + EXESS_MAX_FLOAT_LENGTH, + 0, // integer + 0, // nonPositiveInteger + 0, // negativeInteger + EXESS_MAX_LONG_LENGTH, + EXESS_MAX_INT_LENGTH, + EXESS_MAX_SHORT_LENGTH, + EXESS_MAX_BYTE_LENGTH, + 0, // nonNegativeInteger + EXESS_MAX_ULONG_LENGTH, + EXESS_MAX_UINT_LENGTH, + EXESS_MAX_USHORT_LENGTH, + EXESS_MAX_UBYTE_LENGTH, + 0, // positiveInteger + EXESS_MAX_DURATION_LENGTH, + EXESS_MAX_DATETIME_LENGTH, + EXESS_MAX_TIME_LENGTH, + EXESS_MAX_DATE_LENGTH, + 0, // hexBinary + 0, // base64Binary +}; + +/** + @} +*/ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // EXESS_EXESS_H |