1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

lws_strexp: add ability to find output length without write

Sometimes we need to find out the substituted length before we can
allocate and actually store it.  Teach strexp that if we set the
output buffer to NULL (and the output length to something big) we
are asking for the substituted length and to not produce output.
This commit is contained in:
Andy Green 2020-06-15 15:01:35 +01:00
parent 30e6c22e14
commit ac6edaf199
4 changed files with 37 additions and 8 deletions

View file

@ -192,10 +192,15 @@ enum {
* \p exp: the exp object to init
* \p priv: the user's object pointer to pass to callback
* \p cb: the callback to expand named objects
* \p out: the start of the output buffer
* \p out: the start of the output buffer, or NULL just to get the length
* \p olen: the length of the output buffer in bytes
*
* Prepares an lws_strexp_t for use and sets the initial output buffer
*
* If \p out is NULL, substitution proceeds normally, but no output is produced,
* only the length is returned. olen should be set to the largest feasible
* overall length. To use this mode, the substitution callback must also check
* for NULL \p out and avoid producing the output.
*/
LWS_VISIBLE LWS_EXTERN void
lws_strexp_init(lws_strexp_t *exp, void *priv, lws_strexp_expand_cb cb,
@ -205,12 +210,17 @@ lws_strexp_init(lws_strexp_t *exp, void *priv, lws_strexp_expand_cb cb,
* lws_strexp_reset_out() - reset the output buffer on an existing strexp
*
* \p exp: the exp object to init
* \p out: the start of the output buffer
* \p out: the start of the output buffer, or NULL to just get length
* \p olen: the length of the output buffer in bytes
*
* Provides a new output buffer for lws_strexp_expand() to continue to write
* into. It can be the same as the old one if it has been copied out or used.
* The position of the next write will be reset to the start of the given buf.
*
* If \p out is NULL, substitution proceeds normally, but no output is produced,
* only the length is returned. \p olen should be set to the largest feasible
* overall length. To use this mode, the substitution callback must also check
* for NULL \p out and avoid producing the output.
*/
LWS_VISIBLE LWS_EXTERN void
lws_strexp_reset_out(lws_strexp_t *exp, char *out, size_t olen);

View file

@ -936,7 +936,9 @@ lws_strexp_expand(lws_strexp_t *exp, const char *in, size_t len,
break;
}
exp->out[exp->pos++] = *in;
if (exp->out)
exp->out[exp->pos] = *in;
exp->pos++;
if (exp->olen - exp->pos < 1) {
*pused_in = used + 1;
*pused_out = exp->pos;
@ -955,8 +957,11 @@ lws_strexp_expand(lws_strexp_t *exp, const char *in, size_t len,
if (exp->olen - exp->pos < 3)
return -1;
exp->out[exp->pos++] = '$';
exp->out[exp->pos++] = *in;
if (exp->out) {
exp->out[exp->pos++] = '$';
exp->out[exp->pos++] = *in;
} else
exp->pos += 2;
if (*in != '$')
exp->state = LWS_EXPS_LITERAL;
break;
@ -991,7 +996,8 @@ drain:
in++;
}
exp->out[exp->pos] = '\0';
if (exp->out)
exp->out[exp->pos] = '\0';
*pused_in = used;
*pused_out = exp->pos;

View file

@ -167,7 +167,8 @@ lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos,
if (total < budget)
budget = total;
memcpy(out + *pos, replace + (*exp_ofs), budget);
if (out)
memcpy(out + *pos, replace + (*exp_ofs), budget);
*exp_ofs += budget;
*pos += budget;

View file

@ -299,7 +299,8 @@ expand:
if (total < budget)
budget = total;
memcpy(out + *pos, replace + (*exp_ofs), budget);
if (out)
memcpy(out + *pos, replace + (*exp_ofs), budget);
*exp_ofs += budget;
*pos += budget;
@ -354,6 +355,17 @@ int main(int argc, const char **argv)
return 1;
}
/* as above, but don't generate output, just find the length */
lws_strexp_init(&exp, NULL, exp_cb1, NULL, (size_t)-1);
n = lws_strexp_expand(&exp, exp_inp1, 28, &used_in, &used_out);
if (n != LSTRX_DONE || used_in != 28 || used_out != 39) {
lwsl_err("%s: lws_strexp test 2 failed: %d, used_out: %d\n",
__func__, n, (int)used_out);
return 1;
}
p = exp_inp1;
in_len = strlen(p);
memset(obuf, 0, sizeof(obuf));