Commit 71b156af authored by Philipp Schafft's avatar Philipp Schafft 🦁

Feature: Added buffer_push_printf() and buffer_push_vprintf()

parent 03d56ca3
......@@ -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)
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment