BitMask xcode
This commit is contained in:
+48
-4
@@ -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
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user