decoding - read data from the next available byte or bytes.
* Explicitly move the "next byte" pointer either ahead by a number of bytes, to the start, or to the end.
* Ask how the dbuff how many bytes are remaining or have been used.
-
+
When encoding, data can either be one or more bytes or a signed or
unsigned 8, 16, 32, or 64 bit integer. There is also a `memset()`
function for initialising uninitialised areas of the buffer. As
A child dbuff operates on a portion of the buffer, starting where the
parent left off. The creator can control two things about the child:
-* The space available to the child. There are two ways to specify this:
-** Give the child no more than a specified number of bytes (`FR_DBUFF_MAX()`).
-** Insist that the child only be given enough bytes that the parent has a certain number (`FR_DBUFF_RESERVE()`).
+* The space available to the child (`FR_DBUFF_MAX()` gives a child
+ dbuff with no more than a specified number of bytes available).
* Whether the child's advances propagate up to its parents
(`FR_DBUFF_NO_ADVANCE()` gives a child dbuff whose advances don't
- propagate, and `FR_DBUFF_RESERVE_NO_ADVANCE()` lets you reserve and
- prevent propagation).
-
-[IMPORTANT]
-====
-`FR_DBUFF_MAX()` cannott fail, It is like an ad promising "up to one
-million dollars!" where "up to" includes zero. `FR_DBUFF_RESERVE()`,
-though, can fail in a sense, because you're promising the parent at
-least a certain number of bytes. Underneath they're both C compound
-literals, so it's not clear how to indicate an error.
+ propagate).
+
+[IMPORTANT]
====
-
+`FR_DBUFF_MAX()` cannot fail. It is like an ad promising "up to one
+million dollars!" where "up to" includes zero, so the child may have
+less space than the specified maximum.
+====
+
`FR_DBUFF_MAX()` typically shows up when a caller limits a callee to
what will fit in a TLV in some context. `FR_DBUFF_NO_ADVANCE()` came
into existence to let an encoding function write a header and then
ssize_t encode_foo(fr_dbuff_t *dbuff, ...)
{
fr_dbuff_t work_dbuff = FR_DBUFF_NO_ADVANCE(dbuff);
-
+
/* encode, operating on work_dbuff, returning on error */
-
+
return fr_dbuff_advance(dbuff, fr_dbuff_used(&work_dbuff));
}
----
[source,c]
----
f ((val = fr_dbuff_foo(dbuff, ...) < 0) return val;
-----
-
+----
+
letting one return an error to the caller without cluttering the code.
/** @cond */
-/** Reserve _reserve bytes in the dbuff when passing it to another function
+/** Limit available bytes in the dbufft to _max when passing it to another function
*
* @private
*/
-#define _FR_DBUFF_RESERVE(_dbuff, _reserve, _adv_parent) \
+#define _FR_DBUFF_MAX(_dbuff, _max, _adv_parent) \
(fr_dbuff_t){ \
.buff = (_dbuff)->buff, \
.start = (_dbuff)->p, \
- .end = ((_dbuff)->end - (_reserve)) >= ((_dbuff)->p) ? \
- (_dbuff)->end - (_reserve) : \
- (_dbuff)->p, \
+ .end = (((((_dbuff)->end) - (_max) < (_dbuff)->p)) ? (_dbuff)->end : ((_dbuff)->p + (_max))), \
.p = (_dbuff)->p, \
.is_const = (_dbuff)->is_const, \
.adv_parent = _adv_parent, \
}
/* @endcond */
-/** Reserve _reserve bytes in the dbuff when passing it to another function
- *
- @code{.c}
- my_child_encoder(&FR_DBUFF_RESERVE(dbuff, 5), vp);
- @endcode
- *
- * @note Do not use to re-initialise the contents of _dbuff, i.e. to
- * permanently shrink the exiting dbuff. The parent pointer will loop.
- *
- * @note Do not modify the "child" dbuff directly. Use the functions
- * supplied as part of this API.
- *
- * @param[in] _dbuff to reserve bytes in.
- * @param[in] _reserve The number of bytes to reserve.
- */
-#define FR_DBUFF_RESERVE(_dbuff, _reserve) _FR_DBUFF_RESERVE(_dbuff, _reserve, true)
-
-/** Reserve _reserve bytes in the dbuff when passing it to another function
- *
- @code{.c}
- fr_dbuff_t tlv = FR_DBUFF_RESERVE_NO_ADVANCE(dbuff, UINT8_MAX);
-
- if (my_child_encoder(&tlv, vp) < 0) return -1;
-
- return fr_dbuff_advance(dbuff, fr_dbuff_used(tlv));
- @endcode
- *
- * @note Do not use to re-initialise the contents of _dbuff, i.e. to
- * permanently shrink the exiting dbuff. The parent pointer will loop.
- *
- * @note Do not modify the "child" dbuff directly. Use the functions
- * supplied as part of this API.
- *
- * @param[in] _dbuff to reserve bytes in.
- * @param[in] _reserve The number of bytes to reserve.
- */
-#define FR_DBUFF_RESERVE_NO_ADVANCE(_dbuff, _reserve) _FR_DBUFF_RESERVE(_dbuff, _reserve, false)
-
/** Limit the maximum number of bytes available in the dbuff when passing it to another function
*
@code{.c}
* @param[in] _dbuff to reserve bytes in.
* @param[in] _max The maximum number of bytes the caller is allowed to write to.
*/
-#define FR_DBUFF_MAX(_dbuff, _max) \
- _FR_DBUFF_RESERVE(_dbuff, (fr_dbuff_remaining(_dbuff) > (_max)) ? (fr_dbuff_remaining(_dbuff) - (_max)) : 0, true)
+#define FR_DBUFF_MAX(_dbuff, _max) _FR_DBUFF_MAX(_dbuff, _max, true)
/** Limit the maximum number of bytes available in the dbuff when passing it to another function
*
* @param[in] _dbuff to reserve bytes in.
* @param[in] _max The maximum number of bytes the caller is allowed to write to.
*/
-#define FR_DBUFF_MAX_NO_ADVANCE(_dbuff, _max) \
- _FR_DBUFF_RESERVE(_dbuff, (fr_dbuff_remaining(_dbuff) > (_max)) ? (fr_dbuff_remaining(_dbuff) - (_max)) : 0, false)
+#define FR_DBUFF_MAX_NO_ADVANCE(_dbuff, _max) _FR_DBUFF_MAX(_dbuff, _max, false)
/** Does the actual work of initialising a dbuff
* @private