From bbe91a5405e1f95759eeb3c2faa60e7d37fc0fb6 Mon Sep 17 00:00:00 2001 From: TimePath Date: Sun, 20 Dec 2015 14:11:56 +1100 Subject: [PATCH] yEnc binary-to-text encoding with tests --- qcsrc/lib/_all.inc | 1 + qcsrc/lib/iter.qh | 18 ++++++++ qcsrc/lib/test.qc | 33 ++++++-------- qcsrc/lib/test.qh | 19 +++++--- qcsrc/lib/yenc.qh | 63 +++++++++++++++++++++++++++ qcsrc/menu/xonotic/slider_decibels.qc | 7 +-- 6 files changed, 112 insertions(+), 29 deletions(-) create mode 100644 qcsrc/lib/yenc.qh diff --git a/qcsrc/lib/_all.inc b/qcsrc/lib/_all.inc index 2d1c0b974..563a86c3c 100644 --- a/qcsrc/lib/_all.inc +++ b/qcsrc/lib/_all.inc @@ -72,3 +72,4 @@ #include "unsafe.qh" #include "urllib.qc" #include "vector.qh" +#include "yenc.qh" diff --git a/qcsrc/lib/iter.qh b/qcsrc/lib/iter.qh index f293aa149..7a21dab76 100644 --- a/qcsrc/lib/iter.qh +++ b/qcsrc/lib/iter.qh @@ -33,6 +33,24 @@ } \ } MACRO_END +#define STRING_ITERATOR(this, s, i) \ + string this##_s = s; \ + int this##_i = i; \ + MACRO_BEGIN MACRO_END + +#define STRING_ITERATOR_GET(this) str2chr(this##_s, this##_i++) + +#define FOREACH_CHAR(s, cond, body) \ + MACRO_BEGIN \ + { \ + STRING_ITERATOR(iter, s, 0); \ + int it; \ + while ((it = STRING_ITERATOR_GET(iter)) > 0) \ + { \ + if (cond) { LAMBDA(body) } \ + } \ + } MACRO_END + #if defined(CSQC) entity(.string fld, string match, .entity tofield) _findchainstring_tofield = #402; entity(.entity fld, entity match, .entity tofield) findchainentity_tofield = #403; diff --git a/qcsrc/lib/test.qc b/qcsrc/lib/test.qc index 3929bf1c3..23b032768 100644 --- a/qcsrc/lib/test.qc +++ b/qcsrc/lib/test.qc @@ -1,7 +1,7 @@ #include "test.qh" -float TEST_failed; -float TEST_ok; +int TEST_failed; +bool TEST_ok; void TEST_Fail(string cond) { @@ -15,42 +15,37 @@ void TEST_OK() TEST_ok = true; } -float TEST_RunAll() +int TEST_RunAll_accumulated(int init); +bool TEST_RunAll() { - int f = 0; - float n = numentityfields(); - for (int i = 0; i < n; ++i) - { - string name = entityfieldname(i); - if (substring(name, 0, 6) == "_TEST_") - if (!TEST_Run(substring(name, 6, -1))) ++f; - } + int f = TEST_RunAll_accumulated(0); if (f) { LOG_INFOF("%d tests failed\n", f); - return 1; + return true; } else { - LOG_INFOF("All tests OK\n", f); - return 0; + LOG_INFO("All tests OK\n"); + return false; } } -float TEST_Run(string s) +bool TEST_Run(string s) { LOG_INFOF("%s: testing...\n", s); - TEST_failed = TEST_ok = 0; + TEST_failed = 0; + TEST_ok = false; callfunction(strcat("_TEST_", s)); if (TEST_failed > 0) { LOG_INFOF("%s: %d items failed.\n", s, TEST_failed); - return 0; + return false; } else if (!TEST_ok) { LOG_INFOF("%s: did not complete.\n", s); - return 0; + return false; } - return 1; + return true; } diff --git a/qcsrc/lib/test.qh b/qcsrc/lib/test.qh index 2890fcaf9..2f4f2dee5 100644 --- a/qcsrc/lib/test.qh +++ b/qcsrc/lib/test.qh @@ -1,15 +1,20 @@ #ifndef TEST_H #define TEST_H -#define TEST_Check(cond) \ - MACRO_BEGIN \ - { \ - if (!(cond)) TEST_Fail( #cond); \ - } MACRO_END +#define TEST(id) \ + void _TEST_##id(); \ + [[accumulate]] int TEST_RunAll_accumulated(int f) { \ + if (!TEST_Run(#id)) ++f; \ + return = f; \ + } \ + void _TEST_##id() + +#define TEST_Check(cond) MACRO_BEGIN { if (!(cond)) TEST_Fail(#cond); } MACRO_END void TEST_OK(); void TEST_Fail(string cond); -float TEST_RunAll(); -float TEST_Run(string test); +bool TEST_RunAll(); +bool TEST_Run(string test); + #endif diff --git a/qcsrc/lib/yenc.qh b/qcsrc/lib/yenc.qh new file mode 100644 index 000000000..32a1648c3 --- /dev/null +++ b/qcsrc/lib/yenc.qh @@ -0,0 +1,63 @@ +#ifndef YENC_H +#define YENC_H + +#define yenc_single(c, ret) \ + MACRO_BEGIN { \ + int conv = c; \ + conv += 42; \ + if (conv >= 256) conv -= 256; \ + switch (conv) \ + { \ + default: \ + { \ + string yenc_it = chr2str(conv); \ + ret = yenc_it; \ + break; \ + } \ + case '\0': \ + case '\n': \ + case '\r': \ + case '=': \ + { \ + conv += 64; \ + string yenc_it = chr2str('=', conv); \ + ret = yenc_it; \ + break; \ + } \ + } \ + } MACRO_END + +#define ydec_single(stringiter, ret) \ + MACRO_BEGIN { \ + int conv = STRING_ITERATOR_GET(stringiter); \ + bool esc = false; \ + if (conv == '=') \ + { \ + esc = true; \ + conv = STRING_ITERATOR_GET(stringiter); \ + conv -= 64; \ + } \ + if (conv < 42) conv += 256; \ + conv -= 42; \ + ret = conv; \ + } MACRO_END + +TEST(yEncDec) +{ + for (int i = 0; i < 255; ++i) + { + int expect = i; + + string fragment; + yenc_single(expect, fragment); + + int encdec; + STRING_ITERATOR(fragmentiterator, fragment, 0); + ydec_single(fragmentiterator, encdec); + + TEST_Check(encdec == expect); + } + TEST_OK(); +} + +#endif diff --git a/qcsrc/menu/xonotic/slider_decibels.qc b/qcsrc/menu/xonotic/slider_decibels.qc index e577cba66..6a8dc903f 100644 --- a/qcsrc/menu/xonotic/slider_decibels.qc +++ b/qcsrc/menu/xonotic/slider_decibels.qc @@ -94,10 +94,11 @@ string XonoticDecibelsSlider_valueToText(entity me, float v) return sprintf(_("%s dB"), ftos_decimals(toDecibelOfSquare(fromDecibelOfSquare(v, me.valueMin), 0), me.valueDigits)); } -void _TEST_XonoticDecibelsSlider() +bool autocvar_test_XonoticDecibelsSlider = false; +TEST(XonoticDecibelsSlider) { - float i; - for(i = -400; i < 0; ++i) + if (!autocvar_test_XonoticDecibelsSlider) { TEST_OK(); return; } + for (int i = -400; i < 0; ++i) { float db = i * 0.1; float v = fromDecibelOfSquare(db, -40); -- 2.39.2