blob: 1147ed0eb985115688de486d09a37756723cdc18 [file] [log] [blame]
// After editing this file, run "go generate" in the ../data directory.
// Copyright 2020 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ---------------- String Conversions
// Options (bitwise or'ed together) for wuffs_base__parse_number_xxx
// functions. The XXX options apply to both integer and floating point. The FXX
// options apply only to floating point.
#define WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS ((uint32_t)0x00000000)
// WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES means to accept
// inputs like "00", "0644" and "00.7". By default, they are rejected.
#define WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES \
((uint32_t)0x00000001)
// WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES means to accept inputs like
// "1__2" and "_3.141_592". By default, they are rejected.
#define WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES ((uint32_t)0x00000002)
// WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA means to accept
// "1,5" and not "1.5" as one-and-a-half.
//
// If the caller wants to accept either, it is responsible for canonicalizing
// the input before calling wuffs_base__parse_number_fxx. The caller also has
// more context on e.g. exactly how to treat something like "$1,234".
#define WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA \
((uint32_t)0x00000010)
// WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN means to reject inputs that
// would lead to infinite or Not-a-Number floating point values. By default,
// they are accepted.
//
// This affects the literal "inf" as input, but also affects inputs like
// "1e999" that would overflow double-precision floating point.
#define WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN ((uint32_t)0x00000020)
// --------
// Options (bitwise or'ed together) for wuffs_base__render_number_xxx
// functions. The XXX options apply to both integer and floating point. The FXX
// options apply only to floating point.
#define WUFFS_BASE__RENDER_NUMBER_XXX__DEFAULT_OPTIONS ((uint32_t)0x00000000)
// WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT means to render to the right side
// (higher indexes) of the destination slice, leaving any untouched bytes on
// the left side (lower indexes). The default is vice versa: rendering on the
// left with slack on the right.
#define WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT ((uint32_t)0x00000100)
// WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN means to render the leading
// "+" for non-negative numbers: "+0" and "+12.3" instead of "0" and "12.3".
#define WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN ((uint32_t)0x00000200)
// WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA means to render
// one-and-a-half as "1,5" instead of "1.5".
#define WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA \
((uint32_t)0x00001000)
// WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ETC means whether to never
// (EXPONENT_ABSENT, equivalent to printf's "%f") or to always
// (EXPONENT_PRESENT, equivalent to printf's "%e") render a floating point
// number as "1.23e+05" instead of "123000".
//
// Having both bits set is the same has having neither bit set, where the
// notation used depends on whether the exponent is sufficiently large: "0.5"
// is preferred over "5e-01" but "5e-09" is preferred over "0.000000005".
#define WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT ((uint32_t)0x00002000)
#define WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT ((uint32_t)0x00004000)
// WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION means to render the
// smallest number of digits so that parsing the resultant string will recover
// the same double-precision floating point number.
//
// For example, double-precision cannot distinguish between 0.3 and
// 0.299999999999999988897769753748434595763683319091796875, so when this bit
// is set, rendering the latter will produce "0.3" but rendering
// 0.3000000000000000444089209850062616169452667236328125 will produce
// "0.30000000000000004".
#define WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION \
((uint32_t)0x00008000)
// ---------------- IEEE 754 Floating Point
// wuffs_base__ieee_754_bit_representation__etc converts between a double
// precision numerical value and its IEEE 754 representations:
// - 16-bit: 1 sign bit, 5 exponent bits, 10 explicit significand bits.
// - 32-bit: 1 sign bit, 8 exponent bits, 23 explicit significand bits.
// - 64-bit: 1 sign bit, 11 exponent bits, 52 explicit significand bits.
//
// For example, it converts between:
// - +1.0 and 0x3C00, 0x3F80_0000 or 0x3FF0_0000_0000_0000.
// - +5.5 and 0x4580, 0x40B0_0000 or 0x4016_0000_0000_0000.
// - -inf and 0xFC00, 0xFF80_0000 or 0xFFF0_0000_0000_0000.
//
// Converting from f64 to shorter formats (f16 or f32, represented in C as
// uint16_t and uint32_t) may be lossy. Such functions have names that look
// like etc_truncate, as converting finite numbers produce equal or smaller
// (closer-to-zero) finite numbers. For example, 1048576.0 is a perfectly valid
// f64 number, but converting it to a f16 (with truncation) produces 65504.0,
// the largest finite f16 number. Truncating a f64-typed value d to f32 does
// not always produce the same result as the C-style cast ((float)d), as
// casting can convert from finite numbers to infinite ones.
//
// Converting infinities or NaNs produces infinities or NaNs and always report
// no loss, even though there a multiple NaN representations so that round-
// tripping a f64-typed NaN may produce a different 64 bits. Nonetheless, the
// etc_truncate functions preserve a NaN's "quiet vs signaling" bit.
//
// See https://en.wikipedia.org/wiki/Double-precision_floating-point_format
typedef struct wuffs_base__lossy_value_u16__struct {
uint16_t value;
bool lossy;
} wuffs_base__lossy_value_u16;
typedef struct wuffs_base__lossy_value_u32__struct {
uint32_t value;
bool lossy;
} wuffs_base__lossy_value_u32;
WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16 //
wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f);
WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32 //
wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f);
static inline uint64_t //
wuffs_base__ieee_754_bit_representation__from_f64_to_u64(double f) {
uint64_t u = 0;
if (sizeof(uint64_t) == sizeof(double)) {
memcpy(&u, &f, sizeof(uint64_t));
}
return u;
}
static inline double //
wuffs_base__ieee_754_bit_representation__from_u16_to_f64(uint16_t u) {
uint64_t v = ((uint64_t)(u & 0x8000)) << 48;
do {
uint64_t exp = (u >> 10) & 0x1F;
uint64_t man = u & 0x3FF;
if (exp == 0x1F) { // Infinity or NaN.
exp = 2047;
} else if (exp != 0) { // Normal.
exp += 1008; // 1008 = 1023 - 15, the difference in biases.
} else if (man != 0) { // Subnormal but non-zero.
uint32_t clz = wuffs_base__count_leading_zeroes_u64(man);
exp = 1062 - clz; // 1062 = 1008 + 64 - 10.
man = 0x3FF & (man << (clz - 53));
} else { // Zero.
break;
}
v |= (exp << 52) | (man << 42);
} while (0);
double f = 0;
if (sizeof(uint64_t) == sizeof(double)) {
memcpy(&f, &v, sizeof(uint64_t));
}
return f;
}
static inline double //
wuffs_base__ieee_754_bit_representation__from_u32_to_f64(uint32_t u) {
float f = 0;
if (sizeof(uint32_t) == sizeof(float)) {
memcpy(&f, &u, sizeof(uint32_t));
}
return (double)f;
}
static inline double //
wuffs_base__ieee_754_bit_representation__from_u64_to_f64(uint64_t u) {
double f = 0;
if (sizeof(uint64_t) == sizeof(double)) {
memcpy(&f, &u, sizeof(uint64_t));
}
return f;
}
// ---------------- Parsing and Rendering Numbers
// wuffs_base__parse_number_f64 parses the floating point number in s. For
// example, if s contains the bytes "1.5" then it will return the double 1.5.
//
// It returns an error if s does not contain a floating point number.
//
// It does not necessarily return an error if the conversion is lossy, e.g. if
// s is "0.3", which double-precision floating point cannot represent exactly.
//
// Similarly, the returned value may be infinite (and no error returned) even
// if s was not "inf", when the input is nominally finite but sufficiently
// larger than DBL_MAX, about 1.8e+308.
//
// It is similar to the C standard library's strtod function, but:
// - Errors are returned in-band (in a result type), not out-of-band (errno).
// - It takes a slice (a pointer and length), not a NUL-terminated C string.
// - It does not take an optional endptr argument. It does not allow a partial
// parse: it returns an error unless all of s is consumed.
// - It does not allow whitespace, leading or otherwise.
// - It does not allow hexadecimal floating point numbers.
// - It is not affected by i18n / l10n settings such as environment variables.
//
// The options argument can change these, but by default, it:
// - Allows "inf", "+Infinity" and "-NAN", case insensitive. Similarly,
// without an explicit opt-out, it would successfully parse "1e999" as
// infinity, even though it overflows double-precision floating point.
// - Rejects underscores. With an explicit opt-in, "_3.141_592" would
// successfully parse as an approximation to π.
// - Rejects unnecessary leading zeroes: "00", "0644" and "00.7".
// - Uses a dot '1.5' instead of a comma '1,5' for the decimal separator.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__FLOATCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 //
wuffs_base__parse_number_f64(wuffs_base__slice_u8 s, uint32_t options);
// wuffs_base__parse_number_i64 parses the ASCII integer in s. For example, if
// s contains the bytes "-123" then it will return the int64_t -123.
//
// It returns an error if s does not contain an integer or if the integer
// within would overflow an int64_t.
//
// It is similar to wuffs_base__parse_number_u64 but it returns a signed
// integer, not an unsigned integer. It also allows a leading '+' or '-'.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC wuffs_base__result_i64 //
wuffs_base__parse_number_i64(wuffs_base__slice_u8 s, uint32_t options);
// wuffs_base__parse_number_u64 parses the ASCII integer in s. For example, if
// s contains the bytes "123" then it will return the uint64_t 123.
//
// It returns an error if s does not contain an integer or if the integer
// within would overflow a uint64_t.
//
// It is similar to the C standard library's strtoull function, but:
// - Errors are returned in-band (in a result type), not out-of-band (errno).
// - It takes a slice (a pointer and length), not a NUL-terminated C string.
// - It does not take an optional endptr argument. It does not allow a partial
// parse: it returns an error unless all of s is consumed.
// - It does not allow whitespace, leading or otherwise.
// - It does not allow a leading '+' or '-'.
// - It does not take a base argument (e.g. base 10 vs base 16). Instead, it
// always accepts both decimal (e.g "1234", "0d5678") and hexadecimal (e.g.
// "0x9aBC"). The caller is responsible for prior filtering of e.g. hex
// numbers if they are unwanted. For example, Wuffs' JSON decoder will only
// produce a wuffs_base__token for decimal numbers, not hexadecimal.
// - It is not affected by i18n / l10n settings such as environment variables.
//
// The options argument can change these, but by default, it:
// - Rejects underscores. With an explicit opt-in, "__0D_1_002" would
// successfully parse as "one thousand and two". Underscores are still
// rejected inside the optional 2-byte opening "0d" or "0X" that denotes
// base-10 or base-16.
// - Rejects unnecessary leading zeroes: "00" and "0644".
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC wuffs_base__result_u64 //
wuffs_base__parse_number_u64(wuffs_base__slice_u8 s, uint32_t options);
// --------
// WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL is the string length of
// "-9223372036854775808" and "+9223372036854775807", INT64_MIN and INT64_MAX.
#define WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL 20
// WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL is the string length of
// "+18446744073709551615", UINT64_MAX.
#define WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL 21
// wuffs_base__render_number_f64 writes the decimal encoding of x to dst and
// returns the number of bytes written. If dst is shorter than the entire
// encoding, it returns 0 (and no bytes are written).
//
// For those familiar with C's printf or Go's fmt.Printf functions:
// - "%e" means the WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT option.
// - "%f" means the WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT option.
// - "%g" means neither or both bits are set.
//
// The precision argument controls the number of digits rendered, excluding the
// exponent (the "e+05" in "1.23e+05"):
// - for "%e" and "%f" it is the number of digits after the decimal separator,
// - for "%g" it is the number of significant digits (and trailing zeroes are
// removed).
//
// A precision of 6 gives similar output to printf's defaults.
//
// A precision greater than 4095 is equivalent to 4095.
//
// The precision argument is ignored when the
// WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION option is set. This is
// similar to Go's strconv.FormatFloat with a negative (i.e. non-sensical)
// precision, but there is no corresponding feature in C's printf.
//
// Extreme values of x will be rendered as "NaN", "Inf" (or "+Inf" if the
// WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN option is set) or "-Inf".
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__FLOATCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC size_t //
wuffs_base__render_number_f64(wuffs_base__slice_u8 dst,
double x,
uint32_t precision,
uint32_t options);
// wuffs_base__render_number_i64 writes the decimal encoding of x to dst and
// returns the number of bytes written. If dst is shorter than the entire
// encoding, it returns 0 (and no bytes are written).
//
// dst will never be too short if its length is at least 20, also known as
// WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC size_t //
wuffs_base__render_number_i64(wuffs_base__slice_u8 dst,
int64_t x,
uint32_t options);
// wuffs_base__render_number_u64 writes the decimal encoding of x to dst and
// returns the number of bytes written. If dst is shorter than the entire
// encoding, it returns 0 (and no bytes are written).
//
// dst will never be too short if its length is at least 21, also known as
// WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC size_t //
wuffs_base__render_number_u64(wuffs_base__slice_u8 dst,
uint64_t x,
uint32_t options);
// ---------------- Base-16
// Options (bitwise or'ed together) for wuffs_base__base_16__xxx functions.
#define WUFFS_BASE__BASE_16__DEFAULT_OPTIONS ((uint32_t)0x00000000)
// wuffs_base__base_16__decode2 converts "6A6b" to "jk", where e.g. 'j' is
// U+006A. There are 2 src bytes for every dst byte.
//
// It assumes that the src bytes are two hexadecimal digits (0-9, A-F, a-f),
// repeated. It may write nonsense bytes if not, although it will not read or
// write out of bounds.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
wuffs_base__base_16__decode2(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 src,
bool src_closed,
uint32_t options);
// wuffs_base__base_16__decode4 converts both "\\x6A\\x6b" and "??6a??6B" to
// "jk", where e.g. 'j' is U+006A. There are 4 src bytes for every dst byte.
//
// It assumes that the src bytes are two ignored bytes and then two hexadecimal
// digits (0-9, A-F, a-f), repeated. It may write nonsense bytes if not,
// although it will not read or write out of bounds.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
wuffs_base__base_16__decode4(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 src,
bool src_closed,
uint32_t options);
// wuffs_base__base_16__encode2 converts "jk" to "6A6B", where e.g. 'j' is
// U+006A. There are 2 dst bytes for every src byte.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 src,
bool src_closed,
uint32_t options);
// wuffs_base__base_16__encode4 converts "jk" to "\\x6A\\x6B", where e.g. 'j'
// is U+006A. There are 4 dst bytes for every src byte.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 src,
bool src_closed,
uint32_t options);
// ---------------- Base-64
// Options (bitwise or'ed together) for wuffs_base__base_64__xxx functions.
#define WUFFS_BASE__BASE_64__DEFAULT_OPTIONS ((uint32_t)0x00000000)
// WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING means that, when decoding base-64,
// the input may (but does not need to) be padded with '=' bytes so that the
// overall encoded length in bytes is a multiple of 4. A successful decoding
// will return a num_src that includes those padding bytes.
//
// Excess padding (e.g. three final '='s) will be rejected as bad data.
#define WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING ((uint32_t)0x00000001)
// WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING means that, when encoding base-64,
// the output will be padded with '=' bytes so that the overall encoded length
// in bytes is a multiple of 4.
#define WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING ((uint32_t)0x00000002)
// WUFFS_BASE__BASE_64__URL_ALPHABET means that, for base-64, the URL-friendly
// and file-name-friendly alphabet be used, as per RFC 4648 section 5. When
// this option bit is off, the standard alphabet from section 4 is used.
#define WUFFS_BASE__BASE_64__URL_ALPHABET ((uint32_t)0x00000100)
// wuffs_base__base_64__decode transforms base-64 encoded bytes from src to
// arbitrary bytes in dst.
//
// It will not permit line breaks or other whitespace in src. Filtering those
// out is the responsibility of the caller.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
wuffs_base__base_64__decode(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 src,
bool src_closed,
uint32_t options);
// wuffs_base__base_64__encode transforms arbitrary bytes from src to base-64
// encoded bytes in dst.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
// just WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
wuffs_base__base_64__encode(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 src,
bool src_closed,
uint32_t options);
// ---------------- Unicode and UTF-8
#define WUFFS_BASE__UNICODE_CODE_POINT__MIN_INCL 0x00000000
#define WUFFS_BASE__UNICODE_CODE_POINT__MAX_INCL 0x0010FFFF
#define WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER 0x0000FFFD
#define WUFFS_BASE__UNICODE_SURROGATE__MIN_INCL 0x0000D800
#define WUFFS_BASE__UNICODE_SURROGATE__MAX_INCL 0x0000DFFF
#define WUFFS_BASE__ASCII__MIN_INCL 0x00
#define WUFFS_BASE__ASCII__MAX_INCL 0x7F
#define WUFFS_BASE__UTF_8__BYTE_LENGTH__MIN_INCL 1
#define WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL 4
#define WUFFS_BASE__UTF_8__BYTE_LENGTH_1__CODE_POINT__MIN_INCL 0x00000000
#define WUFFS_BASE__UTF_8__BYTE_LENGTH_1__CODE_POINT__MAX_INCL 0x0000007F
#define WUFFS_BASE__UTF_8__BYTE_LENGTH_2__CODE_POINT__MIN_INCL 0x00000080
#define WUFFS_BASE__UTF_8__BYTE_LENGTH_2__CODE_POINT__MAX_INCL 0x000007FF
#define WUFFS_BASE__UTF_8__BYTE_LENGTH_3__CODE_POINT__MIN_INCL 0x00000800
#define WUFFS_BASE__UTF_8__BYTE_LENGTH_3__CODE_POINT__MAX_INCL 0x0000FFFF
#define WUFFS_BASE__UTF_8__BYTE_LENGTH_4__CODE_POINT__MIN_INCL 0x00010000
#define WUFFS_BASE__UTF_8__BYTE_LENGTH_4__CODE_POINT__MAX_INCL 0x0010FFFF
// --------
// wuffs_base__utf_8__next__output is the type returned by
// wuffs_base__utf_8__next.
typedef struct wuffs_base__utf_8__next__output__struct {
uint32_t code_point;
uint32_t byte_length;
#ifdef __cplusplus
inline bool is_valid() const;
#endif // __cplusplus
} wuffs_base__utf_8__next__output;
static inline wuffs_base__utf_8__next__output //
wuffs_base__make_utf_8__next__output(uint32_t code_point,
uint32_t byte_length) {
wuffs_base__utf_8__next__output ret;
ret.code_point = code_point;
ret.byte_length = byte_length;
return ret;
}
static inline bool //
wuffs_base__utf_8__next__output__is_valid(
const wuffs_base__utf_8__next__output* o) {
if (o) {
uint32_t cp = o->code_point;
switch (o->byte_length) {
case 1:
return (cp <= 0x7F);
case 2:
return (0x080 <= cp) && (cp <= 0x7FF);
case 3:
// Avoid the 0xD800 ..= 0xDFFF surrogate range.
return ((0x0800 <= cp) && (cp <= 0xD7FF)) ||
((0xE000 <= cp) && (cp <= 0xFFFF));
case 4:
return (0x00010000 <= cp) && (cp <= 0x0010FFFF);
}
}
return false;
}
#ifdef __cplusplus
inline bool //
wuffs_base__utf_8__next__output::is_valid() const {
return wuffs_base__utf_8__next__output__is_valid(this);
}
#endif // __cplusplus
// --------
// wuffs_base__utf_8__encode writes the UTF-8 encoding of code_point to s and
// returns the number of bytes written. If code_point is invalid, or if s is
// shorter than the entire encoding, it returns 0 (and no bytes are written).
//
// s will never be too short if its length is at least 4, also known as
// WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
// WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC size_t //
wuffs_base__utf_8__encode(wuffs_base__slice_u8 dst, uint32_t code_point);
// wuffs_base__utf_8__next returns the next UTF-8 code point (and that code
// point's byte length) at the start of the read-only slice (s_ptr, s_len).
//
// There are exactly two cases in which this function returns something where
// wuffs_base__utf_8__next__output__is_valid is false:
// - If s is empty then it returns {.code_point=0, .byte_length=0}.
// - If s is non-empty and starts with invalid UTF-8 then it returns
// {.code_point=WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, .byte_length=1}.
//
// Otherwise, it returns something where
// wuffs_base__utf_8__next__output__is_valid is true.
//
// In any case, it always returns an output that satisfies both of:
// - (output.code_point <= WUFFS_BASE__UNICODE_CODE_POINT__MAX_INCL).
// - (output.byte_length <= s_len).
//
// If s is a sub-slice of a larger slice of valid UTF-8, but that sub-slice
// boundary occurs in the middle of a multi-byte UTF-8 encoding of a single
// code point, then this function may return something invalid. It is the
// caller's responsibility to split on or otherwise manage UTF-8 boundaries.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
// WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output //
wuffs_base__utf_8__next(const uint8_t* s_ptr, size_t s_len);
// wuffs_base__utf_8__next_from_end is like wuffs_base__utf_8__next except that
// it looks at the end of (s_ptr, s_len) instead of the start.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
// WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output //
wuffs_base__utf_8__next_from_end(const uint8_t* s_ptr, size_t s_len);
// wuffs_base__utf_8__longest_valid_prefix returns the largest n such that the
// sub-slice s[..n] is valid UTF-8, where s is the read-only slice (s_ptr,
// s_len).
//
// In particular, it returns s_len if and only if all of s is valid UTF-8.
//
// If s is a sub-slice of a larger slice of valid UTF-8, but that sub-slice
// boundary occurs in the middle of a multi-byte UTF-8 encoding of a single
// code point, then this function will return less than s_len. It is the
// caller's responsibility to split on or otherwise manage UTF-8 boundaries.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
// WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC size_t //
wuffs_base__utf_8__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len);
// wuffs_base__ascii__longest_valid_prefix returns the largest n such that the
// sub-slice s[..n] is valid ASCII, where s is the read-only slice (s_ptr,
// s_len).
//
// In particular, it returns s_len if and only if all of s is valid ASCII.
// Equivalently, when none of the bytes in s have the 0x80 high bit set.
//
// For modular builds that divide the base module into sub-modules, using this
// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
// WUFFS_CONFIG__MODULE__BASE__CORE.
WUFFS_BASE__MAYBE_STATIC size_t //
wuffs_base__ascii__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len);