BitMask xcode

This commit is contained in:
Michael Davidsaver
2019-12-11 20:16:56 -08:00
parent 816838bcd5
commit 841ef0c048
3 changed files with 136 additions and 5 deletions
+48 -4
View File
@@ -7,6 +7,8 @@
#include <algorithm>
#include <pvxs/bitmask.h>
#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
+10
View File
@@ -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
+78 -1
View File
@@ -9,6 +9,7 @@
#include <pvxs/unittest.h>
#include <pvxs/bitmask.h>
#include "pvaproto.h"
#include "utilpvt.h"
using namespace pvxs;
@@ -119,17 +120,93 @@ void testExpr()
testEq(std::string(SB()<<Complex), "{2, 4, 5}");
}
template<size_t N>
void testSerCase(bool be, uint8_t(&actual)[N], const char *expect)
{
std::string sactual((char*)actual, N-1u);
testShow()<<__func__<<"("<<(be?"BE":"LE")<<", \""<<escape(sactual)<<"\", \""<<expect<<"\")";
BitMask mask;
FixedBuf inbuf(be, actual);
from_wire(inbuf, mask);
testEq(std::string(SB()<<mask), expect);
std::vector<uint8_t> 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();
}