From 841ef0c048b68cb90cdd54bbfb91911711f89fc7 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 11 Dec 2019 20:16:56 -0800 Subject: [PATCH] BitMask xcode --- src/bitmask.cpp | 52 ++++++++++++++++++++++++++--- src/pvxs/bitmask.h | 10 ++++++ test/testbitmask.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 136 insertions(+), 5 deletions(-) diff --git a/src/bitmask.cpp b/src/bitmask.cpp index e87a734..4895b23 100644 --- a/src/bitmask.cpp +++ b/src/bitmask.cpp @@ -7,6 +7,8 @@ #include #include +#include "pvaproto.h" +#include "utilpvt.h" namespace pvxs { @@ -85,10 +87,6 @@ size_t BitMask::findSet(size_t start) const return _size; } -//BitMask& BitMask::operator&=(const BitMask& o) {} -//BitMask& BitMask::operator|=(const BitMask& o) {} -//BitMask& BitMask::operator^=(const BitMask& o) {} - std::ostream& operator<<(std::ostream& strm, const BitMask& mask) { strm.put('{'); @@ -102,4 +100,50 @@ std::ostream& operator<<(std::ostream& strm, const BitMask& mask) return strm; } +namespace impl { + +PVXS_API +void to_wire(Buffer& buf, const BitMask& mask) +{ + size_t nbytes = (mask.size() + 7u)/8u; // round up #bits to bytes + size_t nwords = nbytes / 8u; + size_t extra = nbytes % 8u; // trailing single bytes + + to_wire(buf, Size{nbytes}); + for(auto i : range(nwords)) { + to_wire(buf, mask.word(i)); + } + if(extra) { + uint64_t last = mask.word(nwords); + for(auto i : range(extra)) { + to_wire(buf, uint8_t(last>>(8u*i))); + } + } +} + +PVXS_API +void from_wire(Buffer& buf, BitMask& mask) +{ + Size nbytes{0u}; + + from_wire(buf, nbytes); + mask.resize(8u*nbytes.size); + + size_t nwords = nbytes.size / 8u; + size_t extra = nbytes.size % 8u; // trailing single bytes + + for(auto i : range(nwords)) { + from_wire(buf, mask.word(i)); + } + if(extra) { + uint64_t& last = mask.word(nwords); + for(auto i : range(extra)) { + uint8_t b=0; + from_wire(buf, b); + last |= uint64_t(b)<<(8u*i); + } + } +} + +} // namespace impl } // namespace pvxs diff --git a/src/pvxs/bitmask.h b/src/pvxs/bitmask.h index 9a1d41a..75f95f6 100644 --- a/src/pvxs/bitmask.h +++ b/src/pvxs/bitmask.h @@ -236,6 +236,16 @@ public: PVXS_API std::ostream& operator<<(std::ostream& strm, const BitMask& mask); +namespace impl { +struct Buffer; + +PVXS_API +void to_wire(Buffer& buf, const BitMask& mask); + +PVXS_API +void from_wire(Buffer& buf, BitMask& mask); +} + } // namespace pvxs #endif // PVXS_BITMASK_H diff --git a/test/testbitmask.cpp b/test/testbitmask.cpp index 67d4af4..692da05 100644 --- a/test/testbitmask.cpp +++ b/test/testbitmask.cpp @@ -9,6 +9,7 @@ #include #include +#include "pvaproto.h" #include "utilpvt.h" using namespace pvxs; @@ -119,17 +120,93 @@ void testExpr() testEq(std::string(SB()< +void testSerCase(bool be, uint8_t(&actual)[N], const char *expect) +{ + std::string sactual((char*)actual, N-1u); + testShow()<<__func__<<"("<<(be?"BE":"LE")<<", \""< O; + VectorOutBuf outbuf(be, O); + to_wire(outbuf, mask); + + testEq(sactual, + std::string((char*)O.data(), O.size()-outbuf.size())); +} + +void testSer() +{ + testDiag("%s", __func__); + + { + uint8_t actual[] = "\x00"; + testSerCase(true, actual, "{}"); + testSerCase(false, actual, "{}"); + } + { + uint8_t actual[] = "\x01\x01"; + testSerCase(true, actual, "{0}"); + testSerCase(false, actual, "{0}"); + } + { + uint8_t actual[] = "\x01\x02"; + testSerCase(true, actual, "{1}"); + testSerCase(false, actual, "{1}"); + } + { + uint8_t actual[] = "\x02\x00\x01"; + testSerCase(true, actual, "{8}"); + testSerCase(false, actual, "{8}"); + } + { + uint8_t actual[] = "\x07\x02\x00\x00\x00\x00\x00\x80"; + testSerCase(true, actual, "{1, 55}"); + testSerCase(false, actual, "{1, 55}"); + } + { + uint8_t actual[] = "\x08\x80\x00\x00\x00\x00\x00\x00\x02"; + testSerCase(true, actual, "{1, 63}"); + } + { + uint8_t actual[] = "\x08\x02\x00\x00\x00\x00\x00\x00\x80"; + testSerCase(false, actual, "{1, 63}"); + } + { + uint8_t actual[] = "\x09\x80\x00\x00\x00\x00\x00\x01\x02\x01"; + testSerCase(true, actual, "{1, 8, 63, 64}"); + } + { + uint8_t actual[] = "\x09\x02\x01\x00\x00\x00\x00\x00\x80\x01"; + testSerCase(false, actual, "{1, 8, 63, 64}"); + } + { + uint8_t actual[] = "\x10\x80\x00\x00\x00\x00\x00\x00\x02\x40\x00\x00\x00\x00\x00\x00\x01"; + testSerCase(true, actual, "{1, 63, 64, 126}"); + } + { + uint8_t actual[] = "\x10\x02\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\x40"; + testSerCase(false, actual, "{1, 63, 64, 126}"); + } +} + } // namespace MAIN(testbitmask) { - testPlan(44); + testPlan(76); testEmpty(); testBasic1(); testBasic2(); testBasic3(); testOp(); testExpr(); + testSer(); cleanup_for_valgrind(); return testDone(); }