mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-30 08:07:59 +00:00
Merge patch series "membuff: Add tests and update to support a flag for empty/full"
Simon Glass <sjg@chromium.org> says: The membuff implementation curently has no tests. It also assumes that head and tail can never correspond unless the buffer is empty. This series provides a compile-time flag to support a 'full' flag. It also adds some tests of the main routines. The data structure is also renamed to membuf which fits better with U-Boot. There may be some cases in the code which could be optimised a little, but the implementation is functional. Link: https://lore.kernel.org/r/20250318152059.1464369-1-sjg@chromium.org
This commit is contained in:
commit
1aa8b03c01
12 changed files with 366 additions and 114 deletions
|
@ -1281,6 +1281,13 @@ T: git git://github.com/ARM-software/u-boot.git
|
||||||
F: drivers/video/mali_dp.c
|
F: drivers/video/mali_dp.c
|
||||||
F: drivers/i2c/i2c-versatile.c
|
F: drivers/i2c/i2c-versatile.c
|
||||||
|
|
||||||
|
MEMBUF
|
||||||
|
M: Simon Glass <sjg@chromium.org>
|
||||||
|
S: Maintained
|
||||||
|
T: git https://source.denx.de/u-boot/u-boot.git
|
||||||
|
F: include/membuf.h
|
||||||
|
F: lib/membuf.c
|
||||||
|
|
||||||
MICROBLAZE
|
MICROBLAZE
|
||||||
M: Michal Simek <monstr@monstr.eu>
|
M: Michal Simek <monstr@monstr.eu>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
|
@ -44,7 +44,7 @@ void sandbox_serial_endisable(bool enabled);
|
||||||
* @buf: holds input characters available to be read by this driver
|
* @buf: holds input characters available to be read by this driver
|
||||||
*/
|
*/
|
||||||
struct sandbox_serial_priv {
|
struct sandbox_serial_priv {
|
||||||
struct membuff buf;
|
struct membuf buf;
|
||||||
char serial_buf[16];
|
char serial_buf[16];
|
||||||
bool start_of_line;
|
bool start_of_line;
|
||||||
};
|
};
|
||||||
|
|
|
@ -108,15 +108,15 @@ static int extlinux_check(struct udevice *dev, struct bootflow_iter *iter)
|
||||||
*/
|
*/
|
||||||
static int extlinux_fill_info(struct bootflow *bflow)
|
static int extlinux_fill_info(struct bootflow *bflow)
|
||||||
{
|
{
|
||||||
struct membuff mb;
|
struct membuf mb;
|
||||||
char line[200];
|
char line[200];
|
||||||
char *data;
|
char *data;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
log_debug("parsing bflow file size %x\n", bflow->size);
|
log_debug("parsing bflow file size %x\n", bflow->size);
|
||||||
membuff_init(&mb, bflow->buf, bflow->size);
|
membuf_init(&mb, bflow->buf, bflow->size);
|
||||||
membuff_putraw(&mb, bflow->size, true, &data);
|
membuf_putraw(&mb, bflow->size, true, &data);
|
||||||
while (len = membuff_readline(&mb, line, sizeof(line) - 1, ' ', true), len) {
|
while (len = membuf_readline(&mb, line, sizeof(line) - 1, ' ', true), len) {
|
||||||
char *tok, *p = line;
|
char *tok, *p = line;
|
||||||
|
|
||||||
tok = strsep(&p, " ");
|
tok = strsep(&p, " ");
|
||||||
|
|
|
@ -101,7 +101,7 @@ static void console_record_putc(const char c)
|
||||||
if (!(gd->flags & GD_FLG_RECORD))
|
if (!(gd->flags & GD_FLG_RECORD))
|
||||||
return;
|
return;
|
||||||
if (gd->console_out.start &&
|
if (gd->console_out.start &&
|
||||||
!membuff_putbyte((struct membuff *)&gd->console_out, c))
|
!membuf_putbyte((struct membuf *)&gd->console_out, c))
|
||||||
gd->flags |= GD_FLG_RECORD_OVF;
|
gd->flags |= GD_FLG_RECORD_OVF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ static void console_record_puts(const char *s)
|
||||||
if (gd->console_out.start) {
|
if (gd->console_out.start) {
|
||||||
int len = strlen(s);
|
int len = strlen(s);
|
||||||
|
|
||||||
if (membuff_put((struct membuff *)&gd->console_out, s, len) !=
|
if (membuf_put((struct membuf *)&gd->console_out, s, len) !=
|
||||||
len)
|
len)
|
||||||
gd->flags |= GD_FLG_RECORD_OVF;
|
gd->flags |= GD_FLG_RECORD_OVF;
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ static int console_record_getc(void)
|
||||||
if (!gd->console_in.start)
|
if (!gd->console_in.start)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return membuff_getbyte((struct membuff *)&gd->console_in);
|
return membuf_getbyte((struct membuf *)&gd->console_in);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int console_record_tstc(void)
|
static int console_record_tstc(void)
|
||||||
|
@ -133,7 +133,7 @@ static int console_record_tstc(void)
|
||||||
if (!(gd->flags & GD_FLG_RECORD))
|
if (!(gd->flags & GD_FLG_RECORD))
|
||||||
return 0;
|
return 0;
|
||||||
if (gd->console_in.start) {
|
if (gd->console_in.start) {
|
||||||
if (membuff_peekbyte((struct membuff *)&gd->console_in) != -1)
|
if (membuf_peekbyte((struct membuf *)&gd->console_in) != -1)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -810,14 +810,14 @@ int console_record_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = membuff_new((struct membuff *)&gd->console_out,
|
ret = membuf_new((struct membuf *)&gd->console_out,
|
||||||
gd->flags & GD_FLG_RELOC ?
|
gd->flags & GD_FLG_RELOC ?
|
||||||
CONFIG_CONSOLE_RECORD_OUT_SIZE :
|
CONFIG_CONSOLE_RECORD_OUT_SIZE :
|
||||||
CONFIG_CONSOLE_RECORD_OUT_SIZE_F);
|
CONFIG_CONSOLE_RECORD_OUT_SIZE_F);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
ret = membuff_new((struct membuff *)&gd->console_in,
|
ret = membuf_new((struct membuf *)&gd->console_in,
|
||||||
CONFIG_CONSOLE_RECORD_IN_SIZE);
|
CONFIG_CONSOLE_RECORD_IN_SIZE);
|
||||||
|
|
||||||
/* Start recording from the beginning */
|
/* Start recording from the beginning */
|
||||||
gd->flags |= GD_FLG_RECORD;
|
gd->flags |= GD_FLG_RECORD;
|
||||||
|
@ -827,8 +827,8 @@ int console_record_init(void)
|
||||||
|
|
||||||
void console_record_reset(void)
|
void console_record_reset(void)
|
||||||
{
|
{
|
||||||
membuff_purge((struct membuff *)&gd->console_out);
|
membuf_purge((struct membuf *)&gd->console_out);
|
||||||
membuff_purge((struct membuff *)&gd->console_in);
|
membuf_purge((struct membuf *)&gd->console_in);
|
||||||
gd->flags &= ~GD_FLG_RECORD_OVF;
|
gd->flags &= ~GD_FLG_RECORD_OVF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,23 +847,23 @@ int console_record_readline(char *str, int maxlen)
|
||||||
if (console_record_isempty())
|
if (console_record_isempty())
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
return membuff_readline((struct membuff *)&gd->console_out, str,
|
return membuf_readline((struct membuf *)&gd->console_out, str,
|
||||||
maxlen, '\0', false);
|
maxlen, '\0', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int console_record_avail(void)
|
int console_record_avail(void)
|
||||||
{
|
{
|
||||||
return membuff_avail((struct membuff *)&gd->console_out);
|
return membuf_avail((struct membuf *)&gd->console_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool console_record_isempty(void)
|
bool console_record_isempty(void)
|
||||||
{
|
{
|
||||||
return membuff_isempty((struct membuff *)&gd->console_out);
|
return membuf_isempty((struct membuf *)&gd->console_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
int console_in_puts(const char *str)
|
int console_in_puts(const char *str)
|
||||||
{
|
{
|
||||||
return membuff_put((struct membuff *)&gd->console_in, str, strlen(str));
|
return membuf_put((struct membuf *)&gd->console_in, str, strlen(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -63,7 +63,7 @@ static int sandbox_serial_probe(struct udevice *dev)
|
||||||
|
|
||||||
if (state->term_raw != STATE_TERM_RAW)
|
if (state->term_raw != STATE_TERM_RAW)
|
||||||
disable_ctrlc(1);
|
disable_ctrlc(1);
|
||||||
membuff_init(&priv->buf, priv->serial_buf, sizeof(priv->serial_buf));
|
membuf_init(&priv->buf, priv->serial_buf, sizeof(priv->serial_buf));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -138,15 +138,15 @@ static int sandbox_serial_pending(struct udevice *dev, bool input)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
os_usleep(100);
|
os_usleep(100);
|
||||||
avail = membuff_putraw(&priv->buf, 100, false, &data);
|
avail = membuf_putraw(&priv->buf, 100, false, &data);
|
||||||
if (!avail)
|
if (!avail)
|
||||||
return 1; /* buffer full */
|
return 1; /* buffer full */
|
||||||
|
|
||||||
count = os_read(0, data, avail);
|
count = os_read(0, data, avail);
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
membuff_putraw(&priv->buf, count, true, &data);
|
membuf_putraw(&priv->buf, count, true, &data);
|
||||||
|
|
||||||
return membuff_avail(&priv->buf);
|
return membuf_avail(&priv->buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sandbox_serial_getc(struct udevice *dev)
|
static int sandbox_serial_getc(struct udevice *dev)
|
||||||
|
@ -156,7 +156,7 @@ static int sandbox_serial_getc(struct udevice *dev)
|
||||||
if (!sandbox_serial_pending(dev, true))
|
if (!sandbox_serial_pending(dev, true))
|
||||||
return -EAGAIN; /* buffer empty */
|
return -EAGAIN; /* buffer empty */
|
||||||
|
|
||||||
return membuff_getbyte(&priv->buf);
|
return membuf_getbyte(&priv->buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_UART_SANDBOX
|
#ifdef CONFIG_DEBUG_UART_SANDBOX
|
||||||
|
|
|
@ -38,7 +38,7 @@ enum {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct sandbox_keyb_priv {
|
struct sandbox_keyb_priv {
|
||||||
struct membuff in;
|
struct membuf in;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sandbox_keyb_plat {
|
struct sandbox_keyb_plat {
|
||||||
|
@ -167,7 +167,7 @@ int sandbox_usb_keyb_add_string(struct udevice *dev,
|
||||||
struct sandbox_keyb_priv *priv = dev_get_priv(dev);
|
struct sandbox_keyb_priv *priv = dev_get_priv(dev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = membuff_put(&priv->in, scancode, USB_KBD_BOOT_REPORT_SIZE);
|
ret = membuf_put(&priv->in, scancode, USB_KBD_BOOT_REPORT_SIZE);
|
||||||
if (ret != USB_KBD_BOOT_REPORT_SIZE)
|
if (ret != USB_KBD_BOOT_REPORT_SIZE)
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ static int sandbox_keyb_interrupt(struct udevice *dev, struct usb_device *udev,
|
||||||
if (length < USB_KBD_BOOT_REPORT_SIZE)
|
if (length < USB_KBD_BOOT_REPORT_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
membuff_get(&priv->in, buffer, USB_KBD_BOOT_REPORT_SIZE);
|
membuf_get(&priv->in, buffer, USB_KBD_BOOT_REPORT_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ static int sandbox_keyb_probe(struct udevice *dev)
|
||||||
struct sandbox_keyb_priv *priv = dev_get_priv(dev);
|
struct sandbox_keyb_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
/* Provide an 80 character keyboard buffer */
|
/* Provide an 80 character keyboard buffer */
|
||||||
return membuff_new(&priv->in, 80 * USB_KBD_BOOT_REPORT_SIZE);
|
return membuf_new(&priv->in, 80 * USB_KBD_BOOT_REPORT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct dm_usb_ops sandbox_usb_keyb_ops = {
|
static const struct dm_usb_ops sandbox_usb_keyb_ops = {
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include <board_f.h>
|
#include <board_f.h>
|
||||||
#include <event_internal.h>
|
#include <event_internal.h>
|
||||||
#include <fdtdec.h>
|
#include <fdtdec.h>
|
||||||
#include <membuff.h>
|
#include <membuf.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/build_bug.h>
|
#include <linux/build_bug.h>
|
||||||
#include <asm-offsets.h>
|
#include <asm-offsets.h>
|
||||||
|
@ -316,14 +316,14 @@ struct global_data {
|
||||||
*
|
*
|
||||||
* This buffer is used to collect output during console recording.
|
* This buffer is used to collect output during console recording.
|
||||||
*/
|
*/
|
||||||
struct membuff console_out;
|
struct membuf console_out;
|
||||||
/**
|
/**
|
||||||
* @console_in: input buffer for console recording
|
* @console_in: input buffer for console recording
|
||||||
*
|
*
|
||||||
* If console recording is activated, this buffer can be used to
|
* If console recording is activated, this buffer can be used to
|
||||||
* emulate input.
|
* emulate input.
|
||||||
*/
|
*/
|
||||||
struct membuff console_in;
|
struct membuf console_in;
|
||||||
#endif
|
#endif
|
||||||
#if CONFIG_IS_ENABLED(VIDEO)
|
#if CONFIG_IS_ENABLED(VIDEO)
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,11 +6,13 @@
|
||||||
* Copyright (c) 1992 Simon Glass
|
* Copyright (c) 1992 Simon Glass
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MEMBUFF_H
|
#ifndef _membuf_H
|
||||||
#define _MEMBUFF_H
|
#define _membuf_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct membuff: holds the state of a membuff - it is used for input and
|
* @struct membuf: holds the state of a membuff - it is used for input and
|
||||||
* output buffers. The buffer extends from @start to (@start + @size - 1).
|
* output buffers. The buffer extends from @start to (@start + @size - 1).
|
||||||
* Data in the buffer extends from @tail to @head: it is written in at
|
* Data in the buffer extends from @tail to @head: it is written in at
|
||||||
* @head and read out from @tail. The membuff is empty when @head == @tail
|
* @head and read out from @tail. The membuff is empty when @head == @tail
|
||||||
|
@ -23,13 +25,13 @@
|
||||||
*
|
*
|
||||||
* .............xxxxxxxxxxxxxxxx.........................
|
* .............xxxxxxxxxxxxxxxx.........................
|
||||||
* ^ ^
|
* ^ ^
|
||||||
* tail head
|
* ^start tail head ^end
|
||||||
*
|
*
|
||||||
* xxxxxxxxxxxxx................xxxxxxxxxxxxxxxxxxxxxxxxx
|
* xxxxxxxxxxxxx................xxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
* ^ ^
|
* ^ ^
|
||||||
* head tail
|
* head tail
|
||||||
*/
|
*/
|
||||||
struct membuff {
|
struct membuf {
|
||||||
char *start; /** the start of the buffer */
|
char *start; /** the start of the buffer */
|
||||||
char *end; /** the end of the buffer (start + length) */
|
char *end; /** the end of the buffer (start + length) */
|
||||||
char *head; /** current buffer head */
|
char *head; /** current buffer head */
|
||||||
|
@ -37,16 +39,16 @@ struct membuff {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_purge() - reset a membuff to the empty state
|
* membuf_purge() - reset a membuff to the empty state
|
||||||
*
|
*
|
||||||
* Initialise head and tail pointers so that the membuff becomes empty.
|
* Initialise head and tail pointers so that the membuff becomes empty.
|
||||||
*
|
*
|
||||||
* @mb: membuff to purge
|
* @mb: membuff to purge
|
||||||
*/
|
*/
|
||||||
void membuff_purge(struct membuff *mb);
|
void membuf_purge(struct membuf *mb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_putraw() - find out where bytes can be written
|
* membuf_putraw() - find out where bytes can be written
|
||||||
*
|
*
|
||||||
* Work out where in the membuff some data could be written. Return a pointer
|
* Work out where in the membuff some data could be written. Return a pointer
|
||||||
* to the address and the number of bytes which can be written there. If
|
* to the address and the number of bytes which can be written there. If
|
||||||
|
@ -64,10 +66,10 @@ void membuff_purge(struct membuff *mb);
|
||||||
* @data: the address data can be written to
|
* @data: the address data can be written to
|
||||||
* Return: number of bytes which can be written
|
* Return: number of bytes which can be written
|
||||||
*/
|
*/
|
||||||
int membuff_putraw(struct membuff *mb, int maxlen, bool update, char **data);
|
int membuf_putraw(struct membuf *mb, int maxlen, bool update, char **data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_getraw() - find and return a pointer to available bytes
|
* membuf_getraw() - find and return a pointer to available bytes
|
||||||
*
|
*
|
||||||
* Returns a pointer to any valid input data in the given membuff and
|
* Returns a pointer to any valid input data in the given membuff and
|
||||||
* optionally marks it as read. Note that not all input data may not be
|
* optionally marks it as read. Note that not all input data may not be
|
||||||
|
@ -82,37 +84,37 @@ int membuff_putraw(struct membuff *mb, int maxlen, bool update, char **data);
|
||||||
* @data: returns address of data in input membuff
|
* @data: returns address of data in input membuff
|
||||||
* Return: the number of bytes available at *@data
|
* Return: the number of bytes available at *@data
|
||||||
*/
|
*/
|
||||||
int membuff_getraw(struct membuff *mb, int maxlen, bool update, char **data);
|
int membuf_getraw(struct membuf *mb, int maxlen, bool update, char **data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_putbyte() - Writes a byte to a membuff
|
* membuf_putbyte() - Writes a byte to a membuff
|
||||||
*
|
*
|
||||||
* @mb: membuff to adjust
|
* @mb: membuff to adjust
|
||||||
* @ch: byte to write
|
* @ch: byte to write
|
||||||
* Return: true on success, false if membuff is full
|
* Return: true on success, false if membuff is full
|
||||||
*/
|
*/
|
||||||
bool membuff_putbyte(struct membuff *mb, int ch);
|
bool membuf_putbyte(struct membuf *mb, int ch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @mb: membuff to adjust
|
* @mb: membuff to adjust
|
||||||
* membuff_getbyte() - Read a byte from the membuff
|
* membuf_getbyte() - Read a byte from the membuff
|
||||||
* Return: the byte read, or -1 if the membuff is empty
|
* Return: the byte read, or -1 if the membuff is empty
|
||||||
*/
|
*/
|
||||||
int membuff_getbyte(struct membuff *mb);
|
int membuf_getbyte(struct membuf *mb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_peekbyte() - check the next available byte
|
* membuf_peekbyte() - check the next available byte
|
||||||
*
|
*
|
||||||
* Return the next byte which membuff_getbyte() would return, without
|
* Return the next byte which membuf_getbyte() would return, without
|
||||||
* removing it from the membuff.
|
* removing it from the membuff.
|
||||||
*
|
*
|
||||||
* @mb: membuff to adjust
|
* @mb: membuff to adjust
|
||||||
* Return: the byte peeked, or -1 if the membuff is empty
|
* Return: the byte peeked, or -1 if the membuff is empty
|
||||||
*/
|
*/
|
||||||
int membuff_peekbyte(struct membuff *mb);
|
int membuf_peekbyte(struct membuf *mb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_get() - get data from a membuff
|
* membuf_get() - get data from a membuff
|
||||||
*
|
*
|
||||||
* Copies any available data (up to @maxlen bytes) to @buff and removes it
|
* Copies any available data (up to @maxlen bytes) to @buff and removes it
|
||||||
* from the membuff.
|
* from the membuff.
|
||||||
|
@ -122,10 +124,10 @@ int membuff_peekbyte(struct membuff *mb);
|
||||||
* @maxlen: maximum number of bytes to read
|
* @maxlen: maximum number of bytes to read
|
||||||
* Return: the number of bytes read
|
* Return: the number of bytes read
|
||||||
*/
|
*/
|
||||||
int membuff_get(struct membuff *mb, char *buff, int maxlen);
|
int membuf_get(struct membuf *mb, char *buff, int maxlen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_put() - write data to a membuff
|
* membuf_put() - write data to a membuff
|
||||||
*
|
*
|
||||||
* Writes some data to a membuff. Returns the number of bytes added. If this
|
* Writes some data to a membuff. Returns the number of bytes added. If this
|
||||||
* is less than @lnehgt, then the membuff got full
|
* is less than @lnehgt, then the membuff got full
|
||||||
|
@ -135,36 +137,36 @@ int membuff_get(struct membuff *mb, char *buff, int maxlen);
|
||||||
* @length: number of bytes to write from 'data'
|
* @length: number of bytes to write from 'data'
|
||||||
* Return: the number of bytes added
|
* Return: the number of bytes added
|
||||||
*/
|
*/
|
||||||
int membuff_put(struct membuff *mb, const char *buff, int length);
|
int membuf_put(struct membuf *mb, const char *buff, int length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_isempty() - check if a membuff is empty
|
* membuf_isempty() - check if a membuff is empty
|
||||||
*
|
*
|
||||||
* @mb: membuff to check
|
* @mb: membuff to check
|
||||||
* Return: true if empty, else false
|
* Return: true if empty, else false
|
||||||
*/
|
*/
|
||||||
bool membuff_isempty(struct membuff *mb);
|
bool membuf_isempty(struct membuf *mb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_avail() - check available data in a membuff
|
* membuf_avail() - check available data in a membuff
|
||||||
*
|
*
|
||||||
* @mb: membuff to check
|
* @mb: membuff to check
|
||||||
* Return: number of bytes of data available
|
* Return: number of bytes of data available
|
||||||
*/
|
*/
|
||||||
int membuff_avail(struct membuff *mb);
|
int membuf_avail(struct membuf *mb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_size() - get the size of a membuff
|
* membuf_size() - get the size of a membuff
|
||||||
*
|
*
|
||||||
* Note that a membuff can only old data up to one byte less than its size.
|
* Note that a membuff can only old data up to one byte less than its size.
|
||||||
*
|
*
|
||||||
* @mb: membuff to check
|
* @mb: membuff to check
|
||||||
* Return: total size
|
* Return: total size
|
||||||
*/
|
*/
|
||||||
int membuff_size(struct membuff *mb);
|
int membuf_size(struct membuf *mb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_makecontig() - adjust all membuff data to be contiguous
|
* membuf_makecontig() - adjust all membuff data to be contiguous
|
||||||
*
|
*
|
||||||
* This places all data in a membuff into a single contiguous lump, if
|
* This places all data in a membuff into a single contiguous lump, if
|
||||||
* possible
|
* possible
|
||||||
|
@ -172,18 +174,18 @@ int membuff_size(struct membuff *mb);
|
||||||
* @mb: membuff to adjust
|
* @mb: membuff to adjust
|
||||||
* Return: true on success
|
* Return: true on success
|
||||||
*/
|
*/
|
||||||
bool membuff_makecontig(struct membuff *mb);
|
bool membuf_makecontig(struct membuf *mb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_free() - find the number of bytes that can be written to a membuff
|
* membuf_free() - find the number of bytes that can be written to a membuff
|
||||||
*
|
*
|
||||||
* @mb: membuff to check
|
* @mb: membuff to check
|
||||||
* Return: returns the number of bytes free in a membuff
|
* Return: returns the number of bytes free in a membuff
|
||||||
*/
|
*/
|
||||||
int membuff_free(struct membuff *mb);
|
int membuf_free(struct membuf *mb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_readline() - read a line of text from a membuff
|
* membuf_readline() - read a line of text from a membuff
|
||||||
*
|
*
|
||||||
* Reads a line of text of up to 'maxlen' characters from a membuff and puts
|
* Reads a line of text of up to 'maxlen' characters from a membuff and puts
|
||||||
* it in @str. Any character less than @minch is assumed to be the end of
|
* it in @str. Any character less than @minch is assumed to be the end of
|
||||||
|
@ -192,14 +194,16 @@ int membuff_free(struct membuff *mb);
|
||||||
* @mb: membuff to adjust
|
* @mb: membuff to adjust
|
||||||
* @str: Place to put the line
|
* @str: Place to put the line
|
||||||
* @maxlen: Maximum line length (excluding terminator)
|
* @maxlen: Maximum line length (excluding terminator)
|
||||||
|
* @minch: Minimum ASCII character to permit as part of the line (e.g. ' ')
|
||||||
* @must_fit: If true then str is empty if line doesn't fit
|
* @must_fit: If true then str is empty if line doesn't fit
|
||||||
* Return: number of bytes read (including terminator) if a line has been
|
* Return: number of bytes read (including terminator) if a line has been
|
||||||
* read, 0 if nothing was there or line didn't fit when must_fit is set
|
* read, 0 if nothing was there or line didn't fit when must_fit is set
|
||||||
*/
|
*/
|
||||||
int membuff_readline(struct membuff *mb, char *str, int maxlen, int minch, bool must_fit);
|
int membuf_readline(struct membuf *mb, char *str, int maxlen, int minch,
|
||||||
|
bool must_fit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_extend_by() - expand a membuff
|
* membuf_extend_by() - expand a membuff
|
||||||
*
|
*
|
||||||
* Extends a membuff by the given number of bytes
|
* Extends a membuff by the given number of bytes
|
||||||
*
|
*
|
||||||
|
@ -209,38 +213,38 @@ int membuff_readline(struct membuff *mb, char *str, int maxlen, int minch, bool
|
||||||
* Return: 0 if the expand succeeded, -ENOMEM if not enough memory, -E2BIG
|
* Return: 0 if the expand succeeded, -ENOMEM if not enough memory, -E2BIG
|
||||||
* if the the size would exceed @max
|
* if the the size would exceed @max
|
||||||
*/
|
*/
|
||||||
int membuff_extend_by(struct membuff *mb, int by, int max);
|
int membuf_extend_by(struct membuf *mb, int by, int max);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_init() - set up a new membuff using an existing membuff
|
* membuf_init() - set up a new membuff using an existing membuff
|
||||||
*
|
*
|
||||||
* @mb: membuff to set up
|
* @mb: membuff to set up
|
||||||
* @buff: Address of buffer
|
* @buff: Address of buffer
|
||||||
* @size: Size of buffer
|
* @size: Size of buffer
|
||||||
*/
|
*/
|
||||||
void membuff_init(struct membuff *mb, char *buff, int size);
|
void membuf_init(struct membuf *mb, char *buff, int size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_uninit() - clear a membuff so it can no longer be used
|
* membuf_uninit() - clear a membuff so it can no longer be used
|
||||||
*
|
*
|
||||||
* @mb: membuff to uninit
|
* @mb: membuff to uninit
|
||||||
*/
|
*/
|
||||||
void membuff_uninit(struct membuff *mb);
|
void membuf_uninit(struct membuf *mb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_new() - create a new membuff
|
* membuf_new() - create a new membuff
|
||||||
*
|
*
|
||||||
* @mb: membuff to init
|
* @mb: membuff to init
|
||||||
* @size: size of membuff to create
|
* @size: size of membuff to create
|
||||||
* Return: 0 if OK, -ENOMEM if out of memory
|
* Return: 0 if OK, -ENOMEM if out of memory
|
||||||
*/
|
*/
|
||||||
int membuff_new(struct membuff *mb, int size);
|
int membuf_new(struct membuf *mb, int size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* membuff_dispose() - free memory allocated to a membuff and uninit it
|
* membuf_dispose() - free memory allocated to a membuff and uninit it
|
||||||
*
|
*
|
||||||
* @mb: membuff to dispose
|
* @mb: membuff to dispose
|
||||||
*/
|
*/
|
||||||
void membuff_dispose(struct membuff *mb);
|
void membuf_dispose(struct membuf *mb);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -125,7 +125,7 @@ obj-y += hang.o
|
||||||
obj-y += linux_compat.o
|
obj-y += linux_compat.o
|
||||||
obj-y += linux_string.o
|
obj-y += linux_string.o
|
||||||
obj-$(CONFIG_$(PHASE_)LMB) += lmb.o
|
obj-$(CONFIG_$(PHASE_)LMB) += lmb.o
|
||||||
obj-y += membuff.o
|
obj-y += membuf.o
|
||||||
obj-$(CONFIG_REGEX) += slre.o
|
obj-$(CONFIG_REGEX) += slre.o
|
||||||
obj-y += string.o
|
obj-y += string.o
|
||||||
obj-y += tables_csum.o
|
obj-y += tables_csum.o
|
||||||
|
|
|
@ -9,17 +9,17 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <log.h>
|
#include <log.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include "membuff.h"
|
#include "membuf.h"
|
||||||
|
|
||||||
void membuff_purge(struct membuff *mb)
|
void membuf_purge(struct membuf *mb)
|
||||||
{
|
{
|
||||||
/* set mb->head and mb->tail so the buffers look empty */
|
/* set mb->head and mb->tail so the buffers look empty */
|
||||||
mb->head = mb->start;
|
mb->head = mb->start;
|
||||||
mb->tail = mb->start;
|
mb->tail = mb->start;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int membuff_putrawflex(struct membuff *mb, int maxlen, bool update,
|
static int membuf_putrawflex(struct membuf *mb, int maxlen, bool update,
|
||||||
char ***data, int *offsetp)
|
char ***data, int *offsetp)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
@ -72,30 +72,30 @@ static int membuff_putrawflex(struct membuff *mb, int maxlen, bool update,
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_putraw(struct membuff *mb, int maxlen, bool update, char **data)
|
int membuf_putraw(struct membuf *mb, int maxlen, bool update, char **data)
|
||||||
{
|
{
|
||||||
char **datap;
|
char **datap;
|
||||||
int offset;
|
int offset;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
size = membuff_putrawflex(mb, maxlen, update, &datap, &offset);
|
size = membuf_putrawflex(mb, maxlen, update, &datap, &offset);
|
||||||
*data = *datap + offset;
|
*data = *datap + offset;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool membuff_putbyte(struct membuff *mb, int ch)
|
bool membuf_putbyte(struct membuf *mb, int ch)
|
||||||
{
|
{
|
||||||
char *data;
|
char *data;
|
||||||
|
|
||||||
if (membuff_putraw(mb, 1, true, &data) != 1)
|
if (membuf_putraw(mb, 1, true, &data) != 1)
|
||||||
return false;
|
return false;
|
||||||
*data = ch;
|
*data = ch;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_getraw(struct membuff *mb, int maxlen, bool update, char **data)
|
int membuf_getraw(struct membuf *mb, int maxlen, bool update, char **data)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
@ -146,21 +146,21 @@ int membuff_getraw(struct membuff *mb, int maxlen, bool update, char **data)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_getbyte(struct membuff *mb)
|
int membuf_getbyte(struct membuf *mb)
|
||||||
{
|
{
|
||||||
char *data = 0;
|
char *data = 0;
|
||||||
|
|
||||||
return membuff_getraw(mb, 1, true, &data) != 1 ? -1 : *(uint8_t *)data;
|
return membuf_getraw(mb, 1, true, &data) != 1 ? -1 : *(uint8_t *)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_peekbyte(struct membuff *mb)
|
int membuf_peekbyte(struct membuf *mb)
|
||||||
{
|
{
|
||||||
char *data = 0;
|
char *data = 0;
|
||||||
|
|
||||||
return membuff_getraw(mb, 1, false, &data) != 1 ? -1 : *(uint8_t *)data;
|
return membuf_getraw(mb, 1, false, &data) != 1 ? -1 : *(uint8_t *)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_get(struct membuff *mb, char *buff, int maxlen)
|
int membuf_get(struct membuf *mb, char *buff, int maxlen)
|
||||||
{
|
{
|
||||||
char *data = 0, *buffptr = buff;
|
char *data = 0, *buffptr = buff;
|
||||||
int len = 1, i;
|
int len = 1, i;
|
||||||
|
@ -171,7 +171,7 @@ int membuff_get(struct membuff *mb, char *buff, int maxlen)
|
||||||
*/
|
*/
|
||||||
for (i = 0; len && i < 2; i++) {
|
for (i = 0; len && i < 2; i++) {
|
||||||
/* get a pointer to the data available */
|
/* get a pointer to the data available */
|
||||||
len = membuff_getraw(mb, maxlen, true, &data);
|
len = membuf_getraw(mb, maxlen, true, &data);
|
||||||
|
|
||||||
/* copy it into the buffer */
|
/* copy it into the buffer */
|
||||||
memcpy(buffptr, data, len);
|
memcpy(buffptr, data, len);
|
||||||
|
@ -183,14 +183,14 @@ int membuff_get(struct membuff *mb, char *buff, int maxlen)
|
||||||
return buffptr - buff;
|
return buffptr - buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_put(struct membuff *mb, const char *buff, int length)
|
int membuf_put(struct membuf *mb, const char *buff, int length)
|
||||||
{
|
{
|
||||||
char *data;
|
char *data;
|
||||||
int towrite, i, written;
|
int towrite, i, written;
|
||||||
|
|
||||||
for (i = written = 0; i < 2; i++) {
|
for (i = written = 0; i < 2; i++) {
|
||||||
/* ask where some data can be written */
|
/* ask where some data can be written */
|
||||||
towrite = membuff_putraw(mb, length, true, &data);
|
towrite = membuf_putraw(mb, length, true, &data);
|
||||||
|
|
||||||
/* and write it, updating the bytes length */
|
/* and write it, updating the bytes length */
|
||||||
memcpy(data, buff, towrite);
|
memcpy(data, buff, towrite);
|
||||||
|
@ -203,14 +203,14 @@ int membuff_put(struct membuff *mb, const char *buff, int length)
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool membuff_isempty(struct membuff *mb)
|
bool membuf_isempty(struct membuf *mb)
|
||||||
{
|
{
|
||||||
return mb->head == mb->tail;
|
return mb->head == mb->tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_avail(struct membuff *mb)
|
int membuf_avail(struct membuf *mb)
|
||||||
{
|
{
|
||||||
struct membuff copy;
|
struct membuf copy;
|
||||||
int i, avail;
|
int i, avail;
|
||||||
char *data = 0;
|
char *data = 0;
|
||||||
|
|
||||||
|
@ -219,18 +219,18 @@ int membuff_avail(struct membuff *mb)
|
||||||
|
|
||||||
/* now read everything out of the copied buffer */
|
/* now read everything out of the copied buffer */
|
||||||
for (i = avail = 0; i < 2; i++)
|
for (i = avail = 0; i < 2; i++)
|
||||||
avail += membuff_getraw(©, -1, true, &data);
|
avail += membuf_getraw(©, -1, true, &data);
|
||||||
|
|
||||||
/* and return how much we read */
|
/* and return how much we read */
|
||||||
return avail;
|
return avail;
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_size(struct membuff *mb)
|
int membuf_size(struct membuf *mb)
|
||||||
{
|
{
|
||||||
return mb->end - mb->start;
|
return mb->end - mb->start;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool membuff_makecontig(struct membuff *mb)
|
bool membuf_makecontig(struct membuf *mb)
|
||||||
{
|
{
|
||||||
int topsize, botsize;
|
int topsize, botsize;
|
||||||
|
|
||||||
|
@ -281,13 +281,14 @@ bool membuff_makecontig(struct membuff *mb)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_free(struct membuff *mb)
|
int membuf_free(struct membuf *mb)
|
||||||
{
|
{
|
||||||
return mb->end == mb->start ? 0 :
|
return mb->end == mb->start ? 0 :
|
||||||
(mb->end - mb->start) - 1 - membuff_avail(mb);
|
(mb->end - mb->start) - 1 - membuf_avail(mb);
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_readline(struct membuff *mb, char *str, int maxlen, int minch, bool must_fit)
|
int membuf_readline(struct membuf *mb, char *str, int maxlen, int minch,
|
||||||
|
bool must_fit)
|
||||||
{
|
{
|
||||||
int len; /* number of bytes read (!= string length) */
|
int len; /* number of bytes read (!= string length) */
|
||||||
char *s, *end;
|
char *s, *end;
|
||||||
|
@ -322,7 +323,7 @@ int membuff_readline(struct membuff *mb, char *str, int maxlen, int minch, bool
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_extend_by(struct membuff *mb, int by, int max)
|
int membuf_extend_by(struct membuf *mb, int by, int max)
|
||||||
{
|
{
|
||||||
int oldhead, oldtail;
|
int oldhead, oldtail;
|
||||||
int size, orig;
|
int size, orig;
|
||||||
|
@ -358,32 +359,32 @@ int membuff_extend_by(struct membuff *mb, int by, int max)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void membuff_init(struct membuff *mb, char *buff, int size)
|
void membuf_init(struct membuf *mb, char *buff, int size)
|
||||||
{
|
{
|
||||||
mb->start = buff;
|
mb->start = buff;
|
||||||
mb->end = mb->start + size;
|
mb->end = mb->start + size;
|
||||||
membuff_purge(mb);
|
membuf_purge(mb);
|
||||||
}
|
}
|
||||||
|
|
||||||
int membuff_new(struct membuff *mb, int size)
|
int membuf_new(struct membuf *mb, int size)
|
||||||
{
|
{
|
||||||
mb->start = malloc(size);
|
mb->start = malloc(size);
|
||||||
if (!mb->start)
|
if (!mb->start)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
membuff_init(mb, mb->start, size);
|
membuf_init(mb, mb->start, size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void membuff_uninit(struct membuff *mb)
|
void membuf_uninit(struct membuf *mb)
|
||||||
{
|
{
|
||||||
mb->end = NULL;
|
mb->end = NULL;
|
||||||
mb->start = NULL;
|
mb->start = NULL;
|
||||||
membuff_purge(mb);
|
membuf_purge(mb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void membuff_dispose(struct membuff *mb)
|
void membuf_dispose(struct membuf *mb)
|
||||||
{
|
{
|
||||||
free(&mb->start);
|
free(mb->start);
|
||||||
membuff_uninit(mb);
|
membuf_uninit(mb);
|
||||||
}
|
}
|
|
@ -14,6 +14,7 @@ obj-y += hexdump.o
|
||||||
obj-$(CONFIG_SANDBOX) += kconfig.o
|
obj-$(CONFIG_SANDBOX) += kconfig.o
|
||||||
obj-y += lmb.o
|
obj-y += lmb.o
|
||||||
obj-$(CONFIG_HAVE_SETJMP) += longjmp.o
|
obj-$(CONFIG_HAVE_SETJMP) += longjmp.o
|
||||||
|
obj-$(CONFIG_SANDBOX) += membuf.o
|
||||||
obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
|
obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
|
||||||
obj-$(CONFIG_SSCANF) += sscanf.o
|
obj-$(CONFIG_SSCANF) += sscanf.o
|
||||||
obj-$(CONFIG_$(PHASE_)STRTO) += str.o
|
obj-$(CONFIG_$(PHASE_)STRTO) += str.o
|
||||||
|
|
239
test/lib/membuf.c
Normal file
239
test/lib/membuf.c
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Google LLC
|
||||||
|
* Written by Simon Glass <sjg@chromium.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <membuf.h>
|
||||||
|
#include <os.h>
|
||||||
|
#include <rand.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <test/lib.h>
|
||||||
|
#include <test/test.h>
|
||||||
|
#include <test/ut.h>
|
||||||
|
|
||||||
|
#define TEST_SIZE 16
|
||||||
|
#define TEST_COUNT 10000
|
||||||
|
|
||||||
|
static void membuf_zero(struct membuf *mb)
|
||||||
|
{
|
||||||
|
memset(mb->start, '\0', mb->end - mb->start);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int membuf_check(struct unit_test_state *uts, struct membuf *mb,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
/* head is out of range */
|
||||||
|
ut_assert(!(mb->head < mb->start || mb->head >= mb->end));
|
||||||
|
|
||||||
|
/* tail is out of range */
|
||||||
|
ut_assert(!(mb->tail < mb->start || mb->tail >= mb->end));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write from 1 to test_size bytes, and check they come back OK */
|
||||||
|
static int lib_test_membuf_one(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
char in[TEST_SIZE * 2], out[TEST_SIZE * 2];
|
||||||
|
struct membuf mb;
|
||||||
|
int size, ret, test_size, i;
|
||||||
|
|
||||||
|
ut_assertok(membuf_new(&mb, TEST_SIZE));
|
||||||
|
|
||||||
|
/* setup in test */
|
||||||
|
for (i = 0; i < TEST_SIZE; i++) {
|
||||||
|
in[i] = (i & 63) + '0';
|
||||||
|
in[i + TEST_SIZE] = in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
test_size = TEST_SIZE;
|
||||||
|
|
||||||
|
for (i = 1; i < TEST_COUNT; i++) {
|
||||||
|
membuf_zero(&mb);
|
||||||
|
size = rand() % test_size;
|
||||||
|
|
||||||
|
// now write patterns and check they come back OK
|
||||||
|
ret = membuf_put(&mb, in, 0);
|
||||||
|
ret = membuf_put(&mb, in, size);
|
||||||
|
ut_asserteq(size, ret);
|
||||||
|
|
||||||
|
ret = membuf_put(&mb, in, 0);
|
||||||
|
ut_assertok(membuf_check(uts, &mb, i));
|
||||||
|
|
||||||
|
ret = membuf_get(&mb, out, 0);
|
||||||
|
ret = membuf_get(&mb, out, size);
|
||||||
|
ut_asserteq(size, ret);
|
||||||
|
|
||||||
|
ret = membuf_get(&mb, out, 0);
|
||||||
|
ut_assertok(membuf_check(uts, &mb, i));
|
||||||
|
|
||||||
|
ut_asserteq_mem(in, out, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LIB_TEST(lib_test_membuf_one, 0);
|
||||||
|
|
||||||
|
/* write random number of bytes, and check they come back OK */
|
||||||
|
static int lib_test_membuf_random(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
char in[TEST_SIZE * 2];
|
||||||
|
char buf[TEST_SIZE * 2];
|
||||||
|
struct membuf mb;
|
||||||
|
int size, ret, test_size, i;
|
||||||
|
char *inptr, *outptr;
|
||||||
|
int max_avail, min_free;
|
||||||
|
|
||||||
|
ut_assertok(membuf_new(&mb, TEST_SIZE));
|
||||||
|
|
||||||
|
for (i = 0; i < TEST_SIZE; i++) {
|
||||||
|
in[i] = (i & 63) + '0';
|
||||||
|
in[i + TEST_SIZE] = in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
test_size = TEST_SIZE;
|
||||||
|
|
||||||
|
inptr = in;
|
||||||
|
outptr = in;
|
||||||
|
min_free = TEST_COUNT;
|
||||||
|
max_avail = 0;
|
||||||
|
membuf_zero(&mb);
|
||||||
|
for (i = 0; i < TEST_COUNT; i++) {
|
||||||
|
size = rand() % test_size;
|
||||||
|
|
||||||
|
if (membuf_free(&mb) < min_free)
|
||||||
|
min_free = membuf_free(&mb);
|
||||||
|
|
||||||
|
ret = membuf_put(&mb, inptr, size);
|
||||||
|
ut_assertok(membuf_check(uts, &mb, i));
|
||||||
|
inptr += ret;
|
||||||
|
if (inptr >= in + TEST_SIZE)
|
||||||
|
inptr -= TEST_SIZE;
|
||||||
|
|
||||||
|
size = rand() % (test_size - 1);
|
||||||
|
|
||||||
|
if (membuf_avail(&mb) > max_avail)
|
||||||
|
max_avail = membuf_avail(&mb);
|
||||||
|
|
||||||
|
ret = membuf_get(&mb, buf, size);
|
||||||
|
ut_assertok(membuf_check(uts, &mb, i));
|
||||||
|
ut_asserteq_mem(buf, outptr, ret);
|
||||||
|
|
||||||
|
outptr += ret;
|
||||||
|
if (outptr >= in + TEST_SIZE)
|
||||||
|
outptr -= TEST_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LIB_TEST(lib_test_membuf_random, 0);
|
||||||
|
|
||||||
|
/* test membuf_extend() with split segments */
|
||||||
|
static int lib_test_membuf_extend(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
char in[TEST_SIZE * 2];
|
||||||
|
char buf[TEST_SIZE * 2];
|
||||||
|
struct membuf mb;
|
||||||
|
int ret, test_size, i, cur;
|
||||||
|
char *data;
|
||||||
|
|
||||||
|
ut_assertok(membuf_new(&mb, TEST_SIZE));
|
||||||
|
|
||||||
|
for (i = 0; i < TEST_SIZE; i++) {
|
||||||
|
in[i] = (i & 63) + '0';
|
||||||
|
in[i + TEST_SIZE] = in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
test_size = TEST_SIZE - 1;
|
||||||
|
|
||||||
|
for (cur = 0; cur <= test_size; cur++) {
|
||||||
|
ut_assertok(membuf_new(&mb, TEST_SIZE));
|
||||||
|
|
||||||
|
membuf_zero(&mb);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add some bytes, then remove them - this will force the membuf
|
||||||
|
* to have data split into two segments when we fill it
|
||||||
|
*/
|
||||||
|
ret = membuf_putraw(&mb, TEST_SIZE / 2, true, &data);
|
||||||
|
membuf_getraw(&mb, ret, true, &data);
|
||||||
|
ut_asserteq(TEST_SIZE / 2, ret);
|
||||||
|
|
||||||
|
/* fill it */
|
||||||
|
ret = membuf_put(&mb, in, cur);
|
||||||
|
ut_assertok(membuf_check(uts, &mb, cur));
|
||||||
|
ut_asserteq(cur, ret);
|
||||||
|
|
||||||
|
/* extend the buffer */
|
||||||
|
ut_assertok(membuf_extend_by(&mb, TEST_SIZE, -1));
|
||||||
|
ut_assertok(membuf_check(uts, &mb, cur));
|
||||||
|
|
||||||
|
/* check our data is still there */
|
||||||
|
ret = membuf_get(&mb, buf, TEST_SIZE * 2);
|
||||||
|
ut_assertok(membuf_check(uts, &mb, cur));
|
||||||
|
ut_asserteq(cur, ret);
|
||||||
|
ut_asserteq_mem(in, buf, cur);
|
||||||
|
membuf_uninit(&mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LIB_TEST(lib_test_membuf_extend, 0);
|
||||||
|
|
||||||
|
/* test membuf_readline() with generated data */
|
||||||
|
static int lib_test_membuf_readline(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
int size, cur, i, ret, readptr, cmpptr;
|
||||||
|
struct membuf mb;
|
||||||
|
char *data;
|
||||||
|
char str[256];
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
ut_assertok(membuf_new(&mb, 1024));
|
||||||
|
membuf_zero(&mb);
|
||||||
|
|
||||||
|
/* Use the README as test data */
|
||||||
|
ut_assertok(os_read_file("README", (void **)&buf, &size));
|
||||||
|
|
||||||
|
cur = 0;
|
||||||
|
readptr = 0;
|
||||||
|
cmpptr = 0;
|
||||||
|
for (i = 0; i < 100000; i++, cur += 1) {
|
||||||
|
/* fill the buffer with up to 'cur' bytes */
|
||||||
|
ret = membuf_putraw(&mb, cur, false, &data);
|
||||||
|
|
||||||
|
if (ret > 0) {
|
||||||
|
int can_read = min(ret, size - readptr);
|
||||||
|
|
||||||
|
memcpy(data, &buf[readptr], can_read);
|
||||||
|
readptr += can_read;
|
||||||
|
|
||||||
|
membuf_putraw(&mb, can_read, true, &data);
|
||||||
|
ut_assertok(membuf_check(uts, &mb, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read a line and compare */
|
||||||
|
ret = membuf_readline(&mb, str, 256, 0, true);
|
||||||
|
ut_assertok(membuf_check(uts, &mb, i));
|
||||||
|
if (ret) {
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
s = &buf[cmpptr];
|
||||||
|
ptr = strchr(s, '\n');
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
ut_asserteq_str(s, str);
|
||||||
|
cmpptr += strlen(s) + 1;
|
||||||
|
*ptr = '\n';
|
||||||
|
} else {
|
||||||
|
ut_assert(membuf_free(&mb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
membuf_dispose(&mb);
|
||||||
|
os_free(buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LIB_TEST(lib_test_membuf_readline, 0);
|
Loading…
Add table
Reference in a new issue