_logger_vfprintf(FILE *fp, const char *fmt, va_list args) { char sbuf[4096]; wget_buffer_t buf; int err = errno; wget_buffer_init(&buf, sbuf, sizeof(sbuf)); wget_buffer_vprintf(&buf, fmt, args); fwrite(buf.data, 1, buf.length, fp); wget_buffer_deinit(&buf); errno = err; }
_logger_vprintf_func(const wget_logger_t *logger, const char *fmt, va_list args) { char sbuf[4096]; wget_buffer_t buf; int err = errno; wget_buffer_init(&buf, sbuf, sizeof(sbuf)); wget_buffer_vprintf(&buf, fmt, args); logger->func(buf.data, buf.length); wget_buffer_deinit(&buf); errno = err; }
// Callback function, called from CSS parser for each URI found. static void _css_get_url(void *context, const char *url, size_t len, size_t pos) { _CSS_CONTEXT *ctx = context; WGET_PARSED_URL parsed_url = { .len = len, .pos = pos, .url = wget_strmemdup(url, len), .abs_url = NULL }; if (!ctx->uris) { ctx->uris = wget_vector_create(16, -2, NULL); wget_vector_set_destructor(ctx->uris, (wget_vector_destructor_t)_free_url); } wget_vector_add(ctx->uris, &parsed_url, sizeof(parsed_url)); } static void _urls_to_absolute(wget_vector_t *urls, wget_iri_t *base) { if (base && urls) { wget_buffer_t buf; wget_buffer_init(&buf, NULL, 1024); for (int it = 0; it < wget_vector_size(urls); it++) { WGET_PARSED_URL *url = wget_vector_get(urls, it); if (wget_iri_relative_to_abs(base, url->url, url->len, &buf)) url->abs_url = wget_strmemdup(buf.data, buf.length); else error_printf("Cannot resolve relative URI '%s'\n", url->url); } wget_buffer_deinit(&buf); } } wget_vector_t *wget_css_get_urls(const char *css, size_t len, wget_iri_t *base, const char **encoding) { _CSS_CONTEXT context = { .encoding = encoding }; wget_css_parse_buffer(css, len, _css_get_url, encoding ? _css_get_encoding : NULL, &context); _urls_to_absolute(context.uris, base); return context.uris; }
static void test_buffer(void) { char sbuf[16]; wget_buffer_t buf, *bufp; // testing buffer on stack, using initial stack memory // without resizing wget_buffer_init(&buf, sbuf, sizeof(sbuf)); wget_buffer_deinit(&buf); // testing buffer on stack, using initial stack memory // with resizing wget_buffer_init(&buf, sbuf, sizeof(sbuf)); _test_buffer(&buf, "Test 1"); wget_buffer_deinit(&buf); // testing buffer on stack, using initial heap memory // without resizing wget_buffer_init(&buf, NULL, 16); wget_buffer_deinit(&buf); // testing buffer on stack, using initial heap memory // with resizing wget_buffer_init(&buf, NULL, 16); _test_buffer(&buf, "Test 2"); wget_buffer_deinit(&buf); // testing buffer on heap, using initial stack memory // without resizing bufp = wget_buffer_init(NULL, sbuf, sizeof(sbuf)); wget_buffer_deinit(bufp); bufp = wget_buffer_init(NULL, sbuf, sizeof(sbuf)); wget_buffer_free(&bufp); // testing buffer on heap, using initial stack memory // with resizing bufp = wget_buffer_init(NULL, sbuf, sizeof(sbuf)); _test_buffer(bufp, "Test 3"); wget_buffer_deinit(bufp); bufp = wget_buffer_init(NULL, sbuf, sizeof(sbuf)); _test_buffer(bufp, "Test 4"); wget_buffer_free(&bufp); // testing buffer on heap, using initial heap memory // without resizing bufp = wget_buffer_alloc(16); wget_buffer_free(&bufp); // testing buffer on heap, using initial heap memory // with resizing bufp = wget_buffer_alloc(16); _test_buffer(bufp, "Test 5"); wget_buffer_free(&bufp); // check that appending works wget_buffer_init(&buf, sbuf, sizeof(sbuf)); wget_buffer_strcpy(&buf, "A"); wget_buffer_strcat(&buf, "B"); wget_buffer_memcat(&buf, "C", 1); wget_buffer_memset_append(&buf, 'D', 1); wget_buffer_printf_append(&buf, "%s", "E"); if (!strcmp(buf.data, "ABCDE")) ok++; else { failed++; info_printf("test_buffer.append: got %s (expected %s)\n", buf.data, "ABCDE"); } wget_buffer_deinit(&buf); // test wget_buffer_trim() wget_buffer_init(&buf, sbuf, sizeof(sbuf)); for (int mid_ws = 0; mid_ws <= 2; mid_ws++) { char expected[16]; snprintf(expected, sizeof(expected), "x%.*sy", mid_ws, " "); for (int lead_ws = 0; lead_ws <= 2; lead_ws++) { for (int trail_ws = 0; trail_ws <= 2; trail_ws++) { wget_buffer_printf(&buf, "%.*sx%.*sy%.*s", lead_ws, " ", mid_ws, " ", trail_ws, " "); wget_buffer_trim(&buf); if (!strcmp(buf.data, expected)) ok++; else { failed++; info_printf("test_buffer_trim: got '%s' (expected '%s') (%d, %d, %d)\n", buf.data, expected, lead_ws, mid_ws, trail_ws); } } } } wget_buffer_deinit(&buf); }
static void test_buffer_printf(void) { char buf_static[32]; wget_buffer_t buf; // testing buffer_printf() by comparing it with C standard function sprintf() static const char *zero_padded[] = { "", "0" }; static const char *left_adjust[] = { "", "-" }; static const long long number[] = { 0, 1LL, -1LL, 10LL, -10LL, 18446744073709551615ULL }; static const char *modifier[] = { "", "h", "hh", "l", "ll", "z" }; // %L... won't work on OpenBSD5.0 static const char *conversion[] = { "d", "i", "u", "o", "x", "X" }; char fmt[32], result[64], string[32]; size_t z, a, it, n, c, m; int width, precision, skip_left_string_padding; wget_buffer_init(&buf, buf_static, sizeof(buf_static)); wget_buffer_printf(&buf, "%s://%s", "http", "host"); if (strcmp("http://host", buf.data)) { failed++; info_printf("%s: Failed with format ('%%s://%%s','http','host'): '%s' != 'http://host'\n", __func__, buf.data); return; } else ok++; // sprintf on Solaris and Windows uses spaces instead of 0s for e.g. %03s padding // we skip those test when we detect such behavior #if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat" #endif sprintf(result, "%02s", "1"); skip_left_string_padding = (*result != ' '); #if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #pragma GCC diagnostic pop #endif for (z = 0; z < countof(zero_padded); z++) { for (a = 0; a < countof(left_adjust); a++) { for (width = -1; width < 12; width++) { for (precision = -1; precision < 12; precision++) { // testing %s stuff if (skip_left_string_padding && z == 1) goto integer_tests; if (width == -1) { if (precision == -1) { sprintf(fmt,"abc%%%s%ssxyz", left_adjust[a], zero_padded[z]); } else { sprintf(fmt,"abc%%%s%s.%dsxyz", left_adjust[a], zero_padded[z], precision); } } else { if (precision == -1) { sprintf(fmt,"abc%%%s%s%dsxyz", left_adjust[a], zero_padded[z], width); } else { sprintf(fmt,"abc%%%s%s%d.%dsxyz", left_adjust[a], zero_padded[z], width, precision); } } for (it = 0; it < sizeof(string); it++) { memset(string, 'a', it); string[it] = 0; #if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif sprintf(result, fmt, string); wget_buffer_printf(&buf, fmt, string); #if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #pragma GCC diagnostic pop #endif if (strcmp(result, buf.data)) { failed++; info_printf("%s: Failed with format ('%s','%s'): '%s' != '%s'\n", __func__, fmt, string, buf.data, result); return; } else { // info_printf("%s: format ('%s','%s'): '%s' == '%s'\n", __func__, fmt, string, buf.data, result); ok++; } } if (width == -1) { if (precision == -1) { sprintf(fmt,"%%%s%ss", left_adjust[a], zero_padded[z]); } else { sprintf(fmt,"%%%s%s.*s", left_adjust[a], zero_padded[z]); } } else { if (precision == -1) { sprintf(fmt,"%%%s%s*s", left_adjust[a], zero_padded[z]); } else { sprintf(fmt,"%%%s%s*.*s", left_adjust[a], zero_padded[z]); } } for (it = 0; it < sizeof(string); it++) { memset(string, 'a', it); string[it] = 0; #if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif if (width == -1) { if (precision == -1) { sprintf(result, fmt, string); wget_buffer_printf(&buf, fmt, string); } else { sprintf(result, fmt, precision, string); wget_buffer_printf(&buf, fmt, precision, string); } } else { if (precision == -1) { sprintf(result, fmt, width, string); wget_buffer_printf(&buf, fmt, width, string); } else { sprintf(result, fmt, width, precision, string); wget_buffer_printf(&buf, fmt, width, precision, string); } } #if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #pragma GCC diagnostic pop #endif if (strcmp(result, buf.data)) { failed++; info_printf("%s: Failed with format ('%s','%s'): '%s' != '%s'\n", __func__, fmt, string, buf.data, result); return; } else { // info_printf("%s: format ('%s','%s'): '%s' == '%s'\n", __func__, fmt, string, buf.data, result); ok++; } } // testing integer stuff integer_tests: for (m = 0; m < countof(modifier); m++) { for (c = 0; c < countof(conversion); c++) { if (width == -1) { if (precision == -1) { sprintf(fmt,"%%%s%s%s%s", left_adjust[a], zero_padded[z], modifier[m], conversion[c]); } else { sprintf(fmt,"%%%s%s.%d%s%s", left_adjust[a], zero_padded[z], precision, modifier[m], conversion[c]); } } else { if (precision == -1) { sprintf(fmt,"%%%s%s%d%s%s", left_adjust[a], zero_padded[z], width, modifier[m], conversion[c]); } else { sprintf(fmt,"%%%s%s%d.%d%s%s", left_adjust[a], zero_padded[z], width, precision, modifier[m], conversion[c]); } } for (n = 0; n < countof(number); n++) { #if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif sprintf(result, fmt, number[n]); wget_buffer_printf(&buf, fmt, number[n]); #if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #pragma GCC diagnostic pop #endif if (strcmp(result, buf.data)) { failed++; info_printf("%s: Failed with format ('%s','%lld'): '%s' != '%s'\n", __func__, fmt, number[n], buf.data, result); // return; } else { // info_printf("%s: format ('%s','%lld'): '%s' == '%s'\n", __func__, fmt, number[n], buf.data, result); ok++; } } } } } } } } wget_buffer_deinit(&buf); }