mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2025-06-30 22:18:19 -04:00
Feature: Added buffer_push_printf() and buffer_push_vprintf()
This commit is contained in:
parent
03d56ca35f
commit
71b156afc6
69
src/buffer.c
69
src/buffer.c
@ -10,8 +10,10 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "refobject.h"
|
#include "refobject.h"
|
||||||
@ -195,6 +197,73 @@ int buffer_push_string(buffer_t *buffer, const char *string)
|
|||||||
return buffer_push_data(buffer, string, strlen(string));
|
return buffer_push_data(buffer, string, strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int buffer_push_printf(buffer_t *buffer, const char *format, ...)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
if (!buffer || !format)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!*format)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
ret = buffer_push_vprintf(buffer, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int buffer_push_vprintf(buffer_t *buffer, const char *format, va_list ap)
|
||||||
|
{
|
||||||
|
void *buf;
|
||||||
|
int ret;
|
||||||
|
size_t length = 1024;
|
||||||
|
|
||||||
|
if (!buffer || !format)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!*format)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = buffer_zerocopy_push_request(buffer, &buf, length);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = vsnprintf(buf, length, format, ap);
|
||||||
|
if (ret >= 0 && (size_t)ret < length) {
|
||||||
|
return buffer_zerocopy_push_complete(buffer, ret);
|
||||||
|
} else if (ret < 0) {
|
||||||
|
/* This vsnprintf() likely does not follow POSIX.
|
||||||
|
* We don't know what length we need to asume. So asume a big one and hope for the best. */
|
||||||
|
length = 8192;
|
||||||
|
} else {
|
||||||
|
/* Reallocate the buffer to the size reported plus one for '\0'-termination */
|
||||||
|
length = ret + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have not written any data yet. */
|
||||||
|
ret = buffer_zerocopy_push_complete(buffer, 0);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Now let's try again. */
|
||||||
|
ret = buffer_zerocopy_push_request(buffer, &buf, length);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = vsnprintf(buf, length, format, ap);
|
||||||
|
if (ret < 0 || (size_t)ret >= length) {
|
||||||
|
/* This still didn't work. Giving up. */
|
||||||
|
buffer_zerocopy_push_complete(buffer, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer_zerocopy_push_complete(buffer, ret);
|
||||||
|
}
|
||||||
|
|
||||||
int buffer_zerocopy_push_request(buffer_t *buffer, void **data, size_t request)
|
int buffer_zerocopy_push_request(buffer_t *buffer, void **data, size_t request)
|
||||||
{
|
{
|
||||||
if (!buffer || !data)
|
if (!buffer || !data)
|
||||||
|
26
src/buffer.h
26
src/buffer.h
@ -18,6 +18,8 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "icecasttypes.h"
|
#include "icecasttypes.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "refobject.h"
|
#include "refobject.h"
|
||||||
@ -127,6 +129,30 @@ int buffer_push_data(buffer_t *buffer, const void *data, size_t length);
|
|||||||
*/
|
*/
|
||||||
int buffer_push_string(buffer_t *buffer, const char *string);
|
int buffer_push_string(buffer_t *buffer, const char *string);
|
||||||
|
|
||||||
|
/* This pushes a formated string to the end of the buffer.
|
||||||
|
* Parameters:
|
||||||
|
* buffer
|
||||||
|
* The buffer to operate on.
|
||||||
|
* format
|
||||||
|
* The format string as for printf() family functions.
|
||||||
|
* ...
|
||||||
|
* The parameters according to the format string.
|
||||||
|
*/
|
||||||
|
int buffer_push_printf(buffer_t *buffer, const char *format, ...);
|
||||||
|
|
||||||
|
/* This pushes a formated string to the end of the buffer using a va_list.
|
||||||
|
* Parameters:
|
||||||
|
* buffer
|
||||||
|
* The buffer to operate on.
|
||||||
|
* format
|
||||||
|
* The format string as for printf() family functions.
|
||||||
|
* ap
|
||||||
|
* The parameters according to the format string as va_list.
|
||||||
|
* See also:
|
||||||
|
* vprintf(3).
|
||||||
|
*/
|
||||||
|
int buffer_push_vprintf(buffer_t *buffer, const char *format, va_list ap);
|
||||||
|
|
||||||
/* This requests for a memory buffer that can be pushed to without the need for copy.
|
/* This requests for a memory buffer that can be pushed to without the need for copy.
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* buffer
|
* buffer
|
||||||
|
@ -281,6 +281,28 @@ static void test_length(void)
|
|||||||
ctest_test("un-referenced", refobject_unref(a) == 0);
|
ctest_test("un-referenced", refobject_unref(a) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_printf(void)
|
||||||
|
{
|
||||||
|
buffer_t *a;
|
||||||
|
const char *str = "Hello World!";
|
||||||
|
const int num = -127;
|
||||||
|
const char *match_a = ":Hello World!:";
|
||||||
|
const char *match_b = ":Hello World!:<-127 >";
|
||||||
|
const char *match_c = ":Hello World!:<-127 >? +127?";
|
||||||
|
|
||||||
|
a = buffer_new_simple();
|
||||||
|
ctest_test("buffer created", a != NULL);
|
||||||
|
|
||||||
|
ctest_test("Set length to match pattern a", buffer_push_printf(a, ":%s:", str) == 0);
|
||||||
|
test__compare_to_string(a, "string matches pattern a", match_a);
|
||||||
|
ctest_test("Set length to match pattern a", buffer_push_printf(a, "<%-5i>", num) == 0);
|
||||||
|
test__compare_to_string(a, "string matches pattern b", match_b);
|
||||||
|
ctest_test("Set length to match pattern a", buffer_push_printf(a, "?%+5i?", -num) == 0);
|
||||||
|
test__compare_to_string(a, "string matches pattern c", match_c);
|
||||||
|
|
||||||
|
ctest_test("un-referenced", refobject_unref(a) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
int main (void)
|
int main (void)
|
||||||
{
|
{
|
||||||
ctest_init();
|
ctest_init();
|
||||||
@ -299,6 +321,8 @@ int main (void)
|
|||||||
test_shift();
|
test_shift();
|
||||||
test_length();
|
test_length();
|
||||||
|
|
||||||
|
test_printf();
|
||||||
|
|
||||||
ctest_fin();
|
ctest_fin();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user