double f; /* floating point */
struct { unsigned char *p; size_t sz; } bytes; /* binary string of bytes */
struct { char *p; size_t sz; } text; /* text string */
+ struct { /* buffer */
+ unsigned char *p; size_t sz; /* binary string */
+ size_t a, m; /* residue and modulus */
+ size_t off; /* offset into full buffer */
+ } buf;
#ifdef TVEC_REGSLOTS
TVEC_REGSLOTS
#endif
TVBU_BYTE, /* counting bytes (@rbuf >= 0@) */
TVBU_LIMIT /* (number of units) */
};
-struct bench_timing; /* forward declaration */
+struct bench_timing; /* include <mLib/bench.h> for the real definition */
struct tvec_outops {
/* Output operations. */
*
* Arguments: @struct tvec_state *tv@ = test-vector state
* @dstr *d@ = string to append the word to
+ * @const char **p_inout@ = pointer into string, updated
* @const char *delims@ = additional delimiters to stop at
* @const char *expect@, @va_list ap@ = what was expected
*
* word constituents, a null terminator is written to @d@, and
* it is safe to treat the string in @d@ as being null-
* terminated.
+ *
+ * If @p_inout@ is not null, then @*p_inout@ must be a pointer
+ * into @d->buf@, which will be adjusted so that it will
+ * continue to point at the same position even if the buffer is
+ * reallocated. As a subtle tweak, if @*p_inout@ initially
+ * points at the end of the buffer, then it will be adjusted to
+ * point at the beginning of the next word, rather than at the
+ * additional intervening space.
*/
-extern PRINTF_LIKE(4, 5)
+extern PRINTF_LIKE(5, 6)
int tvec_readword(struct tvec_state */*tv*/, dstr */*d*/,
- const char */*delims*/, const char */*expect*/, ...);
+ const char **/*p_inout*/, const char */*delims*/,
+ const char */*expect*/, ...);
extern int tvec_readword_v(struct tvec_state */*tv*/, dstr */*d*/,
- const char */*delims*/, const char */*expect*/,
- va_list */*ap*/);
+ const char **/*p_inout*/, const char */*delims*/,
+ const char */*expect*/, va_list */*ap*/);
/*----- Integer types: signed and unsigned --------------------------------*/
/*----- Buffer type -------------------------------------------------------*/
/* Buffer registers are primarily used for benchmarking. Only a buffer's
- * size is significant: its contents are ignored on comparison and output,
- * and unspecified on input.
+ * allocation parameters are significant: its contents are ignored on
+ * comparison and output, and unspecified on input.
+ *
+ * The input format gives the buffer's size, and an optional alignment
+ * specification, in the form %|SZ [`@' M [`+' A]]|%. Each of %|SZ|%, %|M|%
+ * and %|A|% are sizes, as an integer, optionally suffixed with a unit `kB',
+ * `MB', `GB', `TB', `PB', `EB', `ZB', `YB' (with or without the `B')
+ * denoting a power of 1024. The %|SZ|% gives the (effective) buffer size.
+ * %|M|% is the `alignment quantum' and %|A|% is the `alignment offset'; both
+ * default to zero, but if %|M|% is nonzero then the start of the buffer is
+ * aligned such that it is %|A|% more than a multiple of %|M|% bytes. Note
+ * that %|M|% need not be a power of two, though this is common.
*
- * The input is simply the buffer size, as an integer, optionally suffixed
- * with a unit `kB', `MB', `GB', `TB', `PB', `EB', `ZB', `YB' (with or
- * without the `B') denoting a power of 1024. Units are used on output only
- * when the size would be expressed exactly.
+ * Units other than `B' are used on output only when the size would be
+ * expressed exactly.
+ *
+ * Buffers are %%\emph{not}%% allocated by default. In benchmarks, this is
+ * best done in a @before@ function.
*
* No @claimeq@ functions or macros are provided for buffers because they
* don't seem very useful.
extern const struct tvec_regty tvty_buffer;
+/* --- @tvec_initbuffer@ --- *
+ *
+ * Arguments: @union tvec_regval *rv@ = register value
+ * @const union tvec_regval *src@ = source buffer
+ * @size_t sz@ = size to allocate
+ *
+ * Returns: ---
+ *
+ * Use: Initialize the alignment parameters in @rv@ to match @src@,
+ * and the size to @sz@.
+ */
+
+extern void tvec_initbuffer(union tvec_regval */*rv*/,
+ const union tvec_regval */*src*/, size_t /*sz*/);
+
+/* --- @tvec_allocbuffer@ --- *
+ *
+ * Arguments: @union tvec_regval *rv@ = register value
+ *
+ * Returns: ---
+ *
+ * Use: Allocate @sz@ bytes to the buffer and fill the space with a
+ * distinctive pattern.
+ */
+
+extern void tvec_allocbuffer(union tvec_regval */*rv*/);
+
/*----- That's all, folks -------------------------------------------------*/
#ifdef __cplusplus