wget2: Buffer management functions

| wget2 2.0.0

- Main Page
- Modules
- Data Structures
- Files

Functions
Buffer management functions

## Functions
int | wget_buffer_init (wget_buffer *buf, char *data, size_t size)
wget_buffer * | wget_buffer_alloc (size_t size)
int | wget_buffer_ensure_capacity (wget_buffer *buf, size_t size)
void | wget_buffer_deinit (wget_buffer *buf)
void | wget_buffer_free (wget_buffer **buf)
void | wget_buffer_free_data (wget_buffer *buf)
void | wget_buffer_reset (wget_buffer *buf)
size_t | wget_buffer_memcpy (wget_buffer *buf, const void *data, size_t length)
size_t | wget_buffer_memcat (wget_buffer *buf, const void *data, size_t length)
size_t | wget_buffer_strcpy (wget_buffer *buf, const char *s)
size_t | wget_buffer_strcat (wget_buffer *buf, const char *s)
size_t | wget_buffer_bufcpy (wget_buffer *buf, wget_buffer *src)
size_t | wget_buffer_bufcat (wget_buffer *buf, wget_buffer *src)
size_t | wget_buffer_memset (wget_buffer *buf, char c, size_t length)
size_t | wget_buffer_memset_append (wget_buffer *buf, char c, size_t length)
char * | wget_buffer_trim (wget_buffer *buf)
size_t | wget_buffer_vprintf_append (wget_buffer *buf, const char *fmt, va_list args)
size_t | wget_buffer_vprintf (wget_buffer *buf, const char *fmt, va_list args)
size_t | wget_buffer_printf_append (wget_buffer *buf, const char *fmt,...)
size_t | wget_buffer_printf (wget_buffer *buf, const char *fmt,...)

## Detailed Description

A buffer (represented with an opaque `wget_buffer`) is a managed memory area.

Apart from a pointer to a raw chunk of memory (`char *`), it also has some metadata attached such as the length of the buffer and the actual occupied positions.

Actually, when we talk about the length of the buffer, we refer to the actual number of bytes stored in it by the user. On the other hand, the size is the total number of slots in the buffer, either occupied or not.

The stored data is always 0-terminated, so you safely use it with standard string functions.

The functions here allow you to easily work with buffers, providing shortcuts to commonly used memory and string management operations and avoiding usual pitfalls, such as buffer overflows. They provide a higher-level abstraction to working with memory than the memory management functions.

If your application uses memory allocation functions that may return NULL values (e.g. like the standard libc functions), you have to check the `error` value before using the result. If set, it indicates that a memory allocation failure occurred during internal (re-)allocation.

Example with wget_buffer on the stack (initial 16 bytes heap allocation)

wget_buffer buf;
wet_buffer_init(&buf, NULL, 16);
wget_buffer_strcpy(&buf, "A");
wget_buffer_strcat(&buf, "B");
wget_buffer_memcat(&buf, "C", 1);
wget_buffer_memset_append(&buf, 'D', 1);
wget_buffer_printf_append(&buf, "%s", "E");
// buf.data now contains the 0-terminated string "ABCDE"
printf("buf.data = %s\n", buf.data);
wget_buffer_deinit(&buf);
wget_buffer_memset_append
WGETAPI size_t wget_buffer_memset_append(wget_buffer *buf, char c, size_t length)
Definition: buffer.c:515
wget_buffer_strcat
WGETAPI size_t wget_buffer_strcat(wget_buffer *buf, const char *s)
Definition: buffer.c:436
wget_buffer_printf_append
size_t wget_buffer_printf_append(wget_buffer *buf, const char *fmt,...)
Definition: buffer_printf.c:539
wget_buffer_deinit
WGETAPI void wget_buffer_deinit(wget_buffer *buf) WGET_GCC_NONNULL((1))
Definition: buffer.c:268
wget_buffer_memcat
WGETAPI size_t wget_buffer_memcat(wget_buffer *buf, const void *data, size_t length)
Definition: buffer.c:378
wget_buffer_strcpy
WGETAPI size_t wget_buffer_strcpy(wget_buffer *buf, const char *s)
Definition: buffer.c:414
wget_buffer
Definition: wget.h:542
wget_buffer::data
char * data
pointer to internal memory
Definition: wget.h:544

Example with wget_buffer on the stack and 16 bytes initial stack buffer (no heap allocation is needed)

