This commit is contained in:
claudex 2026-07-30 18:18:30 +08:00 committed by GitHub
commit a207cf33a8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 146 additions and 66 deletions

View file

@ -57,6 +57,12 @@ when using this option to properly escape. If this option is used at the
command prompt then the % cannot be escaped and unintended expansion is
possible.
To format numerical output for better human readability, append the `:pretty`
modifier to a numerical variable name (e.g., `--write-out '%{size_download:pretty}'`).
This modifier applies standard SI metric suffixes (K, M, G, etc.) and
constrains the output to a maximum width of 5 characters, including the
suffix. This works only with numerical variables.
The variables available are:
## `certs`

View file

@ -121,3 +121,36 @@ void customrequest_helper(HttpReq req, const char *method)
"the way you want. Consider using -I/--head instead.");
}
}
char *max5data(curl_off_t bytes, char *max5, size_t mlen)
{
/* a signed 64-bit value is 8192 petabytes maximum */
const char unit[] = {'k', 'M', 'G', 'T', 'P', 'E', 0};
int k = 0;
if(bytes < 100000) {
curl_msnprintf(max5, mlen, "%5" CURL_FORMAT_CURL_OFF_T, bytes);
return max5;
}
do {
curl_off_t nbytes = bytes / 1024;
if(nbytes < 100) {
/* display with a decimal */
curl_msnprintf(max5, mlen,
"%2" CURL_FORMAT_CURL_OFF_T ".%" CURL_FORMAT_CURL_OFF_T
"%c",
bytes / 1024, (bytes % 1024) * 10 / 1024, unit[k]);
break;
}
else if(nbytes < 10000) {
/* no decimals */
curl_msnprintf(max5, mlen, "%4" CURL_FORMAT_CURL_OFF_T "%c", nbytes,
unit[k]);
break;
}
bytes = nbytes;
k++;
DEBUGASSERT(unit[k]);
} while(unit[k]);
return max5;
}

View file

@ -23,10 +23,20 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "tool_getparam.h"
#include "tool_sdecls.h"
#include "tool_setup.h"
const char *param2text(ParameterError error);
int SetHTTPrequest(HttpReq req, HttpReq *store);
void customrequest_helper(HttpReq req, const char *method);
/* The point of this function would be to return a string of the input data,
but never longer than 5 columns (+ one zero byte).
Add suffix k, M, G when suitable...
Unit test @1622
*/
char *max5data(curl_off_t bytes, char *max5, size_t mlen);
#endif /* HEADER_CURL_TOOL_HELPERS_H */

View file

