diff --git a/src/util/xspan.cpp b/src/util/xspan.cpp index c9e72cc5..b9aced8b 100644 --- a/src/util/xspan.cpp +++ b/src/util/xspan.cpp @@ -63,7 +63,6 @@ void span_check_range(const void *p, const void *base, ptrdiff_t size_in_bytes) SPAN_NAMESPACE_END #endif // WITH_SPAN -#if WITH_SPAN >= 2 // lots of tests (and probably quite a number of redundant tests) @@ -71,6 +70,95 @@ SPAN_NAMESPACE_END // **************************************************************************/ +TEST_CASE("basic xspan usage") { + char buf[4] = {0, 1, 2, 3}; + + SUBCASE("SPAN_x") { + SPAN_0(char) a0 = nullptr; + + SPAN_0(char) b0 = buf; + SPAN_P(char) bp = buf; + + SPAN_0(char) c0 = SPAN_0_MAKE(char, buf); + SPAN_P(char) cp = SPAN_P_MAKE(char, buf); + SPAN_S(char) cs = SPAN_S_MAKE(char, buf, sizeof(buf)); + + SPAN_0(const char) const x0 = SPAN_0_MAKE(const char, buf); + SPAN_P(const char) const xp = SPAN_P_MAKE(const char, buf); + SPAN_S(const char) const xs = SPAN_S_MAKE(const char, buf, sizeof(buf)); + SPAN_P(const char) const yp = xs; + SPAN_0(const char) const z0p = yp; + SPAN_0(const char) const z0s = xs; + + CHECK((a0 == nullptr)); + CHECK(c0 == b0); + CHECK(cp == bp); + CHECK(cs == bp); + CHECK(x0 == z0p); + CHECK(xp == z0s); + } + + SUBCASE("SPAN_x_VAR") { + SPAN_0_VAR(char, a0, nullptr); + + SPAN_0_VAR(char, b0, buf); + SPAN_P_VAR(char, bp, buf); + + SPAN_0_VAR(char, c0, buf, sizeof(buf)); + SPAN_P_VAR(char, cp, buf, sizeof(buf)); + SPAN_S_VAR(char, cs, buf, sizeof(buf)); + + SPAN_0_VAR(char, d0, buf + 1, sizeof(buf), buf); + SPAN_P_VAR(char, dp, buf + 1, sizeof(buf), buf); + SPAN_S_VAR(char, ds, buf + 1, sizeof(buf), buf); + + SPAN_0_VAR(const char, const x0, buf, sizeof(buf)); + SPAN_P_VAR(const char, const xp, buf, sizeof(buf)); + SPAN_S_VAR(const char, const xs, buf, sizeof(buf)); + SPAN_P_VAR(const char, const yp, xs); + SPAN_0_VAR(const char, const z0p, yp); + SPAN_0_VAR(const char, const z0s, xs); + + CHECK((a0 == nullptr)); + CHECK(c0 == b0); + CHECK(cp == bp); + CHECK(cs == bp); + CHECK(d0 == dp); + CHECK(d0 == ds); + CHECK(x0 == z0p); + CHECK(xp == z0s); + } + + SUBCASE("xspan in class") { + struct MyType { + SPAN_0(char) s0; + SPAN_P(char) sp; + SPAN_S(char) ss; +#if __cplusplus >= 201103L + SPAN_0(char) x0 = nullptr; +#endif +#if WITH_SPAN >= 2 + // much nicer syntax when using fully checked xspan: + MyType(char *b, size_t n, bool) : s0(b, n), sp(b, n), ss(b, n) {} +#endif + MyType(char *b, size_t n) + : s0(SPAN_0_MAKE(char, b, n)), sp(SPAN_P_MAKE(char, b, n)), + ss(SPAN_S_MAKE(char, b, n)) { + UNUSED(n); + } + }; + MyType x(buf, sizeof(buf)); + MyType y = MyType(buf, sizeof(buf)); + CHECK(x.s0 == y.sp); + } +} + +/************************************************************************* +// +**************************************************************************/ + +#if WITH_SPAN >= 2 + TEST_CASE("PtrOrSpanOrNull") { char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125}; char *base_buf = real_buf + 2; diff --git a/src/util/xspan.h b/src/util/xspan.h index 791a82b3..9f670e9e 100644 --- a/src/util/xspan.h +++ b/src/util/xspan.h @@ -83,16 +83,16 @@ using SPAN_NAMESPACE_NAME::raw_bytes; // overloaded for all classes #define SPAN_P(type) PtrOrSpan #define SPAN_S(type) Span -// define a new variable -#define SPAN_0_VAR(type, var, first, ...) SPAN_0(type) var(first, ##__VA_ARGS__) -#define SPAN_P_VAR(type, var, first, ...) SPAN_P(type) var(first, ##__VA_ARGS__) -#define SPAN_S_VAR(type, var, first, ...) SPAN_S(type) var(first, ##__VA_ARGS__) - // create a value #define SPAN_0_MAKE(type, first, ...) (SPAN_0(type)(first, ##__VA_ARGS__)) #define SPAN_P_MAKE(type, first, ...) (SPAN_P(type)(first, ##__VA_ARGS__)) #define SPAN_S_MAKE(type, first, ...) (SPAN_S(type)(first, ##__VA_ARGS__)) +// define a variable +#define SPAN_0_VAR(type, var, first, ...) SPAN_0(type) var(first, ##__VA_ARGS__) +#define SPAN_P_VAR(type, var, first, ...) SPAN_P(type) var(first, ##__VA_ARGS__) +#define SPAN_S_VAR(type, var, first, ...) SPAN_S(type) var(first, ##__VA_ARGS__) + #elif WITH_SPAN >= 1 // unchecked - just a no-op pointer wrapper, no extra functionality @@ -101,27 +101,31 @@ using SPAN_NAMESPACE_NAME::raw_bytes; // overloaded for all classes #define SPAN_P(type) Ptr #define SPAN_S(type) Ptr -// define a new variable -#define SPAN_0_VAR(type, var, first, ...) SPAN_0(type) var(first) -#define SPAN_P_VAR(type, var, first, ...) SPAN_P(type) var(first) -#define SPAN_S_VAR(type, var, first, ...) SPAN_S(type) var(first) - // create a value #define SPAN_0_MAKE(type, first, ...) (SPAN_0(type)(first)) #define SPAN_P_MAKE(type, first, ...) (SPAN_P(type)(first)) #define SPAN_S_MAKE(type, first, ...) (SPAN_S(type)(first)) +// define a variable +#define SPAN_0_VAR(type, var, first, ...) SPAN_0(type) var(first) +#define SPAN_P_VAR(type, var, first, ...) SPAN_P(type) var(first) +#define SPAN_S_VAR(type, var, first, ...) SPAN_S(type) var(first) + #else -// unchecked raw pointers +// unchecked regular pointers // helper for implicit pointer conversions and MemBuffer overloads template -inline R *span_make__(R * /*dummy*/, T *first) { +inline R *span_make_helper__(R * /*dummy*/, T *first) { return first; // IMPORTANT: no cast here to detect bad usage } template -inline R *span_make__(R * /*dummy*/, MemBuffer &first) { +inline R *span_make_helper__(R * /*dummy*/, std::nullptr_t /*first*/) { + return nullptr; +} +template +inline R *span_make_helper__(R * /*dummy*/, MemBuffer &first) { return (R *) membuffer_get_void_ptr(first); } @@ -129,15 +133,15 @@ inline R *span_make__(R * /*dummy*/, MemBuffer &first) { #define SPAN_P(type) type * #define SPAN_S(type) type * -// define a new variable -#define SPAN_0_VAR(type, var, first, ...) type *var = span_make__((type *) nullptr, first) -#define SPAN_P_VAR(type, var, first, ...) type *var = span_make__((type *) nullptr, first) -#define SPAN_S_VAR(type, var, first, ...) type *var = span_make__((type *) nullptr, first) - // create a value -#define SPAN_0_MAKE(type, first, ...) (span_make__((type *) nullptr, first)) -#define SPAN_P_MAKE(type, first, ...) (span_make__((type *) nullptr, first)) -#define SPAN_S_MAKE(type, first, ...) (span_make__((type *) nullptr, first)) +#define SPAN_0_MAKE(type, first, ...) (span_make_helper__((type *) nullptr, first)) +#define SPAN_P_MAKE(type, first, ...) (span_make_helper__((type *) nullptr, first)) +#define SPAN_S_MAKE(type, first, ...) (span_make_helper__((type *) nullptr, first)) + +// define a variable +#define SPAN_0_VAR(type, var, first, ...) type *var = SPAN_0_MAKE(type, first) +#define SPAN_P_VAR(type, var, first, ...) type *var = SPAN_P_MAKE(type, first) +#define SPAN_S_VAR(type, var, first, ...) type *var = SPAN_S_MAKE(type, first) #endif // WITH_SPAN