[master] f543c06b5 Overhaul and unify handling of BYTES suffixes.
Poul-Henning Kamp
phk at FreeBSD.org
Tue Jan 29 09:43:08 UTC 2019
commit f543c06b5e65b24e9d701adb0107877c92fb8728
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Tue Jan 29 09:38:35 2019 +0000
Overhaul and unify handling of BYTES suffixes.
Closes #2882
diff --git a/bin/varnishtest/tests/v00033.vtc b/bin/varnishtest/tests/v00033.vtc
index bbe21d1ee..fcd7e422b 100644
--- a/bin/varnishtest/tests/v00033.vtc
+++ b/bin/varnishtest/tests/v00033.vtc
@@ -43,7 +43,7 @@ varnish v1 -syntax 4.0 -errvcl {Expected BYTES unit (B, KB, MB...) got '"X"'} {
}
}
}
-varnish v1 -syntax 4.0 -errvcl {Unknown BYTES unit 'X'. Legal are 'B', 'KB', 'MB', 'GB' and 'TB'} {
+varnish v1 -syntax 4.0 -errvcl {Unknown BYTES unit 'X'} {
sub vcl_recv {
if (storage.Transient.free_space > 4 X) {
}
diff --git a/include/vnum.h b/include/vnum.h
index ae8a8e1f2..53da2a8e3 100644
--- a/include/vnum.h
+++ b/include/vnum.h
@@ -33,7 +33,11 @@ double VNUM(const char *p);
double VNUMpfx(const char *p, const char **e);
vtim_dur VNUM_duration_unit(vtim_dur r, const char *b, const char *e);
vtim_dur VNUM_duration(const char *p);
+double VNUM_bytes_unit(double r, const char *b, const char *e, uintmax_t rel);
const char *VNUM_2bytes(const char *p, uintmax_t *r, uintmax_t rel);
#define VNUM_LEGAL_DURATION \
"Legal duration units are 'ms', 's', 'm', 'h', 'd', 'w' and 'y'"
+
+#define VNUM_LEGAL_BYTES \
+ "Legal byte units are 'B', 'KB', 'MB', 'GB', 'TB' and 'PB'"
diff --git a/lib/libvarnish/vnum.c b/lib/libvarnish/vnum.c
index 99a81a8f5..43baa7da5 100644
--- a/lib/libvarnish/vnum.c
+++ b/lib/libvarnish/vnum.c
@@ -44,7 +44,6 @@
static const char err_miss_num[] = "Missing number";
static const char err_invalid_num[] = "Invalid number";
-static const char err_abs_req[] = "Absolute number required";
static const char err_invalid_suff[] = "Invalid suffix";
/**********************************************************************
@@ -114,7 +113,7 @@ VNUM(const char *p)
vtim_dur
VNUM_duration_unit(vtim_dur r, const char *b, const char *e)
{
- double sc = 1.0;
+ double sc;
if (e == NULL)
e = strchr(b, '\0');
@@ -126,6 +125,7 @@ VNUM_duration_unit(vtim_dur r, const char *b, const char *e)
switch (*b++) {
case 's':
+ sc = 1.0;
break;
case 'm':
if (b < e && *b == 's') {
@@ -178,6 +178,44 @@ VNUM_duration(const char *p)
/**********************************************************************/
+double
+VNUM_bytes_unit(double r, const char *b, const char *e, uintmax_t rel)
+{
+ double sc = 1.0;
+
+ if (e == NULL)
+ e = strchr(b, '\0');
+
+ while (b < e && vct_issp(*b))
+ b++;
+ if (b == e)
+ return (nan(""));
+
+ if (rel != 0 && *b == '%') {
+ r *= rel * 0.01;
+ b++;
+ } else {
+ switch (*b) {
+ case 'k': case 'K': sc = exp2(10); b++; break;
+ case 'm': case 'M': sc = exp2(20); b++; break;
+ case 'g': case 'G': sc = exp2(30); b++; break;
+ case 't': case 'T': sc = exp2(40); b++; break;
+ case 'p': case 'P': sc = exp2(50); b++; break;
+ case 'b': case 'B':
+ break;
+ default:
+ return (nan(""));
+ }
+ if (b < e && (*b == 'b' || *b == 'B'))
+ b++;
+ }
+ while (b < e && vct_issp(*b))
+ b++;
+ if (b < e)
+ return (nan(""));
+ return (sc * r);
+}
+
const char *
VNUM_2bytes(const char *p, uintmax_t *r, uintmax_t rel)
{
@@ -196,48 +234,9 @@ VNUM_2bytes(const char *p, uintmax_t *r, uintmax_t rel)
return (NULL);
}
- if (end[0] == '%' && end[1] == '\0') {
- if (rel == 0)
- return (err_abs_req);
- fval *= rel / 100.0;
- } else {
- /* accept a space before the multiplier */
- if (end[0] == ' ' && end[1] != '\0')
- ++end;
-
- switch (end[0]) {
- case 'k': case 'K':
- fval *= (uintmax_t)1 << 10;
- ++end;
- break;
- case 'm': case 'M':
- fval *= (uintmax_t)1 << 20;
- ++end;
- break;
- case 'g': case 'G':
- fval *= (uintmax_t)1 << 30;
- ++end;
- break;
- case 't': case 'T':
- fval *= (uintmax_t)1 << 40;
- ++end;
- break;
- case 'p': case 'P':
- fval *= (uintmax_t)1 << 50;
- ++end;
- break;
- default:
- break;
- }
-
- /* [bB] is a generic suffix of no effect */
- if (end[0] == 'b' || end[0] == 'B')
- end++;
-
- if (end[0] != '\0')
- return (err_invalid_suff);
- }
-
+ fval = VNUM_bytes_unit(fval, end, NULL, rel);
+ if (isnan(fval))
+ return (err_invalid_suff);
*r = (uintmax_t)round(fval);
return (NULL);
}
@@ -279,11 +278,11 @@ static struct test_case {
{ "1T", (uintmax_t)0, (uintmax_t)1<<40 },
{ "1TB", (uintmax_t)0, (uintmax_t)1<<40 },
{ "1.3TB", (uintmax_t)0, (uintmax_t)1429365116109ULL },
- { "1.7TB", (uintmax_t)0, (uintmax_t)1869169767219ULL },
+ { "1.7\tTB", (uintmax_t)0, (uintmax_t)1869169767219ULL },
{ "1125899906842624", (uintmax_t)0, (uintmax_t)1125899906842624ULL},
- { "1P", (uintmax_t)0, (uintmax_t)1125899906842624ULL},
- { "1PB", (uintmax_t)0, (uintmax_t)1125899906842624ULL},
+ { "1P\t", (uintmax_t)0, (uintmax_t)1125899906842624ULL},
+ { "1PB ", (uintmax_t)0, (uintmax_t)1125899906842624ULL},
{ "1.3 PB", (uintmax_t)0, (uintmax_t)1463669878895411ULL},
{ "1%", (uintmax_t)1024, (uintmax_t)10 },
@@ -293,7 +292,7 @@ static struct test_case {
/* Check the error checks */
{ "", 0, 0, err_miss_num },
{ "m", 0, 0, err_invalid_num },
- { "4%", 0, 0, err_abs_req },
+ { "4%", 0, 0, err_invalid_suff },
{ "3*", 0, 0, err_invalid_suff },
/* TODO: add more */
diff --git a/lib/libvcc/vcc_utils.c b/lib/libvcc/vcc_utils.c
index abe4f69b5..832e5357f 100644
--- a/lib/libvcc/vcc_utils.c
+++ b/lib/libvcc/vcc_utils.c
@@ -381,25 +381,14 @@ vcc_ByteVal(struct vcc *tl, double *d)
vcc_ErrWhere(tl, tl->t);
return;
}
- if (vcc_IdIs(tl->t, "B"))
- sc = 1.;
- else if (vcc_IdIs(tl->t, "KB"))
- sc = 1024.;
- else if (vcc_IdIs(tl->t, "MB"))
- sc = 1024. * 1024.;
- else if (vcc_IdIs(tl->t, "GB"))
- sc = 1024. * 1024. * 1024.;
- else if (vcc_IdIs(tl->t, "TB"))
- sc = 1024. * 1024. * 1024. * 1024.;
- else {
+ sc = VNUM_bytes_unit(1.0, tl->t->b, tl->t->e, 0);
+ if (isnan(sc)) {
VSB_printf(tl->sb, "Unknown BYTES unit ");
vcc_ErrToken(tl, tl->t);
- VSB_printf(tl->sb,
- ". Legal are 'B', 'KB', 'MB', 'GB' and 'TB'\n");
+ VSB_printf(tl->sb, "\n%s\n", VNUM_LEGAL_BYTES);
vcc_ErrWhere(tl, tl->t);
return;
}
vcc_NextToken(tl);
*d = v * sc;
}
-
More information about the varnish-commit
mailing list