wget_buffer buf;
char sbuf[16];
wet_buffer_init(&buf, sbuf, sizeof(sbuf));
wget_buffer_strcpy(&buf, "A");
wget_buffer_strcat(&buf, "B");
wget_buffer_memcat(&buf, "C", 1);
wget_buffer_memset_append(&buf, 'D', 1);
wget_buffer_printf_append(&buf, "%s", "E");
// buf.data now contains the 0-terminated string "ABCDE"
printf("buf.data = %s\n", buf.data);
wget_buffer_deinit(&buf);

Example on how to check for memory failure and how to transfer buffer data

wget_buffer buf;
wet_buffer_init(&buf, NULL, 16);
wget_buffer_strcpy(&buf, "A");
wget_buffer_strcat(&buf, "B");
wget_buffer_memcat(&buf, "C", 1);
wget_buffer_memset_append(&buf, 'D', 1);
wget_buffer_printf_append(&buf, "%s", "E");
if (buf.error)
panic("No memory !");
// transfer ownership away from wget_buffer
char *ret = buf.data;
buf.data = NULL; // avoid double frees
wget_buffer_deinit(&buf);
return ret; // the caller must free() this value after use
wget_buffer::error
bool error
a memory failure occurred, the result in 'data' is likely erroneous
Definition: wget.h:552

## Function Documentation

## ◆ wget_buffer_init()

int wget_buffer_init | ( | wget_buffer * | buf,
|  | char * | data,
|  | size_t | size
| ) |  |

Parameters

  [in] | buf | Pointer to the buffer that should become initialized.
  [in] | data | Initial contents of the buffer. Might be NULL.
  [in] | size | Initial length of the buffer. Might be zero (will default to 128 bytes).

Returns
  WGET_E_SUCCESS or WGET_E_MEMORY in case of a memory allocation failure.

Create a new buffer.

If `data` is NULL, the buffer will be empty, but it will be pre-allocated with `size` bytes. This will make future operations on the buffer faster since there will be less re-allocations needed.

If `size` is zero, the buffer will be pre-allocated with 128 bytes.

You may provide some `data` to fill the buffer with it. The contents of the `data` pointer are not copied, but rather the pointer itself is referenced directly within the buffer. If you modify the contents of `data`, those changes will be reflected in the buffer as they both point to the same memory area.

Apart from that, there are other concerns you should keep in mind if you provide your own `data` here:

- wget_buffer_deinit() will not free that memory when you call it. So if you provide a `data` pointer, you must free it yourself before your program ends.
- wget_buffer_realloc() will also not free that memory. It will allocate a new buffer and copy the contents there, but will not touch the old buffer. The new buffer will be freed by these functions since it's been allocated by libwget internally and thus it knows it can be freed without harm.

If an existing buffer is provided in `buf`, it will be initialized with the provided `data` and `size` according to the rules stated above.

## ◆ wget_buffer_alloc()

wget_buffer* wget_buffer_alloc | ( | size_t | size | ) |

Parameters

  [in] | size | Initial length of the buffer.

Returns
  A new buffer.

Allocates a new buffer of size `size` bytes.

The buffer will be pre-allocated with that many bytes, all zeros.

This is equivalent to wget_buffer_init(NULL, NULL, size).

## ◆ wget_buffer_ensure_capacity()

int wget_buffer_ensure_capacity | ( | wget_buffer * | buf,
|  | size_t | size
| ) |  |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()
  [in] | size | Total size (in bytes) required in the buffer

Returns
  WGET_E_SUCCESS on success, else WGET_E_MEMORY if the memory allocation failed

Make sure the buffer `buf` has at least a size of `size` bytes.

If the buffer's size is less than that, it will automatically enlarge it (with wget_buffer_realloc()) to make it at least as long.

## ◆ wget_buffer_deinit()

void wget_buffer_deinit | ( | wget_buffer * | buf | ) |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()

Free the buffer, and all its contents.

If you provided your own data when calling wget_buffer_init() (you passed a non-NULL `data` pointer) then that buffer will not be freed. As stated in the description of wget_buffer_init() you must free that buffer yourself: this function will only free the `wget_buffer` structure.

Similarly, if you provided your own buffer when calling wget_buffer_init() (`buf` was non-NULL) the buffer (the `wget_buffer` structure) will not be freed, and the data might or might not be freed depending on the above condition.

## ◆ wget_buffer_free()

void wget_buffer_free | ( | wget_buffer ** | buf | ) |

Parameters

  [in] | buf | A double pointer to a buffer

Free the buffer, and all its contents.

It behaves like wget_buffer_deinit() but it also sets the `buf` pointer to NULL.

This function is equivalent to:

    wget_buffer_deinit(*buf);
    *buf = NULL;

## ◆ wget_buffer_free_data()

void wget_buffer_free_data | ( | wget_buffer * | buf | ) |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()

Release the buffer's data, but keep the buffer itself (the `wget_buffer` structure).

The length of the buffer will be maintained, but after this function succeeds, the size will obviously be zero.

The same rules that apply to wget_buffer_deinit() also apply here: if you provided your own data when calling wget_buffer_init() (ie. `data` was non-NULL) then that data will not be freed, and this function will essentially be a no-op.

## ◆ wget_buffer_reset()

void wget_buffer_reset | ( | wget_buffer * | buf | ) |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()

This function is lighter than wget_buffer_free_data(). It does not free the data buffer, it just sets its first byte to zero, as well as the length.

This function is equivalent to:

    buf->length = 0;
    *buf->data = 0;

## ◆ wget_buffer_memcpy()

size_t wget_buffer_memcpy | ( | wget_buffer * | buf,
|  | const void * | data,
|  | size_t | length
| ) |  |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()
  [in] | data | A pointer to the data to be copied
  [in] | length | How many bytes from `data` (starting at the beginning) should be copied

Returns
  The new length of the buffer after copying the data

Copy the contents in the pointer `data` to the buffer `buf`, clobbering the previous contents.

The first `length` bytes of `data` are written to `buf`. The content of `buf` is overwritten with the new `data`.

If the buffer is not large enough to store that amount of data, it is enlarged automatically at least `length` bytes (with wget_buffer_realloc()).

## ◆ wget_buffer_memcat()

size_t wget_buffer_memcat | ( | wget_buffer * | buf,
|  | const void * | data,
|  | size_t | length
| ) |  |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()
  [in] | data | A pointer to the data to be appended
  [in] | length | How many bytes of `data` should be written to `buf`

Returns
  The new length of the buffer after appending the data

Append the provided `data` to the end of the buffer `buf` (preserving contents).

If there's not enough space in `buf`, it is enlarged automatically (with wget_buffer_realloc()) at least `length` bytes, so that the whole data can be written.

## ◆ wget_buffer_strcpy()

size_t wget_buffer_strcpy | ( | wget_buffer * | buf,
|  | const char * | s
| ) |  |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()
  [in] | s | A NULL-terminated string

Returns
  The new length of the buffer after copying the string

Copy the NULL-terminated string `s` to the buffer `buf`, overwriting its original contents.

If the buffer is not large enough it is enlarged automatically.

This is essentially equivalent to:

    buf->length = 0;
    wget_buffer_memcat(buf, s, strlen(s));

## ◆ wget_buffer_strcat()

size_t wget_buffer_strcat | ( | wget_buffer * | buf,
|  | const char * | s
| ) |  |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()
  [in] | s | A NULL-terminated string

Returns
  The new length of the buffer after appending the string

Append the NULL-terminated string `s` to the end of the buffer `buf` (preserving its contents).

If the buffer is not large enough it is enlarged automatically.

This is essentially equivalent to calling wget_buffer_memcat() with length equal to `strlen(s)`:

    wget_buffer_memcat(buf, s, strlen(s));

## ◆ wget_buffer_bufcpy()

size_t wget_buffer_bufcpy | ( | wget_buffer * | buf,
|  | wget_buffer * | src
| ) |  |

Parameters

  [in] | buf | The destination buffer
  [in] | src | The source buffer

Returns
  The new length of the destination buffer `buf` after copying the contents of `src`

Copy the contents of the buffer `src` in the buffer `buf`, clobbering its previous contents.

If the buffer `buf` is not large enough it is enlarged automatically.

This is equivalent to:

    wget_buffer_memcpy(buf, src->data, src->length);

## ◆ wget_buffer_bufcat()

size_t wget_buffer_bufcat | ( | wget_buffer * | buf,
|  | wget_buffer * | src
| ) |  |

