mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05: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>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "buffer.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));
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
if (!buffer || !data)
|
||||
|
26
src/buffer.h
26
src/buffer.h
@ -18,6 +18,8 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "icecasttypes.h"
|
||||
#include "compat.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);
|
||||
|
||||
/* 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.
|
||||
* Parameters:
|
||||
* buffer
|
||||
|
@ -281,6 +281,28 @@ static void test_length(void)
|
||||
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)
|
||||
{
|
||||
ctest_init();
|
||||
@ -299,6 +321,8 @@ int main (void)
|
||||
test_shift();
|
||||
test_length();
|
||||
|
||||
test_printf();
|
||||
|
||||
ctest_fin();
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user