|
|
|
strbuf API
|
|
|
|
==========
|
|
|
|
|
|
|
|
strbuf's are meant to be used with all the usual C string and memory
|
|
|
|
APIs. Given that the length of the buffer is known, it's often better to
|
|
|
|
use the mem* functions than a str* one (memchr vs. strchr e.g.).
|
|
|
|
Though, one has to be careful about the fact that str* functions often
|
|
|
|
stop on NULs and that strbufs may have embedded NULs.
|
|
|
|
|
|
|
|
An strbuf is NUL terminated for convenience, but no function in the
|
|
|
|
strbuf API actually relies on the string being free of NULs.
|
|
|
|
|
|
|
|
strbufs has some invariants that are very important to keep in mind:
|
|
|
|
|
|
|
|
. The `buf` member is never NULL, so it can be used in any usual C
|
|
|
|
string operations safely. strbuf's _have_ to be initialized either by
|
|
|
|
`strbuf_init()` or by `= STRBUF_INIT` before the invariants, though.
|
|
|
|
+
|
|
|
|
Do *not* assume anything on what `buf` really is (e.g. if it is
|
|
|
|
allocated memory or not), use `strbuf_detach()` to unwrap a memory
|
|
|
|
buffer from its strbuf shell in a safe way. That is the sole supported
|
|
|
|
way. This will give you a malloced buffer that you can later `free()`.
|
|
|
|
+
|
|
|
|
However, it is totally safe to modify anything in the string pointed by
|
|
|
|
the `buf` member, between the indices `0` and `len-1` (inclusive).
|
|
|
|
|
|
|
|
. The `buf` member is a byte array that has at least `len + 1` bytes
|
|
|
|
allocated. The extra byte is used to store a `'\0'`, allowing the
|
|
|
|
`buf` member to be a valid C-string. Every strbuf function ensure this
|
|
|
|
invariant is preserved.
|
|
|
|
+
|
|
|
|
NOTE: It is OK to "play" with the buffer directly if you work it this
|
|
|
|
way:
|
|
|
|
+
|
|
|
|
----
|
|
|
|
strbuf_grow(sb, SOME_SIZE); <1>
|
|
|
|
strbuf_setlen(sb, sb->len + SOME_OTHER_SIZE);
|
|
|
|
----
|
|
|
|
<1> Here, the memory array starting at `sb->buf`, and of length
|
|
|
|
`strbuf_avail(sb)` is all yours, and you can be sure that
|
|
|
|
`strbuf_avail(sb)` is at least `SOME_SIZE`.
|
|
|
|
+
|
|
|
|
NOTE: `SOME_OTHER_SIZE` must be smaller or equal to `strbuf_avail(sb)`.
|
|
|
|
+
|
|
|
|
Doing so is safe, though if it has to be done in many places, adding the
|
|
|
|
missing API to the strbuf module is the way to go.
|
|
|
|
+
|
|
|
|
WARNING: Do _not_ assume that the area that is yours is of size `alloc
|
|
|
|
- 1` even if it's true in the current implementation. Alloc is somehow a
|
|
|
|
"private" member that should not be messed with. Use `strbuf_avail()`
|
|
|
|
instead.
|
|
|
|
|
|
|
|
Data structures
|
|
|
|
---------------
|
|
|
|
|
|
|
|
* `struct strbuf`
|
|
|
|
|
|
|
|
This is the string buffer structure. The `len` member can be used to
|
|
|
|
determine the current length of the string, and `buf` member provides access to
|
|
|
|
the string itself.
|
|
|
|
|
|
|
|
Functions
|
|
|
|
---------
|
|
|
|
|
|
|
|
* Life cycle
|
|
|
|
|
|
|
|
`strbuf_init`::
|
|
|
|
|
|
|
|
Initialize the structure. The second parameter can be zero or a bigger
|
|
|
|
number to allocate memory, in case you want to prevent further reallocs.
|
|
|
|
|
|
|
|
`strbuf_release`::
|
|
|
|
|
|
|
|
Release a string buffer and the memory it used. You should not use the
|
|
|
|
string buffer after using this function, unless you initialize it again.
|
|
|
|
|
|
|
|
`strbuf_detach`::
|
|
|
|
|
|
|
|
Detach the string from the strbuf and returns it; you now own the
|
|
|
|
storage the string occupies and it is your responsibility from then on
|
|
|
|
to release it with `free(3)` when you are done with it.
|
|
|
|
|
|
|
|
`strbuf_attach`::
|
|
|
|
|
|
|
|
Attach a string to a buffer. You should specify the string to attach,
|
|
|
|
the current length of the string and the amount of allocated memory.
|
|
|
|
The amount must be larger than the string length, because the string you
|
|
|
|
pass is supposed to be a NUL-terminated string. This string _must_ be
|
|
|
|
malloc()ed, and after attaching, the pointer cannot be relied upon
|
|
|
|
anymore, and neither be free()d directly.
|
|
|
|
|
|
|
|
`strbuf_swap`::
|
|
|
|
|
|
|
|
Swap the contents of two string buffers.
|
|
|
|
|
|
|
|
* Related to the size of the buffer
|
|
|
|
|
|
|
|
`strbuf_avail`::
|
|
|
|
|
|
|
|
Determine the amount of allocated but unused memory.
|
|
|
|
|
|
|
|
`strbuf_grow`::
|
|
|
|
|
|
|
|
Ensure that at least this amount of unused memory is available after
|
|
|
|
`len`. This is used when you know a typical size for what you will add
|
|
|
|
and want to avoid repetitive automatic resizing of the underlying buffer.
|
|
|
|
This is never a needed operation, but can be critical for performance in
|
|
|
|
some cases.
|
|
|
|
|
|
|
|
`strbuf_setlen`::
|
|
|
|
|
|
|
|
Set the length of the buffer to a given value. This function does *not*
|
|
|
|
allocate new memory, so you should not perform a `strbuf_setlen()` to a
|
|
|
|
length that is larger than `len + strbuf_avail()`. `strbuf_setlen()` is
|
|
|
|
just meant as a 'please fix invariants from this strbuf I just messed
|
|
|
|
with'.
|
|
|
|
|
|
|
|
`strbuf_reset`::
|
|
|
|
|
|
|
|
Empty the buffer by setting the size of it to zero.
|
|
|
|
|
|
|
|
* Related to the contents of the buffer
|
|
|
|
|
|
|
|
`strbuf_rtrim`::
|
|
|
|
|
|
|
|
Strip whitespace from the end of a string.
|
|
|
|
|
|
|
|
`strbuf_cmp`::
|
|
|
|
|
|
|
|
Compare two buffers. Returns an integer less than, equal to, or greater
|
|
|
|
than zero if the first buffer is found, respectively, to be less than,
|
|
|
|
to match, or be greater than the second buffer.
|
|
|
|
|
|
|
|
* Adding data to the buffer
|
|
|
|
|
|
|
|
NOTE: All of the functions in this section will grow the buffer as necessary.
|
|
|
|
If they fail for some reason other than memory shortage and the buffer hadn't
|
|
|
|
been allocated before (i.e. the `struct strbuf` was set to `STRBUF_INIT`),
|
|
|
|
then they will free() it.
|
|
|
|
|
|
|
|
`strbuf_addch`::
|
|
|
|
|
|
|
|
Add a single character to the buffer.
|
|
|
|
|
|
|
|
`strbuf_insert`::
|
|
|
|
|
|
|
|
Insert data to the given position of the buffer. The remaining contents
|
|
|
|
will be shifted, not overwritten.
|
|
|
|
|
|
|
|
`strbuf_remove`::
|
|
|
|
|
|
|
|
Remove given amount of data from a given position of the buffer.
|
|
|
|
|
|
|
|
`strbuf_splice`::
|
|
|
|
|
|
|
|
Remove the bytes between `pos..pos+len` and replace it with the given
|
|
|
|
data.
|
|
|
|
|
|
|
|
`strbuf_add`::
|
|
|
|
|
|
|
|
Add data of given length to the buffer.
|
|
|
|
|
|
|
|
`strbuf_addstr`::
|
|
|
|
|
|
|
|
Add a NUL-terminated string to the buffer.
|
|
|
|
+
|
|
|
|
NOTE: This function will *always* be implemented as an inline or a macro
|
|
|
|
that expands to:
|
|
|
|
+
|
|
|
|
----
|
|
|
|
strbuf_add(..., s, strlen(s));
|
|
|
|
----
|
|
|
|
+
|
|
|
|
Meaning that this is efficient to write things like:
|
|
|
|
+
|
|
|
|
----
|
|
|
|
strbuf_addstr(sb, "immediate string");
|
|
|
|
----
|
|
|
|
|
|
|
|
`strbuf_addbuf`::
|
|
|
|
|
|
|
|
Copy the contents of an other buffer at the end of the current one.
|
|
|
|
|
|
|
|
`strbuf_adddup`::
|
|
|
|
|
|
|
|
Copy part of the buffer from a given position till a given length to the
|
|
|
|
end of the buffer.
|
|
|
|
|
|
|
|
`strbuf_expand`::
|
|
|
|
|
|
|
|
This function can be used to expand a format string containing
|
|
|
|
placeholders. To that end, it parses the string and calls the specified
|
|
|
|
function for every percent sign found.
|
|
|
|
+
|
|
|
|
The callback function is given a pointer to the character after the `%`
|
|
|
|
and a pointer to the struct strbuf. It is expected to add the expanded
|
|
|
|
version of the placeholder to the strbuf, e.g. to add a newline
|
|
|
|
character if the letter `n` appears after a `%`. The function returns
|
|
|
|
the length of the placeholder recognized and `strbuf_expand()` skips
|
|
|
|
over it.
|
|
|
|
+
|
|
|
|
All other characters (non-percent and not skipped ones) are copied
|
|
|
|
verbatim to the strbuf. If the callback returned zero, meaning that the
|
|
|
|
placeholder is unknown, then the percent sign is copied, too.
|
|
|
|
+
|
|
|
|
In order to facilitate caching and to make it possible to give
|
|
|
|
parameters to the callback, `strbuf_expand()` passes a context pointer,
|
|
|
|
which can be used by the programmer of the callback as she sees fit.
|
|
|
|
|
|
|
|
`strbuf_expand_dict_cb`::
|
|
|
|
|
|
|
|
Used as callback for `strbuf_expand()`, expects an array of
|
|
|
|
struct strbuf_expand_dict_entry as context, i.e. pairs of
|
|
|
|
placeholder and replacement string. The array needs to be
|
|
|
|
terminated by an entry with placeholder set to NULL.
|
|
|
|
|
|
|
|
`strbuf_addf`::
|
|
|
|
|
|
|
|
Add a formatted string to the buffer.
|
|
|
|
|
|
|
|
`strbuf_fread`::
|
|
|
|
|
|
|
|
Read a given size of data from a FILE* pointer to the buffer.
|
|
|
|
+
|
|
|
|
NOTE: The buffer is rewound if the read fails. If -1 is returned,
|
|
|
|
`errno` must be consulted, like you would do for `read(3)`.
|
|
|
|
`strbuf_read()`, `strbuf_read_file()` and `strbuf_getline()` has the
|
|
|
|
same behaviour as well.
|
|
|
|
|
|
|
|
`strbuf_read`::
|
|
|
|
|
|
|
|
Read the contents of a given file descriptor. The third argument can be
|
|
|
|
used to give a hint about the file size, to avoid reallocs.
|
|
|
|
|
|
|
|
`strbuf_read_file`::
|
|
|
|
|
|
|
|
Read the contents of a file, specified by its path. The third argument
|
|
|
|
can be used to give a hint about the file size, to avoid reallocs.
|
|
|
|
|
|
|
|
`strbuf_readlink`::
|
|
|
|
|
|
|
|
Read the target of a symbolic link, specified by its path. The third
|
|
|
|
argument can be used to give a hint about the size, to avoid reallocs.
|
|
|
|
|
|
|
|
`strbuf_getline`::
|
|
|
|
|
|
|
|
Read a line from a FILE* pointer. The second argument specifies the line
|
|
|
|
terminator character, typically `'\n'`.
|
|
|
|
|
|
|
|
`stripspace`::
|
|
|
|
|
|
|
|
Strip whitespace from a buffer. The second parameter controls if
|
|
|
|
comments are considered contents to be removed or not.
|
|
|
|
|
|
|
|
`launch_editor`::
|
|
|
|
|
|
|
|
Launch the user preferred editor to edit a file and fill the buffer
|
|
|
|
with the file's contents upon the user completing their editing. The
|
|
|
|
third argument can be used to set the environment which the editor is
|
|
|
|
run in. If the buffer is NULL the editor is launched as usual but the
|
|
|
|
file's contents are not read into the buffer upon completion.
|