Parameters

  [in] | buf | The destination buffer
  [in] | src | The source buffer

Returns
  The new length of the destination buffer `buf` after appending the contents of `src`

Append the contents of the buffer `src` to the end of the buffer `buf`.

If the buffer `buf` is not large enough it is enlarged automatically.

This is equivalent to:

    wget_buffer_memcat(buf, src->data, src->length);

## ◆ wget_buffer_memset()

size_t wget_buffer_memset | ( | wget_buffer * | buf,
|  | char | c,
|  | size_t | length
| ) |  |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()
  [in] | c | The byte to be copied at the end of the buffer
  [in] | length | How many times will the byte `c` be copied.

Returns
  The new length of the buffer `buf`.

Copy the byte `c` repeatedly `length` times starting at the beginning of the buffer, so the first `length` bytes of the buffer are overwritten.

If there's not enough space in `buf`, it is enlarged automatically (with wget_buffer_realloc()) at least `length` bytes.

## ◆ wget_buffer_memset_append()

size_t wget_buffer_memset_append | ( | wget_buffer * | buf,
|  | char | c,
|  | size_t | length
| ) |  |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()
  [in] | c | The byte to be copied at the end of the buffer
  [in] | length | How many times will the byte `c` be copied.

Returns
  The new length of the buffer `buf`.

Copy the byte `c` at the end of the buffer `buf` repeatedly `length` times.

If there's not enough space in `buf`, it is enlarged automatically (with wget_buffer_realloc()) at least `length` bytes.

## ◆ wget_buffer_trim()

char* wget_buffer_trim | ( | wget_buffer * | buf | ) |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()

Returns
  The buffer's new contents

Remove all leading and trailing whitespace from the buffer `buf`.

The transformation is done in-place, that is, the buffer's original content is overwritten with the new trimmed content.

## ◆ wget_buffer_vprintf_append()

size_t wget_buffer_vprintf_append | ( | wget_buffer * | buf,
|  | const char * | fmt,
|  | va_list | args
| ) |  |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()
  [in] | fmt | A `printf(3)`-like format string
  [in] | args | A `va_list` with the format string placeholders' values

Returns
  Length of the buffer after appending the formatted string

Formats the string `fmt` (with `printf(3)`-like args) and appends the result to the end of the buffer `buf` (using wget_buffer_memcat()).

For more information, see `vprintf(3)`.

## ◆ wget_buffer_vprintf()

size_t wget_buffer_vprintf | ( | wget_buffer * | buf,
|  | const char * | fmt,
|  | va_list | args
| ) |  |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()
  [in] | fmt | A `printf(3)`-like format string
  [in] | args | A `va_list` with the format string placeholders' values

Returns
  Length of the buffer after appending the formatted string

Formats the string `fmt` (with `printf(3)`-like args) and overwrites the contents of the buffer `buf` with that formatted string.

This is equivalent to the following code:

    buf->length = 0;
    wget_buffer_vprintf_append(buf, fmt, args);

For more information, see `vprintf(3)`.

## ◆ wget_buffer_printf_append()

size_t wget_buffer_printf_append | ( | wget_buffer * | buf,
|  | const char * | fmt,
|  |  | ...
| ) |  |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()
  [in] | fmt | A `printf(3)`-like format string
  [in] | ... | Variable arguments

Returns
  Length of the buffer after appending the formatted string

Formats the string `fmt` (with `printf(3)`-like args) and appends the result to the end of the buffer `buf` (using wget_buffer_memcat()).

This function is equivalent to wget_buffer_vprintf_append(), except in that it uses a variable number of arguments rather than a `va_list`.

For more information, see `printf(3)`.

## ◆ wget_buffer_printf()

size_t wget_buffer_printf | ( | wget_buffer * | buf,
|  | const char * | fmt,
|  |  | ...
| ) |  |

Parameters

  [in] | buf | A buffer, created with wget_buffer_init() or wget_buffer_alloc()
  [in] | fmt | A `printf(3)`-like format string
  [in] | ... | Variable arguments

Returns
  Length of the buffer after appending the formatted string

Formats the string `fmt` (with `printf(3)`-like args) and overwrites the contents of the buffer `buf` with that formatted string.

This function is equivalent to wget_buffer_vprintf(), except in that it uses a variable number of arguments rather than a `va_list`.

For more information, see `printf(3)`.