mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-11-03 04:17:17 -05:00
Feature: Added support for %H-style format to string renderer
This commit is contained in:
parent
c4edf52ef8
commit
c2f25a9108
@ -65,11 +65,8 @@ igloo_RO_PUBLIC_TYPE(string_renderer_t, igloo_ro_full_t,
|
||||
igloo_RO_TYPEDECL_NEW(__string_renderer_new)
|
||||
);
|
||||
|
||||
static igloo_error_t string_renderer_append_raw(string_renderer_t *self, const char *string, ssize_t len)
|
||||
static inline igloo_error_t string_renderer_pre_allocate(string_renderer_t *self, size_t len)
|
||||
{
|
||||
if (len < 0)
|
||||
len = strlen(string);
|
||||
|
||||
if (self->len < (self->fill + len + 1)) {
|
||||
size_t new_len = self->len + len + 1 + 64; /* allocate more than we need to avoid re-allocating every time */
|
||||
char *n = realloc(self->buffer, new_len);
|
||||
@ -79,12 +76,36 @@ static igloo_error_t string_renderer_append_raw(string_renderer_t *self, const c
|
||||
self->len = new_len;
|
||||
}
|
||||
|
||||
return igloo_ERROR_NONE;
|
||||
}
|
||||
|
||||
static igloo_error_t string_renderer_append_raw(string_renderer_t *self, const char *string, ssize_t len)
|
||||
{
|
||||
igloo_error_t err;
|
||||
|
||||
if (len < 0)
|
||||
len = strlen(string);
|
||||
|
||||
err = string_renderer_pre_allocate(self, len);
|
||||
if (err != igloo_ERROR_NONE)
|
||||
return err;
|
||||
|
||||
memcpy(self->buffer + self->fill, string, len);
|
||||
self->fill += len;
|
||||
|
||||
return igloo_ERROR_NONE;
|
||||
}
|
||||
|
||||
static inline igloo_error_t string_renderer_append_char(string_renderer_t *self, const char c)
|
||||
{
|
||||
if (self->len < (self->fill + 1 + 1)) {
|
||||
return string_renderer_append_raw(self, &c, 1);
|
||||
}
|
||||
|
||||
self->buffer[self->fill++] = c;
|
||||
return igloo_ERROR_NONE;
|
||||
}
|
||||
|
||||
igloo_error_t string_renderer_start_list(string_renderer_t *self, const char *record_separator, const char *kv_separator, bool allow_null_key, bool allow_null_value, string_renderer_encoding_t encoding)
|
||||
{
|
||||
if (!self)
|
||||
@ -143,6 +164,52 @@ igloo_error_t string_renderer_add_string_with_options(string_renderer_t *s
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
case STRING_RENDERER_ENCODING_H:
|
||||
case STRING_RENDERER_ENCODING_H_ALT:
|
||||
case STRING_RENDERER_ENCODING_H_SPACE:
|
||||
case STRING_RENDERER_ENCODING_H_ALT_SPACE:
|
||||
if (!string) {
|
||||
return string_renderer_append_char(self, '-');
|
||||
} else {
|
||||
bool alt = encoding == STRING_RENDERER_ENCODING_H_ALT || encoding == STRING_RENDERER_ENCODING_H_ALT_SPACE;
|
||||
bool space = encoding == STRING_RENDERER_ENCODING_H_SPACE || encoding == STRING_RENDERER_ENCODING_H_ALT_SPACE;
|
||||
|
||||
/* ignore errors here as we just try to optimise access */
|
||||
string_renderer_pre_allocate(self, strlen(string));
|
||||
|
||||
if (alt) {
|
||||
igloo_error_t err = string_renderer_append_char(self, '"');
|
||||
if (err != igloo_ERROR_NONE)
|
||||
return err;
|
||||
}
|
||||
|
||||
for (const char *sp = string; *sp; sp++) {
|
||||
const char c = *sp;
|
||||
|
||||
/* copied from common/log/log.c __vsnprintf__is_print() */
|
||||
if ((c <= '"' || c == '`' || c == '\\') && !(space && c == ' ')) {
|
||||
static const char hextable[] = "0123456789abcdef";
|
||||
char buf[4] = "\\xXX";
|
||||
buf[2] = hextable[(c >> 4) & 0x0F];
|
||||
buf[3] = hextable[(c >> 0) & 0x0F];
|
||||
igloo_error_t err = string_renderer_append_raw(self, buf, 4);
|
||||
if (err != igloo_ERROR_NONE)
|
||||
return err;
|
||||
} else {
|
||||
igloo_error_t err = string_renderer_append_char(self, c);
|
||||
if (err != igloo_ERROR_NONE)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (alt) {
|
||||
igloo_error_t err = string_renderer_append_char(self, '"');
|
||||
if (err != igloo_ERROR_NONE)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return igloo_ERROR_NONE;
|
||||
break;
|
||||
default:
|
||||
return igloo_ERROR_INVAL;
|
||||
}
|
||||
@ -171,6 +238,10 @@ igloo_error_t string_renderer_add_int_with_options(string_renderer_t *self
|
||||
switch (encoding) {
|
||||
case STRING_RENDERER_ENCODING_PLAIN:
|
||||
case STRING_RENDERER_ENCODING_URI:
|
||||
case STRING_RENDERER_ENCODING_H:
|
||||
case STRING_RENDERER_ENCODING_H_ALT:
|
||||
case STRING_RENDERER_ENCODING_H_SPACE:
|
||||
case STRING_RENDERER_ENCODING_H_ALT_SPACE:
|
||||
{
|
||||
char buffer[64];
|
||||
int ret = snprintf(buffer, sizeof(buffer), "%lli", val);
|
||||
@ -270,7 +341,7 @@ const char * string_renderer_to_string_zero_copy(string_renderer_t *self)
|
||||
return NULL;
|
||||
|
||||
/* add a \0 to the end */
|
||||
if (string_renderer_append_raw(self, "\0", 1) != igloo_ERROR_NONE)
|
||||
if (string_renderer_append_char(self, '\0') != igloo_ERROR_NONE)
|
||||
return NULL;
|
||||
|
||||
/* but do not count it as fill */
|
||||
|
@ -21,7 +21,11 @@ igloo_RO_FORWARD_TYPE(string_renderer_t);
|
||||
typedef enum {
|
||||
STRING_RENDERER_ENCODING_DEFAULT,
|
||||
STRING_RENDERER_ENCODING_PLAIN,
|
||||
STRING_RENDERER_ENCODING_URI
|
||||
STRING_RENDERER_ENCODING_URI,
|
||||
STRING_RENDERER_ENCODING_H, /* same as "%H" */
|
||||
STRING_RENDERER_ENCODING_H_ALT, /* same as "%#H" */
|
||||
STRING_RENDERER_ENCODING_H_SPACE, /* same as "% H" */
|
||||
STRING_RENDERER_ENCODING_H_ALT_SPACE /* same as "%# H" */
|
||||
} string_renderer_encoding_t;
|
||||
|
||||
/* all functions are NOT thread safe */
|
||||
|
85
src/tests/ctest_string_renderer.c
Normal file
85
src/tests/ctest_string_renderer.c
Normal file
@ -0,0 +1,85 @@
|
||||
/* Icecast
|
||||
*
|
||||
* This program is distributed under the GNU General Public License, version 2.
|
||||
* A copy of this license is included with this source.
|
||||
*
|
||||
* Copyright 2022, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> /* for EXIT_FAILURE */
|
||||
#include <string.h> /* for strcmp() */
|
||||
|
||||
#include "../icecasttypes.h"
|
||||
|
||||
#include <igloo/tap.h>
|
||||
#include <igloo/igloo.h>
|
||||
#include <igloo/ro.h>
|
||||
|
||||
#include "../string_renderer.h"
|
||||
|
||||
static igloo_ro_t g_instance;
|
||||
|
||||
static void basic_test(void)
|
||||
{
|
||||
string_renderer_t * renderer;
|
||||
const char *res;
|
||||
|
||||
igloo_tap_test_success("igloo_ro_new renderer", igloo_ro_new(&renderer, string_renderer_t, g_instance));
|
||||
|
||||
igloo_tap_test_success("string_renderer_add_string renderer \"te\"", string_renderer_add_string(renderer, "te"));
|
||||
igloo_tap_test_success("string_renderer_add_string renderer \"st\"", string_renderer_add_string(renderer, "st"));
|
||||
|
||||
res = string_renderer_to_string_zero_copy(renderer);
|
||||
igloo_tap_test("string_renderer_to_string_zero_copy renderer returns non-NULL", res != NULL);
|
||||
if (res) {
|
||||
igloo_tap_test("string_renderer_to_string_zero_copy renderer returns \"test\"", strcmp(res, "test") == 0);
|
||||
}
|
||||
|
||||
igloo_tap_test_success("string_renderer_add_int renderer 133742", string_renderer_add_int(renderer, 133742));
|
||||
igloo_tap_test_success("string_renderer_start_list_formdata renderer", string_renderer_start_list_formdata(renderer));
|
||||
igloo_tap_test_success("string_renderer_add_kv renderer \"key\" \"val ue\"", string_renderer_add_kv(renderer, "key", "val ue"));
|
||||
igloo_tap_test_success("string_renderer_add_ki renderer \"num\", -31415", string_renderer_add_ki(renderer, "num", -31415));
|
||||
igloo_tap_test_success("string_renderer_end_list renderer", string_renderer_end_list(renderer));
|
||||
|
||||
res = string_renderer_to_string_zero_copy(renderer);
|
||||
igloo_tap_test("string_renderer_to_string_zero_copy renderer returns non-NULL", res != NULL);
|
||||
if (res) {
|
||||
igloo_tap_test("string_renderer_to_string_zero_copy renderer returns \"test133742key=val%20ue&num=-31415\"", strcmp(res, "test133742key=val%20ue&num=-31415") == 0);
|
||||
}
|
||||
|
||||
igloo_tap_test_success("string_renderer_add_string_with_options renderer \"te!s t\" false STRING_RENDERER_ENCODING_H", string_renderer_add_string_with_options(renderer, "te!s t", false, STRING_RENDERER_ENCODING_H));
|
||||
igloo_tap_test_success("string_renderer_add_string_with_options renderer \"te!s t\" false STRING_RENDERER_ENCODING_H_ALT", string_renderer_add_string_with_options(renderer, "te!s t", false, STRING_RENDERER_ENCODING_H_ALT));
|
||||
igloo_tap_test_success("string_renderer_add_string_with_options renderer \"te!s t\" false STRING_RENDERER_ENCODING_H_SPACE", string_renderer_add_string_with_options(renderer, "te!s t", false, STRING_RENDERER_ENCODING_H_SPACE));
|
||||
igloo_tap_test_success("string_renderer_add_string_with_options renderer \"te!s t\" false STRING_RENDERER_ENCODING_H_ALT_SPACE", string_renderer_add_string_with_options(renderer, "te!s t", false, STRING_RENDERER_ENCODING_H_ALT_SPACE));
|
||||
igloo_tap_test_success("string_renderer_add_string_with_options renderer NULL true STRING_RENDERER_ENCODING_H", string_renderer_add_string_with_options(renderer, NULL, true, STRING_RENDERER_ENCODING_H));
|
||||
|
||||
res = string_renderer_to_string_zero_copy(renderer);
|
||||
igloo_tap_test("string_renderer_to_string_zero_copy renderer returns non-NULL", res != NULL);
|
||||
if (res) {
|
||||
igloo_tap_test("string_renderer_to_string_zero_copy renderer returns \"test133742key=val%20ue&num=-31415te\\x21s\\x20t\"te\\x21s\\x20t\"te\\x21s t\"te\\x21s t\"-\"", strcmp(res, "test133742key=val%20ue&num=-31415te\\x21s\\x20t\"te\\x21s\\x20t\"te\\x21s t\"te\\x21s t\"-") == 0);
|
||||
}
|
||||
|
||||
igloo_tap_test_success("unref renderer", igloo_ro_unref(&renderer));
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
igloo_tap_init();
|
||||
igloo_tap_exit_on(igloo_TAP_EXIT_ON_FIN, NULL);
|
||||
igloo_tap_test_success("igloo_initialize", igloo_initialize(&g_instance));
|
||||
if (igloo_ro_is_null(g_instance)) {
|
||||
igloo_tap_bail_out("Can not get an instance");
|
||||
return EXIT_FAILURE; // return failure as we should never reach this point!
|
||||
}
|
||||
|
||||
basic_test();
|
||||
|
||||
igloo_tap_test_success("unref instance", igloo_ro_unref(&g_instance));
|
||||
igloo_tap_fin();
|
||||
|
||||
return EXIT_FAILURE; // return failure as we should never reach this point!
|
||||
}
|
Loading…
Reference in New Issue
Block a user