mirror of
https://github.com/curl/curl.git
synced 2025-02-11 14:50:40 +08:00
tool_writeout: bsearch the variable name
As the list of variable names grows, doing a simple loop to find the name get increasingly worse. This switches to a bsearch. Also: do a case sensitive check for the variable name. The names have not been documented to be case insensitive and there is no point in having them so. Closes #13914
This commit is contained in:
parent
374d178f14
commit
4464c9f2c6
@ -70,12 +70,12 @@ static const struct httpmap http_version[] = {
|
|||||||
Yes: "http_version": "1.1"
|
Yes: "http_version": "1.1"
|
||||||
No: "http_version": 1.1
|
No: "http_version": 1.1
|
||||||
|
|
||||||
Variable names should be in alphabetical order.
|
Variable names MUST be in alphabetical order.
|
||||||
*/
|
*/
|
||||||
static const struct writeoutvar variables[] = {
|
static const struct writeoutvar variables[] = {
|
||||||
{"certs", VAR_CERT, CURLINFO_NONE, writeString},
|
{"certs", VAR_CERT, CURLINFO_NONE, writeString},
|
||||||
{"content_type", VAR_CONTENT_TYPE, CURLINFO_CONTENT_TYPE, writeString},
|
|
||||||
{"conn_id", VAR_CONN_ID, CURLINFO_CONN_ID, writeOffset},
|
{"conn_id", VAR_CONN_ID, CURLINFO_CONN_ID, writeOffset},
|
||||||
|
{"content_type", VAR_CONTENT_TYPE, CURLINFO_CONTENT_TYPE, writeString},
|
||||||
{"errormsg", VAR_ERRORMSG, CURLINFO_NONE, writeString},
|
{"errormsg", VAR_ERRORMSG, CURLINFO_NONE, writeString},
|
||||||
{"exitcode", VAR_EXITCODE, CURLINFO_NONE, writeLong},
|
{"exitcode", VAR_EXITCODE, CURLINFO_NONE, writeLong},
|
||||||
{"filename_effective", VAR_EFFECTIVE_FILENAME, CURLINFO_NONE, writeString},
|
{"filename_effective", VAR_EFFECTIVE_FILENAME, CURLINFO_NONE, writeString},
|
||||||
@ -125,30 +125,29 @@ static const struct writeoutvar variables[] = {
|
|||||||
writeTime},
|
writeTime},
|
||||||
{"time_total", VAR_TOTAL_TIME, CURLINFO_TOTAL_TIME_T, writeTime},
|
{"time_total", VAR_TOTAL_TIME, CURLINFO_TOTAL_TIME_T, writeTime},
|
||||||
{"url", VAR_INPUT_URL, CURLINFO_NONE, writeString},
|
{"url", VAR_INPUT_URL, CURLINFO_NONE, writeString},
|
||||||
|
{"url.fragment", VAR_INPUT_URLFRAGMENT, CURLINFO_NONE, writeString},
|
||||||
|
{"url.host", VAR_INPUT_URLHOST, CURLINFO_NONE, writeString},
|
||||||
|
{"url.options", VAR_INPUT_URLOPTIONS, CURLINFO_NONE, writeString},
|
||||||
|
{"url.password", VAR_INPUT_URLPASSWORD, CURLINFO_NONE, writeString},
|
||||||
|
{"url.path", VAR_INPUT_URLPATH, CURLINFO_NONE, writeString},
|
||||||
|
{"url.port", VAR_INPUT_URLPORT, CURLINFO_NONE, writeString},
|
||||||
|
{"url.query", VAR_INPUT_URLQUERY, CURLINFO_NONE, writeString},
|
||||||
{"url.scheme", VAR_INPUT_URLSCHEME, CURLINFO_NONE, writeString},
|
{"url.scheme", VAR_INPUT_URLSCHEME, CURLINFO_NONE, writeString},
|
||||||
{"url.user", VAR_INPUT_URLUSER, CURLINFO_NONE, writeString},
|
{"url.user", VAR_INPUT_URLUSER, CURLINFO_NONE, writeString},
|
||||||
{"url.password", VAR_INPUT_URLPASSWORD, CURLINFO_NONE, writeString},
|
|
||||||
{"url.options", VAR_INPUT_URLOPTIONS, CURLINFO_NONE, writeString},
|
|
||||||
{"url.host", VAR_INPUT_URLHOST, CURLINFO_NONE, writeString},
|
|
||||||
{"url.port", VAR_INPUT_URLPORT, CURLINFO_NONE, writeString},
|
|
||||||
{"url.path", VAR_INPUT_URLPATH, CURLINFO_NONE, writeString},
|
|
||||||
{"url.query", VAR_INPUT_URLQUERY, CURLINFO_NONE, writeString},
|
|
||||||
{"url.fragment", VAR_INPUT_URLFRAGMENT, CURLINFO_NONE, writeString},
|
|
||||||
{"url.zoneid", VAR_INPUT_URLZONEID, CURLINFO_NONE, writeString},
|
{"url.zoneid", VAR_INPUT_URLZONEID, CURLINFO_NONE, writeString},
|
||||||
|
{"url_effective", VAR_EFFECTIVE_URL, CURLINFO_EFFECTIVE_URL, writeString},
|
||||||
|
{"urle.fragment", VAR_INPUT_URLEFRAGMENT, CURLINFO_NONE, writeString},
|
||||||
|
{"urle.host", VAR_INPUT_URLEHOST, CURLINFO_NONE, writeString},
|
||||||
|
{"urle.options", VAR_INPUT_URLEOPTIONS, CURLINFO_NONE, writeString},
|
||||||
|
{"urle.password", VAR_INPUT_URLEPASSWORD, CURLINFO_NONE, writeString},
|
||||||
|
{"urle.path", VAR_INPUT_URLEPATH, CURLINFO_NONE, writeString},
|
||||||
|
{"urle.port", VAR_INPUT_URLEPORT, CURLINFO_NONE, writeString},
|
||||||
|
{"urle.query", VAR_INPUT_URLEQUERY, CURLINFO_NONE, writeString},
|
||||||
{"urle.scheme", VAR_INPUT_URLESCHEME, CURLINFO_NONE, writeString},
|
{"urle.scheme", VAR_INPUT_URLESCHEME, CURLINFO_NONE, writeString},
|
||||||
{"urle.user", VAR_INPUT_URLEUSER, CURLINFO_NONE, writeString},
|
{"urle.user", VAR_INPUT_URLEUSER, CURLINFO_NONE, writeString},
|
||||||
{"urle.password", VAR_INPUT_URLEPASSWORD, CURLINFO_NONE, writeString},
|
|
||||||
{"urle.options", VAR_INPUT_URLEOPTIONS, CURLINFO_NONE, writeString},
|
|
||||||
{"urle.host", VAR_INPUT_URLEHOST, CURLINFO_NONE, writeString},
|
|
||||||
{"urle.port", VAR_INPUT_URLEPORT, CURLINFO_NONE, writeString},
|
|
||||||
{"urle.path", VAR_INPUT_URLEPATH, CURLINFO_NONE, writeString},
|
|
||||||
{"urle.query", VAR_INPUT_URLEQUERY, CURLINFO_NONE, writeString},
|
|
||||||
{"urle.fragment", VAR_INPUT_URLEFRAGMENT, CURLINFO_NONE, writeString},
|
|
||||||
{"urle.zoneid", VAR_INPUT_URLEZONEID, CURLINFO_NONE, writeString},
|
{"urle.zoneid", VAR_INPUT_URLEZONEID, CURLINFO_NONE, writeString},
|
||||||
{"url_effective", VAR_EFFECTIVE_URL, CURLINFO_EFFECTIVE_URL, writeString},
|
|
||||||
{"urlnum", VAR_URLNUM, CURLINFO_NONE, writeLong},
|
{"urlnum", VAR_URLNUM, CURLINFO_NONE, writeLong},
|
||||||
{"xfer_id", VAR_EASY_ID, CURLINFO_XFER_ID, writeOffset},
|
{"xfer_id", VAR_EASY_ID, CURLINFO_XFER_ID, writeOffset}
|
||||||
{NULL, VAR_NONE, CURLINFO_NONE, NULL}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int writeTime(FILE *stream, const struct writeoutvar *wovar,
|
static int writeTime(FILE *stream, const struct writeoutvar *wovar,
|
||||||
@ -509,6 +508,17 @@ static int writeOffset(FILE *stream, const struct writeoutvar *wovar,
|
|||||||
return 1; /* return 1 if anything was written */
|
return 1; /* return 1 if anything was written */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
matchvar(const void *m1, const void *m2)
|
||||||
|
{
|
||||||
|
const struct writeoutvar *v1 = m1;
|
||||||
|
const struct writeoutvar *v2 = m2;
|
||||||
|
|
||||||
|
return strcmp(v1->name, v2->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_WRITEOUT_NAME_LENGTH 24
|
||||||
|
|
||||||
void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
|
void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
|
||||||
CURLcode per_result)
|
CURLcode per_result)
|
||||||
{
|
{
|
||||||
@ -519,6 +529,7 @@ void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
|
|||||||
struct curl_certinfo *certinfo;
|
struct curl_certinfo *certinfo;
|
||||||
CURLcode res = curl_easy_getinfo(per->curl, CURLINFO_CERTINFO, &certinfo);
|
CURLcode res = curl_easy_getinfo(per->curl, CURLINFO_CERTINFO, &certinfo);
|
||||||
bool fclose_stream = FALSE;
|
bool fclose_stream = FALSE;
|
||||||
|
struct dynbuf name;
|
||||||
|
|
||||||
if(!writeinfo)
|
if(!writeinfo)
|
||||||
return;
|
return;
|
||||||
@ -526,6 +537,7 @@ void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
|
|||||||
if(!res && certinfo)
|
if(!res && certinfo)
|
||||||
per->certinfo = certinfo;
|
per->certinfo = certinfo;
|
||||||
|
|
||||||
|
curlx_dyn_init(&name, MAX_WRITEOUT_NAME_LENGTH);
|
||||||
while(ptr && *ptr && !done) {
|
while(ptr && *ptr && !done) {
|
||||||
if('%' == *ptr && ptr[1]) {
|
if('%' == *ptr && ptr[1]) {
|
||||||
if('%' == ptr[1]) {
|
if('%' == ptr[1]) {
|
||||||
@ -538,8 +550,8 @@ void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
|
|||||||
char *end;
|
char *end;
|
||||||
size_t vlen;
|
size_t vlen;
|
||||||
if('{' == ptr[1]) {
|
if('{' == ptr[1]) {
|
||||||
int i;
|
struct writeoutvar *wv = NULL;
|
||||||
bool match = FALSE;
|
struct writeoutvar find = { 0 };
|
||||||
end = strchr(ptr, '}');
|
end = strchr(ptr, '}');
|
||||||
ptr += 2; /* pass the % and the { */
|
ptr += 2; /* pass the % and the { */
|
||||||
if(!end) {
|
if(!end) {
|
||||||
@ -547,43 +559,47 @@ void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
vlen = end - ptr;
|
vlen = end - ptr;
|
||||||
for(i = 0; variables[i].name; i++) {
|
|
||||||
if((strlen(variables[i].name) == vlen) &&
|
curlx_dyn_reset(&name);
|
||||||
curl_strnequal(ptr, variables[i].name, vlen)) {
|
if(!curlx_dyn_addn(&name, ptr, vlen)) {
|
||||||
match = TRUE;
|
find.name = curlx_dyn_ptr(&name);
|
||||||
switch(variables[i].id) {
|
wv = bsearch(&find,
|
||||||
case VAR_ONERROR:
|
variables, sizeof(variables)/sizeof(variables[0]),
|
||||||
if(per_result == CURLE_OK)
|
sizeof(variables[0]), matchvar);
|
||||||
/* this isn't error so skip the rest */
|
}
|
||||||
done = TRUE;
|
if(wv) {
|
||||||
break;
|
switch(wv->id) {
|
||||||
case VAR_STDOUT:
|
case VAR_ONERROR:
|
||||||
if(fclose_stream)
|
if(per_result == CURLE_OK)
|
||||||
fclose(stream);
|
/* this isn't error so skip the rest */
|
||||||
fclose_stream = FALSE;
|
done = TRUE;
|
||||||
stream = stdout;
|
break;
|
||||||
break;
|
case VAR_STDOUT:
|
||||||
case VAR_STDERR:
|
if(fclose_stream)
|
||||||
if(fclose_stream)
|
fclose(stream);
|
||||||
fclose(stream);
|
fclose_stream = FALSE;
|
||||||
fclose_stream = FALSE;
|
stream = stdout;
|
||||||
stream = tool_stderr;
|
break;
|
||||||
break;
|
case VAR_STDERR:
|
||||||
case VAR_JSON:
|
if(fclose_stream)
|
||||||
ourWriteOutJSON(stream, variables, per, per_result);
|
fclose(stream);
|
||||||
break;
|
fclose_stream = FALSE;
|
||||||
case VAR_HEADER_JSON:
|
stream = tool_stderr;
|
||||||
headerJSON(stream, per);
|
break;
|
||||||
break;
|
case VAR_JSON:
|
||||||
default:
|
ourWriteOutJSON(stream, variables,
|
||||||
(void)variables[i].writefunc(stream, &variables[i],
|
sizeof(variables)/sizeof(variables[0]),
|
||||||
per, per_result, false);
|
per, per_result);
|
||||||
break;
|
break;
|
||||||
}
|
case VAR_HEADER_JSON:
|
||||||
|
headerJSON(stream, per);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
(void)wv->writefunc(stream, wv, per, per_result, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!match) {
|
else {
|
||||||
fprintf(tool_stderr,
|
fprintf(tool_stderr,
|
||||||
"curl: unknown --write-out variable: '%.*s'\n",
|
"curl: unknown --write-out variable: '%.*s'\n",
|
||||||
(int)vlen, ptr);
|
(int)vlen, ptr);
|
||||||
@ -673,4 +689,5 @@ void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
|
|||||||
}
|
}
|
||||||
if(fclose_stream)
|
if(fclose_stream)
|
||||||
fclose(stream);
|
fclose(stream);
|
||||||
|
curlx_dyn_free(&name);
|
||||||
}
|
}
|
||||||
|
@ -101,13 +101,14 @@ void jsonWriteString(FILE *stream, const char *in, bool lowercase)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[],
|
void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[],
|
||||||
|
size_t nentries,
|
||||||
struct per_transfer *per, CURLcode per_result)
|
struct per_transfer *per, CURLcode per_result)
|
||||||
{
|
{
|
||||||
int i;
|
size_t i;
|
||||||
|
|
||||||
fputs("{", stream);
|
fputs("{", stream);
|
||||||
|
|
||||||
for(i = 0; mappings[i].name != NULL; i++) {
|
for(i = 0; i < nentries; i++) {
|
||||||
if(mappings[i].writefunc &&
|
if(mappings[i].writefunc &&
|
||||||
mappings[i].writefunc(stream, &mappings[i], per, per_result, true))
|
mappings[i].writefunc(stream, &mappings[i], per, per_result, true))
|
||||||
fputs(",", stream);
|
fputs(",", stream);
|
||||||
|
@ -30,6 +30,7 @@ int jsonquoted(const char *in, size_t len,
|
|||||||
struct curlx_dynbuf *out, bool lowercase);
|
struct curlx_dynbuf *out, bool lowercase);
|
||||||
|
|
||||||
void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[],
|
void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[],
|
||||||
|
size_t nentries,
|
||||||
struct per_transfer *per, CURLcode per_result);
|
struct per_transfer *per, CURLcode per_result);
|
||||||
void headerJSON(FILE *stream, struct per_transfer *per);
|
void headerJSON(FILE *stream, struct per_transfer *per);
|
||||||
void jsonWriteString(FILE *stream, const char *in, bool lowercase);
|
void jsonWriteString(FILE *stream, const char *in, bool lowercase);
|
||||||
|
@ -59,7 +59,7 @@ Accept: */*
|
|||||||
|
|
||||||
</protocol>
|
</protocol>
|
||||||
<stdout nonewline="yes">
|
<stdout nonewline="yes">
|
||||||
{"certs":"","content_type":"text/html","conn_id":0,"errormsg":null,"exitcode":0,"filename_effective":"%LOGDIR/out%TESTNUMBER","ftp_entry_path":null,"http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"127.0.0.1","local_port":13,"method":"GET","num_certs":0,"num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"proxy_used":0,"redirect_url":null,"referer":null,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"http","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","url.scheme":"http","url.user":null,"url.password":null,"url.options":null,"url.host":"%HOSTIP","url.port":"%HTTPPORT","url.path":"/%TESTNUMBER","url.query":null,"url.fragment":null,"url.zoneid":null,"urle.scheme":"http","urle.user":null,"urle.password":null,"urle.options":null,"urle.host":"%HOSTIP","urle.port":"%HTTPPORT","urle.path":"/%TESTNUMBER","urle.query":null,"urle.fragment":null,"urle.zoneid":null,"url_effective":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","urlnum":0,"xfer_id":0,"curl_version":"curl-unit-test-fake-version"}
|
{"certs":"","conn_id":0,"content_type":"text/html","errormsg":null,"exitcode":0,"filename_effective":"%LOGDIR/out%TESTNUMBER","ftp_entry_path":null,"http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"127.0.0.1","local_port":13,"method":"GET","num_certs":0,"num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"proxy_used":0,"redirect_url":null,"referer":null,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"http","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","url.fragment":null,"url.host":"127.0.0.1","url.options":null,"url.password":null,"url.path":"/%TESTNUMBER","url.port":"%HTTPPORT","url.query":null,"url.scheme":"http","url.user":null,"url.zoneid":null,"url_effective":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","urle.fragment":null,"urle.host":"127.0.0.1","urle.options":null,"urle.password":null,"urle.path":"/%TESTNUMBER","urle.port":"%HTTPPORT","urle.query":null,"urle.scheme":"http","urle.user":null,"urle.zoneid":null,"urlnum":0,"xfer_id":0,"curl_version":"curl-unit-test-fake-version"}
|
||||||
</stdout>
|
</stdout>
|
||||||
</verify>
|
</verify>
|
||||||
</testcase>
|
</testcase>
|
||||||
|
@ -60,7 +60,7 @@ Accept: */*
|
|||||||
|
|
||||||
</protocol>
|
</protocol>
|
||||||
<stdout mode="text">
|
<stdout mode="text">
|
||||||
{"certs":"","content_type":"text/html","conn_id":0,"errormsg":null,"exitcode":0,"filename_effective":"%LOGDIR/out972","ftp_entry_path":null,"http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"%HOSTIP","local_port":13,"method":"GET","num_certs":0,"num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"proxy_used":0,"redirect_url":null,"referer":null,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"http","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","url.scheme":"http","url.user":null,"url.password":null,"url.options":null,"url.host":"%HOSTIP","url.port":"%HTTPPORT","url.path":"/%TESTNUMBER","url.query":null,"url.fragment":null,"url.zoneid":null,"urle.scheme":"http","urle.user":null,"urle.password":null,"urle.options":null,"urle.host":"%HOSTIP","urle.port":"%HTTPPORT","urle.path":"/%TESTNUMBER","urle.query":null,"urle.fragment":null,"urle.zoneid":null,"url_effective":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","urlnum":0,"xfer_id":0,"curl_version":"curl-unit-test-fake-version"}
|
{"certs":"","conn_id":0,"content_type":"text/html","errormsg":null,"exitcode":0,"filename_effective":"%LOGDIR/out%TESTNUMBER","ftp_entry_path":null,"http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"127.0.0.1","local_port":13,"method":"GET","num_certs":0,"num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"proxy_used":0,"redirect_url":null,"referer":null,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"http","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","url.fragment":null,"url.host":"127.0.0.1","url.options":null,"url.password":null,"url.path":"/%TESTNUMBER","url.port":"%HTTPPORT","url.query":null,"url.scheme":"http","url.user":null,"url.zoneid":null,"url_effective":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","urle.fragment":null,"urle.host":"127.0.0.1","urle.options":null,"urle.password":null,"urle.path":"/%TESTNUMBER","urle.port":"%HTTPPORT","urle.query":null,"urle.scheme":"http","urle.user":null,"urle.zoneid":null,"urlnum":0,"xfer_id":0,"curl_version":"curl-unit-test-fake-version"}
|
||||||
</stdout>
|
</stdout>
|
||||||
</verify>
|
</verify>
|
||||||
</testcase>
|
</testcase>
|
||||||
|
Loading…
Reference in New Issue
Block a user