PIVariant custom casts works
This commit is contained in:
@@ -112,7 +112,18 @@ void PIVariant::setValueFromString(const PIString & v) {
|
|||||||
case PIVariant::pivDir: {PIVariantTypes::Dir r = toDir(); r.dir = v; setValue(r);} break;
|
case PIVariant::pivDir: {PIVariantTypes::Dir r = toDir(); r.dir = v; setValue(r);} break;
|
||||||
case PIVariant::pivColor: {setValue(PIVariantTypes::Color(v.mid(1).toUInt(16)));} break;
|
case PIVariant::pivColor: {setValue(PIVariantTypes::Color(v.mid(1).toUInt(16)));} break;
|
||||||
case PIVariant::pivIODevice: {setValue(PIVariantTypes::IODevice());} break; // TODO
|
case PIVariant::pivIODevice: {setValue(PIVariantTypes::IODevice());} break; // TODO
|
||||||
case PIVariant::pivCustom: {} break; // TODO;
|
case PIVariant::pivCustom: {
|
||||||
|
#ifdef CUSTOM_PIVARIANT
|
||||||
|
__PIVariantInfo__ * vi = __PIVariantInfoStorage__::get()->map->value(__PIVariantFunctions__<PIString>::typeIDHelper());
|
||||||
|
if (vi) {
|
||||||
|
__PIVariantInfo__::castHelperFunc cf = vi->cast.value(_typeID);
|
||||||
|
if (cf) {
|
||||||
|
PIByteArray sba; sba << v;
|
||||||
|
_content = cf(sba);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,8 +227,10 @@ PIVariant::Type PIVariant::typeFromID(uint type_id) {
|
|||||||
if (type_id == typeID<PIMathMatrixd>()) return PIVariant::pivMathMatrix;
|
if (type_id == typeID<PIMathMatrixd>()) return PIVariant::pivMathMatrix;
|
||||||
if (type_id == typeID<PILined>()) return PIVariant::pivLine;
|
if (type_id == typeID<PILined>()) return PIVariant::pivLine;
|
||||||
if (type_id == typeID<PIVariantTypes::IODevice>()) return PIVariant::pivIODevice;
|
if (type_id == typeID<PIVariantTypes::IODevice>()) return PIVariant::pivIODevice;
|
||||||
|
#ifdef CUSTOM_PIVARIANT
|
||||||
if (__PIVariantInfoStorage__::get()->map->contains(type_id))
|
if (__PIVariantInfoStorage__::get()->map->contains(type_id))
|
||||||
return PIVariant::pivCustom;
|
return PIVariant::pivCustom;
|
||||||
|
#endif
|
||||||
return PIVariant::pivInvalid;
|
return PIVariant::pivInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,12 +136,12 @@ public:
|
|||||||
return ret; \
|
return ret; \
|
||||||
} \
|
} \
|
||||||
STATIC_INITIALIZER_BEGIN \
|
STATIC_INITIALIZER_BEGIN \
|
||||||
__PIVariantInfo__ * vi(__PIVariantInfoStorage__::get()->map->value(name.hash(), nullptr)); \
|
__PIVariantInfo__ * vi(__PIVariantInfoStorage__::get()->map->value(__PIVariantFunctions__< classname_from >::typeIDHelper(), nullptr)); \
|
||||||
if (!vi) { \
|
if (!vi) { \
|
||||||
piCout << "Warning! Using REGISTER_VARIANT_CAST("#classname_from", "#classname_to") before REGISTER_VARIANT("#classname_from"), ignore."; \
|
piCout << "Warning! Using REGISTER_VARIANT_CAST("#classname_from", "#classname_to") before REGISTER_VARIANT("#classname_from"), ignore."; \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
vi->cast[cname.hash()] = __PIVariantFunctions__<classname_from>::castHelper<classname_to>; \
|
vi->cast[__PIVariantFunctions__< classname_to >::typeIDHelper()] = __PIVariantFunctions__<classname_from>::castHelper<classname_to>; \
|
||||||
STATIC_INITIALIZER_END \
|
STATIC_INITIALIZER_END \
|
||||||
template<> template<> \
|
template<> template<> \
|
||||||
classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(const classname_from & v)
|
classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(const classname_from & v)
|
||||||
@@ -737,7 +737,11 @@ public:
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static uint typeID() {
|
static uint typeID() {
|
||||||
|
#ifdef CUSTOM_PIVARIANT
|
||||||
return __PIVariantFunctions__<T>::typeIDHelper();
|
return __PIVariantFunctions__<T>::typeIDHelper();
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -762,13 +766,13 @@ private:
|
|||||||
template<typename T> inline static T getAsValue(const PIVariant & v) {
|
template<typename T> inline static T getAsValue(const PIVariant & v) {
|
||||||
#ifdef CUSTOM_PIVARIANT
|
#ifdef CUSTOM_PIVARIANT
|
||||||
if (v._content.isEmpty() || !v._info) return T();
|
if (v._content.isEmpty() || !v._info) return T();
|
||||||
PIString cn = __PIVariantFunctions__<T>::typeNameHelper();
|
uint cnid = __PIVariantFunctions__<T>::typeIDHelper();
|
||||||
//piCout << "gav" << cn;
|
//piCout << "gav" << cn;
|
||||||
PIByteArray ba;
|
PIByteArray ba;
|
||||||
if (cn == v._info->typeName) {
|
if (cnid == v._info->typeID) {
|
||||||
ba = v._content;
|
ba = v._content;
|
||||||
} else {
|
} else {
|
||||||
__PIVariantInfo__::castHelperFunc cf = v._info->cast.value(cn.hash());
|
__PIVariantInfo__::castHelperFunc cf = v._info->cast.value(cnid);
|
||||||
//piCout << "gav cast" << cf;
|
//piCout << "gav cast" << cf;
|
||||||
if (!cf) return T();
|
if (!cf) return T();
|
||||||
ba = cf(v._content);
|
ba = cf(v._content);
|
||||||
|
|||||||
365
main.cpp
365
main.cpp
@@ -13,217 +13,174 @@ typedef PIVector<PIVariant> PIVariantVector;
|
|||||||
REGISTER_VARIANT(PIVariantMap);
|
REGISTER_VARIANT(PIVariantMap);
|
||||||
REGISTER_VARIANT(PIVariantVector);
|
REGISTER_VARIANT(PIVariantVector);
|
||||||
|
|
||||||
#ifdef WINDOWS
|
|
||||||
# include <namedpipeapi.h>
|
|
||||||
# include <handleapi.h>
|
|
||||||
# include <fileapi.h>
|
|
||||||
# include <processthreadsapi.h>
|
|
||||||
typedef HANDLE pipe_type;
|
|
||||||
#else
|
|
||||||
# include <unistd.h>
|
|
||||||
typedef int pipe_type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct Pipe {
|
class PIValueTree {
|
||||||
pipe_type fd_read = 0;
|
|
||||||
pipe_type fd_write = 0;
|
|
||||||
void create() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
CreatePipe(&fd_read, &fd_write, NULL, 0);
|
|
||||||
#else
|
|
||||||
pipe((int*)this);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
void destoy() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
CloseHandle(fd_read);
|
|
||||||
CloseHandle(fd_write);
|
|
||||||
#else
|
|
||||||
close(fd_read);
|
|
||||||
close(fd_write);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
int read(void * d, int s) {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
DWORD ret(0);
|
|
||||||
ReadFile(fd_read, d, s, &ret, NULL);
|
|
||||||
return ret;
|
|
||||||
#else
|
|
||||||
return ::read(fd_read, d, s);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
int write(void * d, int s) {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
DWORD ret(0);
|
|
||||||
WriteFile(fd_write, d, s, &ret, NULL);
|
|
||||||
return ret;
|
|
||||||
#else
|
|
||||||
return ::write(fd_write, d, s);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr int count = 4;
|
|
||||||
Pipe pipes[count];
|
|
||||||
|
|
||||||
class T: public PIThread {
|
|
||||||
public:
|
public:
|
||||||
T(int index): PIThread() {ind = index; pipe = pipes[index];}
|
PIValueTree();
|
||||||
void run() {
|
PIValueTree(const PIVariant & v);
|
||||||
PIByteArray data(1024);
|
PIValueTree(const PIString & n, const PIVariant & v);
|
||||||
piCout << "[T"<<ind<<"] start";
|
|
||||||
int readed = pipe.read(data.data(), data.size());
|
enum FlagStandard {
|
||||||
piCout << "[T"<<ind<<"] readed" << readed << errorString();
|
Hidden = 0x01,
|
||||||
piCout << "[T"<<ind<<"] end";
|
Editable = 0x02,
|
||||||
}
|
Label = 0x04,
|
||||||
int ind;
|
ArrayReorder = 0x1001,
|
||||||
Pipe pipe;
|
ArrayDynamic = 0x1002,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isNull() const {return _is_null;}
|
||||||
|
bool isValid() const {return _value.isValid();}
|
||||||
|
|
||||||
|
const PIString & name() const {return _name;}
|
||||||
|
void setName(const PIString & n);
|
||||||
|
|
||||||
|
const PIVariant & value() const {return _value;}
|
||||||
|
void setValue(const PIVariant & v);
|
||||||
|
|
||||||
|
const PIVector<PIValueTree> & children() const {return _children;}
|
||||||
|
|
||||||
|
const PIVariantMap & attributes() const {return _attributes;}
|
||||||
|
PIVariantMap & attributes() {return _attributes;}
|
||||||
|
|
||||||
|
PIFlags<FlagStandard> flagsStandard() {return _flags_standard;}
|
||||||
|
uint flagsCustom() {return _flags_custom;}
|
||||||
|
|
||||||
|
bool contains(const PIString & name) const;
|
||||||
|
PIValueTree child(const PIString & name) const;
|
||||||
|
PIValueTree & child(const PIString & name);
|
||||||
|
PIValueTree & insert(const PIValueTree & n);
|
||||||
|
PIValueTree & remove(const PIString & name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static PIValueTree & nullValue();
|
||||||
|
PIString _name;
|
||||||
|
PIVariantMap _attributes;
|
||||||
|
PIVariant _value;
|
||||||
|
PIVector<PIValueTree> _children;
|
||||||
|
uint _flags_standard = Editable;
|
||||||
|
uint _flags_custom = 0u;
|
||||||
|
bool _is_null = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
PITimeMeasurer tm;
|
|
||||||
void phase(const char * msg) {
|
|
||||||
piCout << "";
|
|
||||||
piCout << piRound(tm.elapsed_s() * 10) / 10. << "s" << msg;
|
PIValueTree::PIValueTree() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIValueTree::PIValueTree(const PIVariant & v) {
|
||||||
|
setValue(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIValueTree::PIValueTree(const PIString & n, const PIVariant & v) {
|
||||||
|
setName(n);
|
||||||
|
setValue(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIValueTree::setName(const PIString & n) {
|
||||||
|
if (_is_null) return;
|
||||||
|
_name = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIValueTree::setValue(const PIVariant & v) {
|
||||||
|
if (_is_null) return;
|
||||||
|
_value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIValueTree::contains(const PIString & name) const {
|
||||||
|
if (_is_null) return true;
|
||||||
|
for (const auto & c: _children)
|
||||||
|
if (c.name() == name)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIValueTree PIValueTree::child(const PIString & name) const {
|
||||||
|
if (_is_null) return PIValueTree();
|
||||||
|
for (const auto & c: _children)
|
||||||
|
if (c.name() == name)
|
||||||
|
return c;
|
||||||
|
return PIValueTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIValueTree & PIValueTree::child(const PIString & name) {
|
||||||
|
if (_is_null) return nullValue();
|
||||||
|
for (auto & c: _children)
|
||||||
|
if (c.name() == name)
|
||||||
|
return c;
|
||||||
|
return nullValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIValueTree & PIValueTree::insert(const PIValueTree & n) {
|
||||||
|
if (_is_null) return nullValue();
|
||||||
|
for (auto & c: _children)
|
||||||
|
if (c.name() == n.name()) {
|
||||||
|
c = n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
_children << n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIValueTree & PIValueTree::remove(const PIString & name) {
|
||||||
|
if (_is_null) return nullValue();
|
||||||
|
_children.removeWhere([name](const PIValueTree & i){return i.name() == name;});
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIValueTree & PIValueTree::nullValue() {
|
||||||
|
static PIValueTree ret;
|
||||||
|
ret._is_null = true;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct SomeType {
|
||||||
|
int i;
|
||||||
|
float f;
|
||||||
|
};
|
||||||
|
|
||||||
|
PICout operator <<(PICout c, const SomeType & v) {
|
||||||
|
c << "SomeType(" << v.i << "," << v.f << ")";
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_VARIANT(SomeType);
|
||||||
|
REGISTER_VARIANT_CAST(SomeType, PIString) {
|
||||||
|
return PIString::fromNumber(v.i) + ";" + PIString::fromNumber(v.f);
|
||||||
|
}
|
||||||
|
REGISTER_VARIANT_CAST(PIString, SomeType) {
|
||||||
|
PIStringList sl = v.split(';').resize(2);
|
||||||
|
return SomeType{sl[0].toInt(), sl[1].toFloat()};
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
/*piCout << "main";
|
PIValueTree root;
|
||||||
|
root.insert({"bool", PIVariant(false)});
|
||||||
PITimer timer;
|
root.insert({"integer", PIVariant(256)});
|
||||||
timer.setSlot([](){
|
root.insert({"string", PIVariant("str")});
|
||||||
static int cnt = 0;
|
//for (auto it: root.children()) {
|
||||||
piCout << "tick" << ++cnt;
|
// piCout << it.name() << it.value();
|
||||||
});
|
//}
|
||||||
timer.start(500);
|
PIVariant v = PIVariant::fromValue(SomeType{1, 0.5f});
|
||||||
|
piCout << v;
|
||||||
piSleep(1.12);
|
piCout << v.toString();
|
||||||
piCout << "end";
|
v.setValueFromString("2;-0.1");
|
||||||
PITimeMeasurer tm;
|
piCout << v;
|
||||||
timer.stop();
|
piCout << v.toString();
|
||||||
double tm_ms = tm.elapsed_m();
|
|
||||||
piCout << "stop took" << tm_ms;*/
|
|
||||||
|
|
||||||
/*PIWaitEvent event;
|
|
||||||
event.create();
|
|
||||||
tm.reset();
|
|
||||||
PIThread::runOnce([&event](){
|
|
||||||
//piMSleep(100);
|
|
||||||
piCout << "interrupt";
|
|
||||||
//event.interrupt();
|
|
||||||
});
|
|
||||||
event.sleep(2010000);
|
|
||||||
double tm_ms = tm.elapsed_m();
|
|
||||||
piCout << "waited for" << tm_ms;
|
|
||||||
return 0;*/
|
|
||||||
|
|
||||||
/*for (int i = 0; i < count; ++i)
|
|
||||||
pipes[i].create();
|
|
||||||
|
|
||||||
PIVector<T*> threads;
|
|
||||||
piCout << "main start";
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
T * t = new T(i);
|
|
||||||
threads << t;
|
|
||||||
t->startOnce();
|
|
||||||
}
|
|
||||||
piMSleep(100);
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
//pipes[i].write((void*)"string", 7);
|
|
||||||
piMSleep(500);
|
|
||||||
}
|
|
||||||
piCout << "main wait";
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
threads[i]->interrupt();
|
|
||||||
threads[i]->waitForFinish();
|
|
||||||
piCout << "main T" << i << "done";
|
|
||||||
}
|
|
||||||
piCout << "main end";
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
pipes[i].destoy();
|
|
||||||
delete threads[i];
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//PIEthernet eth(PIEthernet::UDP), seth(PIEthernet::UDP);
|
|
||||||
//eth.setReadAddress("127.0.0.1", 50000);
|
|
||||||
//eth.startThreadedRead();
|
|
||||||
//piCout << eth.open();
|
|
||||||
|
|
||||||
/*PIByteArray req = PIByteArray::fromHex("205e011000000000ef");
|
|
||||||
PISerial ser;
|
|
||||||
ser.setSpeed(PISerial::S9600);
|
|
||||||
ser.setOption(PIIODevice::BlockingRead, false);
|
|
||||||
ser.setVTime(200);
|
|
||||||
ser.open("COM3");
|
|
||||||
CONNECTL(&ser, threadedReadEvent, ([](const uchar * data, ssize_t size){
|
|
||||||
piCout << "*ser readed" << size;
|
|
||||||
}));
|
|
||||||
PIThread thread;
|
|
||||||
thread.start([&](void*){
|
|
||||||
piCout << "[T] start";
|
|
||||||
PIByteArray data = ((PIIODevice*)&ser)->read(1024);
|
|
||||||
piCout << "[T] readed" << data.size();// << errorString();
|
|
||||||
piCout << "[T] end";
|
|
||||||
}, 200);
|
|
||||||
//ser.startThreadedRead();
|
|
||||||
|
|
||||||
piSleep(1);
|
|
||||||
ser.write(req);
|
|
||||||
phase("Send");
|
|
||||||
|
|
||||||
piSleep(2);
|
|
||||||
phase("End");*/
|
|
||||||
|
|
||||||
|
|
||||||
PIEthernet eth(PIEthernet::TCP_Client), seth(PIEthernet::TCP_Server), * server_client = nullptr;
|
|
||||||
|
|
||||||
seth.listen("127.0.0.1", 50000, true);
|
|
||||||
//seth.startThreadedRead();
|
|
||||||
CONNECTL(&seth, newConnection, ([&server_client](PIEthernet * e){
|
|
||||||
server_client = e;
|
|
||||||
e->setName("TCP SC");
|
|
||||||
piCout << "newConn" << e;
|
|
||||||
CONNECTL(e, threadedReadEvent, ([](const uchar * data, ssize_t size){
|
|
||||||
piCout << "*TCP SC* readed" << size;
|
|
||||||
}));
|
|
||||||
CONNECTL(e, disconnected, ([](bool error){
|
|
||||||
piCout << "*TCP SC* disconnected" << error;
|
|
||||||
}));
|
|
||||||
e->startThreadedRead();
|
|
||||||
}));
|
|
||||||
|
|
||||||
eth.setName("TCP CC");
|
|
||||||
//eth.setParameter(PIEthernet::KeepConnection, false);
|
|
||||||
CONNECTL(ð, connected, ([ð](){
|
|
||||||
piCout << "*TCP CC* connected";
|
|
||||||
eth.send("byte", 5);
|
|
||||||
}));
|
|
||||||
CONNECTL(ð, disconnected, ([](bool error){
|
|
||||||
piCout << "*TCP CC* disconnected" << error;
|
|
||||||
}));
|
|
||||||
|
|
||||||
piMSleep(500);
|
|
||||||
phase("Connect");
|
|
||||||
eth.connect("127.0.0.1", 50000);
|
|
||||||
eth.startThreadedRead();
|
|
||||||
|
|
||||||
piMSleep(500);
|
|
||||||
phase("Send 5");
|
|
||||||
piCout << "c-ing" << eth.isConnecting();
|
|
||||||
piCout << "c- ed" << eth.isConnected();
|
|
||||||
eth.send("byte", 5);
|
|
||||||
|
|
||||||
piMSleep(500);
|
|
||||||
phase("Send 6");
|
|
||||||
eth.send("bytes", 6);
|
|
||||||
|
|
||||||
piMSleep(500);
|
|
||||||
phase("Disconnect");
|
|
||||||
if (server_client)
|
|
||||||
server_client->close();
|
|
||||||
//eth.close();
|
|
||||||
|
|
||||||
piMSleep(500);
|
|
||||||
phase("END");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user