diff options
Diffstat (limited to 'src/chunklets')
| -rw-r--r-- | src/chunklets/msg.c | 232 | ||||
| -rw-r--r-- | src/chunklets/msg.h | 572 | 
2 files changed, 638 insertions, 166 deletions
diff --git a/src/chunklets/msg.c b/src/chunklets/msg.c index 5b688cb..25a3018 100644 --- a/src/chunklets/msg.c +++ b/src/chunklets/msg.c @@ -1,5 +1,5 @@  /* - * Copyright © 2024 Michael Smith <mikesmiffy128@gmail.com> + * Copyright © 2025 Michael Smith <mikesmiffy128@gmail.com>   *   * Permission to use, copy, modify, and/or distribute this software for any   * purpose with or without fee is hereby granted, provided that the above @@ -32,6 +32,8 @@ _Static_assert(  );  #endif +#include "msg.h" +  // -- A note on performance hackery --  //  // Clang won't emit byte-swapping instructions in place of bytewise array writes @@ -69,7 +71,9 @@ static inline unsigned long long swap64(unsigned long long x) {  #endif  #endif -static inline void doput16(unsigned char *out, unsigned short val) { +static inline void doput16(unsigned char *out, unsigned char tag, +		unsigned short val) { +	out[0] = tag;  #ifdef USE_BSWAP_NONSENSE  	// Use swap32() here because x86 and ARM don't have instructions for 16-bit  	// swaps, and Clang doesn't realise it could just use the 32-bit one anyway. @@ -79,7 +83,9 @@ static inline void doput16(unsigned char *out, unsigned short val) {  #endif  } -static inline void doput32(unsigned char *out, unsigned int val) { +static inline void doput32(unsigned char *out, unsigned char tag, +		unsigned int val) { +	out[0] = tag;  #ifdef USE_BSWAP_NONSENSE  	*(unsigned int *)(out + 1) = swap32(val);  #else @@ -87,7 +93,9 @@ static inline void doput32(unsigned char *out, unsigned int val) {  #endif  } -static inline void doput64(unsigned char *out, unsigned int val) { +static inline void doput64(unsigned char *out, unsigned char tag, +		unsigned int val) { +	out[0] = tag;  #ifdef USE_BSWAP_NONSENSE  	// Clang is smart enough to make this into two bswaps and a word swap in  	// 32-bit builds. MSVC seems to be fine too when using the above intrinsics. @@ -100,71 +108,103 @@ static inline void doput64(unsigned char *out, unsigned int val) {  #endif  } -void msg_putnil(unsigned char *out) { -	*out = 0xC0; -} - -void msg_putbool(unsigned char *out, _Bool val) { -	*out = 0xC2 | val; -} - -void msg_puti7(unsigned char *out, signed char val) { -	*out = val; // oh, so a fixnum is just the literal byte! genius! -} -  int msg_puts8(unsigned char *out, signed char val) { -	int off = val < -32; // out of -ve fixnum range?  	out[0] = 0xD0; +	int off = val < -32; // out of -ve fixnum range?  	out[off] = val;  	return off + 1;  } +int msg_rputs8(unsigned char *end, signed char val) { +	int off = val < -32; +	end[-1 - off] = 0xD0; +	end[-1] = val; +	return off + 1; +} +  int msg_putu8(unsigned char *out, unsigned char val) { -	int off = val > 127; // out of +ve fixnum range?  	out[0] = 0xCC; +	int off = val > 127; // out of +ve fixnum range?  	out[off] = val;  	return off + 1;  } +int msg_rputu8(unsigned char *end, unsigned char val) { +	int off = val > 127; +	end[-1 - off] = 0xCC; +	end[-1] = val; +	return off + 1; +} +  int msg_puts16(unsigned char *out, short val) {  	if (val >= -128 && val <= 127) return msg_puts8(out, val); -	out[0] = 0xD1; -	doput16(out, val); +	doput16(out, 0xD1, val); +	return 3; +} + +int msg_rputs16(unsigned char *end, short val) { +	if (val >= -128 && val <= 127) return msg_rputs8(end, val); +	doput16(end - 3, 0xD1, val);  	return 3;  }  int msg_putu16(unsigned char *out, unsigned short val) {  	if (val <= 255) return msg_putu8(out, val); -	out[0] = 0xCD; -	doput16(out, val); +	doput16(out, 0xCD, val); +	return 3; +} + +int msg_rputu16(unsigned char *end, unsigned short val) { +	if (val <= 255) return msg_rputu8(end, val); +	doput16(end - 3, 0xCD, val);  	return 3;  }  int msg_puts32(unsigned char *out, int val) {  	if (val >= -32768 && val <= 32767) return msg_puts16(out, val); -	out[0] = 0xD2; -	doput32(out, val); +	doput32(out, 0xD2, val); +	return 5; +} + +int msg_rputs32(unsigned char *end, int val) { +	if (val >= -32768 && val <= 32767) return msg_rputs16(end, val); +	doput32(end - 5, 0xD2, val);  	return 5;  }  int msg_putu32(unsigned char *out, unsigned int val) { -	if (val <= 65535) return msg_putu16(out, val); -	out[0] = 0xCE; -	doput32(out, val); +	if (val <= 65536) return msg_putu16(out, val); +	doput32(out, 0xCE, val); +	return 5; +} + +int msg_rputu32(unsigned char *end, unsigned int val) { +	if (val <= 65536) return msg_rputu16(end, val); +	doput32(end - 5, 0xCE, val);  	return 5;  }  int msg_puts(unsigned char *out, long long val) {  	if (val >= -2147483648 && val <= 2147483647) return msg_puts32(out, val); -	out[0] = 0xD3; -	doput64(out, val); +	doput64(out, 0xD3, val); +	return 9; +} + +int msg_rputs(unsigned char *end, long long val) { +	if (val >= -2147483648 && val <= 2147483647) return msg_rputs32(end, val); +	doput64(end - 9, 0xD3, val);  	return 9;  }  int msg_putu(unsigned char *out, unsigned long long val) {  	if (val <= 4294967295) return msg_putu32(out, val); -	out[0] = 0xCF; -	doput64(out, val); +	doput64(out, 0xCF, val); +	return 9; +} + +int msg_rputu(unsigned char *end, unsigned long long val) { +	if (val <= 4294967295) return msg_rputu32(end, val); +	doput64(end - 9, 0xCF, val);  	return 9;  } @@ -177,96 +217,124 @@ static inline unsigned long long doublebits(double d) {  }  void msg_putf(unsigned char *out, float val) { -	out[0] = 0xCA; -	doput32(out, floatbits(val)); +	doput32(out, 0xCA, floatbits(val));  }  int msg_putd(unsigned char *out, double val) {  	// XXX: is this really the most efficient way to check this?  	float f = val;  	if ((double)f == val) { msg_putf(out, f); return 5; } -	out[0] = 0xCA; -	doput64(out, doublebits(val)); -	return 9; +	doput64(out, 0xCA, doublebits(val)); return 9;  } -void msg_putssz5(unsigned char *out, int sz) { -	*out = 0xA0 | sz; +int msg_rputd(unsigned char *end, double val) { +	float f = val; +	if ((double)f == val) { msg_rputf(end, f); return 5; } +	doput64(end - 9, 0xCA, doublebits(val)); return 9;  }  int msg_putssz8(unsigned char *out, int sz) {  	if (sz < 32) { msg_putssz5(out, sz); return 1; } -	out[0] = 0xD9; -	out[1] = sz; -	return 2; +	out[0] = 0xD9; out[1] = sz; return 2; +} + +int msg_rputssz8(unsigned char *end, int sz) { +	if (sz < 32) { msg_putssz5(end - 1, sz); return 1; } +	end[-2] = 0xD9; end[-1] = sz; return 2;  } -int msg_putssz16(unsigned char *out, int sz) { -	if (sz < 256) return msg_putssz8(out, sz); -	out[0] = 0xDA; -	doput16(out, sz); +int msg_putssz16(unsigned char *out, int val) { +	if (val <= 255) return msg_putssz8(out, val); +	doput16(out, 0xDA, val);  	return 3;  } -int msg_putssz(unsigned char *out, unsigned int sz) { -	if (sz < 65536) return msg_putssz16(out, sz); -	out[0] = 0xDB; -	doput32(out, sz); -	return 5; +int msg_rputssz16(unsigned char *end, int val) { +	if (val <= 255) return msg_rputssz8(end, val); +	doput16(end - 3, 0xDA, val); +	return 3; +} + +int msg_putssz(unsigned char *out, unsigned int val) { +	if (val <= 65535) return msg_putssz16(out, val); +	doput32(out, 0xDB, val); +	return (32) / 8 + 1; +} +int msg_rputssz(unsigned char *end, unsigned int val) { +	if (val <= 65535) return msg_rputssz16(end, val); +	doput32(end - (32) / 8 - 1, 0xDB, val); +	return (32) / 8 + 1;  } -void msg_putbsz8(unsigned char *out, int sz) { -	out[0] = 0xC4; -	out[1] = sz; +int msg_putbsz16(unsigned char *out, int val) { +	if (val <= 255) { msg_putbsz8(out, val); return 2; } +	doput16(out, 0xC5, val); +	return 3;  } -int msg_putbsz16(unsigned char *out, int sz) { -	if (sz < 256) { msg_putbsz8(out, sz); return 2; } -	out[0] = 0xC5; -	doput16(out, sz); -	return 2 + sz; +int msg_rputbsz16(unsigned char *end, int val) { +	if (val <= 255) { msg_rputbsz8(end, val); return 2; } +	doput16(end - 3, 0xC5, val); +	return 3;  } -int msg_putbsz(unsigned char *out, unsigned int sz) { -	if (sz < 65536) return msg_putbsz16(out, sz); -	out[0] = 0xC6; -	doput32(out, sz); +int msg_putbsz(unsigned char *out, unsigned int val) { +	if (val <= 65535) return msg_putbsz16(out, val); +	doput32(out, 0xC6, val);  	return 5;  } -void msg_putasz4(unsigned char *out, int sz) { -	*out = 0x90 | sz; +int msg_rputbsz(unsigned char *end, unsigned int val) { +	if (val <= 65535) return msg_rputbsz16(end, val); +	doput32(end - 5, 0xC6, val); +	return 5; +} + +int msg_putasz16(unsigned char *out, int val) { +	if (val <= 15) { msg_putasz4(out, val); return 1; } +	doput16(out, 0xDC, val); +	return 3;  } -int msg_putasz16(unsigned char *out, int sz) { -	if (sz < 16) { msg_putasz4(out, sz); return 1; } -	out[0] = 0xDC; -	doput16(out, sz); +int msg_rputasz16(unsigned char *end, int val) { +	if (val <= 15) { msg_rputasz4(end, val); return 1; } +	doput16(end - 3, 0xDC, val);  	return 3;  } -int msg_putasz(unsigned char *out, unsigned int sz) { -	if (sz < 65536) return msg_putasz16(out, sz); -	out[0] = 0xDD; -	doput32(out, sz); +int msg_putasz(unsigned char *out, unsigned int val) { +	if (val <= 65535) return msg_putasz16(out, val); +	doput32(out, 0xDD, val);  	return 5;  } -void msg_putmsz4(unsigned char *out, int sz) { -	*out = 0x80 | sz; +int msg_rputasz(unsigned char *end, unsigned int val) { +	if (val <= 65535) return msg_rputasz16(end, val); +	doput32(end - 5, 0xDD, val); +	return 5; +} + +int msg_putmsz16(unsigned char *out, int val) { +	if (val <= 15) { msg_putmsz4(out, val); return 1; } +	doput16(out, 0xDE, val); +	return 3;  } -int msg_putmsz16(unsigned char *out, int sz) { -	if (sz < 16) { msg_putmsz4(out, sz); return 1; } -	out[0] = 0xDE; -	doput16(out, sz); +int msg_rputmsz16(unsigned char *end, int val) { +	if (val <= 15) { msg_rputmsz4(end, val); return 1; } +	doput16(end - 3, 0xDE, val);  	return 3;  } -int msg_putmsz(unsigned char *out, unsigned int sz) { -	if (sz < 65536) return msg_putmsz16(out, sz); -	out[0] = 0xDF; -	doput32(out, sz); +int msg_putmsz(unsigned char *out, unsigned int val) { +	if (val <= 65535) return msg_putmsz16(out, val); +	doput32(out, 0xDF, val); +	return 5; +} + +int msg_rputmsz(unsigned char *end, unsigned int val) { +	if (val <= 65535) return msg_rputmsz16(end, val); +	doput32(end - 5, 0xDF, val);  	return 5;  } diff --git a/src/chunklets/msg.h b/src/chunklets/msg.h index c40bdbe..17a097d 100644 --- a/src/chunklets/msg.h +++ b/src/chunklets/msg.h @@ -1,5 +1,5 @@  /* - * Copyright © 2023 Michael Smith <mikesmiffy128@gmail.com> + * Copyright © 2025 Michael Smith <mikesmiffy128@gmail.com>   *   * Permission to use, copy, modify, and/or distribute this software for any   * purpose with or without fee is hereby granted, provided that the above @@ -25,36 +25,86 @@ extern "C" {  #endif  /* - * Writes a nil (null) message to the buffer out. Always writes a single byte. + * Writes a nil (null) message to the buffer `out`. + * + * `out` must point to at least 1 byte of space. + * + * Always writes a single byte. + */ +static inline void msg_putnil(unsigned char *out) { +	*out = 0xC0; +} + +/* + * Writes a nil (null) message immediately before the pointer `end`. + * + * `end` must point immediately beyond at least 1 byte of space. + * + * Always writes a single byte.   * - * out must point to at least 1 byte.   */ -void msg_putnil(unsigned char *out); +static inline void msg_rputnil(unsigned char *end) { +	end[-1] = 0xC0; +} + +/* + * Writes the boolean `val` to the buffer `out`. + * + * `out` must point to at least 1 byte of space. + * + * Always writes a single byte. + */ +static inline void msg_putbool(unsigned char *out, _msg_Bool val) { +	*out = 0xC2 | val; +}  /* - * Writes the boolean val to the buffer out. Always writes a single byte. + * Writes the boolean `val` immediately before the pointer `end`. + * + * `end` must point immediately beyond at least 1 byte of space.   * - * out must point to at least 1 byte. + * Always writes a single byte.   */ -void msg_putbool(unsigned char *out, _msg_Bool val); +static inline void msg_rputbool(unsigned char *end, _msg_Bool val) { +	end[-1] = 0xC2 | val; +}  /* - * Writes the integer val in the range [-32, 127] to the buffer out. Values - * outside this range will produce an undefined encoding. Always writes a single - * byte. + * Writes the integer `val` in the range [-32, 127] to the buffer `out`. Values + * outside this range will produce an undefined encoding. + * + * `out` must point to at least 1 byte of space.   * - * out must point to at least 1 byte. + * Always writes a single byte.   *   * It is recommended to use msg_puts() for arbitrary signed values or msg_putu()   * for arbitrary unsigned values. Those functions will produce the smallest   * possible encoding for any value.   */ -void msg_puti7(unsigned char *out, signed char val); +static inline void msg_puti7(unsigned char *out, signed char val) { +	*out = val; // a fixnum is just the literal byte! genius! +} + +/* + * Writes the integer `val` in the range [-32, 127] immediately before the + * pointer `end`. Values outside this range will produce an undefined encoding. + * + * `end` must point immediately beyond at least 1 byte of space. + * + * Always writes a single byte. + * + * It is recommended to use msg_rputs() for arbitrary signed values or + * msg_rputu() for arbitrary unsigned values. Those functions will produce the + * smallest possible encoding for any value. + */ +static inline void msg_rputi7(unsigned char *end, signed char val) { +	end[-1] = val; +}  /* - * Writes the signed int val in the range [-128, 127] to the buffer out. + * Writes the signed int `val` in the range [-128, 127] to the buffer `out`.   * - * out must point to at least 2 bytes. + * `out` must point to at least 2 bytes of space.   *   * Returns the number of bytes written, one of {1, 2}.   * @@ -64,9 +114,22 @@ void msg_puti7(unsigned char *out, signed char val);  int msg_puts8(unsigned char *out, signed char val);  /* - * Writes the unsigned int val in the range [0, 255] to the buffer out. + * Writes the signed int `val` in the range [-128, 127] immediately before the + * pointer `end`. + * + * `end` must point immediately beyond at least 2 bytes of space. + * + * Returns the number of bytes written, one of {1, 2}. + * + * It is recommended to use msg_rputs() for arbitrary signed values. That + * function will produce the smallest possible encoding for any value. + */ +int msg_rputs8(unsigned char *end, signed char val); + +/* + * Writes the unsigned int `val` in the range [0, 255] to the buffer `out`.   * - * out must point to at least 2 bytes. + * `out` must point to at least 2 bytes of space.   *   * Returns the number of bytes written, one of {1, 2}.   * @@ -76,9 +139,22 @@ int msg_puts8(unsigned char *out, signed char val);  int msg_putu8(unsigned char *out, unsigned char val);  /* - * Writes the signed int val in the range [-65536, 65535] to the buffer out. + * Writes the unsigned int `val` in the range [0, 255] immediately before the + * pointer `end`. + * + * `end` must point immediately beyond at least 2 bytes of space. + * + * Returns the number of bytes written, one of {1, 2}. + * + * It is recommended to use msg_rputu() for arbitrary unsigned values. That + * function will produce the smallest possible encoding for any value. + */ +int msg_rputu8(unsigned char *end, unsigned char val); + +/* + * Writes the signed int `val` in the range [-32768, 32767] to the buffer `out`.   * - * out must point to at least 3 bytes. + * `out` must point to at least 3 bytes of space.   *   * Returns the number of bytes written, one of {1, 2, 3}.   * @@ -88,9 +164,22 @@ int msg_putu8(unsigned char *out, unsigned char val);  int msg_puts16(unsigned char *out, short val);  /* - * Writes the unsigned int val in the range [0, 65536] to the buffer out. + * Writes the signed int `val` in the range [-32768, 32767] immediately before + * the pointer `end`. + * + * `end` must point immediately beyond at least 3 bytes of space. + * + * Returns the number of bytes written, one of {1, 2, 3}. + * + * It is recommended to use msg_rputs() for arbitrary signed values. That + * function will produce the smallest possible encoding for any value. + */ +int mmsg_rputs16(unsigned char *end, short val); + +/* + * Writes the unsigned int `val` in the range [0, 65536] to the buffer `out`.   * - * out must point to at least 3 bytes. + * `out` must point to at least 3 bytes of space.   *   * Returns the number of bytes written, one of {1, 2, 3}.   * @@ -100,10 +189,23 @@ int msg_puts16(unsigned char *out, short val);  int msg_putu16(unsigned char *out, unsigned short val);  /* - * Writes the signed int val in the range [-2147483648, 2147483647] to the - * buffer out. + * Writes the signed int `val` in the range [0, 65536] immediately before the + * pointer `end`. + * + * `end` must point immediately beyond at least 3 bytes of space. + * + * Returns the number of bytes written, one of {1, 2}. + * + * It is recommended to use msg_rputu() for arbitrary unsigned values. That + * function will produce the smallest possible encoding for any value. + */ +int msg_rputu16(unsigned char *end, unsigned short val); + +/* + * Writes the signed int `val` in the range [-2147483648, 2147483647] to the + * buffer `out`.   * - * out must point to at least 5 bytes. + * `out` must point to at least 5 bytes of space.   *   * Returns the number of bytes written, one of {1, 2, 3, 5}.   * @@ -113,9 +215,23 @@ int msg_putu16(unsigned char *out, unsigned short val);  int msg_puts32(unsigned char *out, int val);  /* - * Writes the unsigned int val in the range [0, 4294967295] to the buffer out. + * Writes the signed int `val` in the range [-2147483648, 2147483647] + * immediately before the pointer `end`.   * - * out must point to at least 5 bytes. + * `end` must point immediately beyond at least least 5 bytes of space. + * + * Returns the number of bytes written, one of {1, 2, 3, 5}. + * + * It is recommended to use msg_rputs() for arbitrary signed values. That + * function will produce the smallest possible encoding for any value. + */ +int msg_rputs32(unsigned char *end, int val); + +/* + * Writes the unsigned int `val` in the range [0, 4294967295] to the buffer + * `out`. + * + * `out` must point to at least 5 bytes of space.   *   * Returns the number of bytes written, one of {1, 2, 3, 5}.   * @@ -125,64 +241,145 @@ int msg_puts32(unsigned char *out, int val);  int msg_putu32(unsigned char *out, unsigned int val);  /* - * Writes the signed int val in the range [-9223372036854775808, - * 9223372036854775807] to the buffer out. + * Writes the unsigned int `val` in the range [0, 4294967295] immediately before + * the pointer `end`. + * + * `end` must point immediately beyond at least 5 bytes of space. + * + * Returns the number of bytes written, one of {1, 2, 3, 5}. + * + * It is recommended to use msg_rputu() for arbitrary unsigned values. That + * function will produce the smallest possible encoding for any value. + */ +int msg_rputu32(unsigned char *end, unsigned int val); + +/* + * Writes the signed int `val` in the range [-9223372036854775808, + * 9223372036854775807] to the buffer `out`.   * - * out must point to at least 9 bytes. + * `out` must point to at least 9 bytes of space.   *   * Returns the number of bytes written, one of {1, 2, 3, 5, 9}.   */  int msg_puts(unsigned char *out, long long val);  /* - * Writes the unsigned int val in the range [0, 18446744073709551616] to the - * buffer out. + * Writes the signed int `val` in the range [-9223372036854775808, + * 9223372036854775807] immediately before the pointer `end`. + * + * `end` must point immediately beyond at least 9 bytes of space. + * + * Returns the number of bytes written, one of {1, 2, 3, 5, 9}. + */ +int msg_rputs(unsigned char *end, long long val); + +/* + * Writes the unsigned int `val` in the range [0, 18446744073709551616] to the + * buffer `out`.   * - * out must point to at least 9 bytes. + * `out` must point to at least 9 bytes of space.   *   * Returns the number of bytes written, one of {1, 2, 3, 5, 9}.   */  int msg_putu(unsigned char *out, unsigned long long val);  /* - * Writes the IEEE 754 single-precision float val to the buffer out. Always - * writes 5 bytes. + * Writes the unsigned int `val` in the range [0, 18446744073709551616] + * immediately before the pointer `end`.   * - * out must point to at least 5 bytes. + * `end` must point immediately beyond at least 9 bytes of space. + * + * Returns the number of bytes written, one of {1, 2, 3, 5, 9}. + */ +int msg_rputu(unsigned char *end, unsigned long long val); + +/* + * Writes the IEEE 754 single-precision float `val` to the buffer `out`. + * + * `out` must point to at least 5 bytes of space. + * + * Always writes 5 bytes.   */  void msg_putf(unsigned char *out, float val);  /* - * Writes the IEEE 754 double-precision float val to the buffer out. + * Writes the IEEE 754 single-precision float `val` immediately before the pointer + * `end`. + * + * `end` must point immediately beyond at least 5 bytes of space. + * + * Always writes 5 bytes. + */ +static inline void msg_rputf(unsigned char *end, float val) { +	msg_putf(end - 5, val); +} + +/* + * Writes the IEEE 754 double-precision float `val` to the buffer `out`, or writes + * a single-precision float if the exact value is the same.   * - * out must point to at least 9 bytes. + * `out` must point to at least 9 bytes of space.   *   * Returns the number of bytes written, one of {5, 9}.   */  int msg_putd(unsigned char *out, double val);  /* - * Writes the string size sz in the range [0, 31] to the buffer out. Values - * outside this range will produce an undefined encoding. Always writes a single - * byte. + * Writes the IEEE 754 double-precision float `val` immediately before the pointer + * `end`, or writes a single-precision float if the exact value is the same. + * + * `end` must point immediately beyond at least 9 bytes of space. + * + * Returns the number of bytes written, one of {5, 9}. + */ +int msg_rputd(unsigned char *end, double val); + +/* + * Writes the string size `sz` in the range [0, 31] to the buffer `out`. Values + * outside this range will produce an undefined encoding. + * + * `out` must point to at least 1 byte of space. + * + * Always writes a single byte.   *   * In a complete message stream, a size of N must be immediately followed by N   * bytes of the actual string, which must be valid UTF-8.   * - * out must point to at least 1 byte. - *   * It is recommended to use msg_putssz() for arbitrary string sizes. That   * function will produce the smallest possible encoding for any size value.   */ -void msg_putssz5(unsigned char *out, int sz); +static inline void msg_putssz5(unsigned char *out, int sz) { +	*out = 0xA0 | sz; +}  /* - * Writes the string size sz in the range [0, 255] to the buffer out. + * Writes the string size `sz` in the range [0, 31] immediately before the pointer + * `end`. Values outside this range will produce an undefined encoding. + * + * `end` must point immediately beyond at least 1 byte of space. + * + * Always writes a single byte.   *   * In a complete message stream, a size of N must be immediately followed by N   * bytes of the actual string, which must be valid UTF-8.   * - * out must point to at least 2 bytes. + * It is recommended to use msg_rputssz() for arbitrary string sizes. That + * function will produce the smallest possible encoding for any size value. + */ +static inline void msg_rputssz5(unsigned char *end, int sz) { +	msg_putssz5(end - 1, sz); +} + +/* + * Writes the string size `sz` in the range [0, 255] to the buffer `out`. Values + * outside this range will produce an undefined encoding. + * + * `out` must point to at least 2 bytes of space. + * + * Returns the number of bytes written, one of {1, 2}. + * + * In a complete message stream, a size of N must be immediately followed by N + * bytes of the actual string, which must be valid UTF-8.   *   * It is recommended to use msg_putssz() for arbitrary string sizes. That   * function will produce the smallest possible encoding for any size value. @@ -190,12 +387,31 @@ void msg_putssz5(unsigned char *out, int sz);  int msg_putssz8(unsigned char *out, int sz);  /* - * Writes the string size sz in the range [0, 65535] to the buffer out. + * Writes the string size `sz` in the range [0, 255] immediately before the + * pointer `end`. Values outside this range will produce an undefined encoding. + * + * `end` must point immediately beyond at least 2 byte of space. + * + * Returns the number of bytes written, one of {1, 2}.   *   * In a complete message stream, a size of N must be immediately followed by N   * bytes of the actual string, which must be valid UTF-8.   * - * out must point to at least 3 bytes. + * It is recommended to use msg_rputssz() for arbitrary string sizes. That + * function will produce the smallest possible encoding for any size value. + */ +int msg_rputssz8(unsigned char *end, int sz); + +/* + * Writes the string size `sz` in the range [0, 65535] to the buffer `out`. Values + * outside this range will produce an undefined encoding. + * + * `out` must point to at least 3 bytes of space. + * + * Returns the number of bytes written, one of {1, 2, 3}. + * + * In a complete message stream, a size of N must be immediately followed by N + * bytes of the actual string, which must be valid UTF-8.   *   * It is recommended to use msg_putssz() for arbitrary string sizes. That   * function will produce the smallest possible encoding for any size value. @@ -203,38 +419,92 @@ int msg_putssz8(unsigned char *out, int sz);  int msg_putssz16(unsigned char *out, int sz);  /* - * Writes the string size sz in the range [0, 4294967295] to the buffer out. + * Writes the string size `sz` in the range [0, 65535] immediately before the + * pointer `end`. Values outside this range will produce an undefined encoding. + * + * `end` must point immediately beyond at least 3 bytes of space. + * + * Returns the number of bytes written, one of {1, 2, 3}.   *   * In a complete message stream, a size of N must be immediately followed by N   * bytes of the actual string, which must be valid UTF-8.   * - * out must point to at least 5 bytes. + * It is recommended to use msg_rputssz() for arbitrary string sizes. That + * function will produce the smallest possible encoding for any size value. + */ +int msg_rputssz16(unsigned char *end, int sz); + +/* + * Writes the string size `sz` in the range [0, 4294967295] to the buffer `out`. + * + * `out` must point to at least 5 bytes of space. + * + * Returns the number of bytes written, one of {1, 2, 3, 5}. + * + * In a complete message stream, a size of N must be immediately followed by N + * bytes of the actual string, which must be valid UTF-8.   */  int msg_putssz(unsigned char *out, unsigned int sz);  /* - * Writes the binary blob size sz in the range [0, 255] to the buffer out. + * Writes the string size `sz` in the range [0, 4294967295] immediately before + * the pointer `end`. + * + * `end` must point immediately beyond at least 5 bytes of space. + * + * Returns the number of bytes written, one of {1, 2, 3, 5}. + * + * In a complete message stream, a size of N must be immediately followed by N + * bytes of the actual string, which must be valid UTF-8. + */ +int msg_rputssz(unsigned char *end, unsigned int sz); + +/* + * Writes the binary blob size `sz` in the range [0, 255] to the buffer `out`. + * Values outside this range will produce an undefined encoding. + * + * `out` must point to at least 2 bytes of space. + *   * Always writes 2 bytes.   *   * In a complete message stream, a size of N must be immediately followed by   * N bytes of the actual data.   * - * out must point to at least 2 bytes. - *   * It is recommended to use msg_putbsz() for arbitrary binary blob sizes. That   * function will produce the smallest possible encoding for any size value.   */ -void msg_putbsz8(unsigned char *out, int sz); +static inline void msg_putbsz8(unsigned char *out, int sz) { +	out[0] = 0xC4; out[1] = sz; +}  /* - * Writes the binary blob size sz in the range [0, 65535] to the buffer out. + * Writes the binary blob size `sz` in the range [0, 255] immediately before the + * pointer `end`. Values outside this range will produce an undefined encoding. + * + * `end` must point immediately beyond at least 2 bytes of space. + * + * Always writes 2 bytes.   *   * In a complete message stream, a size of N must be immediately followed by   * N bytes of the actual data.   * - * out must point to at least 3 bytes. + * It is recommended to use msg_rputbsz() for arbitrary binary blob sizes. That + * function will produce the smallest possible encoding for any size value. + */ +static inline void msg_rputbsz8(unsigned char *end, int sz) { +	end[-2] = 0xC4; end[-1] = sz; +} + +/* + * Writes the binary blob size `sz` in the range [0, 65535] to the buffer `out`. + * Values outside this range will produce an undefined encoding.   * - * Returns the number of bytes written, one of {1, 2, 3}. + * `out` must point to at least 3 bytes of space. + * + * Returns the number of bytes written, one of {2, 3}. + * + * In a complete message stream, a size of N must be immediately followed by + * N bytes of the actual data.   *   * It is recommended to use msg_putbsz() for arbitrary binary blob sizes. That   * function will produce the smallest possible encoding for any size value. @@ -242,104 +512,238 @@ void msg_putbsz8(unsigned char *out, int sz);  int msg_putbsz16(unsigned char *out, int sz);  /* - * Writes the binary blob size sz in the range [0, 4294967295] to the buffer out. + * Writes the binary blob size `sz` in the range [0, 65535] immediately before + * the pointer `end`. Values outside this range will produce an undefined + * encoding. + * + * `end` must point immediately beyond at least 3 bytes of space. + * + * Returns the number of bytes written, one of {2, 3}.   *   * In a complete message stream, a size of N must be immediately followed by   * N bytes of the actual data.   * - * out must point to at least 5 bytes. + * It is recommended to use msg_rputbsz() for arbitrary binary blob sizes. That + * function will produce the smallest possible encoding for any size value. + */ +int msg_rputbsz16(unsigned char *end, int sz); + +/* + * Writes the binary blob size `sz` in the range [0, 4294967295] to the buffer + * `out`.   * - * Returns the number of bytes written, one of {1, 2, 3, 5}. + * `out` must point to at least 5 bytes of space. + * + * Returns the number of bytes written, one of {2, 3, 5}. + * + * In a complete message stream, a size of N must be immediately followed by + * N bytes of the actual data.   */  int msg_putbsz(unsigned char *out, unsigned int sz);  /* - * Writes the array size sz in the range [0, 15] to the buffer out. Values - * outside this range will produce an undefined encoding. Always writes a single - * byte. + * Writes the binary blob size `sz` in the range [0, 4294967295] immediately + * before the pointer `end`. + * + * `end` must point immediately beyond at least 5 bytes of space. + * + * Returns the number of bytes written, one of {2, 3, 5}. + * + * In a complete message stream, a size of N must be immediately followed by + * N bytes of the actual data. + */ +int msg_rputbsz(unsigned char *end, unsigned int sz); + +/* + * Writes the array size `sz` in the range [0, 15] to the buffer `out`. Values + * outside this range will produce an undefined encoding. + * + * `out` must point to at least 1 byte of space. + * + * Always writes a single byte.   *   * In a complete message stream, a size of N must be immediately followed by N   * other messages, which form the contents of the array.   * - * out must point to at least 1 byte. - *   * It is recommended to use msg_putasz() for arbitrary array sizes. That   * function will produce the smallest possible encoding for any size value.   */ -void msg_putasz4(unsigned char *out, int sz); +static inline void msg_putasz4(unsigned char *out, int sz) { +	*out = 0x90 | sz; +}  /* - * Writes the array size sz in the range [0, 65535] to the buffer out. + * Writes the array size `sz` in the range [0, 15] immediately before the + * pointer `end`. Values outside this range will produce an undefined encoding. + * + * `end` must point immediately beyond at least 1 byte of space. + * + * Always writes a single byte.   *   * In a complete message stream, a size of N must be immediately followed by N   * other messages, which form the contents of the array.   * - * out must point to at least 3 bytes. + * It is recommended to use msg_rputasz() for arbitrary array sizes. That + * function will produce the smallest possible encoding for any size value. + */ +static inline void msg_rputasz4(unsigned char *end, int sz) { +	end[-1] = 0x90 | sz; +} + +/* + * Writes the array size `sz` in the range [0, 65535] to the buffer `out`. + * Values outside this range will produce an undefined encoding. + * + * `out` must point to at least 3 bytes of space.   *   * Returns the number of bytes written, one of {1, 3}.   * + * In a complete message stream, a size of N must be immediately followed by N + * other messages, which form the contents of the array. + *   * It is recommended to use msg_putasz() for arbitrary array sizes. That   * function will produce the smallest possible encoding for any size value.   */  int msg_putasz16(unsigned char *out, int sz);  /* - * Writes the array size sz in the range [0, 4294967295] to the buffer out. + * Writes the array size `sz` in the range [0, 65535] immediately before the + * pointer `end`. + * + * `end` must point immediately beyond at least 3 bytes of space. + * + * Returns the number of bytes written, one of {1, 3}.   *   * In a complete message stream, a size of N must be immediately followed by N   * other messages, which form the contents of the array.   * - * out must point to at least 5 bytes. + * It is recommended to use msg_rputasz() for arbitrary array sizes. That + * function will produce the smallest possible encoding for any size value. + */ +int msg_rputasz16(unsigned char *end, int sz); + +/* + * Writes the array size `sz` in the range [0, 4294967295] to the buffer `out`. + * + * `out` must point to at least 5 bytes of space.   *   * Returns the number of bytes written, one of {1, 3, 5}. + * + * In a complete message stream, a size of N must be immediately followed by N + * other messages, which form the contents of the array.   */  int msg_putasz(unsigned char *out, unsigned int sz);  /* - * Writes the map size sz in the range [0, 15] to the buffer out. Values - * outside this range will produce an undefined encoding. Always writes a single - * byte. + * Writes the array size `sz` in the range [0, 4294967295] immediately before + * the pointer `end`.   * - * In a complete message stream, a size of N must be immediately followed by - * N * 2 other messages, which form the contents of the map as keys followed by - * values in alternation. + * `end` must point immediately beyond at least 5 bytes of space. + * + * Returns the number of bytes written, one of {1, 3, 5}. + * + * In a complete message stream, a size of N must be immediately followed by N + * other messages, which form the contents of the array. + */ +int msg_rputasz(unsigned char *end, unsigned int sz); + +/* + * Writes the map size `sz` in the range [0, 15] to the buffer `out`. Values + * outside this range will produce an undefined encoding. + * `out` must point to at least 1 byte of space.   * - * out must point to at least 1 byte. + * Always writes a single byte. + * + * In a complete message stream, a size of N must be immediately followed by + * N other pairs of messages, each containing a key followed by a value, making + * up the contents of the map.   *   * It is recommended to use msg_putmsz() for arbitrary map sizes. That function   * will produce the smallest possible encoding for any size value.   */ -void msg_putmsz4(unsigned char *out, int sz); +static inline void msg_putmsz4(unsigned char *out, int sz) { +	*out = 0x80 | sz; +}  /* - * Writes the array size sz in the range [0, 65536] to the buffer out. + * Writes the map size `sz` in the range [0, 15] immediately before the pointer + * `end`. Values outside this range will produce an undefined encoding. + * + * `end` must point immediately at least 1 byte of space. + * + * Always writes a single byte.   *   * In a complete message stream, a size of N must be immediately followed by - * N * 2 other messages, which form the contents of the map as keys followed by - * values in alternation. + * N other pairs of messages, each containing a key followed by a value, making + * up the contents of the map. + * + * It is recommended to use msg_rputmsz() for arbitrary map sizes. That function + * will produce the smallest possible encoding for any size value. + */ +static inline void msg_rputmsz4(unsigned char *end, int sz) { +	end[-1] = 0x80 | sz; +} + +/* + * Writes the map size `sz` in the range [0, 65536] to the buffer `out`.   * - * out must point to at least 3 bytes. + * `out` must point to at least 3 bytes of space.   *   * Returns the number of bytes written, one of {1, 3}.   * + * In a complete message stream, a size of N must be immediately followed by + * N * 2 other messages, which form the contents of the map as alternating + * pairs, each containing one key followed by one value. + *   * It is recommended to use msg_putmsz() for arbitrary map sizes. That function   * will produce the smallest possible encoding for any size value.   */  int msg_putmsz16(unsigned char *out, int sz);  /* - * Writes the array size sz in the range [0, 4294967295] to the buffer out. + * Writes the map size `sz` in the range [0, 65536] immediately before the + * pointer `end`. Values outside this range will produce an undefined encoding. + * + * `end` must point immediately beyond least 3 bytes of space. + * + * Returns the number of bytes written, one of {1, 3}.   *   * In a complete message stream, a size of N must be immediately followed by - * N * 2 other messages, which form the contents of the map as keys followed by - * values in alternation. + * N other pairs of messages, each containing a key followed by a value, making + * up the contents of the map.   * - * out must point to at least 5 bytes. + * It is recommended to use msg_rputmsz() for arbitrary map sizes. That function + * will produce the smallest possible encoding for any size value. + */ +int msg_rputmsz16(unsigned char *end, int sz); + +/* + * Writes the map size `sz` in the range [0, 4294967295] to the buffer `out`. + * + * `out` must point to at least 5 bytes of space.   *   * Returns the number of bytes written, one of {1, 3, 5}. + * + * In a complete message stream, a size of N must be immediately followed by + * N other pairs of messages, each containing a key followed by a value, making + * up the contents of the map.   */  int msg_putmsz(unsigned char *out, unsigned int sz); +/* + * Writes the map size `sz` in the range [0, 4294967295] immediately before the  + * pointer `end`. + * + * `end` must point immediately beyond at least 5 bytes of space. + * + * Returns the number of bytes written, one of {1, 3, 5}. + * + * In a complete message stream, a size of N must be immediately followed by + * N other pairs of messages, each containing a key followed by a value, making + * up the contents of the map. + */ +int msg_putmszr(unsigned char *end, unsigned int sz); +  #ifdef __cplusplus  }  #endif  | 
