mirror of
https://git.savannah.gnu.org/git/gnulib.git
synced 2025-08-08 17:22:05 +03:00
string-buffer-reversed: New module.
* lib/string-buffer-reversed.h: New file, based on lib/string-buffer.h. * lib/string-buffer-reversed.c: New file, based on lib/string-buffer.c. * lib/string-buffer-reversed-printf.c: New file, based on lib/string-buffer-printf.c. * modules/string-buffer-reversed: New file.
This commit is contained in:
@@ -1,3 +1,12 @@
|
|||||||
|
2025-02-05 Bruno Haible <bruno@clisp.org>
|
||||||
|
|
||||||
|
string-buffer-reversed: New module.
|
||||||
|
* lib/string-buffer-reversed.h: New file, based on lib/string-buffer.h.
|
||||||
|
* lib/string-buffer-reversed.c: New file, based on lib/string-buffer.c.
|
||||||
|
* lib/string-buffer-reversed-printf.c: New file, based on
|
||||||
|
lib/string-buffer-printf.c.
|
||||||
|
* modules/string-buffer-reversed: New file.
|
||||||
|
|
||||||
2025-02-05 Bruno Haible <bruno@clisp.org>
|
2025-02-05 Bruno Haible <bruno@clisp.org>
|
||||||
|
|
||||||
string-buffer: Improve comments.
|
string-buffer: Improve comments.
|
||||||
|
207
lib/string-buffer-reversed-printf.c
Normal file
207
lib/string-buffer-reversed-printf.c
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
/* A buffer that accumulates a string by piecewise concatenation, from the end
|
||||||
|
to the start.
|
||||||
|
Copyright (C) 2021-2025 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This file is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* Written by Bruno Haible <bruno@clisp.org>, 2025. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include "string-buffer-reversed.h"
|
||||||
|
|
||||||
|
/* Undocumented. */
|
||||||
|
extern int sbr_ensure_more_bytes (struct string_buffer_reversed *buffer,
|
||||||
|
size_t increment);
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
sbr_prependvf (struct string_buffer_reversed *buffer, const char *formatstring,
|
||||||
|
va_list list)
|
||||||
|
{
|
||||||
|
va_list list_copy;
|
||||||
|
|
||||||
|
/* Make a bit of room, so that the probability that the first vsnzprintf()
|
||||||
|
call succeeds is high. */
|
||||||
|
size_t room = buffer->allocated - buffer->length;
|
||||||
|
if (room < 64)
|
||||||
|
{
|
||||||
|
if (sbr_ensure_more_bytes (buffer, 64) < 0)
|
||||||
|
{
|
||||||
|
buffer->error = true;
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
room = buffer->allocated - buffer->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_copy (list_copy, list);
|
||||||
|
|
||||||
|
/* First vsnzprintf() call. */
|
||||||
|
ptrdiff_t ret = vsnzprintf (buffer->data, room, formatstring, list);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
/* Failed. errno is set. */
|
||||||
|
buffer->error = true;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ret <= room)
|
||||||
|
{
|
||||||
|
/* The result has fit into room bytes. */
|
||||||
|
memmove (buffer->data + buffer->allocated - buffer->length - (size_t) ret,
|
||||||
|
buffer->data,
|
||||||
|
(size_t) ret);
|
||||||
|
buffer->length += (size_t) ret;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The result was truncated. Make more room, for a second
|
||||||
|
vsnzprintf() call. */
|
||||||
|
if (sbr_ensure_more_bytes (buffer, (size_t) ret) < 0)
|
||||||
|
{
|
||||||
|
buffer->error = true;
|
||||||
|
errno = ENOMEM;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Second vsnzprintf() call. */
|
||||||
|
room = buffer->allocated - buffer->length;
|
||||||
|
ret = vsnzprintf (buffer->data, room, formatstring, list_copy);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
/* Failed. errno is set. */
|
||||||
|
buffer->error = true;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ret <= room)
|
||||||
|
{
|
||||||
|
/* The result has fit into room bytes. */
|
||||||
|
memmove (buffer->data + buffer->allocated - buffer->length - (size_t) ret,
|
||||||
|
buffer->data,
|
||||||
|
(size_t) ret);
|
||||||
|
buffer->length += (size_t) ret;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* The return values of the vsnzprintf() calls are not
|
||||||
|
consistent. */
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end (list_copy);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sbr_prependf (struct string_buffer_reversed *buffer, const char *formatstring,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
/* Make a bit of room, so that the probability that the first vsnzprintf()
|
||||||
|
call succeeds is high. */
|
||||||
|
size_t room = buffer->allocated - buffer->length;
|
||||||
|
if (room < 64)
|
||||||
|
{
|
||||||
|
if (sbr_ensure_more_bytes (buffer, 64) < 0)
|
||||||
|
{
|
||||||
|
buffer->error = true;
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
room = buffer->allocated - buffer->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start (args, formatstring);
|
||||||
|
|
||||||
|
/* First vsnzprintf() call. */
|
||||||
|
ptrdiff_t ret = vsnzprintf (buffer->data, room, formatstring, args);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
/* Failed. errno is set. */
|
||||||
|
buffer->error = true;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ret <= room)
|
||||||
|
{
|
||||||
|
/* The result has fit into room bytes. */
|
||||||
|
memmove (buffer->data + buffer->allocated - buffer->length - (size_t) ret,
|
||||||
|
buffer->data,
|
||||||
|
(size_t) ret);
|
||||||
|
buffer->length += (size_t) ret;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The result was truncated. Make more room, for a second
|
||||||
|
vsnzprintf() call. */
|
||||||
|
if (sbr_ensure_more_bytes (buffer, (size_t) ret) < 0)
|
||||||
|
{
|
||||||
|
buffer->error = true;
|
||||||
|
errno = ENOMEM;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Second vsnzprintf() call. */
|
||||||
|
room = buffer->allocated - buffer->length;
|
||||||
|
va_end (args);
|
||||||
|
va_start (args, formatstring);
|
||||||
|
ret = vsnzprintf (buffer->data, room, formatstring, args);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
/* Failed. errno is set. */
|
||||||
|
buffer->error = true;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ret <= room)
|
||||||
|
{
|
||||||
|
/* The result has fit into room bytes. */
|
||||||
|
memmove (buffer->data + buffer->allocated - buffer->length - (size_t) ret,
|
||||||
|
buffer->data,
|
||||||
|
(size_t) ret);
|
||||||
|
buffer->length += (size_t) ret;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* The return values of the vsnzprintf() calls are not
|
||||||
|
consistent. */
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end (args);
|
||||||
|
return ret;
|
||||||
|
}
|
222
lib/string-buffer-reversed.c
Normal file
222
lib/string-buffer-reversed.c
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
/* A buffer that accumulates a string by piecewise concatenation, from the end
|
||||||
|
to the start.
|
||||||
|
Copyright (C) 2021-2025 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This file is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* Written by Bruno Haible <bruno@clisp.org>, 2025. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include "string-buffer-reversed.h"
|
||||||
|
|
||||||
|
/* Undocumented. */
|
||||||
|
extern int sbr_ensure_more_bytes (struct string_buffer_reversed *buffer,
|
||||||
|
size_t increment);
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* The warnings about memory resource 'buffer->data' in this file are not
|
||||||
|
relevant. Silence them. */
|
||||||
|
#if __clang_major__ >= 3
|
||||||
|
# pragma clang diagnostic ignored "-Wthread-safety"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
sbr_init (struct string_buffer_reversed *buffer)
|
||||||
|
{
|
||||||
|
buffer->data = buffer->space;
|
||||||
|
/* Pre-allocate a trailing NUL. This makes it easy to implement
|
||||||
|
sbr_contents_c(). */
|
||||||
|
buffer->data[sizeof (buffer->space) - 1] = '\0';
|
||||||
|
buffer->length = 1;
|
||||||
|
buffer->allocated = sizeof (buffer->space);
|
||||||
|
buffer->error = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensures that INCREMENT bytes are available beyond the current used length
|
||||||
|
of BUFFER.
|
||||||
|
Returns 0, or -1 in case of out-of-memory error. */
|
||||||
|
int
|
||||||
|
sbr_ensure_more_bytes (struct string_buffer_reversed *buffer, size_t increment)
|
||||||
|
{
|
||||||
|
size_t incremented_length = increment + buffer->length;
|
||||||
|
if (incremented_length < increment)
|
||||||
|
/* Overflow. */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (buffer->allocated < incremented_length)
|
||||||
|
{
|
||||||
|
size_t new_allocated = 2 * buffer->allocated;
|
||||||
|
if (new_allocated < buffer->allocated)
|
||||||
|
/* Overflow. */
|
||||||
|
return -1;
|
||||||
|
if (new_allocated < incremented_length)
|
||||||
|
new_allocated = incremented_length;
|
||||||
|
|
||||||
|
char *new_data;
|
||||||
|
if (buffer->data == buffer->space)
|
||||||
|
{
|
||||||
|
new_data = (char *) malloc (new_allocated);
|
||||||
|
if (new_data == NULL)
|
||||||
|
/* Out-of-memory. */
|
||||||
|
return -1;
|
||||||
|
memcpy (new_data + new_allocated - buffer->length,
|
||||||
|
buffer->data + buffer->allocated - buffer->length,
|
||||||
|
buffer->length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_data = (char *) realloc (buffer->data, new_allocated);
|
||||||
|
if (new_data == NULL)
|
||||||
|
/* Out-of-memory. */
|
||||||
|
return -1;
|
||||||
|
memmove (new_data + new_allocated - buffer->length,
|
||||||
|
new_data + buffer->allocated - buffer->length,
|
||||||
|
buffer->length);
|
||||||
|
}
|
||||||
|
buffer->data = new_data;
|
||||||
|
buffer->allocated = new_allocated;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sbr_prepend1 (struct string_buffer_reversed *buffer, char c)
|
||||||
|
{
|
||||||
|
if (sbr_ensure_more_bytes (buffer, 1) < 0)
|
||||||
|
{
|
||||||
|
buffer->error = true;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
buffer->data[buffer->allocated - buffer->length - 1] = c;
|
||||||
|
buffer->length++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sbr_prepend_desc (struct string_buffer_reversed *buffer, string_desc_t s)
|
||||||
|
{
|
||||||
|
size_t len = sd_length (s);
|
||||||
|
if (sbr_ensure_more_bytes (buffer, len) < 0)
|
||||||
|
{
|
||||||
|
buffer->error = true;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy (buffer->data + buffer->allocated - buffer->length - len, sd_data (s), len);
|
||||||
|
buffer->length += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sbr_prepend_c (struct string_buffer_reversed *buffer, const char *str)
|
||||||
|
{
|
||||||
|
size_t len = strlen (str);
|
||||||
|
if (sbr_ensure_more_bytes (buffer, len) < 0)
|
||||||
|
{
|
||||||
|
buffer->error = true;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy (buffer->data + buffer->allocated - buffer->length - len, str, len);
|
||||||
|
buffer->length += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sbr_free (struct string_buffer_reversed *buffer)
|
||||||
|
{
|
||||||
|
if (buffer->data != buffer->space)
|
||||||
|
free (buffer->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
string_desc_t
|
||||||
|
sbr_contents (struct string_buffer_reversed *buffer)
|
||||||
|
{
|
||||||
|
return sd_new_addr (buffer->length - 1,
|
||||||
|
buffer->data + buffer->allocated - buffer->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
sbr_contents_c (struct string_buffer_reversed *buffer)
|
||||||
|
{
|
||||||
|
return buffer->data + buffer->allocated - buffer->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_desc_t
|
||||||
|
sbr_dupfree (struct string_buffer_reversed *buffer)
|
||||||
|
{
|
||||||
|
if (buffer->error)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
size_t length = buffer->length;
|
||||||
|
if (buffer->data == buffer->space)
|
||||||
|
{
|
||||||
|
char *copy = (char *) malloc (length > 1 ? length - 1 : 1);
|
||||||
|
if (copy == NULL)
|
||||||
|
goto fail;
|
||||||
|
memcpy (copy, buffer->data + buffer->allocated - length, length - 1);
|
||||||
|
return sd_new_addr (length - 1, copy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Shrink the string before returning it. */
|
||||||
|
char *contents = buffer->data;
|
||||||
|
memmove (contents, contents + buffer->allocated - length, length - 1);
|
||||||
|
contents = realloc (contents, length > 1 ? length - 1 : 1);
|
||||||
|
if (contents == NULL)
|
||||||
|
goto fail;
|
||||||
|
return sd_new_addr (length - 1, contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
sbr_free (buffer);
|
||||||
|
return sd_new_addr (0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
sbr_dupfree_c (struct string_buffer_reversed *buffer)
|
||||||
|
{
|
||||||
|
if (buffer->error)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
size_t length = buffer->length;
|
||||||
|
if (buffer->data == buffer->space)
|
||||||
|
{
|
||||||
|
char *copy = (char *) malloc (length);
|
||||||
|
if (copy == NULL)
|
||||||
|
goto fail;
|
||||||
|
memcpy (copy, buffer->data + buffer->allocated - length, length);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Shrink the string before returning it. */
|
||||||
|
char *contents = buffer->data;
|
||||||
|
if (length < buffer->allocated)
|
||||||
|
{
|
||||||
|
memmove (contents, contents + buffer->allocated - length, length);
|
||||||
|
contents = realloc (contents, length);
|
||||||
|
if (contents == NULL)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
sbr_free (buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
202
lib/string-buffer-reversed.h
Normal file
202
lib/string-buffer-reversed.h
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/* A buffer that accumulates a string by piecewise concatenation, from the end
|
||||||
|
to the start.
|
||||||
|
Copyright (C) 2021-2025 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This file is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* Written by Bruno Haible <bruno@clisp.org>, 2025. */
|
||||||
|
|
||||||
|
#ifndef _STRING_BUFFER_REVERSED_H
|
||||||
|
#define _STRING_BUFFER_REVERSED_H
|
||||||
|
|
||||||
|
/* This file uses _GL_ATTRIBUTE_MALLOC, _GL_ATTRIBUTE_RETURNS_NONNULL,
|
||||||
|
_GL_ATTRIBUTE_CAPABILITY_TYPE, _GL_ATTRIBUTE_ACQUIRE_CAPABILITY,
|
||||||
|
_GL_ATTRIBUTE_RELEASE_CAPABILITY. */
|
||||||
|
#if !_GL_CONFIG_H_INCLUDED
|
||||||
|
#error "Please include config.h first."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "attribute.h"
|
||||||
|
#include "string-desc.h"
|
||||||
|
|
||||||
|
typedef char * _GL_ATTRIBUTE_CAPABILITY_TYPE ("memory resource")
|
||||||
|
sbr_heap_allocated_pointer_t;
|
||||||
|
|
||||||
|
/* A string buffer type. */
|
||||||
|
struct string_buffer_reversed
|
||||||
|
{
|
||||||
|
/* data[allocated-length .. allocated-1] are used. */
|
||||||
|
sbr_heap_allocated_pointer_t data;
|
||||||
|
size_t length; /* used bytes, <= allocated */
|
||||||
|
size_t allocated; /* allocated bytes */
|
||||||
|
bool error; /* true if there was an error */
|
||||||
|
char space[1024]; /* stack allocated space */
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ================== Functions in module 'string-buffer' ================== */
|
||||||
|
|
||||||
|
/* Initializes BUFFER to the empty string. */
|
||||||
|
extern void sbr_init (struct string_buffer_reversed *buffer)
|
||||||
|
_GL_ATTRIBUTE_ACQUIRE_CAPABILITY (buffer->data);
|
||||||
|
|
||||||
|
/* Prepends the character C to BUFFER.
|
||||||
|
Returns 0, or -1 in case of out-of-memory error. */
|
||||||
|
extern int sbr_prepend1 (struct string_buffer_reversed *buffer, char c);
|
||||||
|
|
||||||
|
/* Prepends the contents of the memory area S to BUFFER.
|
||||||
|
Returns 0, or -1 in case of out-of-memory error. */
|
||||||
|
extern int sbr_prepend_desc (struct string_buffer_reversed *buffer,
|
||||||
|
string_desc_t s);
|
||||||
|
|
||||||
|
/* Prepends the contents of the C string STR to BUFFER.
|
||||||
|
Returns 0, or -1 in case of out-of-memory error. */
|
||||||
|
extern int sbr_prepend_c (struct string_buffer_reversed *buffer,
|
||||||
|
const char *str);
|
||||||
|
|
||||||
|
/* Prepends the result of the printf-compatible FORMATSTRING with the argument
|
||||||
|
list LIST to BUFFER.
|
||||||
|
Returns 0, or -1 with errno set in case of error.
|
||||||
|
Error code EOVERFLOW can only occur when a width > INT_MAX is used.
|
||||||
|
Therefore, if the format string is valid and does not use %ls/%lc
|
||||||
|
directives nor widths, the only possible error code is ENOMEM. */
|
||||||
|
extern int sbr_prependvf (struct string_buffer_reversed *buffer,
|
||||||
|
const char *formatstring, va_list list)
|
||||||
|
#if (__GNUC__ + (__GNUC_MINOR__ >= 4) > 4) && !defined __clang__
|
||||||
|
ATTRIBUTE_FORMAT ((__gnu_printf__, 2, 0))
|
||||||
|
#else
|
||||||
|
ATTRIBUTE_FORMAT ((__printf__, 2, 0))
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Prepends the result of the printf-compatible FORMATSTRING with the following
|
||||||
|
arguments to BUFFER.
|
||||||
|
Returns 0, or -1 with errno set in case of error.
|
||||||
|
Error code EOVERFLOW can only occur when a width > INT_MAX is used.
|
||||||
|
Therefore, if the format string is valid and does not use %ls/%lc
|
||||||
|
directives nor widths, the only possible error code is ENOMEM. */
|
||||||
|
extern int sbr_prependf (struct string_buffer_reversed *buffer,
|
||||||
|
const char *formatstring, ...)
|
||||||
|
#if (__GNUC__ + (__GNUC_MINOR__ >= 4) > 4) && !defined __clang__
|
||||||
|
ATTRIBUTE_FORMAT ((__gnu_printf__, 2, 3))
|
||||||
|
#else
|
||||||
|
ATTRIBUTE_FORMAT ((__printf__, 2, 3))
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Frees the memory held by BUFFER. */
|
||||||
|
extern void sbr_free (struct string_buffer_reversed *buffer)
|
||||||
|
_GL_ATTRIBUTE_RELEASE_CAPABILITY (buffer->data);
|
||||||
|
|
||||||
|
/* Returns a read-only view of the current contents of BUFFER.
|
||||||
|
The result is only valid until the next operation on BUFFER. */
|
||||||
|
extern string_desc_t sbr_contents (struct string_buffer_reversed *buffer);
|
||||||
|
|
||||||
|
/* Ensures the contents of BUFFER is followed by a NUL byte (without
|
||||||
|
incrementing the length of the contents).
|
||||||
|
Then returns a read-only view of the current contents of BUFFER,
|
||||||
|
that is, the current contents of BUFFER as a C string.
|
||||||
|
The result is only valid until the next operation on BUFFER. */
|
||||||
|
extern const char * sbr_contents_c (struct string_buffer_reversed *buffer);
|
||||||
|
|
||||||
|
/* Returns the contents of BUFFER and frees all other memory held by BUFFER.
|
||||||
|
Returns NULL upon failure or if there was an error earlier.
|
||||||
|
It is the responsibility of the caller to sd_free() the result. */
|
||||||
|
extern string_desc_t sbr_dupfree (struct string_buffer_reversed *buffer)
|
||||||
|
_GL_ATTRIBUTE_RELEASE_CAPABILITY (buffer->data);
|
||||||
|
|
||||||
|
/* Returns the contents of BUFFER (with an added trailing NUL, that is,
|
||||||
|
as a C string), and frees all other memory held by BUFFER.
|
||||||
|
Returns NULL upon failure or if there was an error earlier.
|
||||||
|
It is the responsibility of the caller to free() the result. */
|
||||||
|
extern char * sbr_dupfree_c (struct string_buffer_reversed *buffer)
|
||||||
|
_GL_ATTRIBUTE_RELEASE_CAPABILITY (buffer->data);
|
||||||
|
|
||||||
|
/* ================== Functions in module 'xstring-buffer' ================== */
|
||||||
|
|
||||||
|
#if GNULIB_XSTRING_BUFFER_REVERSED
|
||||||
|
|
||||||
|
/* The following functions invoke xalloc_die () in case of out-of-memory
|
||||||
|
error. */
|
||||||
|
|
||||||
|
/* Prepends the character C to BUFFER. */
|
||||||
|
extern void sbr_xprepend1 (struct string_buffer_reversed *buffer, char c);
|
||||||
|
|
||||||
|
/* Prepends the contents of the memory area S to BUFFER. */
|
||||||
|
extern void sbr_xprepend_desc (struct string_buffer_reversed *buffer,
|
||||||
|
string_desc_t s);
|
||||||
|
|
||||||
|
/* Prepends the contents of the C string STR to BUFFER. */
|
||||||
|
extern void sbr_xprepend_c (struct string_buffer_reversed *buffer,
|
||||||
|
const char *str);
|
||||||
|
|
||||||
|
/* Prepends the result of the printf-compatible FORMATSTRING with the argument
|
||||||
|
list LIST to BUFFER.
|
||||||
|
Returns 0, or -1 in case of error other than out-of-memory error.
|
||||||
|
Error code EOVERFLOW can only occur when a width > INT_MAX is used.
|
||||||
|
Therefore, if the format string is valid and does not use %ls/%lc
|
||||||
|
directives nor widths, no error is possible. */
|
||||||
|
extern int sbr_xprependvf (struct string_buffer_reversed *buffer,
|
||||||
|
const char *formatstring, va_list list)
|
||||||
|
#if (__GNUC__ + (__GNUC_MINOR__ >= 4) > 4) && !defined __clang__
|
||||||
|
ATTRIBUTE_FORMAT ((__gnu_printf__, 2, 0))
|
||||||
|
#else
|
||||||
|
ATTRIBUTE_FORMAT ((__printf__, 2, 0))
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Prepends the result of the printf-compatible FORMATSTRING with the following
|
||||||
|
arguments to BUFFER.
|
||||||
|
Returns 0, or -1 in case of error other than out-of-memory error.
|
||||||
|
Error code EOVERFLOW can only occur when a width > INT_MAX is used.
|
||||||
|
Therefore, if the format string is valid and does not use %ls/%lc
|
||||||
|
directives nor widths, no error is possible. */
|
||||||
|
extern int sbr_xprependf (struct string_buffer_reversed *buffer,
|
||||||
|
const char *formatstring, ...)
|
||||||
|
#if (__GNUC__ + (__GNUC_MINOR__ >= 4) > 4) && !defined __clang__
|
||||||
|
ATTRIBUTE_FORMAT ((__gnu_printf__, 2, 3))
|
||||||
|
#else
|
||||||
|
ATTRIBUTE_FORMAT ((__printf__, 2, 3))
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Returns the contents of BUFFER and frees all other memory held by BUFFER.
|
||||||
|
Returns (0, NULL) if there was an error earlier.
|
||||||
|
It is the responsibility of the caller to sd_free() the result. */
|
||||||
|
extern string_desc_t sbr_xdupfree (struct string_buffer_reversed *buffer)
|
||||||
|
_GL_ATTRIBUTE_RELEASE_CAPABILITY (buffer->data);
|
||||||
|
|
||||||
|
/* Returns the contents of BUFFER (with an added trailing NUL, that is,
|
||||||
|
as a C string), and frees all other memory held by BUFFER.
|
||||||
|
Returns NULL if there was an error earlier.
|
||||||
|
It is the responsibility of the caller to free() the result. */
|
||||||
|
extern char * sbr_xdupfree_c (struct string_buffer_reversed *buffer)
|
||||||
|
_GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
|
||||||
|
_GL_ATTRIBUTE_RELEASE_CAPABILITY (buffer->data);
|
||||||
|
|
||||||
|
#endif /* GNULIB_XSTRING_BUFFER_REVERSED */
|
||||||
|
|
||||||
|
/* ========================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _STRING_BUFFER_REVERSED_H */
|
29
modules/string-buffer-reversed
Normal file
29
modules/string-buffer-reversed
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
Description:
|
||||||
|
A buffer that accumulates a string by piecewise concatenation,
|
||||||
|
from the end to the start.
|
||||||
|
|
||||||
|
Files:
|
||||||
|
lib/string-buffer-reversed.h
|
||||||
|
lib/string-buffer-reversed.c
|
||||||
|
lib/string-buffer-reversed-printf.c
|
||||||
|
|
||||||
|
Depends-on:
|
||||||
|
bool
|
||||||
|
attribute
|
||||||
|
string-desc
|
||||||
|
stdarg-h
|
||||||
|
vsnzprintf-posix
|
||||||
|
|
||||||
|
configure.ac:
|
||||||
|
|
||||||
|
Makefile.am:
|
||||||
|
lib_SOURCES += string-buffer-reversed.c string-buffer-reversed-printf.c
|
||||||
|
|
||||||
|
Include:
|
||||||
|
"string-buffer-reversed.h"
|
||||||
|
|
||||||
|
License:
|
||||||
|
LGPL
|
||||||
|
|
||||||
|
Maintainer:
|
||||||
|
all
|
Reference in New Issue
Block a user