PIChunkStream::set() new feature
This commit is contained in:
@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.0)
|
|||||||
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
||||||
project(pip)
|
project(pip)
|
||||||
set(pip_MAJOR 2)
|
set(pip_MAJOR 2)
|
||||||
set(pip_MINOR 26)
|
set(pip_MINOR 27)
|
||||||
set(pip_REVISION 1)
|
set(pip_REVISION 0)
|
||||||
set(pip_SUFFIX )
|
set(pip_SUFFIX )
|
||||||
set(pip_COMPANY SHS)
|
set(pip_COMPANY SHS)
|
||||||
set(pip_DOMAIN org.SHS)
|
set(pip_DOMAIN org.SHS)
|
||||||
|
|||||||
@@ -72,6 +72,16 @@ void PIChunkStream::setSource(PIByteArray * data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIByteArray PIChunkStream::data() const {
|
||||||
|
if (first_byte_taken) {
|
||||||
|
PIByteArray ret(*data_);
|
||||||
|
ret.prepend((uchar)(0x80 | version_));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return *data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int PIChunkStream::read() {
|
int PIChunkStream::read() {
|
||||||
switch (version_) {
|
switch (version_) {
|
||||||
case Version_1:
|
case Version_1:
|
||||||
@@ -108,16 +118,40 @@ int PIChunkStream::peekVInt(Version version_, PIByteArray * data_, int pos, PIBy
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIChunkStream::replaceChunk(int id, const PIByteArray & v) {
|
||||||
|
if (!data_map.contains(id)) return;
|
||||||
|
auto & pos(data_map[id]);
|
||||||
|
PIByteArray nsba;
|
||||||
|
writeVInt(nsba, v.size());
|
||||||
|
int size_mod = (v.size_s() + nsba.size_s()) - (pos.length + pos.size_bytes);
|
||||||
|
pos.length = v.size_s();
|
||||||
|
if (size_mod != 0) {
|
||||||
|
auto it = data_map.makeIterator();
|
||||||
|
while (it.next())
|
||||||
|
if (it.valueRef().start > pos.start)
|
||||||
|
it.valueRef().start += size_mod;
|
||||||
|
if (size_mod > 0)
|
||||||
|
data_->insert(pos.start, PIByteArray(size_mod));
|
||||||
|
else
|
||||||
|
data_->remove(pos.start, -size_mod);
|
||||||
|
}
|
||||||
|
memcpy(data_->data(pos.start - pos.size_bytes), nsba.data(), nsba.size());
|
||||||
|
pos.start += nsba.size_s() - pos.size_bytes;
|
||||||
|
memcpy(data_->data(pos.start), v.data(), pos.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIChunkStream::readAll() {
|
void PIChunkStream::readAll() {
|
||||||
data_map.clear();
|
data_map.clear();
|
||||||
if (!data_) return;
|
if (!data_) return;
|
||||||
int pos = 0, sz = data_->size_s();
|
int pos = 0, sz = data_->size_s(), hsz = 0;
|
||||||
uint csz = 0, cid = 0;
|
uint csz = 0, cid = 0;
|
||||||
PIByteArray hdr;
|
PIByteArray hdr;
|
||||||
while (pos < sz) {
|
while (pos < sz) {
|
||||||
pos += peekVInt((Version)version_, data_, pos, hdr, cid);
|
pos += peekVInt((Version)version_, data_, pos, hdr, cid);
|
||||||
pos += peekVInt((Version)version_, data_, pos, hdr, csz);
|
hsz = peekVInt((Version)version_, data_, pos, hdr, csz);
|
||||||
data_map[cid] = PIPair<int, int>(pos, csz);
|
pos += hsz;
|
||||||
|
data_map[cid] = CacheEntry(pos, csz, hsz);
|
||||||
pos += csz;
|
pos += csz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,6 +174,7 @@ bool PIChunkStream::extract(PIByteArray & data, bool read_all) {
|
|||||||
|
|
||||||
|
|
||||||
void PIChunkStream::_init() {
|
void PIChunkStream::_init() {
|
||||||
|
first_byte_taken = false;
|
||||||
last_id = -1;
|
last_id = -1;
|
||||||
last_data.clear();
|
last_data.clear();
|
||||||
if (!data_->isEmpty()) {
|
if (!data_->isEmpty()) {
|
||||||
@@ -147,7 +182,7 @@ void PIChunkStream::_init() {
|
|||||||
if ((v & 0x80) == 0x80) {
|
if ((v & 0x80) == 0x80) {
|
||||||
v &= 0x7f;
|
v &= 0x7f;
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case 2: version_ = (uchar)Version_2; data_->pop_front(); break;
|
case 2: version_ = (uchar)Version_2; data_->pop_front(); first_byte_taken = true; break;
|
||||||
default: version_ = Version_1; break;
|
default: version_ = Version_1; break;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public:
|
|||||||
void setSource(PIByteArray * data);
|
void setSource(PIByteArray * data);
|
||||||
|
|
||||||
//! Returns internal buffer with written data
|
//! Returns internal buffer with written data
|
||||||
PIByteArray data() const {return tmp_data;}
|
PIByteArray data() const;
|
||||||
|
|
||||||
//! Returns if there is end of stream
|
//! Returns if there is end of stream
|
||||||
bool atEnd() const {return data_->size_s() <= 1;}
|
bool atEnd() const {return data_->size_s() <= 1;}
|
||||||
@@ -105,25 +105,43 @@ public:
|
|||||||
//! Place value of chunk with id \"id\" into \"v\". You should call \a readAll() before using this function!
|
//! Place value of chunk with id \"id\" into \"v\". You should call \a readAll() before using this function!
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const PIChunkStream & get(int id, T & v) const {
|
const PIChunkStream & get(int id, T & v) const {
|
||||||
PIPair<int, int> pos = data_map.value(id);
|
CacheEntry pos = data_map.value(id);
|
||||||
if (pos.first < 0 || pos.second == 0) return *this;
|
if (pos.start < 0 || pos.length == 0) return *this;
|
||||||
PIByteArray ba(data_->data(pos.first), pos.second);
|
PIByteArray ba(data_->data(pos.start), pos.length);
|
||||||
if (!ba.isEmpty())
|
if (!ba.isEmpty())
|
||||||
ba >> v;
|
ba >> v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Replace value of chunk with ID \"id\" to \"v\". You should call \a readAll() before using this function!
|
||||||
|
template <typename T>
|
||||||
|
PIChunkStream & set(int id, const T & v) {
|
||||||
|
PIByteArray ba;
|
||||||
|
ba << v;
|
||||||
|
replaceChunk(id, ba);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _init();
|
void _init();
|
||||||
|
|
||||||
|
struct CacheEntry {
|
||||||
|
CacheEntry(int s = 0, int l = 0, int b = 0): start(s), length(l), size_bytes(b) {}
|
||||||
|
int start;
|
||||||
|
int length;
|
||||||
|
int size_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
static uint readVInt(PIByteArray & s, uchar * bytes = 0);
|
static uint readVInt(PIByteArray & s, uchar * bytes = 0);
|
||||||
static void writeVInt(PIByteArray & s, uint val);
|
static void writeVInt(PIByteArray & s, uint val);
|
||||||
static int peekVInt(Version version_, PIByteArray * data_, int pos, PIByteArray & hdr, uint & ret);
|
static int peekVInt(Version version_, PIByteArray * data_, int pos, PIByteArray & hdr, uint & ret);
|
||||||
|
void replaceChunk(int id, const PIByteArray & v);
|
||||||
|
|
||||||
int last_id;
|
int last_id;
|
||||||
uchar version_;
|
uchar version_;
|
||||||
PIByteArray * data_, last_data, tmp_data;
|
mutable PIByteArray * data_, last_data, tmp_data;
|
||||||
PIMap<int, PIPair<int, int>> data_map;
|
PIMap<int, CacheEntry> data_map;
|
||||||
|
bool first_byte_taken;
|
||||||
|
|
||||||
template <typename T> friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::Chunk<T> & c);
|
template <typename T> friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::Chunk<T> & c);
|
||||||
template <typename T> friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::ChunkConst<T> & c);
|
template <typename T> friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::ChunkConst<T> & c);
|
||||||
|
|||||||
36
main.cpp
36
main.cpp
@@ -1,11 +1,39 @@
|
|||||||
#include "pip.h"
|
#include "pip.h"
|
||||||
|
|
||||||
|
|
||||||
PIPeer p0("p0"), p1("p1");
|
//PIPeer p0("p0"), p1("p1");
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
PIByteArray ba, bd, ext;
|
||||||
PIMap<uint, int> sends, recs;
|
bd.resize(4096);
|
||||||
|
for (int i = 0; i < bd.size_s(); ++i) bd[i] = rand() % 256;
|
||||||
|
uint hash = bd.hash();
|
||||||
|
piCout << hash;
|
||||||
|
{
|
||||||
|
PIChunkStream cs;
|
||||||
|
cs.add(1, PIString("string")).add(3, 123456).add(2, PIString("!!-second-!!"));
|
||||||
|
ba = cs.data();
|
||||||
|
}
|
||||||
|
//piCout << ba.toHex();
|
||||||
|
{
|
||||||
|
PIChunkStream cs(ba);
|
||||||
|
cs.readAll();
|
||||||
|
PIString s1, s2; int i = 0;
|
||||||
|
cs.get(1, s1).get(3, i).get(2, s2);
|
||||||
|
piCout << s1 << s2 << i;
|
||||||
|
cs.set(3, PIString("WHATSAP!"));
|
||||||
|
cs.set(1, bd);
|
||||||
|
ba = cs.data();
|
||||||
|
}
|
||||||
|
//piCout << ba.toHex();
|
||||||
|
{
|
||||||
|
PIChunkStream cs(ba);
|
||||||
|
cs.readAll();
|
||||||
|
PIString s1, s2, s3;
|
||||||
|
cs.get(1, ext).get(2, s2).get(3, s3);
|
||||||
|
piCout << ext.hash() << s2 << s3;
|
||||||
|
}
|
||||||
|
/*PIMap<uint, int> sends, recs;
|
||||||
PISet<uint> errors, missed;
|
PISet<uint> errors, missed;
|
||||||
|
|
||||||
CONNECTL(&p0, dataReceivedEvent, ([&](const PIString & from, const PIByteArray & data){
|
CONNECTL(&p0, dataReceivedEvent, ([&](const PIString & from, const PIByteArray & data){
|
||||||
@@ -38,7 +66,7 @@ int main() {
|
|||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
if (!recs.contains(i)) missed << i;
|
if (!recs.contains(i)) missed << i;
|
||||||
piCout << "errors" << errors;
|
piCout << "errors" << errors;
|
||||||
piCout << "missed" << missed;
|
piCout << "missed" << missed;*/
|
||||||
|
|
||||||
|
|
||||||
/*PIDataTransfer tr0, tr1;
|
/*PIDataTransfer tr0, tr1;
|
||||||
|
|||||||
Reference in New Issue
Block a user