@ -26,44 +26,6 @@
#include "tool_operate.h"
#include "tool_progress.h"
/* The point of this function would be to return a string of the input data,
but never longer than 5 columns (+ one zero byte).
Add suffix k, M, G when suitable...
Unit test 1622
*/
UNITTEST char *max5data(curl_off_t bytes, char *max5, size_t mlen)
{
/* a signed 64-bit value is 8192 petabytes maximum */
static const char unit[] = { 'k', 'M', 'G', 'T', 'P', 'E', 0 };
int k = 0;
if(bytes < 100000) {
curl_msnprintf(max5, mlen, "%5" CURL_FORMAT_CURL_OFF_T, bytes);
return max5;
}
do {
curl_off_t nbytes = bytes / 1024;
if(nbytes < 100) {
/* display with a decimal */
curl_msnprintf(max5, mlen, "%2" CURL_FORMAT_CURL_OFF_T ".%"
CURL_FORMAT_CURL_OFF_T "%c", bytes / 1024,
(bytes % 1024) * 10 / 1024, unit[k]);
break;
}
else if(nbytes < 10000) {
/* no decimals */
curl_msnprintf(max5, mlen, "%4" CURL_FORMAT_CURL_OFF_T "%c", nbytes,
unit[k]);
break;
}
bytes = nbytes;
k++;
DEBUGASSERT(unit[k]);
} while(unit[k]);
return max5;
}
int xferinfo_cb(void *clientp,
curl_off_t dltotal,
curl_off_t dlnow,

View file

@ -24,6 +24,7 @@
*
***************************************************************************/
#include "tool_setup.h"
#include "tool_helpers.h"
int xferinfo_cb(void *clientp,
curl_off_t dltotal,
@ -38,7 +39,6 @@ struct per_transfer;
void progress_finalize(struct per_transfer *per);
#ifdef UNITTESTS
UNITTEST char *max5data(curl_off_t bytes, char *max5, size_t mlen);
UNITTEST void timebuf(char *r, size_t rlen, curl_off_t seconds);
#endif

View file

@ -21,11 +21,17 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "curlx/dynbuf.h"
#include "tool_msgs.h"
#include "tool_setup.h"
#include "tool_cfgable.h"
#include "tool_helpers.h"
#include "tool_writeout.h"
#include "tool_writeout_json.h"
#include <stdlib.h>
#include <string.h>
struct httpmap {
const char *str;
@ -43,8 +49,7 @@ static const struct httpmap http_version[] = {
static int writeTime(FILE *stream, const struct writeoutvar *wovar,
struct per_transfer *per, CURLcode per_result,
bool use_json)
{
bool use_json, const struct writeoutfilter *filter) {
bool valid = FALSE;
curl_off_t us = 0;
@ -69,6 +74,13 @@ static int writeTime(FILE *stream, const struct writeoutvar *wovar,
curl_mfprintf(stream, "%" CURL_FORMAT_CURL_OFF_T
".%06" CURL_FORMAT_CURL_OFF_T, secs, us);
switch(filter->id) {
case FILTER_NONE:
break;
default:
curl_mfprintf(stream, ":%s", filter->name);
break;
}
}
else {
if(use_json)
@ -79,8 +91,7 @@ static int writeTime(FILE *stream, const struct writeoutvar *wovar,
}
static int urlpart(struct per_transfer *per, writeoutid vid,
const char **contentp)
{
const char **contentp) {
CURLU *uh = curl_url();
int rc = 0;
if(uh) {
@ -171,8 +182,7 @@ static void certinfo(struct per_transfer *per)
static int writeString(FILE *stream, const struct writeoutvar *wovar,
struct per_transfer *per, CURLcode per_result,
bool use_json)
{
bool use_json, const struct writeoutfilter *filter) {
bool valid = FALSE;
const char *strinfo = NULL;
const char *freestr = NULL;
@ -307,8 +317,16 @@ static int writeString(FILE *stream, const struct writeoutvar *wovar,
curl_mfprintf(stream, "\"%s\":", wovar->name);
jsonWriteString(stream, strinfo, FALSE);
}
else
else {
fputs(strinfo, stream);
switch(filter->id) {
case FILTER_NONE:
break;
default:
curl_mfprintf(stream, ":%s", filter->name);
break;
}
}
}
else {
if(use_json)
@ -322,8 +340,7 @@ static int writeString(FILE *stream, const struct writeoutvar *wovar,
static int writeLong(FILE *stream, const struct writeoutvar *wovar,
struct per_transfer *per, CURLcode per_result,
bool use_json)
{
bool use_json, const struct writeoutfilter *filter) {
bool valid = FALSE;
long longinfo = 0;
@ -364,8 +381,16 @@ static int writeLong(FILE *stream, const struct writeoutvar *wovar,
else {
if(wovar->id == VAR_HTTP_CODE || wovar->id == VAR_HTTP_CODE_PROXY)
curl_mfprintf(stream, "%03ld", longinfo);
else
else {
curl_mfprintf(stream, "%ld", longinfo);
switch(filter->id) {
case FILTER_NONE:
break;
default:
curl_mfprintf(stream, ":%s", filter->name);
break;
}
}
}
}
else {
@ -378,10 +403,10 @@ static int writeLong(FILE *stream, const struct writeoutvar *wovar,
static int writeOffset(FILE *stream, const struct writeoutvar *wovar,
struct per_transfer *per, CURLcode per_result,
bool use_json)
{
bool use_json, const struct writeoutfilter *filter) {
bool valid = FALSE;
curl_off_t offinfo = 0;
char prettyOff[6];
(void)per;
(void)per_result;
@ -408,7 +433,18 @@ static int writeOffset(FILE *stream, const struct writeoutvar *wovar,
if(use_json)
curl_mfprintf(stream, "\"%s\":", wovar->name);
curl_mfprintf(stream, "%" CURL_FORMAT_CURL_OFF_T, offinfo);
switch(filter->id) {
case FILTER_NONE:
curl_mfprintf(stream, "%" CURL_FORMAT_CURL_OFF_T, offinfo);
break;
case FILTER_BYTES_PRETTY:
fputs(max5data(offinfo, prettyOff, sizeof(prettyOff)), stream);
break;
default:
curl_mfprintf(stream, "%" CURL_FORMAT_CURL_OFF_T ":%s", offinfo,
filter->name);
}
}
else {
if(use_json)
@ -759,18 +795,39 @@ void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
else {
/* this is meant as a variable to output */
const char *end;
size_t vlen;
const char *filter;
size_t vlen, filen;
if('{' == ptr[1]) {
const struct writeoutvar *wv = NULL;
struct writeoutvar find = { 0 };
struct writeoutfilter cur_fil;
struct writeoutvar find = {0};
filter = strchr(ptr, ':');
end = strchr(ptr, '}');
ptr += 2; /* pass the % and the { */
if(!end) {
fputs("%{", stream);
continue;
}
vlen = end - ptr;
if(filter && filter < end) {
vlen = filter - ptr;
filter += 1; /* remove the : */
filen = end - filter;
if(strncmp("pretty}", filter, filen) == 0) {
cur_fil.name = "pretty";
cur_fil.id = FILTER_BYTES_PRETTY;
}
else {
errorf("Unknown --write-out filter: %s", filter);
break;
}
}
else {
vlen = end - ptr;
cur_fil.name = "none";
cur_fil.id = FILTER_NONE;
}
curlx_dyn_reset(&name);
if(!curlx_dyn_addn(&name, ptr, vlen)) {
find.name = curlx_dyn_ptr(&name);
@ -800,15 +857,15 @@ void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
stream = tool_stderr;
break;
case VAR_JSON:
ourWriteOutJSON(stream, variables,
CURL_ARRAYSIZE(variables),
per, per_result);
ourWriteOutJSON(stream, variables, CURL_ARRAYSIZE(variables),
per, per_result, &cur_fil);
break;
case VAR_HEADER_JSON:
headerJSON(stream, per);
break;
default:
(void)wv->writefunc(stream, wv, per, per_result, FALSE);
(void)wv->writefunc(stream, wv, per, per_result, FALSE,
&cur_fil);
break;
}
}

View file

@ -105,13 +105,23 @@ typedef enum {
VAR_NUM_OF_VARS /* must be the last */
} writeoutid;
typedef enum {
FILTER_NONE,
FILTER_BYTES_PRETTY
} writeoutfilterid;
struct writeoutfilter {
const char *name;
writeoutfilterid id;
};
struct writeoutvar {
const char *name;
writeoutid id;
CURLINFO ci;
int (*writefunc)(FILE *stream, const struct writeoutvar *wovar,
struct per_transfer *per, CURLcode per_result,
bool use_json);
bool use_json, const struct writeoutfilter *filter);
};
void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,

View file

@ -24,8 +24,8 @@
#include "tool_setup.h"
#include "tool_cfgable.h"
#include "tool_writeout_json.h"
#include "tool_writeout.h"
#include "tool_writeout_json.h"
#define MAX_JSON_STRING 100000
@ -95,8 +95,8 @@ void jsonWriteString(FILE *stream, const char *in, bool lowercase)
}
void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[],
size_t nentries,
struct per_transfer *per, CURLcode per_result)
size_t nentries, struct per_transfer *per,
CURLcode per_result, const struct writeoutfilter *filter)
{
size_t i;
@ -104,7 +104,8 @@ void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[],
for(i = 0; i < nentries; i++) {
if(mappings[i].writefunc &&
mappings[i].writefunc(stream, &mappings[i], per, per_result, TRUE))
mappings[i].writefunc(stream, &mappings[i], per, per_result, TRUE,
filter))
fputs(",", stream);
}

View file

@ -30,8 +30,8 @@
int jsonquoted(const char *in, size_t len, struct dynbuf *out, bool lowercase);
void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[],
size_t nentries,
struct per_transfer *per, CURLcode per_result);
size_t nentries, struct per_transfer *per,
CURLcode per_result, const struct writeoutfilter *filter);
void headerJSON(FILE *stream, struct per_transfer *per);
void jsonWriteString(FILE *stream, const char *in, bool lowercase);

View file

@ -23,6 +23,7 @@
***************************************************************************/
#include "unitcheck.h"
#include "tool_progress.h"
#include "tool_helpers.h"
static CURLcode test_tool1622(const char *arg)
{