diff --git a/CMakeLists.txt b/CMakeLists.txt index c72a778b..acb02565 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(pip) set(pip_MAJOR 2) -set(pip_MINOR 35) +set(pip_MINOR 36) set(pip_REVISION 0) set(pip_SUFFIX ) set(pip_COMPANY SHS) diff --git a/libs/main/core/picout.cpp b/libs/main/core/picout.cpp index dd55b0b5..138cc1ad 100644 --- a/libs/main/core/picout.cpp +++ b/libs/main/core/picout.cpp @@ -338,7 +338,7 @@ PICout PICout::operator <<(const PIFlags & v) } -PICout PICout::operator <<(const char * v) {if (!act_) return *this; if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;} +PICout PICout::operator <<(const char * v) {if (!act_ || !v) return *this; if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;} PICout PICout::operator <<(const bool v) {if (!act_) return *this; space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;} diff --git a/libs/main/core/piobject.cpp b/libs/main/core/piobject.cpp index 700a5ff8..feef0ca3 100644 --- a/libs/main/core/piobject.cpp +++ b/libs/main/core/piobject.cpp @@ -110,22 +110,80 @@ //! \} +PIObject::__MetaFunc::__MetaFunc() { + for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) { + types[i] = names[i] = nullptr; + types_id[i] = 0; + } +} + + +int PIObject::__MetaFunc::argumentsCount() const { + for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) + if (!types[i]) + return i; + return __PIOBJECT_MAX_ARGS__; +} + + PIString PIObject::__MetaFunc::arguments() const { - return types.join(","); + PIString ret; + for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) { + if (!types[i]) break; + if (!ret.isEmpty()) ret += ','; + ret += PIStringAscii(types[i]); + } + return ret; } PIString PIObject::__MetaFunc::fullFormat() const { - PIString ret = type_ret + " " + scope + "::" + func_name +"("; - for (int i = 0; i < types.size_s(); ++i) { + PIString ret = PIStringAscii(type_ret) + " " + + PIStringAscii(scope) + "::" + + PIStringAscii(func_name) +"("; + for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) { + if (!types[i]) break; if (i > 0) ret += ", "; - ret += types[i] + " " + names[i]; + ret += PIStringAscii(types[i]) + " " + PIStringAscii(names[i]); } ret += ")"; return ret; } +void PIObject::__MetaFunc::__setFuncName(const char * n) { + func_name = n; + func_name_id = PIStringAscii(n).hash(); +} + + +void PIObject::__MetaFunc::__addArgument(const char * t, const char * n) { + for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) { + if (types[i]) continue; + types[i] = t; + names[i] = n; + types_id[i] = PIObject::simplifyType(t, false).hash(); + break; + } + //PICout(PICoutManipulators::DefaultControls | PICoutManipulators::AddQuotes) + // << "__addArgument" << t << n << PIObject::simplifyType(t) << types_id.back(); +} + + +bool PIObject::__MetaFunc::canConnectTo(const __MetaFunc & dst, int & args_count) const { + for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) { + //piCout << "canConnectTo" << i << types[i] << dst.types[i]; + args_count = i; + if (!dst.types[i]) break; + if (!types[i]) return false; + if (types_id[i] != dst.types_id[i]) + return false; + } + return true; + +} + + PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__), emitter_(0), thread_safe_(false), proc_event_queue(false) { in_event_cnt = 0; setName(name); @@ -196,8 +254,13 @@ bool PIObject::executeQueued(PIObject * performer, const PIString & method, cons PIStringList PIObject::scopeList() const { + PIStringList ret; + ret.reserve(2); PIMutexLocker ml(__meta_mutex()); - return __meta_data()[classNameID()].scope_list; + const PIVector & scope(__meta_data()[classNameID()].scope_list); + for (const char * c: scope) + ret = PIStringAscii(c); + return ret; } @@ -212,10 +275,11 @@ PIStringList PIObject::methodsEH() const { bool PIObject::isMethodEHContains(const PIString & name) const { + uint search_id = name.hash(); PIMutexLocker ml(__meta_mutex()); const __MetaData & ehd(__meta_data()[classNameID()]); for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { - if (eh.value().func_name == name) + if (eh.value().func_name_id == search_id) return true; } return false; @@ -223,10 +287,11 @@ bool PIObject::isMethodEHContains(const PIString & name) const { PIString PIObject::methodEHArguments(const PIString & name) const { + uint search_id = name.hash(); PIMutexLocker ml(__meta_mutex()); const __MetaData & ehd(__meta_data()[classNameID()]); for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { - if (eh.value().func_name == name) + if (eh.value().func_name_id == search_id) return eh.value().arguments(); } return PIString(); @@ -234,10 +299,11 @@ PIString PIObject::methodEHArguments(const PIString & name) const { PIString PIObject::methodEHFullFormat(const PIString & name) const { + uint search_id = name.hash(); PIMutexLocker ml(__meta_mutex()); const __MetaData & ehd(__meta_data()[classNameID()]); for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { - if (eh.value().func_name == name) + if (eh.value().func_name_id == search_id) return eh.value().fullFormat(); } return PIString(); @@ -250,10 +316,11 @@ PIString PIObject::methodEHFromAddr(const void * addr) const { PIVector PIObject::findEH(const PIString & name) const { + uint search_id = name.hash(); PIVector<__MetaFunc> ret; const __MetaData & ehd(__meta_data()[classNameID()]); for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { - if (eh.value().func_name == name) + if (eh.value().func_name_id == search_id) ret << eh.value(); } return ret; @@ -313,10 +380,9 @@ PIObject::Connection PIObject::piConnectU(PIObject * src, const PIString & sig, if (addr_src != 0) break; piForeachC (__MetaFunc & fd, m_dest) { if (addr_src != 0) break; - if (fs.arguments().startsWith(fd.arguments()) || fd.arguments().isEmpty()) { + if (fs.canConnectTo(fd, args)) { addr_src = fs.addr; addr_dest = que ? fd.addrV : fd.addr; - args = fd.names.size_s(); } } } @@ -528,7 +594,7 @@ bool PIObject::findSuitableMethodV(const PIString & method, int args, int & ret_ int mfi = -1, ac = -1, mac = -1; for (int i = 0; i < ml.size_s(); ++i) { __MetaFunc & m(ml[i]); - int j = m.names.size_s(); + int j = m.argumentsCount(); if (mac < 0 || mac > j) mac = j; if ((j <= args) && (ac < j)) { ac = j; @@ -570,30 +636,46 @@ void PIObject::callAddrV(void * slot, void * obj, int args, const PIVector", '>'); + ret.replaceAll(" &", '&'); + ret.replaceAll(" *", '*'); + ret.replaceAll("[ ", '['); + ret.replaceAll("] ", ']'); + ret.replaceAll("< ", '<'); + ret.replaceAll("> ", '>'); + ret.replaceAll("& ", '&'); + ret.replaceAll("* ", '*'); + if (ret.startsWith("const ") && ret.endsWith("&")) + ret.cutLeft(6).cutRight(1).trim(); + } else { + if (ret.startsWith("const ") && ret.endsWith("&")) + ret.cutLeft(6).cutRight(1).trim(); + ret.removeAll(' ').removeAll('\t').removeAll('\r').removeAll('\n'); } - ret.replaceAll(" &", "&"); - ret.replaceAll(" *", "*"); - if (ret.startsWith("const ") && ret.endsWith("&")) - ret.cutLeft(6).cutRight(1).trim(); return ret; } @@ -632,13 +714,14 @@ void PIObject::dump(const PIString & line_prefix) const { PIObject * dst = c.dest_o; __MetaFunc ef = methodEH(c.signal); PIString src(c.event); - if (!ef.func_name.isEmpty()) - src = ef.func_name + "(" + ef.arguments() + ")"; + if (ef.func_name) + src = PIStringAscii(ef.func_name) + "(" + ef.arguments() + ")"; if (dst) { __MetaFunc hf = dst->methodEH(c.slot); - if (hf.func_name.isEmpty()) hf.func_name = "[BROKEN]"; - else hf.func_name += "(" + hf.arguments() + ")"; - PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf.func_name; + PIString hf_fn; + if (!hf.func_name) hf_fn = "[BROKEN]"; + else hf_fn = PIStringAscii(hf.func_name) + "(" + hf.arguments() + ")"; + PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf_fn; } else { PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << "[lambda]"; } @@ -693,7 +776,7 @@ bool dumpApplicationToFile(const PIString & path) { #endif -void PIObject::__MetaData::addScope(const PIString & s, uint shash) { +void PIObject::__MetaData::addScope(const char * s, uint shash) { if (!scope_id.contains(shash)) { scope_list << s; scope_id << shash; diff --git a/libs/main/core/piobject.h b/libs/main/core/piobject.h index 1ae3b5d5..492b56e6 100644 --- a/libs/main/core/piobject.h +++ b/libs/main/core/piobject.h @@ -34,7 +34,6 @@ #include "piqueue.h" #include "piobject_macros.h" - typedef void (*Handler)(void * ); class PIP_EXPORT PIObject { @@ -123,6 +122,7 @@ public: virtual uint classNameID() const {static uint ret = PIStringAscii("PIObject").hash(); return ret;} static const PIString __classNameS() {return PIStringAscii("PIObject");} + static const char * __classNameCC() {return "PIObject";} static uint __classNameIDS() {static uint ret = PIStringAscii("PIObject").hash(); return ret;} //! \~english Returns parent class name @@ -437,7 +437,8 @@ public: template bool isTypeOf() const { if (!isPIObject()) return false; - return scopeList().contains(T::__classNameS()); + PIMutexLocker ml(__meta_mutex()); + return __meta_data()[classNameID()].scope_id.contains(T::__classNameIDS()); } //! \~english Returns cast to T if this is valid subclass "T" (check by \a isTypeOf()) or "nullptr" @@ -459,26 +460,32 @@ public: static bool isTypeOf(const PIObject * o) {return o->isTypeOf();} template static bool isTypeOf(const void * o) {return isTypeOf((PIObject*)o);} - static PIString simplifyType(const char * a); + static PIString simplifyType(const char * a, bool readable = true); struct PIP_EXPORT __MetaFunc { - __MetaFunc(): addr(0), addrV(0) {;} - bool isNull() const {return addr == 0;} + __MetaFunc(); + bool isNull() const {return addr == nullptr;} + int argumentsCount() const; PIString arguments() const; PIString fullFormat() const; - void * addr; - void * addrV; - PIString func_name; - PIString type_ret; - PIString scope; - PIStringList types; - PIStringList names; + void __setFuncName(const char * n); + void __addArgument(const char * t, const char * n); + bool canConnectTo(const __MetaFunc & dst, int & args_count) const; + void * addr = nullptr; + void * addrV = nullptr; + uint func_name_id = 0; + const char * func_name = nullptr; + const char * type_ret = nullptr; + const char * scope = nullptr; + const char * types[__PIOBJECT_MAX_ARGS__]; + const char * names[__PIOBJECT_MAX_ARGS__]; + uint types_id[__PIOBJECT_MAX_ARGS__]; }; struct PIP_EXPORT __MetaData { - __MetaData() {scope_list << PIStringAscii("PIObject"); scope_id << PIStringAscii("PIObject").hash();} - void addScope(const PIString & s, uint shash); - PIStringList scope_list; + __MetaData() {scope_list << "PIObject"; scope_id << PIStringAscii("PIObject").hash();} + void addScope(const char * s, uint shash); + PIVector scope_list; PISet scope_id; PISet eh_set; PIMap eh_func; diff --git a/libs/main/core/piobject_macros.h b/libs/main/core/piobject_macros.h index a046c71d..e663c880 100644 --- a/libs/main/core/piobject_macros.h +++ b/libs/main/core/piobject_macros.h @@ -385,6 +385,7 @@ # define __PTYPE(t) __PIVariantTypeInfo__::PureType #endif #define __VVALUE(t, v) v.value< __PTYPE(t) >() +#define __PIOBJECT_MAX_ARGS__ 4 #define PIOBJECT(name) \ @@ -392,6 +393,7 @@ typedef name __PIObject__; \ public: \ static const PIString __classNameS() {static PIString ret = PIStringAscii(#name); return ret;} \ + static const char * __classNameCC() {return #name;} \ static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \ virtual const char * className() const {return #name;} \ virtual uint classNameID() const {static uint ret = PIStringAscii(#name).hash(); return ret;} \ @@ -411,7 +413,7 @@ __MetaData & eh(__meta_data()[id]); \ eh.eh_set << ehp.eh_set; \ eh.eh_func << ehp.eh_func; \ - eh.addScope(__classNameS(), id); \ + eh.addScope(__classNameCC(), id); \ } \ }; \ __BaseInitializer__ __base_init__; @@ -431,7 +433,7 @@ eh.eh_func << ehp.eh_func; \ eh.scope_id = ehp.scope_id; \ eh.scope_list = ehp.scope_list; \ - eh.addScope(__classNameS(), id); \ + eh.addScope(__classNameCC(), id); \ } \ }; \ __ParentInitializer__ __parent_init__; \ @@ -443,92 +445,61 @@ #define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent) +#define __EH_INIT_BASE__(ret, name) \ + PIMutexLocker ml(__meta_mutex()); \ + __MetaData & eh(__meta_data()[__classNameIDS()]); \ + if (eh.eh_set[fp]) return; \ + eh.eh_set << fp; \ + __MetaFunc & f(eh.eh_func[fp]); \ + f.scope = __classNameCC(); \ + f.__setFuncName(#name); \ + f.addr = fp; \ + f.addrV = fpV; \ + f.type_ret = #ret; + #define EH_INIT0(ret, name) \ STATIC_INITIALIZER_BEGIN \ - PIMutexLocker ml(__meta_mutex()); \ - __MetaData & eh(__meta_data()[__classNameIDS()]); \ void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \ void * fpV = fp; \ - if (eh.eh_set[fp]) return; \ - eh.eh_set << fp; \ - __MetaFunc & f(eh.eh_func[fp]); \ - f.scope = __classNameS(); \ - f.func_name = PIStringAscii(#name); \ - f.addr = fp; \ - f.addrV = fpV; \ - f.type_ret = PIStringAscii(#ret); \ + __EH_INIT_BASE__(ret, name) \ STATIC_INITIALIZER_END #define EH_INIT1(ret, name, a0, n0) \ STATIC_INITIALIZER_BEGIN \ - PIMutexLocker ml(__meta_mutex()); \ - __MetaData & eh(__meta_data()[__classNameIDS()]); \ void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &))__stat_eh_v_##name##__; \ - if (eh.eh_set[fp]) return; \ - eh.eh_set << fp; \ - __MetaFunc & f(eh.eh_func[fp]); \ - f.scope = __classNameS(); \ - f.func_name = PIStringAscii(#name); \ - f.addr = fp; \ - f.addrV = fpV; \ - f.type_ret = PIStringAscii(#ret); \ - f.types << PIObject::simplifyType(#a0); \ - f.names << PIStringAscii(#n0); \ + __EH_INIT_BASE__(ret, name) \ + f.__addArgument(#a0, #n0); \ STATIC_INITIALIZER_END #define EH_INIT2(ret, name, a0, n0, a1, n1) \ STATIC_INITIALIZER_BEGIN \ - PIMutexLocker ml(__meta_mutex()); \ - __MetaData & eh(__meta_data()[__classNameIDS()]); \ void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ - if (eh.eh_set[fp]) return; \ - eh.eh_set << fp; \ - __MetaFunc & f(eh.eh_func[fp]); \ - f.scope = __classNameS(); \ - f.func_name = PIStringAscii(#name); \ - f.addr = fp; \ - f.addrV = fpV; \ - f.type_ret = PIStringAscii(#ret); \ - f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1); \ - f.names << PIStringAscii(#n0) << PIStringAscii(#n1); \ + __EH_INIT_BASE__(ret, name) \ + f.__addArgument(#a0, #n0); \ + f.__addArgument(#a1, #n1); \ STATIC_INITIALIZER_END #define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \ STATIC_INITIALIZER_BEGIN \ - PIMutexLocker ml(__meta_mutex()); \ - __MetaData & eh(__meta_data()[__classNameIDS()]); \ void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ - if (eh.eh_set[fp]) return; \ - eh.eh_set << fp; \ - __MetaFunc & f(eh.eh_func[fp]); \ - f.scope = __classNameS(); \ - f.func_name = PIStringAscii(#name); \ - f.addr = fp; \ - f.addrV = fpV; \ - f.type_ret = PIStringAscii(#ret); \ - f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1) << PIObject::simplifyType(#a2); \ - f.names << PIStringAscii(#n0) << PIStringAscii(#n1) << PIStringAscii(#n2); \ + __EH_INIT_BASE__(ret, name) \ + f.__addArgument(#a0, #n0); \ + f.__addArgument(#a1, #n1); \ + f.__addArgument(#a2, #n2); \ STATIC_INITIALIZER_END #define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ STATIC_INITIALIZER_BEGIN \ - PIMutexLocker ml(__meta_mutex()); \ - __MetaData & eh(__meta_data()[__classNameIDS()]); \ void * fp = (void*)(ret(*)(void*, a0, a1, a2, a3))__stat_eh_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ - if (eh.eh_set[fp]) return; \ - eh.eh_set << fp; \ - __MetaFunc & f(eh.eh_func[fp]); \ - f.scope = __classNameS(); \ - f.func_name = PIStringAscii(#name); \ - f.addr = fp; \ - f.addrV = fpV; \ - f.type_ret = PIStringAscii(#ret); \ - f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1) << PIObject::simplifyType(#a2) << PIObject::simplifyType(#a3); \ - f.names << PIStringAscii(#n0) << PIStringAscii(#n1) << PIStringAscii(#n2) << PIStringAscii(#n3); \ + __EH_INIT_BASE__(ret, name) \ + f.__addArgument(#a0, #n0); \ + f.__addArgument(#a1, #n1); \ + f.__addArgument(#a2, #n2); \ + f.__addArgument(#a3, #n3); \ STATIC_INITIALIZER_END diff --git a/tests/math/testpimathmatrixt.cpp b/tests/math/testpimathmatrixt.cpp index 98fc78db..b015176c 100644 --- a/tests/math/testpimathmatrixt.cpp +++ b/tests/math/testpimathmatrixt.cpp @@ -376,7 +376,7 @@ TEST(PIMathMatrixT_Test, invert) { d2 = matrix2.determinant(); matrix3 = matrix1; matrix1.invert(); - ASSERT_TRUE((matrix1 == matrix3) && (d1 == 1/d2)); + ASSERT_TRUE((matrix1 == matrix3) && piCompare(d1, 1/d2)); } TEST(PIMathMatrixT_Test, inverted) {