From 2e5e75c4c4a6c08a95d4a4d3214a6418c8e04f2e Mon Sep 17 00:00:00 2001 From: peri4 Date: Tue, 29 Apr 2014 11:50:13 +0400 Subject: [PATCH] 29.04.2014 - Version 0.4.0_prealpha. PICodeParser, namespace PICodeInfo, new tool "pip_cmg" in dir "code_model_generator". New feature in PIIODevice - "createFromFullPath", all parameters of all I/O devices now works with PIObjects`s properties. --- CMakeLists.txt | 1 + clean | 4 + code_model_generator/CMakeLists.txt | 17 + code_model_generator/main.cpp | 225 ++++++++ code_model_generator/main_test.cpp | 48 ++ main.cpp | 140 ++++- pibinarylog.cpp | 50 +- pibinarylog.h | 45 +- pibitarray.h | 2 +- pibytearray.cpp | 2 +- pibytearray.h | 5 +- pichar.h | 2 +- picli.cpp | 7 +- picli.h | 12 +- picode.cpp | 189 ------- picode.h | 80 --- picodec.cpp | 2 +- picodec.h | 2 +- picodeinfo.cpp | 26 + picodeinfo.h | 147 ++++++ picodeparser.cpp | 762 ++++++++++++++++++++++++++++ picodeparser.h | 148 ++++++ picollection.cpp | 17 +- picollection.h | 19 +- piconfig.cpp | 3 +- piconfig.h | 2 +- piconsole.cpp | 2 +- piconsole.h | 2 +- picontainers.cpp | 2 +- picontainers.h | 8 +- picrc.h | 2 +- pidevicepool.cpp | 44 ++ pidevicepool.h | 65 +++ pidiagnostics.cpp | 2 +- pidiagnostics.h | 2 +- pidir.cpp | 4 +- pidir.h | 2 +- piethernet.cpp | 105 ++-- piethernet.h | 43 +- pievaluator.cpp | 7 +- pievaluator.h | 33 +- pifile.cpp | 13 +- pifile.h | 16 +- pigeometry.h | 2 +- piincludes.cpp | 4 +- piincludes.h | 65 ++- piiodevice.cpp | 118 +++-- piiodevice.h | 65 ++- pikbdlistener.cpp | 12 +- pikbdlistener.h | 11 +- pimap.h | 13 +- pimath.cpp | 2 +- pimath.h | 2 +- pimonitor.cpp | 2 +- pimonitor.h | 2 +- pimultiprotocol.h | 2 +- pimutex.cpp | 2 +- pimutex.h | 2 +- piobject.cpp | 10 +- piobject.h | 34 +- pip.h | 4 +- pip.pro | 18 +- pip_resource.rc | 38 -- pip_resource_win.rc | 6 +- pipacketextractor.cpp | 4 +- pipacketextractor.h | 5 +- pipeer.cpp | 10 +- pipeer.h | 6 +- piprocess.cpp | 2 +- piprocess.h | 2 +- piprotocol.cpp | 10 +- piprotocol.h | 2 +- piqueue.h | 2 +- piserial.cpp | 127 +++-- piserial.h | 40 +- pisignals.cpp | 2 +- pisignals.h | 2 +- pistack.h | 2 +- pistatemachine.h | 2 +- pistring.cpp | 40 +- pistring.h | 97 ++-- pisystemmonitor.cpp | 2 +- pisystemmonitor.h | 2 +- pisystemtests.cpp | 2 +- pisystemtests.h | 2 +- pithread.cpp | 2 +- pithread.h | 2 +- pitime.cpp | 2 +- pitime.h | 2 +- pitimer.cpp | 2 +- pitimer.h | 2 +- piusb.cpp | 34 +- piusb.h | 57 ++- pivariant.cpp | 8 +- pivariant.h | 101 +++- pivector.h | 11 +- remote_console/main.cpp | 2 +- system_test/main.cpp | 2 +- 98 files changed, 2545 insertions(+), 768 deletions(-) create mode 100644 code_model_generator/CMakeLists.txt create mode 100644 code_model_generator/main.cpp create mode 100644 code_model_generator/main_test.cpp delete mode 100644 picode.cpp delete mode 100644 picode.h create mode 100644 picodeinfo.cpp create mode 100644 picodeinfo.h create mode 100644 picodeparser.cpp create mode 100644 picodeparser.h create mode 100644 pidevicepool.cpp create mode 100644 pidevicepool.h delete mode 100644 pip_resource.rc diff --git a/CMakeLists.txt b/CMakeLists.txt index e0ee1043..9fb4bd90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,6 +101,7 @@ target_link_libraries(pip_test pip) add_subdirectory(system_test) add_subdirectory(remote_console) +add_subdirectory(code_model_generator) if (DEFINED LIB) unset(LIB) diff --git a/clean b/clean index 36c280aa..81218f4e 100755 --- a/clean +++ b/clean @@ -10,3 +10,7 @@ cd remote_console rm -rvf ./CMakeFiles rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core cd .. +cd code_model_generator +rm -rvf ./CMakeFiles +rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core +cd .. diff --git a/code_model_generator/CMakeLists.txt b/code_model_generator/CMakeLists.txt new file mode 100644 index 00000000..40d2ef62 --- /dev/null +++ b/code_model_generator/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 2.6) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} . ../) +file(GLOB CPPS "*.cpp") +add_definitions(-Wall -O2) +add_executable(pip_cmg "main.cpp") +target_link_libraries(pip_cmg pip) +if (DEFINED LIB) + unset(LIB) + if (${WIN32}) + get_filename_component(MGWDIR ${CMAKE_C_COMPILER} PATH) + set(CMAKE_INSTALL_PREFIX) + install(TARGETS pip_cmg DESTINATION ${MGWDIR}/../bin) + else () + set(CMAKE_INSTALL_PREFIX /usr) + install(TARGETS pip_cmg DESTINATION bin) + endif () +endif () diff --git a/code_model_generator/main.cpp b/code_model_generator/main.cpp new file mode 100644 index 00000000..92ba0c98 --- /dev/null +++ b/code_model_generator/main.cpp @@ -0,0 +1,225 @@ +/* + PIP - Platform Independent Primitives + Code model generator + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "picli.h" +#include "picodeparser.h" + + +void usage() { + piCout << Bold << "PIP Code model generator"; + piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine; + piCout << Green << Bold << "Usage:" << Default << "\"pip_cmg [-h] -o [-I] [-I] [...] [-D] [-D] [...] [] [] [...]\"" << NewLine; + piCout << Green << Bold << "Details:"; + piCout << "-h " << Green << "- display this message and exit"; + piCout << "-o " << Green << "- output file for code model without extension (e.g. \"ccm\" - files \"ccm.h\" and \"ccm.cpp\" will be created)"; + piCout << "-I " << Green << "- add include dir (e.g. -I.. -I../some_dir -I/usr/include)"; + piCout << "-D " << Green << "- add define to preprocessor, define PICODE is always defined (e.g. -DMY_DEFINE will add MY_DEFINE define)"; + piCout << " " << Green << "- add file to code model, all includes of this file will be proceed (e.g. \"main.cpp\")"; +} + + +void makeClassInfo(PIFile & f, const PICodeParser::Entity * e) { + f << "\n\tci = new ClassInfo();\n"; + f << "\t(*classesInfo)[\"" << e->name << "\"] = ci;\n"; + f << "\tci->name = \"" << e->name << "\";\n"; + piForeachC (PICodeParser::Entity * p, e->parents) + f << "\tci->parents << \"" << p->name << "\";\n"; + piForeachC (PICodeParser::Member & m, e->members) { + f << "\tci->variables << TypeInfo(\"" << m.name << "\", \"" << m.type << "\""; + if (m.attributes != 0) { + bool fir = true; + f << ", "; + if (m.attributes[PICodeParser::Const]) {if (fir) fir = false; else f << " | "; f << "Const";} + if (m.attributes[PICodeParser::Static]) {if (fir) fir = false; else f << " | "; f << "Static";} + if (m.attributes[PICodeParser::Mutable]) {if (fir) fir = false; else f << " | "; f << "Mutable";} + if (m.attributes[PICodeParser::Volatile]) {if (fir) fir = false; else f << " | "; f << "Volatile";} + if (m.attributes[PICodeParser::Inline]) {if (fir) fir = false; else f << " | "; f << "Inline";} + if (m.attributes[PICodeParser::Virtual]) {if (fir) fir = false; else f << " | "; f << "Virtual";} + } + f << ");\n"; + } + PIString arg; + piForeachC (PICodeParser::Member & m, e->functions) { + if (e->name.findCWord(m.name) >= 0) continue; + f << "\tci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back());\n"; + f << "\tfi->name = \"" << m.name << "\";"; + f << " fi->return_type = TypeInfo(\"\", \"" << m.type << "\""; + if (m.attributes[PICodeParser::Const] || m.attributes[PICodeParser::Static]) { + bool fir = true; + f << ", "; + if (m.attributes[PICodeParser::Const]) {if (fir) fir = false; else f << " | "; f << "Const";} + if (m.attributes[PICodeParser::Static]) {if (fir) fir = false; else f << " | "; f << "Static";} + } + f << ");\n"; + //piCout << "write func" << m.name; + piForeachC (PIString & a, m.arguments_full) { + //piCout << "write arg" << a; + f << "\tfi->arguments << TypeInfo("; + arg = a; + bool con = false; + arg.prepend(" "); + if (arg.find(" const ") >= 0) { + arg.replaceAll(" const ", " "); + con = true; + } + arg.trim(); + int ts = 0; + for (ts = arg.size_s() - 1; ts > 0; --ts) + if (!_isCChar(arg[ts]) && !(arg[ts].isDigit())) break; + f << "\"" << arg.takeRight(arg.size_s() - ts - 1).trim() << "\", "; + f << "\"" << arg.trim() << "\""; + if (con) f << ", Const"; + f << ");\n"; + } + } +} + + +void makeEnumInfo(PIFile & f, const PICodeParser::Enum * e) { + f << "\n\tei = new EnumInfo();\n"; + f << "\t(*enumsInfo)[\"" << e->name << "\"] = ei;\n"; + f << "\tei->name = \"" << e->name << "\";\n"; + piForeachC (PICodeParser::Enumerator & m, e->members) + f << "\tei->members << PICodeInfo::EnumeratorInfo(\"" << m.first << "\", " << m.second << ");\n"; +} + + +void writeModel(PICodeParser & parser, const PIString out) { + PIVector ventities; + PIString defname = out.replaceAll(".", "_").replaceAll("/", "_").toUpperCase() + "_H"; + + PISet inc_files; + piForeachC (PICodeParser::Entity * e, parser.entities) + if (e->name.find("::") < 0 && !e->name.startsWith("_PI")) + inc_files << e->file; + + PIFile f(out + ".cpp"); + f.clear(); + f.open(PIIODevice::WriteOnly); + f << "// Generated by \"PIP Code model generator\" " << currentDateTime().toString("dd.MM.yyyy hh:mm:ss\n\n"); + f << "#include \n#include \"" << out << ".h\"\n\nusing namespace PICodeInfo;\n\n"; + piForeachC (PIString & i, inc_files) + f << "#include \"" << i << "\"\n"; + f << "\n"; + PIString entry, argtype, rettype, args; + piForeachC (PICodeParser::Entity * e, parser.entities) { + if (e->name.find("::") >= 0 || e->name.startsWith("_PI")) continue; + entry.clear(); + entry << "\nPIVariant execFunction(" << e->name << " * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) {\n"; + const PIVector & fl(e->functions); + bool efunc = true; + piForeachC (PICodeParser::Member & m, fl) { + if (m.name.startsWith("__stat") || m.attributes[PICodeParser::Static]) continue; + //piCout << e->name << m.name << m.visibility; + args.clear(); + rettype = m.type; + if (rettype.startsWith("const") && rettype.endsWith("&")) + rettype.cutLeft(5).cutRight(1).trim(); + if (rettype.endsWith("&")) continue; + bool aok = true, ret = (m.type != "void"); + if (m.arguments_full.size() > 4 || m.visibility != PICodeParser::Public) continue; + for (int i = 0; i < m.arguments_full.size_s(); ++i) { + if (i > 0) args << ", "; + argtype = m.arguments_type[i]; + if (argtype.startsWith("const") && argtype.endsWith("&")) + argtype.cutLeft(5).cutRight(1).trim(); + if (argtype.endsWith("&")) { + aok = false; + continue; + } + //entry << "(" << m.arguments_type[i] << ")"; + //if (parser.isEnum(m.arguments_type[i])) entry << "(int)"; + args << "arg" << i << ".toValue<" << argtype << " >()"; + } + if (!aok) continue; + efunc = false; + entry << "\tif (strcmp(function, \"" << m.name << "\") == 0) {"; + if (ret) entry << "return PIVariant::fromValue<" << rettype << " >("; + entry << "object->" << m.name << "(" << args << ")"; + if (ret) entry << ");"; + else entry << "; return PIVariant();"; + entry << "}\n"; + } + if (efunc) continue; + f << entry << "\tPICout(AddNewLine) << \"Can`t find function \\\"\" << function << \"\\\" in " + << e->type << " \\\"" << e->name << "\\\"!\";\n\treturn PIVariant();\n}\n"; + ventities << e; + } + f << "\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n"; + f << "\tif (_inited_) return;\n\t_inited_ = true;\n\n"; + f << "\tClassInfo * ci;\n\tTypeInfo * ni;\n\tFunctionInfo * fi;\n\tEnumInfo * ei;"; + f << "\n\n// Classes\n"; + piForeachC (PICodeParser::Entity * e, parser.entities) { + if (e->name.startsWith("_PI")) continue; + makeClassInfo(f, e); + } + f << "\n// Enums\n"; + piForeachC (PICodeParser::Enum & e, parser.enums) + makeEnumInfo(f, &e); + f << "}\n"; + f << "\n\nbool __ClassInfo_" << defname << "_Initializer__::_inited_ = false;\n"; + f.close(); + + + f.setPath(out + ".h"); + f.clear(); + f.open(PIIODevice::WriteOnly); + f << "// Generated by \"PIP Code model generator\" " << currentDateTime().toString("dd.MM.yyyy hh:mm:ss\n\n"); + f << "#ifndef " << defname << "\n#define " << defname << "\n\n"; + f << "#include \"pivariant.h\"\n#include \"picodeinfo.h\"\n\n"; + piForeachC (PICodeParser::Entity * e, ventities) + f << e->type << " " << e->name << ";\n"; + f << "\n"; + piForeachC (PICodeParser::Entity * e, ventities) { + f << "\nPIVariant execFunction(" << e->name << " * object, const char * function, const PIVariant & arg0 = PIVariant(), \ +const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());"; + } + f << "\n\n\nclass __ClassInfo_" << defname << "_Initializer__ {\n"; + f << "public:\n\t__ClassInfo_" << defname << "_Initializer__();\n\tstatic bool _inited_;\n};\n"; + f << "\nstatic __ClassInfo_" << defname << "_Initializer__ __classinfo_" << defname.toLowerCase() << "_initializer__;\n"; + f << "\n\n#endif // " << defname << "\n"; + f.close(); +} + + +int main(int argc, char * argv[]) { + PICLI cli(argc, argv); + cli.setOptionalArgumentsCount(-1); + cli.addArgument("output", true); + cli.addArgument("help"); + if (cli.hasArgument("help") || cli.argumentValue("output").isEmpty() || cli.optionalArguments().isEmpty()) { + usage(); + return 0; + } + PICodeParser parser; + piForeachC (PIString & a, cli.rawArguments()) { + if (a.startsWith("-I")) parser.includeDirectory(a.mid(2)); + if (a.startsWith("-D")) parser.addDefine(a.mid(2), PIString()); + } + PIStringList files; + piForeachC (PIString & a, cli.optionalArguments()) + if (!a.startsWith("-")) files << a; + piCout << Cyan << Bold << "Parse files" << files << "..."; + parser.parseFiles(files); + piCout << Cyan << Bold << "Parsing done"; + piCout << Cyan << Bold << "Writing code model ..."; + writeModel(parser, cli.argumentValue("output")); + piCout << Cyan << Bold << "Writing done"; + return 0; +}; diff --git a/code_model_generator/main_test.cpp b/code_model_generator/main_test.cpp new file mode 100644 index 00000000..f307d860 --- /dev/null +++ b/code_model_generator/main_test.cpp @@ -0,0 +1,48 @@ +/* + PIP - Platform Independent Primitives + Code model generator + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pitimer.h" +#include "test.h" + +void event(void * , int d) { + piCout << "tick" << d; +} + +PITimer tm; + +int main(int argc, char * argv[]) { + //tm.setSlot(event); + //tm.start(200); + /*execFunction(&tm, "setSlot", PIVariant::fromValue(event)); + execFunction(&tm, "start", 200); + piMSleep(1000); + execFunction(&tm, "addDelimiter", 2); + piMSleep(1000); + execFunction(&tm, "stop"); + execFunction(&tm, "stop_"); + piMSleep(1000);*/ + typedef std::pair mpair; + piForeachC (mpair & i, *(PICodeInfo::classesInfo)) + piCout << *i.second; + piCout << "\n\n"; + typedef std::pair epair; + piForeachC (epair & i, *(PICodeInfo::enumsInfo)) + piCout << *i.second; + return 0; +}; diff --git a/main.cpp b/main.cpp index a1aa87bc..b58862b5 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Test program - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -55,23 +55,147 @@ Test::PIVariant newVariant(const T & v) {return Test::PIVariant(v);} template Test::PIVariant * castVariant(Test::__PIVariantBase * v, const T & t) {return static_cast * >(v);} */ -#include "picode.h" +#include "picodeparser.h" #define S(a, b) a#b +enum TypeFlag {NoFlag, Const = 0x01, Static = 0x02, Mutable = 0x04, Volatile = 0x08, Inline = 0x10, Virtual = 0x20}; +typedef PIFlags TypeFlags; +struct TypeInfo { + TypeInfo() {flags = 0;} + PIString name; + PIString type; + TypeFlags flags; +}; +struct FunctionInfo { + PIString name; + TypeInfo return_type; + PIVector arguments; +}; +struct ClassInfo { + PIString name; + PIStringList parents; + PIVector variables; + PIVector functions; +}; +inline PICout operator <<(PICout s, const TypeInfo & v) { + if (v.flags[Inline]) s << "inline "; + if (v.flags[Virtual]) s << "virtual "; + if (v.flags[Static]) s << "static "; + if (v.flags[Const]) s << "const "; + if (v.flags[Mutable]) s << "mutable "; + if (v.flags[Volatile]) s << "volatile "; + s << v.type; + if (!v.name.isEmpty()) + s << " " << v.name; + return s; +} +inline PICout operator <<(PICout s, const ClassInfo & v) { + s.setControl(0, true); + s << "class " << v.name; + if (!v.parents.isEmpty()) { + s << ": "; + bool first = true; + piForeachC (PIString & i, v.parents) { + if (first) first = false; + else s << ", "; + s << i; + } + s << " {\n"; + piForeachC (FunctionInfo & i, v.functions) { + s << Tab << i.return_type << " " << i.name << "("; + bool fa = true; + piForeachC (TypeInfo & a, i.arguments) { + if (fa) fa = false; + else s << ", "; + s << a; + } + s << ");\n"; + } + if (!v.functions.isEmpty() && !v.variables.isEmpty()) + s << "\n"; + piForeachC (TypeInfo & i, v.variables) { + s << Tab << i << ";\n"; + } + s << "}\n"; + } + s.restoreControl(); + return s; +} + + int main (int argc, char * argv[]) { - //piCout << (S(1,2)); - //(1,2)); - //CodeParser cd; - //cd.parseFile("test.cpp"); + PIString s("this\t :is \n(SPARTA)!"); + piCout << s.findCWord("this"); + piCout << s.findCWord("is"); + piCout << s.findCWord("SPARTA"); + piCout << s.findCWord("SPARTA!"); + if (argc < 2) return 0; + PICodeParser cd; + //cd.includeDirectory("../qpicalculator"); + cd.parseFile(argv[1]); + piForeachC (PICodeParser::Enum & e, cd.enums) + piCout << e.name << e.members; + + ClassInfo ci; + PICodeParser::Entity * e = cd.findEntityByName("PITimer"); + if (!e) return 0; + ci.name = e->name; + piForeachC (PICodeParser::Entity * p, e->parents) + ci.parents << p->name; + piForeachC (PICodeParser::Member & m, e->members) { + TypeInfo ni; + ni.name = m.name; + ni.type = m.type; + if (m.attributes[PICodeParser::Const]) ni.flags |= Const; + if (m.attributes[PICodeParser::Static]) ni.flags |= Static; + if (m.attributes[PICodeParser::Mutable]) ni.flags |= Mutable; + if (m.attributes[PICodeParser::Volatile]) ni.flags |= Volatile; + if (m.attributes[PICodeParser::Inline]) ni.flags |= Inline; + if (m.attributes[PICodeParser::Virtual]) ni.flags |= Virtual; + ci.variables << ni; + } + piForeachC (PICodeParser::Member & m, e->functions) { + FunctionInfo fi; + fi.name = m.name; + fi.return_type.type = m.type; + if (m.attributes[PICodeParser::Const]) fi.return_type.flags |= Const; + if (m.attributes[PICodeParser::Static]) fi.return_type.flags |= Static; + piForeachC (PIString & a, m.arguments_full) { + TypeInfo ni; + PIString arg(a); + arg.prepend(" "); + if (arg.find(" const ") >= 0) { + ni.flags |= Const; + arg.replaceAll(" const ", " "); + } + int ts = 0; + for (ts = arg.size_s() - 1; ts >= 0; --ts) + if (!_isCChar(arg[ts]) && !(arg[ts].isDigit())) break; + ni.name = arg.takeRight(arg.size_s() - ts - 1).trim(); + ni.type = arg.trim(); + fi.arguments << ni; + } + ci.functions << fi; + } + piCout << NewLine << ci; + //piCout << v.toType(); //piCout << v.toType().toType(); //PIFile::remove("ki"); /*PIConfig conf("protocols_commod.conf"); piCout << conf.allTree(); conf.setValue("rmd.123", 456);*/ - piCout << PIString("1.1").toFloat(); - piCout << PIString("1,1").toFloat(); + + /*PITimer tm; + piCout << tm.debug() << tm.properties(); + tm.setDebug(false); + piCout << tm.debug() << tm.properties(); + tm.setDebug(true); + piCout << tm.debug() << tm.properties();*/ + + //PIObject * ser = (PIObject * )PIIODevice::createFromFullPath("file://OM2:38400:7"); + //piCout << ser << NewLine << ser->properties(); } diff --git a/pibinarylog.cpp b/pibinarylog.cpp index a330c75f..c2b3b24a 100644 --- a/pibinarylog.cpp +++ b/pibinarylog.cpp @@ -42,6 +42,8 @@ * */ +REGISTER_DEVICE(PIBinaryLog); + PIBinaryLog::PIBinaryLog() { binlog_sig[0] = 'B'; @@ -51,10 +53,13 @@ PIBinaryLog::PIBinaryLog() { binlog_sig[4] = 'O'; binlog_sig[5] = 'G'; setThreadedReadBufferSize(65536); - is_started = rapid_start = false; - playspeed = 1.0f; - default_id = 1; - playmode = PlayVariableSpeed; + is_started = false; + setPlaySpeed(1.f); + setDefaultID(1); + setPlayMode(PlayVariableSpeed); + setLogDir(PIString()); + setFilePrefix(PIString()); + setRapidStart(false); } @@ -64,23 +69,23 @@ bool PIBinaryLog::openDevice() { is_started = false; is_thread_ok = true; if (mode_ == ReadWrite) { - piCoutObj << "ReadWrite mode not supported, use WriteOnly or ReadOnly"; + piCoutObj << "Error: ReadWrite mode not supported, use WriteOnly or ReadOnly"; return false; } - if (!file.open(path_, mode_)) + if (!file.open(path(), mode_)) return false; - setName(path_); + setName(path()); if (mode_ == WriteOnly) { file.resize(0); if (!writeFileHeader()) { - piCoutObj << "Can't write binlog file header"; + piCoutObj << "Error: Can't write binlog file header"; return false; } is_started = true; } if (mode_ == ReadOnly) { if (file.isEmpty()) { - piCoutObj << "File is null"; + piCoutObj << "Error: File is null"; fileError(); return false; } @@ -88,11 +93,11 @@ bool PIBinaryLog::openDevice() { fileError(); return false; } - if (isEmpty()) piCoutObj << "Empty BinLog file"; + if (isEmpty()) piCoutObj << "Error: Empty BinLog file"; // startlogtime = currentSystemTime(); play_time = 0; // nextrecord = readsRecord(); - if (!rapid_start) is_started = true; + if (!rapidStart()) is_started = true; } startlogtime = currentSystemTime(); return true; @@ -112,7 +117,7 @@ bool PIBinaryLog::threadedRead(uchar *readed, int size) { is_thread_ok = false; PISystemTime pt; double delay; - switch (playmode) { + switch (playMode()) { case PlayRealTime: pt = currentSystemTime() - startlogtime; // if (real_speedX > 0) @@ -129,7 +134,7 @@ bool PIBinaryLog::threadedRead(uchar *readed, int size) { break; case PlayVariableSpeed: delay = lastrecord.timestamp.toMilliseconds() - play_time; - delay /= playspeed; + delay /= playSpeed(); if (is_started) { if (delay > 0) PISystemTime::fromMilliseconds(delay).sleep(); @@ -147,7 +152,7 @@ bool PIBinaryLog::threadedRead(uchar *readed, int size) { PIString PIBinaryLog::createNewFile() { if (!file.close()) return PIString(); - if (open(logdir + "/" + fileprefix + currentDateTime().toString("yyyy_MM_dd__hh_mm_ss.binlog"), PIIODevice::WriteOnly)) + if (open(logDir() + "/" + filePrefix() + currentDateTime().toString("yyyy_MM_dd__hh_mm_ss.binlog"), PIIODevice::WriteOnly)) return file.path(); piCoutObj << "Can't create new file, maybe LogDir is invalid."; return PIString(); @@ -225,15 +230,14 @@ int PIBinaryLog::read(void *read_to, int max_size) { } -void PIBinaryLog::restart() -{ +void PIBinaryLog::restart() { bool th = isRunning(); if (th) stopThreadedRead(); if (!canRead()) return; lastrecord.timestamp = PISystemTime(); lastrecord.id = 0; is_thread_ok = true; - if (rapid_start) is_started = false; + if (rapidStart()) is_started = false; else is_started = true; play_time = 0; file.seekToBegin(); @@ -302,3 +306,15 @@ PIBinaryLog::BinLogRecord PIBinaryLog::readRecord() { } +void PIBinaryLog::configureFromFullPath(const PIString & full_path) { + PIStringList pl = full_path.split(":"); + for (int i = 0; i < pl.size_s(); ++i) { + PIString p(pl[i]); + switch (i) { + case 0: setLogDir(p); break; + case 1: setFilePrefix(p); break; + case 2: setDefaultID(p.toInt()); break; + } + } +} + diff --git a/pibinarylog.h b/pibinarylog.h index 8ac1abb3..d9feebb8 100644 --- a/pibinarylog.h +++ b/pibinarylog.h @@ -31,7 +31,7 @@ class PIBinaryLog: public PIIODevice { - PIOBJECT(PIBinaryLog) + PIIODEVICE(PIBinaryLog) public: PIBinaryLog(); ~PIBinaryLog() {closeDevice();} @@ -44,32 +44,38 @@ public: //! Current \a PlayMode - PlayMode playMode() const {return playmode;} + PlayMode playMode() const {return (PlayMode)(property("playMode").toInt());} //! Current directory where billogs wiil be saved - const PIString & logDir() const {return logdir;} + PIString logDir() const {return property("logDir").toString();} //! Returns current file prefix - const PIString & filePrefix() const {return fileprefix;} + PIString filePrefix() const {return property("filePrefix").toString();} //! Current LogDir, returns directory where billogs wiil be saved - int dafaultID() const {return default_id;} + int defaultID() const {return property("defaultID").toInt();} //! Returns current play speed - float speed() const {return playspeed;} + float playSpeed() const {return property("playSpeed").toFloat();} + + //! Returns if rapid start enabled + bool rapidStart() const {return property("rapidStart").toBool();} //! Set \a PlayMode - void setPlayMode(PlayMode mode) {playmode = mode;} + void setPlayMode(PlayMode mode) {setProperty("playMode", (int)mode);} //! Set path to directory where binlogs will be saved - void setLogDir(const PIString & path) {logdir = path;} + void setLogDir(const PIString & path) {setProperty("logDir", path);} //! Set file prefix, used to - void setFilePrefix(const PIString & prefix) {fileprefix = prefix;} + void setFilePrefix(const PIString & prefix) {setProperty("filePrefix", prefix);} //! Set defaultID, used in \a write function - void setDefaultID(int id) {default_id = id;} + void setDefaultID(int id) {setProperty("defaultID", id);} + + //! If enabled BinLog \a ThreadedRead starts without delay for first record, e.g. first record will be readed immediately + void setRapidStart(bool enabled) {setProperty("rapidStart", enabled);} // /** \brief Set play speed multiplyer, used only in \a PlayMode = \a PlayRealTime default value 1x. // * If "speedX" > 0 than it use as speed increase by X times, else as speed decrease by X times. @@ -77,8 +83,8 @@ public: // bool setRealSpeedX(int speedX) {if (speedX == 0 || isRunning()) return false; real_speedX = speedX; return true;} // //! Returns current play speed multiplyer // float realSpeedX() const {return real_speedX;} - //! Set play speed, used only in \a PlayMode = \a PlayVariableSpeed, default value 1.0 - void setSpeed(float speed) {playspeed = speed;} + //! Set play speed, used only if \a playMode = \a PlayVariableSpeed, default value 1.0 + void setPlaySpeed(float speed) {setProperty("playSpeed", speed);} //! Write one record to BinLog file, with ID = id, id must be greather than 0 @@ -89,7 +95,7 @@ public: //! Read one record from BinLog file, with ID = id, if id = 0 than any id will be readed PIByteArray readBinLog(int id = 0); - int readBinLog(int id, void *read_to, int max_size); + int readBinLog(int id, void * read_to, int max_size); //! Return true, if position at the end of BinLog file bool isEnd() {if (!opened_) return true; return file.isEnd();} @@ -103,14 +109,11 @@ public: int read(void *read_to, int max_size); //! Write one record to BinLog file, with ID = "defaultID" - int write(const void * data, int size) {return writeBinLog(default_id, data, size);} + int write(const void * data, int size) {return writeBinLog(defaultID(), data, size);} //! Array of ID, that BinLog can read from binlog file, when use \a read function, or in \a ThreadedRead PIVector filterID; - //! If "RapidStart" enabled, than BinLog \a ThreadedRead starts without delay for first record, e.g. first record will be readed immediately - void setRapidStart(bool enabled = false) {rapid_start = enabled;} - //! Go to begin of BinLog file void restart(); @@ -139,6 +142,8 @@ public: EVENT(fileError) protected: + PIString fullPathPrefix() const {return "binlog";} + void configureFromFullPath(const PIString & full_path); bool openDevice(); bool closeDevice(); bool threadedRead(uchar *readed, int size); @@ -156,16 +161,12 @@ private: BinLogRecord readRecord(); PIFile file; - PIString logdir, fileprefix; BinLogRecord lastrecord; PISystemTime startlogtime; //BinLogRecord nextrecord; - PlayMode playmode; double play_time; //milliseconds - float playspeed; - int default_id; //int real_speedX; // in X - bool is_started, rapid_start, is_thread_ok; + bool is_started, is_thread_ok; uchar binlog_sig[PIBINARYLOG_SIGNATURE_SIZE]; }; diff --git a/pibitarray.h b/pibitarray.h index 6fbe159a..2c874f0e 100644 --- a/pibitarray.h +++ b/pibitarray.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Bit array - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pibytearray.cpp b/pibytearray.cpp index 913f34d4..ade7e436 100644 --- a/pibytearray.cpp +++ b/pibytearray.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Byte array - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pibytearray.h b/pibytearray.h index 285499c4..7ecc1dcc 100644 --- a/pibytearray.h +++ b/pibytearray.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Byte array - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -70,7 +70,7 @@ public: friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v); public: //! Constructs data block - RawData(void * data, int size) {d = data; s = size;} + RawData(void * data = 0, int size = 0) {d = data; s = size;} //! Constructs data block RawData(const void * data, const int size) {d = const_cast(data); s = size;} RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;} @@ -153,6 +153,7 @@ private: }; +inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {if (v0.size() == v1.size()) {for (uint i = 0; i < v0.size(); ++i) if (v0[i] != v1[i]) return v0[i] < v1[i]; return false;} return v0.size() < v1.size();} //! \relatesalso PIByteArray \brief Output to std::ostream operator inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba) {s << "{"; for (uint i = 0; i < ba.size(); ++i) {s << ba[i]; if (i < ba.size() - 1) s << ", ";} s << "}"; return s;} diff --git a/pichar.h b/pichar.h index 56e683f8..76eafe62 100644 --- a/pichar.h +++ b/pichar.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Unicode char - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/picli.cpp b/picli.cpp index aab3307d..eeeae750 100644 --- a/picli.cpp +++ b/picli.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Command-Line Parser - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -63,13 +63,16 @@ void PICLI::parse() { if (cra.left(1) == _prefix_short) { last = 0; for (int j = 1; j < cra.length(); ++j) { + bool found = false; piForeach (Argument & a, _args) { if (a.short_key == cra[j]) { a.found = true; last = &a; + found = true; break; } } + if (!found) break; } } else { if (last == 0 ? true : !last->has_value) { @@ -77,7 +80,7 @@ void PICLI::parse() { _args_mand << cra; continue; } - if (_args_opt.size_s() < _count_opt) { + if (_args_opt.size_s() < _count_opt || _count_opt < 0) { _args_opt << cra; continue; } diff --git a/picli.h b/picli.h index 93681fa8..ce58d5f8 100644 --- a/picli.h +++ b/picli.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Command-Line Parser - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -61,7 +61,7 @@ public: const PIStringList & optionalArguments() {parse(); return _args_opt;} //! Returns program execute command without arguments - const PIString programCommand() {parse(); return _args_raw.size() > 0 ? _args_raw.front() : PIString();} + PIString programCommand() {parse(); return _args_raw.size() > 0 ? _args_raw.front() : PIString();} bool hasArgument(const PIString & name) {parse(); piForeach (Argument & i, _args) if (i.name == name && i.found) return true; return false;} PIString argumentValue(const PIString & name) {parse(); piForeach (Argument &i, _args) if (i.name == name && i.found) return i.value; return PIString();} PIString argumentShortKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.short_key; return PIString();} @@ -71,10 +71,10 @@ public: const PIString & fullKeyPrefix() const {return _prefix_full;} int mandatoryArgumentsCount() const {return _count_mand;} int optionalArgumentsCount() const {return _count_opt;} - void setShortKeyPrefix(const PIString & prefix) {_prefix_short = prefix;} - void setFullKeyPrefix(const PIString & prefix) {_prefix_full = prefix;} - void setMandatoryArgumentsCount(const int count) {_count_mand = count;} - void setOptionalArgumentsCount(const int count) {_count_opt = count;} + void setShortKeyPrefix(const PIString & prefix) {_prefix_short = prefix; needParse = true;} + void setFullKeyPrefix(const PIString & prefix) {_prefix_full = prefix; needParse = true;} + void setMandatoryArgumentsCount(const int count) {_count_mand = count; needParse = true;} + void setOptionalArgumentsCount(const int count) {_count_opt = count; needParse = true;} private: struct Argument { diff --git a/picode.cpp b/picode.cpp deleted file mode 100644 index 230b81a4..00000000 --- a/picode.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - PIP - Platform Independent Primitives - Packets extractor - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "picode.h" - - - -PIString CodeParser::Macro::expand(const PIStringList & arg_vals, bool * ok) const { - if (args.size() != arg_vals.size()) { - piCout << ("Error: in expansion of macro \"" + name + "(" + args.join(", ") + ")\": expect") - << args.size() << "arguments but takes" << arg_vals.size() << "!"; - if (ok != 0) *ok = false; - return PIString(); - } - PIString ret = value; - for (int i = 0; i < args.size_s(); ++i) { - const PIString & an(args[i]), av(arg_vals[i]); - int ind(-1); - while ((ind = ret.find(an, ind + 1)) >= 0) { - PIChar ppc(0), pc(0), nc(0); - if (ind > 1) ppc = ret[ind - 2]; - if (ind > 0) pc = ret[ind - 1]; - if (ind + an.size_s() < ret.size_s()) nc = ret[ind + an.size_s()]; - if (ppc != '#' && pc == '#' && !_isCChar(nc)) { // to chars - ind--; - ret.replace(ind, an.size_s() + 1, "\"" + av + "\""); - ind -= an.size_s() - av.size_s() - 1; - continue; - } - if (_isCChar(pc) || _isCChar(nc)) continue; - ret.replace(ind, an.size_s(), av); - ind -= an.size_s() - av.size_s(); - } - } - ret.replaceAll("##", ""); - if (ok != 0) *ok = true; - return ret; -} - - - -CodeParser::CodeParser() { - -} - - -bool CodeParser::parseFile(const PIString & file) { - //piCout << "parse" << file << "..."; - PIFile f(file, PIIODevice::ReadOnly); - if (!f.isOpened()) { - piCout << ("Error: can`t open file \"" + file + "\"!"); - return false; - } - PIString fc = f.readAll(); - return parseFileContent(fc); -} - - -void CodeParser::clear() { - defines.clear(); - typedefs.clear(); - tree.clear(); - entities.clear(); -} - - -bool CodeParser::parseFileContent(PIString & fc) { - bool mlc = false, cc = false; - int mls = 0, ole = -1, ccs = 0; - char c; - PIString pfc, line, ccmn; - PIMap cchars; - - /// Remove comments, join multiline "" and replace "" to $n (cchars) - fc.replaceAll("\r\n", "\n"); - fc.replaceAll("\r", "\n"); - for (int i = 0; i < fc.size_s() - 1; ++i) { - c = fc[i].toAscii(); - if (c == '"') { - if (i > 0) if (fc[i - 1] == '\\') continue; - cc = !cc; - if (cc) ccs = i; - if (!cc) { - ccmn = "$" + PIString::fromNumber(cchars.size()); - cchars[ccmn] = fc.mid(ccs, i - ccs + 1); - fc.replace(ccs, i - ccs + 1, ccmn); - i = ccs - 1 + ccmn.size_s(); - } - continue; - } - if (i > 0) { - if (c == '\\' && fc[i - 1] != '\\') {fc.cutMid(i, 2); --i;} - continue; - } - if (cc) continue; - if (fc.mid(i, 2) == "/*") {mlc = true; mls = i; ++i; continue;} - if (fc.mid(i, 2) == "/*") {mlc = true; mls = i; ++i; continue;} - if (fc.mid(i, 2) == "*/" && mlc) {mlc = false; fc.cutMid(mls, i - mls + 2); i = mls - 1; continue;} - if (fc.mid(i, 2) == "//" && !mlc) {ole = fc.find('\n', i); fc.cutMid(i, ole < 0 ? -1 : ole - i + 1); --i; continue;} - } - while (!fc.isEmpty()) { - line = fc.takeLine().trimmed(); - if (line.left(1) == "#") { - if (!parseDirective(line.cutLeft(1).trim())) - return false; - } else pfc << line << "\n"; - } - bool replaced = true; - int replaced_cnt = 0; - while (replaced) { - if (replaced_cnt >= 64) { - piCout << "Error: recursive macros detected!"; - return false; - } - replaced_cnt++; - replaced = false; - piForeachC (Define & d, defines) { - int ind(-1); - while ((ind = pfc.find(d.first, ind + 1)) >= 0) { - PIChar pc(0), nc(0); - if (ind > 0) pc = pfc[ind - 1]; - if (ind + d.first.size_s() < pfc.size_s()) nc = pfc[ind + d.first.size_s()]; - if (_isCChar(pc) || _isCChar(nc)) continue; - pfc.replace(ind, d.first.size_s(), d.second); - ind -= d.first.size_s() - d.second.size_s(); - replaced = true; - } - } - piForeachC (Macro & m, macros) { - int ind(-1); - while ((ind = pfc.find(m.name, ind + 1)) >= 0) { - PIChar pc(0), nc(0); - if (ind > 0) pc = pfc[ind - 1]; - if (ind + m.name.size_s() < pfc.size_s()) nc = pfc[ind + m.name.size_s()]; - if (_isCChar(pc) || _isCChar(nc)) continue; - PIString ret, range; bool ok(false); - range = pfc.mid(ind + m.name.size_s()).takeRange("(", ")"); - ret = m.expand(range.split(",").trim(), &ok); - //piCout << "range" << ret; - if (!ok) return false; - int rlen = pfc.find(range, ind + m.name.size_s()) + range.size_s() + 1 - ind; - pfc.replace(ind, rlen, ret); - ind -= rlen - ret.size_s(); - replaced = true; - } - } - } - - - piCout << pfc; - return true; -} - - -bool CodeParser::parseDirective(PIString d) { - if (d.isEmpty()) return true; - PIString dname = d.takeCWord(); - if (dname == "include") { - d.replaceAll("<", "\"").replaceAll(">", "\""); - return parseFile(d.takeRange("\"", "\"")); - } - if (dname == "define") { - PIString mname = d.takeCWord(); - if (d.left(1) == "(") { // macro - PIStringList args = d.takeRange("(", ")").split(",").trim(); - macros << Macro(mname, d.trim(), args); - } else { // define - defines << Define(mname, d.trim()); - } - return true; - } - return true; -} diff --git a/picode.h b/picode.h deleted file mode 100644 index 4045fb62..00000000 --- a/picode.h +++ /dev/null @@ -1,80 +0,0 @@ -/*! \file pipacketextractor.h - * \brief Packets extractor -*/ -/* - PIP - Platform Independent Primitives - Packets extractor - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - - -#ifndef CODE_H -#define CODE_H - -#include "pifile.h" - -inline bool _isCChar(const PIChar & c) {return (c.isAlpha() || (c == '_'));} -inline bool _isCChar(const PIString & c) {if (c.isEmpty()) return false; return _isCChar(c[0]);} - -class CodeParser { -public: - CodeParser(); - - bool parseFile(const PIString & file); - -private: - void clear(); - bool parseFileContent(PIString & fc); - bool parseDirective(PIString d); - - enum Visibility {Global, Public, Protected, Private}; - typedef PIPair Define; - typedef PIPair Typedef; - struct Macro { - Macro(const PIString & n = PIString(), const PIString & v = PIString(), const PIStringList & a = PIStringList()) { - name = n; - value = v; - args = a; - } - PIString expand(const PIStringList & arg_vals, bool * ok = 0) const; - PIString name; - PIString value; - PIStringList args; - }; - struct Entity { - Entity() { - visibility = Global; - size = 0; - parent = 0; - } - PIString type; - PIString name; - PIString file; - Visibility visibility; - int size; - Entity * parent; - PIVector children; - }; - - PIVector defines; - PIVector macros; - PIVector typedefs; - PIVector entities; - PIVector tree; - -}; - -#endif // PIPACKETEXTRACTOR_H diff --git a/picodec.cpp b/picodec.cpp index afd0ff05..cecb3d32 100644 --- a/picodec.cpp +++ b/picodec.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Text codings coder, based on "iconv" - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/picodec.h b/picodec.h index 25baefdf..81517b48 100644 --- a/picodec.h +++ b/picodec.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Text codings coder, based on "iconv" - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/picodeinfo.cpp b/picodeinfo.cpp new file mode 100644 index 00000000..1d3956e5 --- /dev/null +++ b/picodeinfo.cpp @@ -0,0 +1,26 @@ +/* + PIP - Platform Independent Primitives + C++ code info structs + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "picodeinfo.h" + + +PIMap * PICodeInfo::classesInfo; +PIMap * PICodeInfo::enumsInfo; + +bool __PICodeInfoInitializer__::_inited_ = false; diff --git a/picodeinfo.h b/picodeinfo.h new file mode 100644 index 00000000..08b6d2c2 --- /dev/null +++ b/picodeinfo.h @@ -0,0 +1,147 @@ +/*! \file picodeinfo.h + * \brief C++ code info structs +*/ +/* + PIP - Platform Independent Primitives + C++ code info structs + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifndef PICODEINFO_H +#define PICODEINFO_H + +#include "pistring.h" + +namespace PICodeInfo { + +enum TypeFlag {NoFlag, Const = 0x01, Static = 0x02, Mutable = 0x04, Volatile = 0x08, Inline = 0x10, Virtual = 0x20}; + +typedef PIFlags TypeFlags; + +struct TypeInfo { + TypeInfo(const PIString & n = PIString(), const PIString & t = PIString(), PICodeInfo::TypeFlags f = 0) {name = n; type = t; flags = f;} + PIString name; + PIString type; + PICodeInfo::TypeFlags flags; +}; + +struct FunctionInfo { + PIString name; + TypeInfo return_type; + PIVector arguments; +}; + +struct ClassInfo { + PIString name; + PIStringList parents; + PIVector variables; + PIVector functions; +}; + +struct EnumeratorInfo { + EnumeratorInfo(const PIString & n = PIString(), int v = 0) {name = n; value = v;} + PIString name; + int value; +}; + +struct EnumInfo { + PIString name; + PIVector members; +}; + + +inline PICout operator <<(PICout s, const PICodeInfo::TypeInfo & v) { + if (v.flags[Inline]) s << "inline "; + if (v.flags[Virtual]) s << "virtual "; + if (v.flags[Mutable]) s << "mutable "; + if (v.flags[Volatile]) s << "volatile "; + if (v.flags[Static]) s << "static "; + if (v.flags[Const]) s << "const "; + s << v.type; + if (!v.name.isEmpty()) + s << " " << v.name; + return s; +} + +inline PICout operator <<(PICout s, const PICodeInfo::EnumeratorInfo & v) {s << v.name << " = " << v.value; return s;} + +inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) { + s.setControl(0, true); + s << "class " << v.name; + if (!v.parents.isEmpty()) { + s << ": "; + bool first = true; + piForeachC (PIString & i, v.parents) { + if (first) first = false; + else s << ", "; + s << i; + } + } + s << " {\n"; + piForeachC (FunctionInfo & i, v.functions) { + s << Tab << i.return_type << " " << i.name << "("; + bool fa = true; + piForeachC (TypeInfo & a, i.arguments) { + if (fa) fa = false; + else s << ", "; + s << a; + } + s << ");\n"; + } + if (!v.functions.isEmpty() && !v.variables.isEmpty()) + s << "\n"; + piForeachC (TypeInfo & i, v.variables) { + s << Tab << i << ";\n"; + } + s << "}\n"; + s.restoreControl(); + return s; +} + +inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) { + s.setControl(0, true); + s << "enum " << v.name << " {\n"; + piForeachC (EnumeratorInfo & i, v.members) { + bool f = true; + if (f) f = false; + else s << ", "; + s << Tab << i << "\n"; + } + s << "}\n"; + s.restoreControl(); + return s; +} + +extern PIMap * classesInfo; +extern PIMap * enumsInfo; + +} + +class __PICodeInfoInitializer__ { +public: + __PICodeInfoInitializer__() { + if (_inited_) return; + _inited_ = true; + PICodeInfo::classesInfo = new PIMap; + PICodeInfo::enumsInfo = new PIMap; + } + static bool _inited_; +}; + +static __PICodeInfoInitializer__ __picodeinfoinitializer__; + +#endif // PICODEINFO_H diff --git a/picodeparser.cpp b/picodeparser.cpp new file mode 100644 index 00000000..04644f15 --- /dev/null +++ b/picodeparser.cpp @@ -0,0 +1,762 @@ +/* + PIP - Platform Independent Primitives + C++ code parser + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "picodeparser.h" + + + +PIString PICodeParser::Macro::expand(const PIStringList & arg_vals, bool * ok) const { + if (args.size() != arg_vals.size()) { + piCout << ("Error: in expansion of macro \"" + name + "(" + args.join(", ") + ")\": expect") + << args.size() << "arguments but takes" << arg_vals.size() << "!"; + if (ok != 0) *ok = false; + return PIString(); + } + PIString ret = value; + for (int i = 0; i < args.size_s(); ++i) { + const PIString & an(args[i]), av(arg_vals[i]); + int ind(-1); + while ((ind = ret.find(an, ind + 1)) >= 0) { + PIChar ppc(0), pc(0), nc(0); + if (ind > 1) ppc = ret[ind - 2]; + if (ind > 0) pc = ret[ind - 1]; + if (ind + an.size_s() < ret.size_s()) nc = ret[ind + an.size_s()]; + if (ppc != '#' && pc == '#' && !_isCChar(nc)) { // to chars + ind--; + ret.replace(ind, an.size_s() + 1, "\"" + av + "\""); + ind -= an.size_s() - av.size_s() - 1; + continue; + } + if (_isCChar(pc) || _isCChar(nc)) continue; + ret.replace(ind, an.size_s(), av); + ind -= an.size_s() - av.size_s(); + } + } + ret.replaceAll("##", ""); + if (ok != 0) *ok = true; + return ret; +} + + + +PICodeParser::PICodeParser() { + macros_iter = 32; + clear(); + includes << ""; +} + + +void PICodeParser::parseFile(const PIString & file) { + clear(); + parseFileInternal(file); + /*piCout << "\n\nDefines:"; + piForeachC (Define & m, defines) + piCout << "define" << m.first << m.second; + piCout << "\n\nMacros:"; + piForeachC (Macro & m, macros) + piCout << "Macro:" << m.name << m.args << m.value; + piCout << "\n\nClasses:"; + piForeachC (Entity * c, entities) + piCout << "class" << c->name << c->parents; + piCout << "\n\nEnums:"; + piForeachC (Enum & c, enums) + piCout << "enum" << c.name << c.members; + piCout << "\n\nTypedefs:"; + piForeachC (Typedef & c, typedefs) + piCout << "typedef" << c;*/ +} + + +void PICodeParser::parseFiles(const PIStringList & files) { + clear(); + piForeachC (PIString & f, files) + parseFileInternal(f); + /*piCout << "\n\nDefines:"; + piForeachC (Define & m, defines) + piCout << "define" << m.first << m.second; + piCout << "\n\nMacros:"; + piForeachC (Macro & m, macros) + piCout << "Macro:" << m.name << m.args << m.value; + piCout << "\n\nClasses:"; + piForeachC (Entity * c, entities) + piCout << "class" << c->name << c->parents; + piCout << "\n\nEnums:"; + piForeachC (Enum & c, enums) + piCout << "enum" << c.name << c.members; + piCout << "\n\nTypedefs:"; + piForeachC (Typedef & c, typedefs) + piCout << "typedef" << c;*/ +} + + +bool PICodeParser::isEnum(const PIString & name) { + piForeachC (Enum & e, enums) + if (e.name == name) + return true; + return false; +} + + +bool PICodeParser::parseFileInternal(const PIString & file) { + if (proc_files[file]) return true; + proc_files << file; + cur_file = file; + PIFile f(file, PIIODevice::ReadOnly); + int ii = 0; + while (!f.isOpened() && ii < (includes.size_s() - 1)) { + f.setPath(includes[++ii] + "/" + file); + //piCout << "try" << f.path(); + f.open(PIIODevice::ReadOnly); + } + if (!f.isOpened()) { + //piCout << ("Error: can`t open file \"" + file + "\"!"); + return false; + } + PIString fc = f.readAll(); + piCout << "parsing" << f.path() << "..."; + bool ret = parseFileContent(fc); + piCout << "parsing" << f.path() << "done"; + return ret; +} + + +void PICodeParser::clear() { + piForeach (Entity * i, entities) delete i; + defines.clear(); + macros.clear(); + enums.clear(); + typedefs.clear(); + entities.clear(); + proc_files.clear(); + cur_namespace.clear(); + evaluator.clearCustomVariables(); + defines << Define("PICODE", "") << custom_defines; +} + + +bool PICodeParser::parseFileContent(PIString & fc) { + bool mlc = false, cc = false; + int mls = 0, ole = -1, /*ccs = 0,*/ end = 0; + char c = 0, pc = 0; + PIString pfc, line, ccmn, tmp; + PIMap cchars; + + /// Remove comments, join multiline "*" and replace "*" to $n (cchars) + fc.replaceAll("\r\n", "\n"); + fc.replaceAll("\r", "\n"); + for (int i = 0; i < fc.size_s() - 1; ++i) { + if (i > 0) pc = c; + c = fc[i].toAscii(); + if (c == '"' && !mlc && pc != '\'') { + if (i > 0) if (fc[i - 1] == '\\') continue; + cc = !cc; + /*if (cc) ccs = i; + if (!cc) { + ccmn = "$" + PIString::fromNumber(cchars.size()); + cchars[ccmn] = fc.mid(ccs, i - ccs + 1); + fc.replace(ccs, i - ccs + 1, ccmn); + i = ccs - 1 + ccmn.size_s(); + }*/ + continue; + } + if (i > 0) + if (c == '\\' && fc[i - 1].toAscii() != '\\') { + fc.cutMid(i, 2); + --i; + continue; + } + if (cc) continue; + if (fc.mid(i, 2) == "/*") {mlc = true; mls = i; ++i; continue;} + if (fc.mid(i, 2) == "*/" && mlc) {mlc = false; fc.cutMid(mls, i - mls + 2); i = mls - 1; continue;} + if (fc.mid(i, 2) == "//" && !mlc) {ole = fc.find('\n', i); fc.cutMid(i, ole < 0 ? -1 : ole - i); --i; continue;} + } + //piCout << fc; + pfc = procMacros(fc); + + bool replaced = true; + int replaced_cnt = 0; + while (replaced) { + //piCout << "MACRO iter" << replaced_cnt; + if (replaced_cnt >= macros_iter) { + piCout << "Error: recursive macros detected!"; + break;//return false; + } + replaced_cnt++; + replaced = false; + piForeachC (Define & d, defines) { + int ind(-1); + while ((ind = pfc.find(d.first, ind + 1)) >= 0) { + PIChar pc(0), nc(0); + if (ind > 0) pc = pfc[ind - 1]; + if (ind + d.first.size_s() < pfc.size_s()) nc = pfc[ind + d.first.size_s()]; + if (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue; + pfc.replace(ind, d.first.size_s(), d.second); + ind -= d.first.size_s() - d.second.size_s(); + replaced = true; + } + } + piForeachC (Macro & m, macros) { + int ind(-1); + while ((ind = pfc.find(m.name, ind + 1)) >= 0) { + PIChar pc(0), nc(0); + if (ind > 0) pc = pfc[ind - 1]; + if (ind + m.name.size_s() < pfc.size_s()) nc = pfc[ind + m.name.size_s()]; + if (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue; + PIString ret, range; bool ok(false); + range = pfc.mid(ind + m.name.size_s()).takeRange("(", ")"); + ret = m.expand(range.split(",").trim(), &ok); + if (!ok) return false; + int rlen = pfc.find(range, ind + m.name.size_s()) + range.size_s() + 1 - ind; + pfc.replace(ind, rlen, ret); + ind -= rlen - ret.size_s(); + replaced = true; + } + } + } + + //piCout << NewLine << "file" << cur_file << pfc; + for (int i = 0; i < pfc.size_s() - 5; ++i) { + if (pfc.mid(i, 8) == "template") { + pfc.cutLeft(i + 8); + pfc.takeRange("<", ">"); + bool def = !isDeclaration(pfc, 0, &end); + pfc.cutLeft(end); + if (def) pfc.takeRange("{", "}"); + else pfc.takeSymbol(); + i = 0; + continue; + } + if (pfc.mid(i, 5) == "class" || pfc.mid(i, 6) == "struct") { + int dind = pfc.find("{", i), find = pfc.find(";", i); + if (dind < 0 && find < 0) {pfc.cutLeft(i + 6); i = 0; continue;} + if (dind < 0 || find < dind) {pfc.cutLeft(i + 6); i = 0; continue;} + ccmn = pfc.mid(i, dind - i) + "{\n" + pfc.mid(dind).takeRange('{', '}') + "\n}\n"; + pfc.remove(i, ccmn.size()); + parseClass(ccmn); + i = 0; + continue; + } + if (pfc.mid(i, 4) == "enum") { + pfc.cutLeft(i + 4); + tmp = pfc.takeCWord(); + parseEnum(cur_namespace + tmp, pfc.takeRange("{", "}")); + pfc.takeSymbol(); + i = 0; + continue; + } + if (pfc.mid(i, 7) == "typedef") { + pfc.cutLeft(i + 7); + typedefs << parseTypedef(pfc.takeLeft(pfc.find(";"))); + if (typedefs.back().first.isEmpty()) typedefs.pop_back(); + pfc.takeSymbol(); + i = 0; + continue; + } + } + + return true; +} + + +PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc) { + PIString cd = fc.trimmed().removeAll('\n').replaceAll("\t", " ").replaceAll(" ", " "), pn; + //piCout << "found class <****\n" << cd << "\n****>"; + int ind = cd.find(":"); + PIVector parents; + if (ind > 0) { + PIStringList pl = cd.takeMid(ind + 1).trim().split(","); + cd.cutRight(1); + Entity * pe = 0; + piForeachC (PIString & p, pl) { + if (p.contains(" ")) pn = p.mid(p.find(" ") + 1); + else pn = p; + pe = findEntityByName(pn); + if (pe == 0) ;//{piCout << "Error: can`t find" << pn;} + else parents << pe; + } + } + bool is_class = cd.left(5) == "class"; + cur_def_vis = (is_class ? Private : Public); + PIString cn = cd.mid(6).trim(); + if (cn.isEmpty()) return 0; + Entity * e = new Entity(); + e->name = cur_namespace + cn; + e->type = (is_class ? "class" : "struct"); + e->parents = parents; + e->file = cur_file; + entities << e; + return e; +} + + +PIString PICodeParser::parseClass(PIString & fc) { + Visibility prev_vis = cur_def_vis; + int dind = fc.find("{"), find = fc.find(";"), end = 0; + if (dind < 0 && find < 0) return PIString(); + if (dind < 0 || find < dind) return fc.left(find); + Entity * ce = parseClassDeclaration(fc.takeLeft(dind)); + fc.trim().cutLeft(1).cutRight(1).trim(); + //piCout << "found class <****\n" << fc << "\n****>"; + if (!ce) return PIString(); + int ps = -1; + bool def = false; + PIString prev_namespace = cur_namespace, stmp; + cur_namespace = ce->name + "::"; + //piCout << "parse class" << ce->name << "namespace" << cur_namespace; + //piCout << "\nparse class" << ce->name << "namespace" << cur_namespace; + while (!fc.isEmpty()) { + PIString cw = fc.takeCWord(), tmp; + //piCout << "\ntaked word" << cw; + if (cw == "public") {cur_def_vis = Public; fc.cutLeft(1); continue;} + if (cw == "protected") {cur_def_vis = Protected; fc.cutLeft(1); continue;} + if (cw == "private") {cur_def_vis = Private; fc.cutLeft(1); continue;} + if (cw == "class") {if (isDeclaration(fc, 0, &end)) {fc.cutLeft(end); fc.takeSymbol(); continue;} tmp = fc.takeLeft(fc.find("{")); stmp = fc.takeRange("{", "}"); fc.takeSymbol(); stmp = "class " + tmp + "{" + stmp + "}"; parseClass(stmp); continue;} + if (cw == "struct") {if (isDeclaration(fc, 0, &end)) {fc.cutLeft(end); fc.takeSymbol(); continue;} tmp = fc.takeLeft(fc.find("{")); stmp = fc.takeRange("{", "}"); fc.takeSymbol(); stmp = "struct " + tmp + "{" + stmp + "}"; parseClass(stmp); continue;} + if (cw == "enum") {tmp = fc.takeCWord(); parseEnum(cur_namespace + tmp, fc.takeRange("{", "}")); fc.takeSymbol(); continue;} + if (cw == "friend") {fc.cutLeft(fc.find(";") + 1); continue;} + if (cw == "typedef") {ce->typedefs << parseTypedef(fc.takeLeft(fc.find(";"))); typedefs << ce->typedefs.back(); typedefs.back().first.insert(0, cur_namespace); if (ce->typedefs.back().first.isEmpty()) ce->typedefs.pop_back(); fc.takeSymbol(); continue;} + if (cw == "template") { + fc.takeRange("<", ">"); + def = !isDeclaration(fc, 0, &end); + fc.cutLeft(end); + if (def) fc.takeRange("{", "}"); + else fc.takeSymbol(); + continue; + } + def = !isDeclaration(fc, 0, &end); + tmp = (cw + fc.takeLeft(end)).trim(); + if (!tmp.isEmpty()) + parseMember(ce, tmp); + if (def) fc.takeRange("{", "}"); + else fc.takeSymbol(); + if (ps == fc.size_s()) {/*cur_namespace = prev_namespace;*/ fc.cutLeft(1);/*return false*/;} + ps = fc.size_s(); + } + cur_def_vis = prev_vis; + cur_namespace = prev_namespace; + return ce->name; +} + + +bool PICodeParser::parseEnum(const PIString & name, PIString fc) { + //piCout << "enum" << name << fc; + Enum e(name); + PIStringList vl(fc.split(",")); + PIString vn; + int cv = -1, ind = 0; + piForeachC (PIString & v, vl) { + vn = v; ind = v.find("="); + if (ind > 0) {cv = v.right(v.size_s() - ind - 1).toInt(); vn = v.left(ind);} + if (ind < 0) ++cv; + e.members << Enumerator(vn.trim(), cv); + } + enums << e; + return true; +} + + +PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) { + //piCout << "parse typedef" << fc; + Typedef td; + fc.replaceAll("\t", " "); + + if (fc.contains("(")) { + int start = fc.find("("), end = fc.find(")"); + td.first = fc.takeMid(start + 1, end - start - 1).trim(); + if (td.first.left(1) == "*") {td.first.cutLeft(1).trim(); fc.insert(start + 1, "*");} + td.second = fc.trim(); + } else { + td.first = fc.takeMid(fc.findLast(" ")).trim(); + td.second = fc.trim(); + } + //piCout << "found typedef" << td; + return td; +} + + +bool PICodeParser::parseMember(Entity * parent, PIString & fc) { + if (fc.trim().isEmpty()) return true; + if (fc.find("operator") >= 0) return true; + tmp_temp.clear(); + //piCout << "parse member" << fc; + int ts = fc.find("<"), te = 0; + PIString ctemp, crepl; + while (ts >= 0) { + ctemp = fc.mid(ts).takeRange("<", ">"); + if (ctemp.isEmpty()) {te = ts + 1; ts = fc.find("<", te); continue;} + crepl = "$" + PIString::fromNumber(tmp_temp.size_s()).expandLeftTo(3, "0"); + fc.replace(ts, ctemp.size_s() + 2, crepl); + tmp_temp[crepl] = "<" + ctemp + ">"; + ts = fc.find("<", te); + } + fc.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " ").replaceAll(", ", ","); + PIStringList tl, al; + Member me; + //piCout << fc; + if (fc.contains("(")) { + fc.cutRight(fc.size_s() - fc.findLast(")") - 1); + te = fc.find("("); + //piCout << fc; + for (ts = te - 1; ts >= 0; --ts) + if (!_isCChar(fc[ts]) && !(fc[ts].isDigit())) break; + //piCout << "takeMid" << ts + 1 << te - ts - 1; + me.name = fc.takeMid(ts + 1, te - ts - 1); + if (me.name == parent->name) return true; + me.arguments_full = fc.takeMid(ts + 2).cutRight(1).split(","); + me.type = fc.cutRight(1).trim(); + me.visibility = cur_def_vis; + if (me.type.find("inline ") >= 0) { + me.attributes |= Inline; + me.type.removeAll("inline "); + } + if (me.type.find("static ") >= 0) { + me.attributes |= Static; + me.type.removeAll("static "); + } + if (me.type.find("virtual ") >= 0) { + me.attributes |= Virtual; + me.type.removeAll("virtual "); + } + normalizeEntityNamespace(me.type); + int i = 0; + piForeach (PIString & a, me.arguments_full) + if ((i = a.find("=")) > 0) + a.cutRight(a.size_s() - i).trim(); + me.arguments_type = me.arguments_full; + piForeach (PIString & a, me.arguments_type) { + crepl.clear(); + if (a.contains("[")) + crepl = a.takeMid(a.find("["), a.findLast("]") - a.find("[") + 1); + for (ts = a.size_s() - 1; ts >= 0; --ts) + if (!_isCChar(a[ts]) && !(a[ts].isDigit())) break; + a.cutRight(a.size_s() - ts - 1); + normalizeEntityNamespace(a); + a += crepl; + a.trim(); + } + restoreTmpTemp(&me); + //piCout << "func" << me.type << me.name << me.arguments_full << me.arguments_type; + parent->functions << me; + } else { + tl = fc.split(","); + bool vn = true; + ctemp = tl.front(); + for (ts = ctemp.size_s() - 1; ts > 0; --ts) { + if (vn) {if (!_isCChar(ctemp[ts]) && !ctemp[ts].isDigit() && ctemp[ts] != '[' && ctemp[ts] != ']') vn = false;} + else {if (_isCChar(ctemp[ts]) || ctemp[ts].isDigit()) break;} + } + me.type = ctemp.takeLeft(ts + 1); + me.visibility = cur_def_vis; + restoreTmpTemp(&me); + PIString type = " " + me.type; + if (type.find(" const ") >= 0) { + me.attributes |= Const; + type.replaceAll(" const ", " "); + } + if (type.find(" static ") >= 0) { + me.attributes |= Static; + type.replaceAll(" static ", " "); + } + if (type.find(" mutable ") >= 0) { + me.attributes |= Mutable; + type.replaceAll(" mutable ", " "); + } + if (type.find(" volatile ") >= 0) { + me.attributes |= Volatile; + type.replaceAll(" volatile ", " "); + } + type.trim(); + normalizeEntityNamespace(type); + tl[0] = ctemp.trim(); + piForeachC (PIString & v, tl) { + crepl.clear(); + me.name = v.trimmed(); + me.type = type; + if (me.name.isEmpty()) continue; + if (me.name.contains("[")) + crepl = me.name.takeMid(me.name.find("["), me.name.findLast("]") - me.name.find("[") + 1); + while (!me.name.isEmpty()) { + if (me.name.front() == "*" || me.name.front() == "&") { + me.type += me.name.takeLeft(1); + me.name.trim(); + } else break; + } + me.is_type_ptr = (me.type.right(1) == "]" || me.type.right(1) == "*"); + me.type += crepl; + //piCout << "var" << me.type << me.name << me.is_const << me.is_static; + parent->members << me; + } + } + //piCout << "parse member" << fc; + return true; +} + + +void PICodeParser::normalizeEntityNamespace(PIString & n) { + PIString suff, pref; + for (int i = n.size_s() - 1; i > 0; --i) + if (_isCChar(n[i]) || n[i].isDigit()) { + suff = n.right(n.size_s() - i - 1); + n.cutRight(suff.size_s()); + break; + } + n.push_front(" "); + if (n.find(" static ") >= 0) {n.replaceAll(" static ", ""); pref += "static ";} + if (n.find(" const ") >= 0) {n.replaceAll(" const ", ""); pref += "const ";} + if (n.find(" mutable ") >= 0) {n.replaceAll(" mutable ", ""); pref += "mutable ";} + if (n.find(" volatile ") >= 0) {n.replaceAll(" volatile ", ""); pref += "volatile ";} + n.trim(); + int f = 0; + piForeachC (Entity * e, entities) { + if (e->name == n) { + n = (pref + n + suff).trim(); + return; + } + if ((f = e->name.find(n)) >= 0) + if (e->name.mid(f - 1, 1) == ":") + if (e->name.find(cur_namespace) >= 0) { + n = pref + e->name + suff; + return; + } + } + piForeachC (Enum & e, enums) + if ((f = e.name.find(n)) >= 0) + if (e.name.mid(f - 1, 1) == ":") + if (e.name.find(cur_namespace) >= 0) { + //piCout << "change" << n << "to" << e.name + suff; + n = pref + e.name + suff; + return; + } + piForeachC (Typedef & e, typedefs) + if ((f = e.first.find(n)) >= 0) + if (e.first.mid(f - 1, 1) == ":") + if (e.first.find(cur_namespace) >= 0) { + //piCout << "change" << n << "to" << e.name + suff; + n = pref + e.first + suff; + return; + } + n = (pref + n + suff).trim(); +} + + +void PICodeParser::restoreTmpTemp(Member * e) { + int i = 0; + piForeach (PIString & a, e->arguments_full) { + while ((i = a.find("$")) >= 0) + a.replace(i, 4, tmp_temp[a.mid(i, 4)]); + } + piForeach (PIString & a, e->arguments_type) { + while ((i = a.find("$")) >= 0) + a.replace(i, 4, tmp_temp[a.mid(i, 4)]); + } + while ((i = e->type.find("$")) >= 0) + e->type.replace(i, 4, tmp_temp[e->type.mid(i, 4)]); +} + + +bool PICodeParser::macroCondition(const PIString & mif, PIString mifcond) { + //piCout << "macroCondition" << mif << mifcond; + if (mif == "ifdef") return isDefineExists(mifcond); + if (mif == "ifndef") return !isDefineExists(mifcond); + if (mif == "if" || mif == "elif") { + mifcond.removeAll(" ").removeAll("\t"); + return procMacrosCond(mifcond) > 0.; + } + return false; +} + + +double PICodeParser::procMacrosCond(PIString fc) { + bool neg = false, first = true, br = false; + double ret = 0., brv = 0.; + int oper = 0, ps = -1; + char cc, nc; + PIString ce; + fc.removeAll("defined"); + //piCout << "procMacrosCond" << fc; + while (!fc.isEmpty()) { + cc = fc[0].toAscii(); + nc = (fc.size() > 1 ? fc[1].toAscii() : 0); + if (cc == '!') {neg = true; fc.pop_front(); continue;} + if (cc == '(') {br = true; brv = procMacrosCond(fc.takeRange('(', ')'));} + if (cc == '&' && nc == '&') {fc.remove(0, 2); oper = 1; continue;} + if (cc == '|' && nc == '|') {fc.remove(0, 2); oper = 2; continue;} + if (!br) { + ce = fc.takeCWord(); + if (ce.isEmpty()) ce = fc.takeNumber(); + } + if (first) { + first = false; + ret = br ? brv : defineValue(ce); + if (neg) ret = -ret; + } else { + //piCout << "oper" << oper << "with" << ce; + if (!br) brv = defineValue(ce); + switch (oper) { + case 1: ret = ret && (neg ? -brv : brv); break; + case 2: ret = ret || (neg ? -brv : brv); break; + } + } + if (ps == fc.size_s()) fc.cutLeft(1); + ps = fc.size_s(); + br = neg = false; + } + //piCout << "return" << ret; + return ret; +} + + +bool PICodeParser::isDefineExists(const PIString & dn) { + piForeachC (Define & d, defines) { + if (d.first == dn) + return true; + } + return false; +} + + +double PICodeParser::defineValue(const PIString & dn) { + piForeachC (Define & d, defines) { + if (d.first == dn) + return d.second.isEmpty() ? 1. : d.second.toDouble(); + } + return dn.toDouble(); +} + + +PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) { + piForeach (Entity * e, entities) + if (e->name == en) + return e; + return 0; +} + + +bool PICodeParser::isDeclaration(const PIString & fc, int start, int * end) { + int dind = fc.find("{", start), find = fc.find(";", start); + //piCout << "isDeclaration" << dind << find; + if (dind < 0 && find < 0) {if (end) *end = -1; return true;} + if (dind < 0 || find < dind) {if (end) *end = find; return true;} + if (end) *end = dind; + return false; +} + + +PIString PICodeParser::procMacros(PIString fc) { + if (fc.isEmpty()) return PIString(); + int ifcnt = 0; + bool grab = false, skip = false, cond_ok = false; + PIString pfc, nfc, line, mif, mifcond; + //piCout << "procMacros\n<******" << fc << "\n******>"; + fc += "\n"; + while (!fc.isEmpty()) { + line = fc.takeLine().trimmed(); + if (line.left(1) == "#") { + mifcond = line.mid(1); + mif = mifcond.takeCWord(); + //piCout << "mif mifcond" << mif << mifcond << ifcnt; + if (skip || grab) { + if (mif.left(2) == "if") ifcnt++; + if (mif.left(5) == "endif") { + if (ifcnt > 0) ifcnt--; + else { + //piCout << "main endif" << skip << grab; + if (grab) pfc << procMacros(nfc); + skip = grab = false; + continue; + } + } + if (mif.left(4) == "elif" && ifcnt == 0) { + //piCout << "main elif" << skip << grab << cond_ok; + if (cond_ok) { + if (grab) { + pfc << procMacros(nfc); + skip = true; grab = false; + } + continue; + } + if (skip) { + //piCout << "check elif" << skip << grab << cond_ok; + if (!macroCondition(mif, mifcond.trimmed())) continue; + //piCout << "check elif ok"; + skip = false; grab = cond_ok = true; + continue; + } + continue; + } + if (mif.left(4) == "else" && ifcnt == 0) { + //piCout << "main else" << skip << grab; + if (grab) pfc << procMacros(nfc); + if (skip && !cond_ok) {skip = false; grab = true;} + else {skip = true; grab = false;} + continue; + } + if (grab) nfc << line << "\n"; + continue; + } + if (mif.left(2) == "if") { + //piCout << "main if"; + skip = grab = cond_ok = false; + if (macroCondition(mif, mifcond.trimmed())) grab = cond_ok = true; + else skip = true; + ifcnt = 0; + nfc.clear(); + } else { + if (!parseDirective(line.cutLeft(1).trim())) + ;//return false; /// WARNING + } + } else { + if (grab) nfc << line << "\n"; + else if (!skip) pfc << line << "\n"; + } + } + return pfc; +} + + +bool PICodeParser::parseDirective(PIString d) { + if (d.isEmpty()) return true; + PIString dname = d.takeCWord(); + //piCout << "parseDirective" << d; + if (dname == "include") { + d.replaceAll("<", "\"").replaceAll(">", "\""); + PIString cf = cur_file; + bool ret = parseFileInternal(d.takeRange("\"", "\"")); + cur_file = cf; + return ret; + } + if (dname == "define") { + PIString mname = d.takeCWord(); + if (d.left(1) == "(") { // macro + PIStringList args = d.takeRange("(", ")").split(",").trim(); + macros << Macro(mname, d.trim(), args); + } else { // define + defines << Define(mname, d.trim()); + evaluator.setVariable(mname, complexd_1); + } + return true; + } + if (dname == "undef") { + PIString mname = d.takeCWord(); + for (int i = 0; i < defines.size_s(); ++i) + if (defines[i].first == mname) {defines.remove(i); --i;} + return true; + } + return true; +} diff --git a/picodeparser.h b/picodeparser.h new file mode 100644 index 00000000..9ed6b1cd --- /dev/null +++ b/picodeparser.h @@ -0,0 +1,148 @@ +/*! \file picodeparser.h + * \brief C++ code parser +*/ +/* + PIP - Platform Independent Primitives + C++ code parser + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifndef PICODEPARSER_H +#define PICODEPARSER_H + +#include "pifile.h" +#include "pievaluator.h" + +inline bool _isCChar(const PIChar & c) {return (c.isAlpha() || (c.toAscii() == '_'));} +inline bool _isCChar(const PIString & c) {if (c.isEmpty()) return false; return _isCChar(c[0]);} + +class PIP_EXPORT PICodeParser { +public: + PICodeParser(); + + enum PIP_EXPORT Visibility {Global, Public, Protected, Private}; + enum PIP_EXPORT Attribute {NoAttributes = 0x0, Const = 0x01, Static = 0x02, Mutable = 0x04, Volatile = 0x08, Inline = 0x10, Virtual = 0x20}; + + typedef PIFlags Attributes; + typedef PIPair Define; + typedef PIPair Typedef; + typedef PIPair Enumerator; + + struct PIP_EXPORT Macro { + Macro(const PIString & n = PIString(), const PIString & v = PIString(), const PIStringList & a = PIStringList()) { + name = n; + value = v; + args = a; + } + PIString expand(const PIStringList & arg_vals, bool * ok = 0) const; + PIString name; + PIString value; + PIStringList args; + }; + + struct PIP_EXPORT Member { + Member() { + visibility = Global; + size = 0; + is_type_ptr = false; + attributes = NoAttributes; + } + PIString type; + PIString name; + PIStringList arguments_full; + PIStringList arguments_type; + Visibility visibility; + Attributes attributes; + bool is_type_ptr; + int size; + }; + + struct PIP_EXPORT Entity { + Entity() { + visibility = Global; + size = 0; + } + PIString type; + PIString name; + PIString file; + Visibility visibility; + int size; + PIVector parents; + //PIVector children; + PIVector functions; + PIVector members; + PIVector typedefs; + }; + + struct PIP_EXPORT Enum { + Enum(const PIString & n = PIString()) { + name = n; + } + PIString name; + PIVector members; + }; + + void parseFile(const PIString & file); + void parseFiles(const PIStringList & files); + + void includeDirectory(const PIString & dir) {includes << dir;} + void addDefine(const PIString & def_name, const PIString & def_value) {custom_defines << Define(def_name, def_value);} + bool isEnum(const PIString & name); + Entity * findEntityByName(const PIString & en); + + int macrosSubstitutionMaxIterations() const {return macros_iter;} + void setMacrosSubstitutionMaxIterations(int value) {macros_iter = value;} + + PIVector defines, custom_defines; + PIVector macros; + PIVector enums; + PIVector typedefs; + PIVector entities; + +private: + void clear(); + bool parseFileInternal(const PIString & file); + bool parseFileContent(PIString & fc); + bool parseDirective(PIString d); + Entity * parseClassDeclaration(const PIString & fc); + PIString parseClass(PIString & fc); + bool parseEnum(const PIString & name, PIString fc); + Typedef parseTypedef(PIString fc); + bool parseMember(Entity * parent, PIString & fc); + void restoreTmpTemp(Member * e); + bool macroCondition(const PIString & mif, PIString mifcond); + bool isDefineExists(const PIString & dn); + double defineValue(const PIString & dn); + PIString procMacros(PIString fc); + double procMacrosCond(PIString fc); + bool isDeclaration(const PIString & fc, int start, int * end); + void normalizeEntityNamespace(PIString & n); + + int macros_iter; + PIEvaluator evaluator; + //PIVector tree; + PISet proc_files; + PIString cur_file; + PIStringList includes; + Entity root_; + Visibility cur_def_vis; + PIString cur_namespace; + PIMap tmp_temp; + +}; + +#endif // PICODEPARSER_H diff --git a/picollection.cpp b/picollection.cpp index 56348442..ad64b690 100644 --- a/picollection.cpp +++ b/picollection.cpp @@ -14,14 +14,14 @@ PIStringList PICollection::groups() { PIStringList sl; - piForeachC (Group & g, _groups) + piForeachC (Group & g, *_groups) sl << g.name; return sl; } PIVector PICollection::groupElements(const PIString & group) { - piForeachC (Group & g, _groups) + piForeachC (Group & g, *_groups) if (g.name == group) return g.elements; return PIVector(); @@ -29,18 +29,21 @@ PIVector PICollection::groupElements(const PIString & group) void PICollection::addToGroup(const PIString & group, const PIObject * element) { + //piCout << "add to" << group << element; PIString n = element->className(); - piForeach (Group & g, _groups) + piForeach (Group & g, *_groups) if (g.name == group) { for (int i = 0; i < g.elements.size_s(); ++i) if (PIString(g.elements[i]->className()) == n) return; g.elements << element; + //piCout << "new group" << group << ", ok"; return; } - _groups << Group(group); - _groups.back().elements << element; + *_groups << Group(group); + _groups->back().elements << element; + //piCout << "new group" << group << ", ok"; } - -PIVector PICollection::_groups; +bool __PICollectionInitializer::_inited_(false); +PIVector * PICollection::_groups; diff --git a/picollection.h b/picollection.h index b20b1385..b9f0488e 100644 --- a/picollection.h +++ b/picollection.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Peer - named I/O ethernet node, forming self-organized peering network - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -48,8 +48,9 @@ # define ADD_NEW_TO_COLLECTION(group, class) static PICollection::CollectionAdder __##group##_##class##_##adder##__(#group, new class()); #endif -class PICollection +class PIP_EXPORT PICollection { + friend class __PICollectionInitializer; public: PICollection() {;} @@ -74,8 +75,20 @@ protected: PIVector elements; }; - static PIVector _groups; + static PIVector * _groups; }; +class PIP_EXPORT __PICollectionInitializer { +public: + __PICollectionInitializer() { + if (_inited_) return; + _inited_ = true; + PICollection::_groups = new PIVector(); + } + static bool _inited_; +}; + +static __PICollectionInitializer __picollectioninitializer; + #endif // PICOLLECTION_H diff --git a/piconfig.cpp b/piconfig.cpp index 3e49524f..15cd1d48 100644 --- a/piconfig.cpp +++ b/piconfig.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Config parser - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -83,6 +83,7 @@ * */ + PIConfig::Entry PIConfig::Branch::_empty; PIConfig::Entry PIConfig::Entry::_empty; diff --git a/piconfig.h b/piconfig.h index 9bc7cd9e..43b7840e 100644 --- a/piconfig.h +++ b/piconfig.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Config parser - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piconsole.cpp b/piconsole.cpp index c7566510..7f56b6d8 100644 --- a/piconsole.cpp +++ b/piconsole.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Console output/input - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piconsole.h b/piconsole.h index 6e2b59a6..429fdd53 100644 --- a/piconsole.h +++ b/piconsole.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Console output/input - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/picontainers.cpp b/picontainers.cpp index 6a07a3b9..bf438569 100644 --- a/picontainers.cpp +++ b/picontainers.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Generic containers - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/picontainers.h b/picontainers.h index 683ac921..a68d404f 100644 --- a/picontainers.h +++ b/picontainers.h @@ -7,7 +7,7 @@ /* PIP - Platform Independent Primitives Generic containers - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,6 +39,10 @@ public: template inline bool operator <(const PIPair & value0, const PIPair & value1) {return value0.first < value1.first;} template +inline bool operator ==(const PIPair & value0, const PIPair & value1) {return (value0.first == value1.first) && (value0.second == value1.second);} +template +inline bool operator !=(const PIPair & value0, const PIPair & value1) {return (value0.first != value1.first) || (value0.second != value1.second);} +template inline std::ostream & operator <<(std::ostream & s, const PIPair & v) {s << "(" << v.first << ", " << v.second << ")"; return s;} template inline PICout operator <<(PICout s, const PIPair & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;} @@ -284,7 +288,7 @@ public: _CSet & operator <<(const Type & t) {_stlc::insert(t); return *this;} //! Returns if element "t" exists in this set - bool operator [](const Type & t) {return _stlc::find(t);} + bool operator [](const Type & t) {return _stlc::find(t) != _stlc::end();} //! Returns content of set as PIVector PIVector toVector() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} diff --git a/picrc.h b/picrc.h index 94dfa646..7677fbf6 100644 --- a/picrc.h +++ b/picrc.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Abstract input/output device - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pidevicepool.cpp b/pidevicepool.cpp new file mode 100644 index 00000000..27ff3792 --- /dev/null +++ b/pidevicepool.cpp @@ -0,0 +1,44 @@ +/* + PIP - Platform Independent Primitives + Single collection of devices + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pidevicepool.h" + + +/*! \class PIDevicePool + * \brief Single collection of devices + * + * \section PIDevicePool_sec0 Synopsis + * + * \section PIDevicePool_ex0 Example + * \snippet pidevicepool.cpp 0 + */ + + +PIDevicePool::PIDevicePool(): PIObject() { +} + + +PIDevicePool::~PIDevicePool() { + /*stop(); + if (opened_) { + closeDevice(); + if (!opened_) + closed(); + }*/ +} diff --git a/pidevicepool.h b/pidevicepool.h new file mode 100644 index 00000000..6a1538bb --- /dev/null +++ b/pidevicepool.h @@ -0,0 +1,65 @@ +/*! \file pidevicepool.h + * \brief Single collection of devices +*/ +/* + PIP - Platform Independent Primitives + Single collection of devices + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIDEVICEPOOL_H +#define PIDEVICEPOOL_H + +#include "piiodevice.h" + +class PIP_EXPORT PIDevicePool: public PIObject +{ + PIOBJECT(PIDevicePool) +public: + + PIDevicePool(); + ~PIDevicePool(); + + +//! \handlers +//! \{ + + //! \fn bool initialize() + //! \brief Initialize device + +//! \} +//! \vhandlers +//! \{ + + //! \fn void flush() + //! \brief Immediate write all buffers + +//! \} +//! \events +//! \{ + + //! \fn void threadedWriteEvent(ullong id, int written_size) + //! \brief Raise if write thread succesfull write some data of task with ID "id" + +//! \} + +protected: + +private: + +}; + +#endif // PIDEVICEPOOL_H diff --git a/pidiagnostics.cpp b/pidiagnostics.cpp index e94e6608..d199912f 100644 --- a/pidiagnostics.cpp +++ b/pidiagnostics.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Speed and quality in/out diagnostics - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pidiagnostics.h b/pidiagnostics.h index 1285dc00..cecd9abf 100644 --- a/pidiagnostics.h +++ b/pidiagnostics.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Speed and quality in/out diagnostics - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pidir.cpp b/pidir.cpp index 15eb50fb..6690eb2d 100644 --- a/pidir.cpp +++ b/pidir.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Directory - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -165,7 +165,7 @@ PIVector PIDir::entries() { struct stat fs; PIVector l; for (int i = 0; i < cnt; ++i) { - stat((p + separator + list[i]->d_name).data(), &fs); + stat((p + separator + PIString(list[i]->d_name)).data(), &fs); l.push_back(DirEntry(list[i]->d_name, fs.st_mode, fs.st_size)); delete list[i]; } diff --git a/pidir.h b/pidir.h index 5cdb4011..ae0957fe 100644 --- a/pidir.h +++ b/pidir.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Directory - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piethernet.cpp b/piethernet.cpp index 56d486aa..ac3ae118 100644 --- a/piethernet.cpp +++ b/piethernet.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Ethernet, UDP/TCP Broadcast/Multicast - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,58 +38,60 @@ * * * \section PIEthernet_sec2 UDP - * User Datagram Protocol + * User Datagram Protocol * * \section PIEthernet_sec3 TCP * Transmission Control Protocol * * */ +REGISTER_DEVICE(PIEthernet); + PIEthernet::PIEthernet(): PIIODevice("", ReadWrite) { piMonitor.ethernets++; - setPriority(piHigh); - type_ = UDP; ip_ = ip_s = ""; port_ = port_s = 0; sock = sock_s = -1; connected_ = connecting_ = false; - params = PIEthernet::ReuseAddress; server_thread_.setData(this); setThreadedReadBufferSize(65536); - if (type_ != UDP) init(); + setPriority(piHigh); + setType(UDP); + setParameters(PIEthernet::ReuseAddress); + //if (type_ != UDP) init(); } -PIEthernet::PIEthernet(PIEthernet::Type type, const PIString & ip_port, const PIFlags params_): PIIODevice(ip_port, ReadWrite) { +PIEthernet::PIEthernet(PIEthernet::Type type_, const PIString & ip_port, const PIFlags params_): PIIODevice(ip_port, ReadWrite) { piMonitor.ethernets++; - setPriority(piHigh); - type_ = type; parseAddress(ip_port, &ip_, &port_); ip_s = ""; port_s = 0; sock = sock_s = -1; connected_ = connecting_ = false; - params = params_; server_thread_.setData(this); setThreadedReadBufferSize(65536); + setPriority(piHigh); + setType(type_); + setParameters(params_); if (type_ != UDP) init(); } PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) { piMonitor.ethernets++; - setPriority(piHigh); - type_ = TCP_Client; - path_ = ip_port; parseAddress(ip_port, &ip_s, &port_s); sock = sock_; sock_s = -1; - server_thread_.setData(this); - params = PIEthernet::ReuseAddress; init_ = opened_ = connected_ = true; connecting_ = false; + server_thread_.setData(this); + setParameters(PIEthernet::ReuseAddress); setThreadedReadBufferSize(65536); + setPriority(piHigh); + setType(TCP_Client); + setPath(ip_port); } @@ -114,7 +116,7 @@ bool PIEthernet::init() { #else int so = 1; #endif - if (type_ == UDP) { + if (type() == UDP) { st = SOCK_DGRAM; pr = IPPROTO_UDP; } else { @@ -122,7 +124,7 @@ bool PIEthernet::init() { pr = IPPROTO_TCP; } #ifdef WINDOWS - if (type_ == UDP) flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF; + if (type() == UDP) flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF; sock = WSASocket(AF_INET, st, pr, NULL, 0, flags); sock_s = WSASocket(AF_INET, st, pr, NULL, 0, WSA_FLAG_OVERLAPPED); #else @@ -133,6 +135,7 @@ bool PIEthernet::init() { piCoutObj << "Can`t create socket, " << ethErrorString(); return false; } + PIFlags params = parameters(); #ifndef WINDOWS timeval to; to.tv_sec = 10; @@ -160,14 +163,15 @@ void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) { bool PIEthernet::openDevice() { if (connected_) return true; init(); - if (sock == -1 || path_.isEmpty()) return false; - parseAddress(path_, &ip_, &port_); - if (type_ != UDP) + if (sock == -1 || path().isEmpty()) return false; + parseAddress(path(), &ip_, &port_); + if (type() != UDP) return true; //piCout << "bind to" << (params[PIEthernet::Broadcast] ? "bc" : ip_) << ":" << port_ << " ..."; memset(&addr_, 0, sizeof(addr_)); addr_.sin_family = AF_INET; addr_.sin_port = htons(port_); + PIFlags params = parameters(); if (params[PIEthernet::Broadcast]) addr_.sin_addr.s_addr = INADDR_ANY; else addr_.sin_addr.s_addr = inet_addr(ip_.data()); #ifdef QNX @@ -218,10 +222,17 @@ void PIEthernet::closeSocket(int & sd) { } +void PIEthernet::setParameter(PIEthernet::Parameters parameter, bool on) { + PIFlags cp = (PIFlags)(property("parameters").toInt()); + cp.setFlag(parameter, on); + setParameters(cp); +} + + bool PIEthernet::joinMulticastGroup(const PIString & group) { if (sock == -1) init(); if (sock == -1) return false; - if (type_ != UDP) { + if (type() != UDP) { piCoutObj << "Only UDP sockets can join multicast groups"; return false; } @@ -229,10 +240,12 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) { if (mcast_queue.contains(group)) return false; mcast_queue.enqueue(group); + if (!mcast_groups.contains(group)) mcast_groups << group; return true; } + PIFlags params = parameters(); #ifdef WINDOWS - parseAddress(path_, &ip_, &port_); + parseAddress(path(), &ip_, &port_); memset(&addr_, 0, sizeof(addr_)); addr_.sin_family = AF_INET; addr_.sin_addr.s_addr = inet_addr(group.data()); @@ -243,12 +256,15 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) { piCoutObj << "Can`t join multicast group " << group << ", " << ethErrorString(); return false; } - if (ret != sock) leafs.insert(group, ret); + if (ret != sock) { + leafs.insert(group, ret); + if (!mcast_groups.contains(group)) mcast_groups << group; + } #else # ifndef QNX if (!params[Broadcast]) piCoutObj << "Warning: \"Broadcast\" parameter not set, \"joinMulticastGroup(\"" << group << "\")\" may be useless!"; - parseAddress(path_, &ip_, &port_); + parseAddress(path(), &ip_, &port_); struct ip_mreqn mreq; memset(&mreq, 0, sizeof(mreq)); mreq.imr_ifindex = 0; @@ -267,6 +283,7 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) { piCoutObj << "Can`t join multicast group " << group << ", " << ethErrorString(); return false; } + if (!mcast_groups.contains(group)) mcast_groups << group; # endif #endif return true; @@ -276,19 +293,21 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) { bool PIEthernet::leaveMulticastGroup(const PIString & group) { if (sock == -1) init(); if (sock == -1) return false; - if (type_ != UDP) { + if (type() != UDP) { piCoutObj << "Only UDP sockets can leave multicast groups"; return false; } + PIFlags params = parameters(); #ifdef WINDOWS SOCKET s = leafs[group]; if (s != SOCKET()) { leafs.erase(group); closesocket(s); + mcast_groups.removeAll(group); } #else # ifndef QNX - parseAddress(path_, &ip_, &port_); + parseAddress(path(), &ip_, &port_); struct ip_mreqn mreq; memset(&mreq, 0, sizeof(mreq)); if (params[PIEthernet::Broadcast]) mreq.imr_address.s_addr = INADDR_ANY; @@ -299,6 +318,7 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) { piCoutObj << "Can`t leave multicast group " << group << ", " << ethErrorString(); return false; } + mcast_groups.removeAll(group); #endif #endif return true; @@ -330,7 +350,7 @@ bool PIEthernet::connect() { bool PIEthernet::listen() { if (sock == -1) init(); if (sock == -1) return false; - parseAddress(path_, &ip_, &port_); + parseAddress(path(), &ip_, &port_); memset(&addr_, 0, sizeof(addr_)); addr_.sin_port = htons(port_); addr_.sin_addr.s_addr = inet_addr(ip_.data()); @@ -367,7 +387,7 @@ int PIEthernet::read(void * read_to, int max_size) { sockaddr_in client_addr; socklen_t slen = sizeof(client_addr); //piCoutObj << "read from " << ip_ << ":" << port_ << endl; - switch (type_) { + switch (type()) { case TCP_SingleTCP: ::listen(sock, 64); s = accept(sock, (sockaddr * )&client_addr, &slen); @@ -382,7 +402,7 @@ int PIEthernet::read(void * read_to, int max_size) { case TCP_Client: if (connecting_) { memset(&addr_, 0, sizeof(addr_)); - parseAddress(path_, &ip_, &port_); + parseAddress(path(), &ip_, &port_); addr_.sin_port = htons(port_); addr_.sin_addr.s_addr = inet_addr(ip_.data()); addr_.sin_family = AF_INET; @@ -450,7 +470,7 @@ int PIEthernet::write(const void * data, int max_size) { } //piCoutObj << "sending to " << ip_s << ":" << port_s << " " << max_size << " bytes"; int ret = 0; - switch (type_) { + switch (type()) { case TCP_SingleTCP: memset(&addr_, 0, sizeof(addr_)); addr_.sin_port = htons(port_s); @@ -486,7 +506,7 @@ int PIEthernet::write(const void * data, int max_size) { case TCP_Client: if (connecting_) { memset(&addr_, 0, sizeof(addr_)); - parseAddress(path_, &ip_, &port_); + parseAddress(path(), &ip_, &port_); addr_.sin_port = htons(port_); addr_.sin_addr.s_addr = inet_addr(ip_.data()); addr_.sin_family = AF_INET; @@ -517,7 +537,7 @@ void PIEthernet::server_func(void * eth) { socklen_t slen = sizeof(client_addr); int s = accept(ce->sock, (sockaddr * )&client_addr, &slen); if (s == -1) { - if (ce->debug_) piCout << "[PIEthernet] Can`t accept new connection, " << ethErrorString(); + if (ce->debug()) piCout << "[PIEthernet] Can`t accept new connection, " << ethErrorString(); return; } PIString ip(inet_ntoa(client_addr.sin_addr)); @@ -543,6 +563,27 @@ bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) { } +void PIEthernet::configureFromFullPath(const PIString & full_path) { + PIStringList pl = full_path.split(":"); + bool mcast = false; + for (int i = 0; i < pl.size_s(); ++i) { + PIString p(pl[i]); + switch (i) { + case 0: + p = p.toLowerCase(); + if (p == "udp") setType(UDP); + if (p == "tcp") setType(TCP_Client); + break; + case 1: setReadIP(p); break; + case 2: setReadPort(p.toInt()); break; + } + if (i <= 2) continue; + if (i % 2 == 1) {if (p.toLowerCase() == "mcast") mcast = true;} + else {if (mcast) {joinMulticastGroup(p); mcast = false;}} + } +} + + PIEthernet::InterfaceList PIEthernet::interfaces() { PIEthernet::InterfaceList il; Interface ci; diff --git a/piethernet.h b/piethernet.h index 5cf9b48d..d868f229 100644 --- a/piethernet.h +++ b/piethernet.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Ethernet, UDP/TCP Broadcast/Multicast - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,7 +29,7 @@ class PIP_EXPORT PIEthernet: public PIIODevice { - PIOBJECT(PIEthernet) + PIIODEVICE(PIEthernet) friend class PIPeer; public: @@ -57,16 +57,16 @@ public: //! Set read address - void setReadAddress(const PIString & ip, int port) {path_ = ip + ":" + PIString::fromNumber(port);} + void setReadAddress(const PIString & ip, int port) {setPath(ip + ":" + PIString::fromNumber(port));} //! Set read address in format "i.i.i.i:p" - void setReadAddress(const PIString & ip_port) {path_ = ip_port;} + void setReadAddress(const PIString & ip_port) {setPath(ip_port);} //! Set read IP - void setReadIP(const PIString & ip) {parseAddress(path_, &ip_, &port_); path_ = ip + ":" + PIString::fromNumber(port_);} + void setReadIP(const PIString & ip) {parseAddress(path(), &ip_, &port_); setPath(ip + ":" + PIString::fromNumber(port_));} //! Set read port - void setReadPort(int port) {parseAddress(path_, &ip_, &port_); path_ = ip_ + ":" + PIString::fromNumber(port);} + void setReadPort(int port) {parseAddress(path(), &ip_, &port_); setPath(ip_ + ":" + PIString::fromNumber(port));} //! Set send address @@ -83,13 +83,13 @@ public: //! Returns read address in format "i.i.i.i:p" - PIString readAddress() {return path_;} + PIString readAddress() {return path();} //! Returns read IP - PIString readIP() {parseAddress(path_, &ip_, &port_); return ip_;} + PIString readIP() {parseAddress(path(), &ip_, &port_); return ip_;} //! Returns read port - int readPort() {parseAddress(path_, &ip_, &port_); return port_;} + int readPort() {parseAddress(path(), &ip_, &port_); return port_;} //! Returns send address in format "i.i.i.i:p" @@ -103,21 +103,21 @@ public: //! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them - void setParameters(PIFlags parameters_) {params = parameters_;} + void setParameters(PIFlags parameters_) {setProperty("parameters", (int)parameters_);} //! Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this - void setParameter(PIEthernet::Parameters parameter, bool on = true) {params.setFlag(parameter, on);} + void setParameter(PIEthernet::Parameters parameter, bool on = true); //! Returns if parameter "parameter" is set - bool isParameterSet(PIEthernet::Parameters parameter) const {return params[parameter];} + bool isParameterSet(PIEthernet::Parameters parameter) const {return ((PIFlags)(property("parameters").toInt()))[parameter];} //! Returns parameters - PIFlags parameters() const {return params;} + PIFlags parameters() const {return (PIFlags)(property("parameters").toInt());} //PIByteArray macAddress() {if (!init_) init(); struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); memcpy(ifr.ifr_name, "eth0", 5); ioctl(sock, SIOCSIFHWADDR, &ifr); return PIByteArray(&ifr.ifr_hwaddr.sa_data, 6);} //! Returns %PIEthernet type - Type type() const {return type_;} + Type type() const {return (Type)(property("type").toInt());} //! Join to multicast group with address "group". Use only for UDP @@ -126,15 +126,18 @@ public: //! Leave multicast group with address "group". Use only for UDP bool leaveMulticastGroup(const PIString & group); + //! Returns joined multicast groups. Use only for UDP + const PIStringList & multicastGroups() const {return mcast_groups;} + //! Connect to TCP server with address \a readAddress(). Use only for TCP_Client bool connect(); //! Connect to TCP server with address "ip":"port". Use only for TCP_Client - bool connect(const PIString & ip, int port) {path_ = ip + ":" + PIString::fromNumber(port); return connect();} + bool connect(const PIString & ip, int port) {setPath(ip + ":" + PIString::fromNumber(port)); return connect();} //! Connect to TCP server with address "ip_port". Use only for TCP_Client - bool connect(const PIString & ip_port) {path_ = ip_port; return connect();} + bool connect(const PIString & ip_port) {setPath(ip_port); return connect();} //! Returns if %PIEthernet connected to TCP server. Use only for TCP_Client bool isConnected() const {return connected_;} @@ -308,6 +311,8 @@ public: protected: PIEthernet(int sock, PIString ip_port); + PIString fullPathPrefix() const {return "eth";} + void configureFromFullPath(const PIString & full_path); bool configureDevice(const void * e_main, const void * e_parent = 0); //! Executes when any read function was successful. Default implementation does nothing @@ -329,14 +334,14 @@ protected: PIThread server_thread_; PIVector clients_; PIQueue mcast_queue; + PIStringList mcast_groups; #ifdef WINDOWS PIMap leafs; #endif - PIFlags params; - Type type_; private: static void server_func(void * eth); + void setType(Type t) {setProperty("type", (int)t); if (isOpened()) {closeDevice(); init(); openDevice();}} static std::string ethErrorString() { #ifdef WINDOWS @@ -351,4 +356,6 @@ private: }; +inline bool operator <(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {return (v0.name < v1.name);} + #endif // PIETHERNET_H diff --git a/pievaluator.cpp b/pievaluator.cpp index 7b00eb2a..98821562 100644 --- a/pievaluator.cpp +++ b/pievaluator.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Evaluator designed for stream computing - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -158,6 +158,7 @@ PIEvaluatorContent::PIEvaluatorContent() { addFunction("clamp", 3); // (x,a,b) = x < a ? a : (x > b ? b : x) addFunction("step", 2); // (x,s) = x >= s ? 1. : 0. (1 if 'x' >= 's', else 0) addFunction("mix", 3); // (x,a,b) = a*(1.-x) + b*x (interpolate between 'a' and 'b' linear for 'x') + addFunction("defined", 1); clearCustomVariables(); //addVariable("n", 0.); //addVariable("x1", 123); @@ -245,6 +246,7 @@ PIEvaluatorTypes::BaseFunctions PIEvaluatorContent::getBaseFunction(const PIStri if (name == "clamp") return PIEvaluatorTypes::bfClamp; if (name == "step") return PIEvaluatorTypes::bfStep; if (name == "mix") return PIEvaluatorTypes::bfMix; + if (name == "defined") return PIEvaluatorTypes::bfDefined; return PIEvaluatorTypes::bfUnknown; } @@ -1148,6 +1150,9 @@ inline void PIEvaluator::execFunction(const PIEvaluatorTypes::Instruction & ci) ttmp = value(ci.operators[2]); tmpvars[oi].value = stmp.real() * (1. - tmp.real()) + ttmp.real() * tmp.real(); break; + case PIEvaluatorTypes::bfDefined: + tmpvars[oi].value = value(ci.operators[0]).real() > 0. ? complexd_1 : complexd_0; + break; case PIEvaluatorTypes::bfRandom: tmp = static_cast(rand()) / RAND_MAX; stmp = value(ci.operators[1]) - value(ci.operators[0]); diff --git a/pievaluator.h b/pievaluator.h index 018cb314..f2a9bf90 100644 --- a/pievaluator.h +++ b/pievaluator.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Evaluator designed for stream computing - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,6 +26,8 @@ #include "pistring.h" #include "pimath.h" +typedef complexd (*FuncFunc)(void * , int, complexd * ); + namespace PIEvaluatorTypes { static const int operationCount = 14; @@ -42,9 +44,10 @@ namespace PIEvaluatorTypes { bfIm, bfRe, bfArg, bfLen, bfConj, bfRad, bfDeg, bfJ0, bfJ1, bfJN, bfY0, bfY1, bfYN, bfMin, bfMax, - bfClamp, bfStep, bfMix + bfClamp, bfStep, bfMix, bfDefined, + bfCustom = 0xFFFF }; - + struct Instruction { Instruction() {;} Instruction(Operation oper, PIVector opers, int out_ind, int func = -1) { @@ -63,10 +66,12 @@ namespace PIEvaluatorTypes { int var_num; }; struct Function { - Function() {arguments = 0; type = bfUnknown;} - Function(const PIString & name, int args, BaseFunctions ftype) {identifier = name; arguments = args; type = ftype;} + Function() {arguments = 0; type = bfUnknown; handler = 0;} + Function(const PIString & name, int args, BaseFunctions ftype) {identifier = name; arguments = args; type = ftype; handler = 0;} + Function(const PIString & name, int args, FuncFunc h) {identifier = name; arguments = args; type = bfCustom; handler = h;} PIString identifier; BaseFunctions type; + FuncFunc handler; int arguments; }; struct Variable { @@ -83,6 +88,7 @@ namespace PIEvaluatorTypes { ⋀ & ⋁ | */ + class PIP_EXPORT PIEvaluatorContent { friend class PIEvaluator; @@ -92,6 +98,7 @@ public: void addFunction(const PIString & name, int args = 1) {functions.push_back(PIEvaluatorTypes::Function(name, args, getBaseFunction(name)));} void addVariable(const PIString & name, const complexd & val = 0.) {variables.push_back(PIEvaluatorTypes::Variable(name, val)); sortVariables();} + void addCustomFunction(const PIString & name, int args_count, FuncFunc func) {functions << PIEvaluatorTypes::Function(name, args_count, func);} int functionsCount() const {return functions.size();} int variablesCount() const {return variables.size();} int customVariablesCount() const {return variables.size() - cv_count;} @@ -119,16 +126,24 @@ private: }; + class PIP_EXPORT PIEvaluator { public: //! Constructs an empty evaluator - PIEvaluator() {correct = false;} + PIEvaluator() {correct = false; data_ = 0;} ~PIEvaluator() {;} + //! Returns custom data + void * data() {return data_;} + + //! Set custom data to "_data" + void setData(void * _data) {data_ = _data;} + + //! Check mathematical expression and parse it to list of instructions bool check(const PIString & string); @@ -142,7 +157,10 @@ public: void setVariable(int index, complexd value = 0.) {if (index >= 0 && index < content.variablesCount()) content.setVariableValue(index, value);} void setCustomVariableValue(int index, complexd value = 0.) {content.variables[index + content.cv_count].value = value;} - +/* + //! Add function "name" with arguments count "args_count" and handler "func". Three arguments will be passed to handler: \a data(), "args_count" and array of input values. + void addFunction(const PIString & name, int args_count, FuncFunc func) {content.addCustomFunction(name, args_count, func);} +*/ //! Evaluate last successfully checked with function \a check() expression and returns result complexd evaluate(); @@ -200,6 +218,7 @@ private: PIString currentString, lastError; complexd out; bool correct; + void * data_; }; inline bool operator ==(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {return (e1.type == e2.type && e1.num == e2.num);} diff --git a/pifile.cpp b/pifile.cpp index 67544070..36f6bf05 100644 --- a/pifile.cpp +++ b/pifile.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives File - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,12 +40,14 @@ * */ +REGISTER_DEVICE(PIFile); + bool PIFile::openDevice() { close(); - if (path_.isEmpty()) return false; + if (path().isEmpty()) return false; //piCout << "fopen " << path_.data() << ": " << strType(mode_).data() << fd; - fd = fopen(path_.data(), strType(mode_).data()); + fd = fopen(path().data(), strType(mode_).data()); opened_ = (fd != 0); #ifndef WINDOWS if (opened_) fcntl(fileno(fd), F_SETFL, O_NONBLOCK); @@ -144,3 +146,8 @@ bool PIFile::isExists(const PIString & path) { if (ok) fclose(f); return ok; } + + +void PIFile::configureFromFullPath(const PIString & full_path) { + setPath(full_path); +} diff --git a/pifile.h b/pifile.h index 880b3aad..6901652a 100644 --- a/pifile.h +++ b/pifile.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives File - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,11 +28,11 @@ class PIP_EXPORT PIFile: public PIIODevice { - PIOBJECT(PIFile) + PIIODEVICE(PIFile) public: //! Constructs a file with path "path" nad open mode "type" - PIFile(const PIString & path = PIString(), DeviceMode type = ReadWrite): PIIODevice(path, type) {setPrecision(5); openDevice();} + PIFile(const PIString & path = PIString(), DeviceMode mode = ReadWrite): PIIODevice(path, mode) {setPrecision(5); if (!path.isEmpty()) openDevice();} ~PIFile() {close();} @@ -69,7 +69,7 @@ public: //! Set file path to "path" and reopen file if need - void setPath(const PIString & path) {path_ = path; if (opened_) openDevice();} + void setPath(const PIString & path) {PIIODevice::setPath(path); if (opened_) openDevice();} //! Returns file size llong size(); @@ -125,7 +125,7 @@ public: //! Write to file binary content of "v" PIFile & writeBinary(const double v) {write(&v, sizeof(v)); return *this;} - PIFile & operator =(const PIFile & f) {path_ = f.path_; mode_ = f.mode_; return *this;} + PIFile & operator =(const PIFile & f) {PIIODevice::setPath(f.path()); mode_ = f.mode_; return *this;} //! Write to file text representation of "v" PIFile & operator <<(const char v) {if (canWrite() && fd != 0) write(&v, 1); return *this;} @@ -184,8 +184,8 @@ public: PIFile & operator >>(double & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lf", &v); return *this;} - EVENT_HANDLER(void, clear) {close(); fd = fopen(path_.data(), "w"); if (fd != 0) fclose(fd); fd = 0; opened_ = false; open();} - EVENT_HANDLER0(void, remove) {close(); std::remove(path_.data());} + EVENT_HANDLER(void, clear) {close(); fd = fopen(path().data(), "w"); if (fd != 0) fclose(fd); fd = 0; opened_ = false; open();} + EVENT_HANDLER0(void, remove) {close(); std::remove(path().data());} EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);} EVENT_HANDLER2(void, resize, llong, new_size, uchar, fill); @@ -222,6 +222,8 @@ public: //! \} protected: + PIString fullPathPrefix() const {return "file";} + void configureFromFullPath(const PIString & full_path); bool openDevice(); bool closeDevice(); diff --git a/pigeometry.h b/pigeometry.h index a743b481..dd8c25f6 100644 --- a/pigeometry.h +++ b/pigeometry.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Geometry - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piincludes.cpp b/piincludes.cpp index 9ff83210..21de759a 100644 --- a/piincludes.cpp +++ b/piincludes.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Global includes - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -235,7 +235,7 @@ PICout PICout::operator <<(const double v) {space(); std::cout << v; return *thi PICout PICout::operator <<(const void * v) {space(); std::cout << "0x" << PIString::fromNumber(ullong(v), 16); return *this;} -PICout PICout::operator <<(const PIObject * v) {space(); std::cout << v->className() << "*(" << "0x" << PIString::fromNumber(ullong(v), 16) << ", \"" << v->name() << "\")"; return *this;} +PICout PICout::operator <<(const PIObject * v) {space(); if (v == 0) std::cout << "PIObject*(0x0)"; else std::cout << v->className() << "*(" << "0x" << PIString::fromNumber(ullong(v), 16) << ", \"" << v->name() << "\")"; return *this;} #undef PINUMERICCOUT diff --git a/piincludes.h b/piincludes.h index 7283b029..c85ba065 100644 --- a/piincludes.h +++ b/piincludes.h @@ -7,7 +7,7 @@ /* PIP - Platform Independent Primitives Global includes - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ #define PIINCLUDES_H //! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision) -#define PIP_VERSION 0x000308 +#define PIP_VERSION 0x000400 //! Major value of PIP version #define PIP_VERSION_MAJOR (PIP_VERSION & 0xFF0000) >> 16 @@ -39,7 +39,7 @@ #define PIP_VERSION_REVISION PIP_VERSION & 0xFF //! Suffix of PIP version -#define PIP_VERSION_SUFFIX "_beta" +#define PIP_VERSION_SUFFIX "_prealpha" #ifdef DOXYGEN @@ -84,8 +84,13 @@ #endif -#if defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__WIN64__) +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) # define WINDOWS +# define ARCH_BITS_32 +#endif +#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) +# define WINDOWS +# define ARCH_BITS_64 #endif #if defined(__QNX__) || defined(__QNXNTO__) # define QNX @@ -112,6 +117,15 @@ # endif # endif #endif + +#ifndef WINDOWS +# if defined(__LP64__) || defined(_LP64_) || defined(LP64) +# define ARCH_BITS_64 +# else +# define ARCH_BITS_32 +# endif +#endif + #ifdef __GNUC__ # define CC_GCC # define CC_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__) @@ -128,8 +142,10 @@ # pragma GCC diagnostic ignored "-Wextra" # pragma GCC diagnostic ignored "-Wliteral-suffix" # endif +# define DEPRECATED __attribute__((deprecated)) #elif defined(_MSC_VER) # define CC_VC +# pragma warning(disable: 4018) # pragma warning(disable: 4061) # pragma warning(disable: 4100) # pragma warning(disable: 4239) @@ -144,15 +160,15 @@ # pragma warning(disable: 4820) # pragma warning(disable: 4986) # pragma warning(disable: 4996) +# define DEPRECATED +# ifdef ARCH_BITS_32 + typedef long ssize_t; +# else + typedef long long ssize_t; +# endif #else # define CC_OTHER -#endif -#ifdef PIP_DEBUG -# undef NDEBUG -#else -# ifndef NDEBUG -# define NDEBUG -# endif +# define DEPRECATED #endif #ifdef WINDOWS @@ -164,7 +180,7 @@ #endif #include "pip_export.h" -#if defined(DOXYGEN) || defined(CC_GCC) +#if defined(DOXYGEN) || defined(CC_GCC) || defined(PICODE) # undef PIP_EXPORT # define PIP_EXPORT #endif @@ -190,6 +206,7 @@ #include #include #include +#include //#include #include #include @@ -236,7 +253,7 @@ # endif #endif #ifdef ANDROID -# include "ifaddrs_3rd.h" +//# include "ifaddrs_3rd.h" # define tcdrain(fd) ioctl(fd, TCSBRK, 1) inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;} inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;} @@ -259,6 +276,13 @@ #ifdef FREE_BSD extern char ** environ; #endif +#if defined(DOXYGEN) || defined(PICODE) +# undef PIP_EXPORT +# define PIP_EXPORT +# undef DEPRECATED +# define DEPRECATED +#endif + #include "pimonitor.h" extern PIMonitor piMonitor; @@ -294,12 +318,9 @@ using std::map; using std::multimap; using std::string; #ifndef QNX -using std::wstring; -//# ifndef WINDOWS -//static locale_t currentLocale_t = 0; -//# endif + using std::wstring; #else -typedef std::basic_string wstring; + typedef std::basic_string wstring; #endif /*! \brief Templated function for swap two values @@ -458,8 +479,8 @@ template inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, size template<> inline ushort piLetobe(const ushort & v) {return (v << 8) | (v >> 8);} template<> inline uint piLetobe(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} -__attribute__((deprecated)) inline ushort letobe_s(const ushort & v) {return (v << 8) | (v >> 8);} -__attribute__((deprecated)) inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} +DEPRECATED inline ushort letobe_s(const ushort & v) {return (v << 8) | (v >> 8);} +DEPRECATED inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} #ifdef DOXYGEN @@ -721,7 +742,7 @@ private: #else # define piCout if (piDebug) PICout() -# define piCoutObj if (piDebug && debug_) PICout() << "" << (PIString("[") + className() + " \"" + name() + "\"]") +# define piCoutObj if (piDebug && debug()) PICout() << "" << (PIString("[") + className() + " \"" + name() + "\"]") #endif class PIObject; @@ -787,7 +808,7 @@ namespace PICoutManipulators { BackMagenta /*! Magenta background */ = 0x800000, BackCyan /*! Cyan background */ = 0x1000000, BackWhite /*! White background */ = 0x2000000, - Default /*! Default format */ = 0x4000000, + Default /*! Default format */ = 0x4000000 }; }; diff --git a/piiodevice.cpp b/piiodevice.cpp index 4c48b556..8b01cd8b 100644 --- a/piiodevice.cpp +++ b/piiodevice.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Abstract input/output device - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -53,7 +53,7 @@ * PIIODevice have internal buffer for threaded read, and \a threadedRead() function * receive pointer to this buffer in first argument. You can adjust size of this buffer * by function \a setThreadedReadBufferSize() \n - * Default size of this buffer is 4096 bytes + * Default size of this buffer is 4096 bytes. * * \section PIIODevice_sec5 Reopen * When threaded read is begin its call \a open() if device is closed. While threaded @@ -70,11 +70,42 @@ * function \a configureDevice(). * \n Each ancestor of %PIIODevice reimlements \a configureDevice() function to be able * to be confured from configuration file. This parameters described at section - * "Configurable parameters" in the class reference. Usage example: + * "Configurable parameters" in the class reference. \n Usage example: * \snippet piiodevice.cpp configure - * Implement example: + * Implementation example: * \snippet piiodevice.cpp configureDevice * + * \section PIIODevice_sec7 Creating devices by unambiguous string + * There are some virtual functions to describe child class without its declaration. + * \n \a fullPathPrefix() should returns unique prefix of device + * \n \a constructFullPath() should returns full unambiguous string, contains prefix and all device parameters + * \n \a configureFromFullPath() provide configuring device from full unambiguous string without prefix and "://" + * \n Macro PIIODEVICE should be used instead of PIOBJECT + * \n Macro REGISTER_DEVICE should be used after definition of class, i.e. at the last line of *.cpp file + * \n \n If custom I/O device corresponds there rules, it can be returned by function \a createFromFullPath(). + * \n Each PIP I/O device has custom unambiguous string description: + * * PIFile: "file://" + * * PIBinaryLog: "binlog://[:][:]" + * * PISerial: "ser://:[:][:][:]" + * * PIEthernet: "eth://::[:)>]" + * * PIUSB: "usb://:[:][:][:]" + * \n \n Examples: + * * PIFile: "file://../text.txt" + * * PIBinaryLog: "binlog://../logs/:mylog_:1" + * * PISerial: "ser:///dev/ttyUSB0:9600:8:N:1", equivalent "ser:///dev/ttyUSB0:9600" + * * PIEthernet: "eth://TCP:127.0.0.1:16666", "eth://UDP:192.168.0.5:16666:mcast:234.0.2.1:mcast:234.0.2.2" + * * PIUSB: "usb://0bb4:0c86:1:1:2" + * \n \n + * So, custom I/O device can be created with next call: + * \code{cpp} + * // creatring devices + * PISerial * ser = (PISerial * )PIIODevice::createFromFullPath("ser://COM1:115200"); + * PIEthernet * eth = (PIEthernet * )PIIODevice::createFromFullPath("eth://UDP:127.0.0.1:4001"); + * // examine devices + * piCout << ser << ser->properties(); + * piCout << eth << eth->properties(); + * \endcode + * * \section PIIODevice_ex0 Example * \snippet piiodevice.cpp 0 */ @@ -82,38 +113,18 @@ PIIODevice::PIIODevice(): PIThread() { mode_ = ReadOnly; - opened_ = init_ = thread_started_ = false; - reopen_enabled_ = raise_threaded_read_ = true; - reopen_timeout_ = 1000; - ret_func_ = 0; - ret_data_ = 0; - tri = 0; - buffer_tr.resize(4096); - CONNECT2(void, void * , int, &timer, timeout, this, check_start); - CONNECT(void, &write_thread, started, this, write_func); - created(); - init(); + _init(); + setPath(PIString()); } /*! \brief Constructs a PIIODevice with path and mode * \param path path to device - * \param type mode for open - * \param initNow init or not in constructor */ -PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode type, bool initNow): PIThread() { - path_ = path; - mode_ = type; - opened_ = init_ = thread_started_ = false; - reopen_enabled_ = raise_threaded_read_ = true; - reopen_timeout_ = 1000; - ret_func_ = 0; - ret_data_ = 0; - tri = 0; - buffer_tr.resize(4096); - CONNECT2(void, void * , int, &timer, timeout, this, check_start); - CONNECT(void, &write_thread, started, this, write_func); - created(); - if (initNow) init(); + * \param type mode for open */ +PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode mode): PIThread() { + mode_ = mode; + _init(); + setPath(path); } @@ -127,6 +138,20 @@ PIIODevice::~PIIODevice() { } +void PIIODevice::_init() { + opened_ = init_ = thread_started_ = false; + raise_threaded_read_ = true; + ret_func_ = 0; + ret_data_ = 0; + tri = 0; + setReopenEnabled(true); + setReopenTimeout(1000); + setThreadedReadBufferSize(4096); + CONNECT2(void, void * , int, &timer, timeout, this, check_start); + CONNECT(void, &write_thread, started, this, write_func); +} + + void PIIODevice::check_start(void * data, int delim) { //cout << "check " << tread_started_ << endl; if (open()) { @@ -176,7 +201,7 @@ void PIIODevice::begin() { return; } //init(); - if (!timer.isRunning() && reopen_enabled_) timer.start(reopen_timeout_); + if (!timer.isRunning() && isReopenEnabled()) timer.start(reopenTimeout()); } @@ -206,13 +231,14 @@ PIByteArray PIIODevice::readForTime(double timeout_ms) { PIByteArray str; if (timeout_ms <= 0.) return str; int ret; - uchar td[threadedReadBufferSize()]; + uchar * td = new uchar[threadedReadBufferSize()]; timer.reset(); while (timer.elapsed_m() < timeout_ms) { ret = read(td, threadedReadBufferSize()); if (ret <= 0) msleep(1); else str.append(td, ret); } + delete td; return str; } @@ -237,16 +263,30 @@ bool PIIODevice::configure(const PIString & config_file, const PIString & sectio PIConfig::Entry * ep = 0; if (parent_section) ep = em.parent(); if (ep != 0) { - setReopenEnabled(ep->getValue("reopenEnabled", reopen_enabled_, &ex)); - if (!ex) setReopenEnabled(em.getValue("reopenEnabled", reopen_enabled_)); - setReopenTimeout(ep->getValue("reopenTimeout", reopen_timeout_, &ex)); - if (!ex) setReopenTimeout(em.getValue("reopenTimeout", reopen_timeout_)); + setReopenEnabled(ep->getValue("reopenEnabled", isReopenEnabled(), &ex)); + if (!ex) setReopenEnabled(em.getValue("reopenEnabled", isReopenEnabled())); + setReopenTimeout(ep->getValue("reopenTimeout", reopenTimeout(), &ex)); + if (!ex) setReopenTimeout(em.getValue("reopenTimeout", reopenTimeout())); setThreadedReadBufferSize(ep->getValue("threadedReadBufferSize", buffer_tr.size_s(), &ex)); if (!ex) setThreadedReadBufferSize(em.getValue("threadedReadBufferSize", buffer_tr.size_s())); } else { - setReopenEnabled(em.getValue("reopenEnabled", reopen_enabled_)); - setReopenTimeout(em.getValue("reopenTimeout", reopen_timeout_)); + setReopenEnabled(em.getValue("reopenEnabled", isReopenEnabled())); + setReopenTimeout(em.getValue("reopenTimeout", reopenTimeout())); setThreadedReadBufferSize(em.getValue("threadedReadBufferSize", buffer_tr.size_s())); } return configureDevice(&em, ep); } + + +PIIODevice * PIIODevice::createFromFullPath(const PIString & full_path) { + PIString prefix = full_path.left(full_path.find(":")); + if (prefix.isEmpty()) return 0; + PIVector rd(PICollection::groupElements("__PIIODevices__")); + piForeachC (PIObject * d, rd) + if (prefix == ((const PIIODevice * )d)->fullPathPrefix()) { + PIIODevice * nd = ((const PIIODevice * )d)->copy(); + if (nd) nd->configureFromFullPath(full_path.mid(prefix.length() + 3)); + return nd; + } + return 0; +} diff --git a/piiodevice.h b/piiodevice.h index a2f1084c..0744c0d2 100644 --- a/piiodevice.h +++ b/piiodevice.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Abstract input/output device - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,12 +23,27 @@ #ifndef PIIODEVICE_H #define PIIODEVICE_H +#include "picollection.h" #include "pivariant.h" #include "pitimer.h" // function executed from threaded read, pass ThreadedReadData, readedData, sizeOfData typedef bool (*ReadRetFunc)(void * , uchar * , int ); +#ifdef DOXYGEN + +//! \relatesalso PIIODevice \brief Use this macro to enable automatic creation instances of your class with \a createFromFullPath() function +# define REGISTER_DEVICE(class) + +//! \relatesalso PIIODevice \brief Use this macro instead of PIOBJECT when describe your own PIIODevice +# define PIIODEVICE(class) + +#else + +# define REGISTER_DEVICE(class) ADD_NEW_TO_COLLECTION(__PIIODevices__, class) +# define PIIODEVICE(class) PIOBJECT(class) PIIODevice * copy() const {return new class();} + +#endif class PIP_EXPORT PIIODevice: public PIThread { @@ -45,17 +60,17 @@ public: ReadWrite /*! Device can both read and write */ = 0x03 }; - PIIODevice(const PIString & path, DeviceMode type = ReadWrite, bool initNow = true); + PIIODevice(const PIString & path, DeviceMode mode = ReadWrite); virtual ~PIIODevice(); //! Current open mode of device DeviceMode mode() const {return mode_;} //! Current path of device - PIString path() const {return path_;} + PIString path() const {return property("path").toString();} //! Set path of device - void setPath(const PIString & path) {path_ = path;} + void setPath(const PIString & path) {setProperty("path", path);} //! Return \b true if mode is ReadOnly or ReadWrite bool isReadable() const {return (mode_ & ReadOnly);} @@ -79,17 +94,17 @@ public: //! Set execution of \a open enabled while threaded read on closed device - void setReopenEnabled(bool yes = true) {reopen_enabled_ = yes;} + void setReopenEnabled(bool yes = true) {setProperty("reopenEnabled", yes);} //! Set timeout in milliseconds between \a open tryings if reopen is enabled - void setReopenTimeout(int msecs = 1000) {reopen_timeout_ = msecs;} + void setReopenTimeout(int msecs) {setProperty("reopenTimeout", msecs);} //! Return reopen enable - bool isReopenEnabled() const {return reopen_enabled_;} + bool isReopenEnabled() const {return property("reopenEnabled").toBool();} //! Return reopen timeout - int reopenTimeout() {return reopen_timeout_;} + int reopenTimeout() {return property("reopenTimeout").toInt();} /** \brief Set "threaded read slot" @@ -172,12 +187,18 @@ public: //! Configure device from section "section" of file "config_file", if "parent_section" parent section also will be read bool configure(const PIString & config_file, const PIString & section, bool parent_section = false); - + + + //! \brief Try to determine suitable device, create new one, configure it with \a configureFromFullPath() and returns it. + //! \details To function \a configureFromFullPath() "full_path" passed without \a fullPathPrefix() + "://". + //! See \ref PIIODevice_sec7 + static PIIODevice * createFromFullPath(const PIString & full_path); + EVENT_HANDLER(bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} - EVENT_HANDLER1(bool, open, const PIString &, _path) {path_ = _path; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} + EVENT_HANDLER1(bool, open, const PIString &, _path) {setPath(_path); if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} EVENT_HANDLER1(bool, open, const DeviceMode &, _type) {mode_ = _type; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} - EVENT_HANDLER2(bool, open, const PIString &, _path, const DeviceMode &, _type) {path_ = _path; mode_ = _type; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} + EVENT_HANDLER2(bool, open, const PIString &, _path, const DeviceMode &, _mode) {setPath(_path); mode_ = _mode; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} EVENT_HANDLER(bool, close) {opened_ = !closeDevice(); if (!opened_) closed(); return !opened_;} EVENT_HANDLER(bool, initialize) {init_ = init(); return init_;} @@ -249,12 +270,9 @@ public: protected: - //! Function executed from the end of constructor - virtual void created() {;} - //! Function executed before first \a openDevice() or from constructor virtual bool init() {return true;} - + //! Reimplement to configure device from entries "e_main" and "e_parent", cast arguments to \a PIConfig::Entry* virtual bool configureDevice(const void * e_main, const void * e_parent = 0) {return true;} @@ -267,20 +285,31 @@ protected: //! Function executed when thread read some data, default implementation execute external slot "ret_func_" virtual bool threadedRead(uchar * readed, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, readed, size); return true;} + + //! Reimplement to construct full unambiguous string prefix. \ref PIIODevice_sec7 + virtual PIString fullPathPrefix() const {return PIString();} + + //! Reimplement to construct full unambiguous string, describes this device, default returns \a path() + virtual PIString constructFullPath() const {return path();} + + //! Reimplement to configure your device with parameters of full unambiguous string. Default implementation does nothing + virtual void configureFromFullPath(const PIString & full_path) {;} + + void terminate(); - PIString path_; DeviceMode mode_; ReadRetFunc ret_func_; - bool init_, opened_, thread_started_, reopen_enabled_, raise_threaded_read_; - int reopen_timeout_; + bool init_, opened_, thread_started_, raise_threaded_read_; void * ret_data_; private: EVENT_HANDLER2(void, check_start, void * , data, int, delim); EVENT_HANDLER(void, write_func); + virtual PIIODevice * copy() const {return 0;} + void _init(); void begin(); void run(); void end() {terminate();} diff --git a/pikbdlistener.cpp b/pikbdlistener.cpp index 6905a868..22ac9135 100644 --- a/pikbdlistener.cpp +++ b/pikbdlistener.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Keyboard grabber for console - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,7 +24,7 @@ * \brief Keyboard console input listener * \details This class provide listening of console keyboard input. * There is two ways to receive pressed key: - * * external static functionwith format "void func(char key, void * data)" + * * external static functionwith format "void func(char key, void * data_)" * * event \a keyPressed() * * Also there is static variable \a exiting which by default is set to @@ -38,7 +38,7 @@ bool PIKbdListener::exiting; -PIKbdListener::PIKbdListener(KBFunc slot, void * data_): PIThread() { +PIKbdListener::PIKbdListener(KBFunc slot, void * _data): PIThread() { #ifdef WINDOWS hIn = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(hIn, &smode); @@ -49,7 +49,7 @@ PIKbdListener::PIKbdListener(KBFunc slot, void * data_): PIThread() { #endif is_active = true; ret_func = slot; - data = data_; + data_ = _data; PIKbdListener::exiting = exit_enabled = false; start(); } @@ -134,8 +134,8 @@ void PIKbdListener::run() { return; } if (ret > 0) { - keyPressed(lc, data); - if (ret_func != 0) ret_func(lc, data); + keyPressed(lc, data_); + if (ret_func != 0) ret_func(lc, data_); } } diff --git a/pikbdlistener.h b/pikbdlistener.h index a7c5dc3e..801b80da 100644 --- a/pikbdlistener.h +++ b/pikbdlistener.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Keyboard grabber for console - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -56,8 +56,11 @@ public: ~PIKbdListener() {terminate(); end();} - //! Set custom data to "data" - void setData(void * data_) {data = data_;} + //! Returns custom data + void * data() {return data_;} + + //! Set custom data to "_data" + void setData(void * _data) {data_ = _data;} //! Set external function to "slot" void setSlot(KBFunc slot) {ret_func = slot;} @@ -111,7 +114,7 @@ private: KBFunc ret_func; char exit_key; bool exit_enabled, is_active; - void * data; + void * data_; #ifdef WINDOWS DWORD ret, rc; void * hIn; diff --git a/pimap.h b/pimap.h index 59088b15..8368cd09 100644 --- a/pimap.h +++ b/pimap.h @@ -6,7 +6,7 @@ /* PIP - Platform Independent Primitives Dynamic array of any type - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -302,9 +302,14 @@ public: _CMap & insert(const Key & key_, const Type & value_) {_stlc::insert(_stlpair(key_, value_)); return *this;} _CMap & insert(PIPair entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;} Key key(Type value_) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return Key();} - Type & value(const Key & key_) {typename _stlc::iterator it = _stlc::find(key_); if (it == _stlc::end()) it->second = Type(); return it->second;} - Type & at(const Key & key_) {return value(key_);} - Type value(const Key & key_) const {return _stlc::find(key_)->second;} + PIVector keys() const { + PIVector ret; + for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) + ret << i->first; + return ret; + } + Type & at(const Key & key_) {return _stlc::find(key_)->second;} + Type value(const Key & key_) const {typename _stlc::const_iterator it = _stlc::find(key_); if (it != _stlc::end()) return it->second; return Type();} }; diff --git a/pimath.cpp b/pimath.cpp index 79a6ccb6..6284aa40 100644 --- a/pimath.cpp +++ b/pimath.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Math - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pimath.h b/pimath.h index feac8693..1ad57bc3 100644 --- a/pimath.h +++ b/pimath.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Math - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pimonitor.cpp b/pimonitor.cpp index f4a666b3..73ea3f1a 100644 --- a/pimonitor.cpp +++ b/pimonitor.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Counter of some PIP types - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pimonitor.h b/pimonitor.h index 95f4f8e9..288e9634 100644 --- a/pimonitor.h +++ b/pimonitor.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Counter of some PIP types - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pimultiprotocol.h b/pimultiprotocol.h index 08641c58..d7bc65d8 100644 --- a/pimultiprotocol.h +++ b/pimultiprotocol.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Multiprotocol - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pimutex.cpp b/pimutex.cpp index d165b416..37f19baf 100644 --- a/pimutex.cpp +++ b/pimutex.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Mutex - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pimutex.h b/pimutex.h index 5b36ab3a..e8f82eb5 100644 --- a/pimutex.h +++ b/pimutex.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Mutex - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piobject.cpp b/piobject.cpp index 810ec52d..8a0843df 100644 --- a/piobject.cpp +++ b/piobject.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -55,6 +55,14 @@ handler A: event to event */ +PIObject::PIObject(const PIString & name) { + piMonitor.objects++; + setName(name); + setDebug(true); + objects << this; +} + + void PIObject::piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h) { PIObject * o = findByName(src); if (o == 0) { diff --git a/piobject.h b/piobject.h index 280206c9..77cf7bfe 100644 --- a/piobject.h +++ b/piobject.h @@ -6,7 +6,7 @@ /* PIP - Platform Independent Primitives Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -227,26 +227,26 @@ class PIP_EXPORT PIObject public: //! Contructs PIObject with name "name" - PIObject(const PIString & name = PIString()) {piMonitor.objects++; setName(name); objects << this; debug_ = true;} + PIObject(const PIString & name = PIString()); virtual ~PIObject() {piMonitor.objects--; objects.removeAll(this);} //! Returns object name - const PIString & name() const {return name_;} + PIString name() const {return property("name").toString();} //! Returns object class name virtual const char * className() const {return "PIObject";} //! Return if debug of this object is active - bool debug() const {return debug_;} + bool debug() const {return property("debug").toBool();} //! Set object name - void setName(const PIString & name) {name_ = name;} + void setName(const PIString & name) {setProperty("name", name);} //! Set object debug active - void setDebug(bool debug) {debug_ = debug;} + void setDebug(bool debug) {setProperty("debug", debug);} //! Returns properties of the object const PIMap & properties() const {return properties_;} @@ -255,13 +255,13 @@ public: int propertiesCount() const {return properties_.size_s();} //! Returns property with name "name" - PIVariant property(const PIString & name) {if (!properties_.contains(name)) return PIVariant(); return properties_.value(name);} + PIVariant property(const PIString & name) const {if (!properties_.contains(name)) return PIVariant(); return properties_.value(name);} //! Set property with name "name" to "value". If there is no such property in object it will be added void setProperty(const PIString & name, const PIVariant & value) {properties_[name] = value;} //! Returns if property with name "name" exists - bool isPropertyExists(const PIString & name) {return properties_.contains(name);} + bool isPropertyExists(const PIString & name) const {return properties_.contains(name);} /* PIStringList events(); @@ -475,10 +475,17 @@ public: } raiseEvent(name,dest , v0, v1, v2, v3); } + + //! Returns PIObject* with name "name" or 0, if there is no objects found + static PIObject * findByName(const PIString & name) { + piForeach (PIObject * i, PIObject::objects) { + if (i->name() != name) continue; + return i; + } + return 0; + }; protected: - PIString name_; - bool debug_; private: struct Connection { @@ -493,13 +500,6 @@ private: PIMap properties_; static PIVector objects; - static PIObject * findByName(const PIString & name) { - piForeach (PIObject * i, PIObject::objects) { - if (i->name_ != name) continue; - return i; - } - return 0; - }; }; diff --git a/pip.h b/pip.h index f1f2f568..a2f12005 100644 --- a/pip.h +++ b/pip.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives All includes - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,4 +31,6 @@ #include "picrc.h" #include "pistatemachine.h" #include "picollection.h" +#include "piserial.h" +#include "pibinarylog.h" #include "piusb.h" diff --git a/pip.pro b/pip.pro index 60e421da..6ac42c67 100644 --- a/pip.pro +++ b/pip.pro @@ -9,11 +9,11 @@ INCLUDEPATH += . QT -= core gui CONFIG -= qt CONFIG += dll -VERSION = 0.3.8 +VERSION = 0.4.0 # Input HEADERS += \ - pivariable.h \ + pivariant.h \ pitimer.h \ pithread.h \ pisystemtests.h \ @@ -49,10 +49,12 @@ HEADERS += \ pibytearray.h \ pibitarray.h \ picollection.h \ - ifaddrs_3rd.h \ - pidiagnostics.h + pidiagnostics.h \ + pibinarylog.h \ + picodeparser.h \ + piusb.h SOURCES += main.cpp \ - pivariable.cpp \ + pivariant.cpp \ pitimer.cpp \ pithread.cpp \ pisystemtests.cpp \ @@ -80,8 +82,10 @@ SOURCES += main.cpp \ picli.cpp \ pibytearray.cpp \ picollection.cpp \ - ifaddrs_3rd.c \ - pidiagnostics.cpp + pidiagnostics.cpp \ + pibinarylog.cpp \ + picodeparser.cpp \ + piusb.cpp win32 { LIBS += -lws2_32 -lIphlpapi } else { diff --git a/pip_resource.rc b/pip_resource.rc deleted file mode 100644 index 61bd735b..00000000 --- a/pip_resource.rc +++ /dev/null @@ -1,38 +0,0 @@ -# if defined(UNDER_CE) -# include -# else -# include -# endif - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,3,8,0 - PRODUCTVERSION 0,3,8,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0x0L - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "\0" - VALUE "FileDescription", "\0" - VALUE "FileVersion", "0.3.8.0\0" - VALUE "LegalCopyright", "\0" - VALUE "OriginalFilename", "pip0.dll\0" - VALUE "ProductName", "pip\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END - END -/* End of Version info */ - diff --git a/pip_resource_win.rc b/pip_resource_win.rc index bcbb0214..3e6fa186 100644 --- a/pip_resource_win.rc +++ b/pip_resource_win.rc @@ -5,8 +5,8 @@ # endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,3,8,0 - PRODUCTVERSION 0,3,8,0 + FILEVERSION 0,4,0,0 + PRODUCTVERSION 0,4,0,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS VOS__WINDOWS32 @@ -19,7 +19,7 @@ VS_VERSION_INFO VERSIONINFO BEGIN VALUE "CompanyName", "Peri4\0" VALUE "FileDescription", "Platform-Independent Primitives\0" - VALUE "FileVersion", "0.3.8_alpha\0" + VALUE "FileVersion", "0.4.0_prealpha\0" VALUE "LegalCopyright", "\0" VALUE "OriginalFilename", "libpip.dll\0" VALUE "ProductName", "PIP\0" diff --git a/pipacketextractor.cpp b/pipacketextractor.cpp index 1da0eb8f..0392baf8 100644 --- a/pipacketextractor.cpp +++ b/pipacketextractor.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Packets extractor - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -57,6 +57,8 @@ * * */ +REGISTER_DEVICE(PIPacketExtractor); + PIPacketExtractor::PIPacketExtractor(PIIODevice * device_, void * recHeaderPtr, int recHeaderSize, int recDataSize) { ret_func_header = 0; diff --git a/pipacketextractor.h b/pipacketextractor.h index 4e5facf0..90d1efb4 100644 --- a/pipacketextractor.h +++ b/pipacketextractor.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Packets extractor - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,7 +31,7 @@ typedef bool (*HeaderCheckFunc)(void * , uchar * , uchar * , int ); class PIP_EXPORT PIPacketExtractor: public PIIODevice { - PIOBJECT(PIPacketExtractor) + PIIODEVICE(PIPacketExtractor) public: //! Contructs extractor with child device "device_", header content pointer "recHeaderPtr", header size "recHeaderSize" and payload size "recDataSize" @@ -106,6 +106,7 @@ protected: private: bool threadedRead(uchar * readed, int size); + PIString fullPathPrefix() const {return "pckext";} bool openDevice() {if (dev == 0) return false; return dev->open();} PIIODevice * dev; diff --git a/pipeer.cpp b/pipeer.cpp index 0256c84a..c672b18a 100644 --- a/pipeer.cpp +++ b/pipeer.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Peer - named I/O ethernet node - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,9 +24,9 @@ #define _PIPEER_IP_MULTICAST "230.13.3.12" #define _PIPEER_MSG_SIZE 8192 -PIPeer::PIPeer(const PIString & name): PIObject() { +PIPeer::PIPeer(const PIString & name_): PIObject() { rec_mc = rec_bc = false; - setName(name); + setName(name_); self_info.name = name_; self_info.dist = 0; eth_send = 0; @@ -272,7 +272,7 @@ bool PIPeer::multicastRead(uchar * data, int size) { PIVector rpeers; ba >> pi.name; //piCout << "read type" << type << "from" << pi.name; - if (pi.name == name_) return true; + if (pi.name == name()) return true; PIMutexLocker locker(mc_mutex); diag_s.received(size); //piCout << "analyz ..."; @@ -319,7 +319,7 @@ bool PIPeer::multicastRead(uchar * data, int size) { for (uint i = 0; i < rpeers.size(); ++i) { PeerInfo & rpeer(rpeers[i]); //piCout << " to sync " << rpeer.name; - if (rpeer.name == name_) continue; + if (rpeer.name == name()) continue; bool exist = false; for (uint j = 0; j < peers.size(); ++j) { PeerInfo & peer(peers[j]); diff --git a/pipeer.h b/pipeer.h index 3caff714..841174e7 100644 --- a/pipeer.h +++ b/pipeer.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Peer - named I/O ethernet node, forming self-organized peering network - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -99,7 +99,7 @@ public: PIDiagnostics & diagnosticService() {return diag_s;} PIDiagnostics & diagnosticData() {return diag_d;} - const PIVector & allPeers() const {return peers;} + const PIVector & allPeers() const {return peers;} bool isPeerExists(const PIString & name) const {return getPeerByName(name) != 0;} const PeerInfo * getPeerByName(const PIString & name) const {piForeachC (PeerInfo & i, peers) if (i.name == name) return &i; return 0;} @@ -128,7 +128,7 @@ private: void sendPeerInfo(const PeerInfo & info); void sendPeerRemove(const PIString & peer); void sendSelfInfo() {sendPeerInfo(self_info);} - void sendSelfRemove() {sendPeerRemove(name_);} + void sendSelfRemove() {sendPeerRemove(name());} void syncPeers(); void findNearestAddresses(); void initEths(const PIStringList & al); diff --git a/piprocess.cpp b/piprocess.cpp index 9b3e955c..3f237575 100644 --- a/piprocess.cpp +++ b/piprocess.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Process - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piprocess.h b/piprocess.h index 40b7fbb9..ae6f03d9 100644 --- a/piprocess.h +++ b/piprocess.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Process - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piprotocol.cpp b/piprotocol.cpp index 90891200..4ba54bea 100644 --- a/piprotocol.cpp +++ b/piprotocol.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Protocol, input/output channel (COM, UDP) - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -187,7 +187,7 @@ void PIProtocol::init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PI if (sendDataSize_ == 0) piCoutObj << "Warning: null send data size!";*/ } else { - piCoutObj << "Can`t find \"" << name_ << ".sender.port\" or \"" << name_ << ".port\" in \"" << config << "\"!"; + piCoutObj << "Can`t find \"" << name() << ".sender.port\" or \"" << name() << ".port\" in \"" << config << "\"!"; devSenderState = "Config error"; return; } @@ -233,7 +233,7 @@ void PIProtocol::init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PI pp.setFlag(PISerial::TwoStopBits, flag); } } else { - piCoutObj << "Can`t find \"" << name_ << ".sender.speed\" or \"" << name_ << ".speed\" in \"" << config << "\"!"; + piCoutObj << "Can`t find \"" << name() << ".sender.speed\" or \"" << name() << ".speed\" in \"" << config << "\"!"; devSenderState = "Config error"; return; } @@ -346,7 +346,7 @@ void PIProtocol::init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const if (recDataSize == 0) piCoutObj << "Warning: null receive data size!";*/ } else { - piCoutObj << "Can`t find \"" << name_ << ".receiver.port\" or \"" << name_ << ".port\" in \"" << config << "\"!"; + piCoutObj << "Can`t find \"" << name() << ".receiver.port\" or \"" << name() << ".port\" in \"" << config << "\"!"; devReceiverState = "Config error"; return; } @@ -416,7 +416,7 @@ void PIProtocol::init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const if (recDataSize == 0) piCoutObj << "Warning: null receive data size!";*/ } else { - piCoutObj << "Can`t find \"" << name_ << ".receiver.speed\" or \"" << name_ << ".speed\" in \"" << config << "\"!"; + piCoutObj << "Can`t find \"" << name() << ".receiver.speed\" or \"" << name() << ".speed\" in \"" << config << "\"!"; devReceiverState = "Config error"; return; } diff --git a/piprotocol.h b/piprotocol.h index 7f03ef15..09064ea5 100644 --- a/piprotocol.h +++ b/piprotocol.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Protocol, input/output channel (COM, UDP) - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piqueue.h b/piqueue.h index ca387b01..23f808ea 100644 --- a/piqueue.h +++ b/piqueue.h @@ -6,7 +6,7 @@ /* PIP - Platform Independent Primitives Queue container - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piserial.cpp b/piserial.cpp index e7ab306f..825dc936 100644 --- a/piserial.cpp +++ b/piserial.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives COM - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,39 +32,19 @@ * */ +REGISTER_DEVICE(PISerial); + PISerial::PISerial(): PIIODevice("", ReadWrite) { - piMonitor.serials++; - setPriority(piHigh); - fd = -1; - block_read = true; - params = 0; - ispeed = ospeed = S115200; - vtime = 1; -#ifdef WINDOWS - block_write = true; - hCom = 0; -#endif - dbits = 8; - init(); + _init(); } PISerial::PISerial(const PIString & device_, PISerial::Speed speed_, PIFlags params_): PIIODevice(device_, ReadWrite) { - piMonitor.serials++; - setPriority(piHigh); - path_ = device_; - fd = -1; - block_read = true; - params = params_; - ispeed = ospeed = speed_; - vtime = 1; -#ifdef WINDOWS - block_write = true; - hCom = 0; -#endif - dbits = 8; - init(); + _init(); + setPath(device_); + setSpeed(speed_); + setParameters(params_); } @@ -73,6 +53,36 @@ PISerial::~PISerial() { } +void PISerial::_init() { + fd = -1; + piMonitor.serials++; + setPriority(piHigh); + block_read = true; + vtime = 1; +#ifdef WINDOWS + block_write = true; + hCom = 0; +#endif + setParameters(0); + setSpeed(S115200); + setDataBitsCount(8); + //init(); +} + + +void PISerial::setParameter(PISerial::Parameters parameter, bool on) { + PIFlags cp = (PIFlags)(property("parameters").toInt()); + cp.setFlag(parameter, on); + setParameters(cp); +} + + +bool PISerial::isParameterSet(PISerial::Parameters parameter) const { + PIFlags cp = (PIFlags)(property("parameters").toInt()); + return cp[parameter]; +} + + bool PISerial::setPin(int number, bool on) { switch (number) { case 1: return setCAR(on); break; @@ -116,7 +126,7 @@ bool PISerial::isPin(int number) const { bool PISerial::setBit(int bit, bool on, const PIString & bname) { #ifndef WINDOWS if (fd < 0) { - piCoutObj << "setBit" << bname << " error: \"" << path_ << "\" is not opened!"; + piCoutObj << "setBit" << bname << " error: \"" << path() << "\" is not opened!"; return false; } if (ioctl(fd, on ? TIOCMBIS : TIOCMBIC, &bit) < 0) { @@ -134,7 +144,7 @@ bool PISerial::setBit(int bit, bool on, const PIString & bname) { bool PISerial::isBit(int bit, const PIString & bname) const { #ifndef WINDOWS if (fd < 0) { - piCoutObj << "isBit" << bname << " error: \"" << path_ << "\" is not opened!"; + piCoutObj << "isBit" << bname << " error: \"" << path() << "\" is not opened!"; return false; } int ret = 0; @@ -334,29 +344,31 @@ PIByteArray PISerial::readData(int size, double timeout_ms) { bool PISerial::openDevice() { + piCout << "ser open" << path(); + if (path().isEmpty()) return false; #ifdef WINDOWS DWORD ds = 0, sm = 0; if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;} if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;} - PIString wp = "//./" + path_; + PIString wp = "//./" + path(); hCom = CreateFileA(wp.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); if (hCom == INVALID_HANDLE_VALUE) { - piCoutObj << "Unable to open \"" << path_ << "\""; + piCoutObj << "Unable to open \"" << path() << "\""; fd = -1; return false; } fd = 0; #else int om = 0; - switch (mode_) { + switch (mode()) { case PIIODevice::ReadOnly: om = O_RDONLY; break; case PIIODevice::WriteOnly: om = O_WRONLY; break; case PIIODevice::ReadWrite: om = O_RDWR; break; } //cout << "init ser " << path_ << " mode " << om << " param " << params << endl; - fd = ::open(path_.data(), O_NOCTTY | om); + fd = ::open(path().data(), O_NOCTTY | om); if (fd == -1) { - piCoutObj << "Unable to open \"" << path_ << "\""; + piCoutObj << "Unable to open \"" << path() << "\""; return false; } tcgetattr(fd, &desc); @@ -378,24 +390,25 @@ void PISerial::applySettings() { times.WriteTotalTimeoutConstant = 0; times.WriteTotalTimeoutMultiplier = block_write ? 0 : 1; if (SetCommTimeouts(hCom, ×) == -1) - piCoutObj << "Unable to set timeouts for \"" << path_ << "\""; + piCoutObj << "Unable to set timeouts for \"" << path() << "\""; GetCommMask(hCom, &mask); SetCommMask(hCom, EV_RXCHAR); GetCommState(hCom, &sdesc); desc = sdesc; desc.DCBlength = sizeof(desc); - desc.BaudRate = convertSpeed(ispeed); - if (dbits >= 5 && dbits <= 8) - desc.ByteSize = dbits; + desc.BaudRate = convertSpeed(outSpeed()); + if (dataBitsCount() >= 5 && dataBitsCount() <= 8) + desc.ByteSize = dataBitsCount(); else desc.ByteSize = 8; + PIFlags params = parameters(); if (params[PISerial::ParityControl]) { desc.fParity = 1; desc.Parity = params[PISerial::ParityOdd] ? 1 : 2; } desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT; if (SetCommState(hCom, &desc) == -1) { - piCoutObj << "Unable to set comm state for \"" << path_ << "\""; + piCoutObj << "Unable to set comm state for \"" << path() << "\""; return; } #else @@ -404,13 +417,14 @@ void PISerial::applySettings() { desc.c_oflag = desc.c_lflag = desc.c_cflag = 0; desc.c_iflag = IGNBRK; desc.c_cflag = CLOCAL | HUPCL; - switch (dbits) { + switch (dataBitsCount()) { case 5: desc.c_cflag |= (CSIZE & CS5); break; case 6: desc.c_cflag |= (CSIZE & CS6); break; case 7: desc.c_cflag |= (CSIZE & CS7); break; case 8: default: desc.c_cflag |= (CSIZE & CS8); break; }; if (isReadable()) desc.c_cflag |= CREAD; + PIFlags params = parameters(); if (params[PISerial::TwoStopBits]) desc.c_cflag |= CSTOPB; if (params[PISerial::ParityControl]) { desc.c_iflag |= INPCK; @@ -420,14 +434,14 @@ void PISerial::applySettings() { desc.c_cc[VMIN] = 1; desc.c_cc[VTIME] = vtime; - cfsetispeed(&desc, convertSpeed(ispeed)); - cfsetospeed(&desc, convertSpeed(ospeed)); + cfsetispeed(&desc, convertSpeed(inSpeed())); + cfsetospeed(&desc, convertSpeed(outSpeed())); tcflush(fd, TCIOFLUSH); fcntl(fd, F_SETFL, block_read ? 0 : O_NONBLOCK); if(tcsetattr(fd, TCSANOW, &desc) < 0) { - piCoutObj << "Can`t set attributes for \"" << path_ << "\""; + piCoutObj << "Can`t set attributes for \"" << path() << "\""; return; } #endif @@ -496,7 +510,7 @@ bool PISerial::configureDevice(const void * e_main, const void * e_parent) { PIConfig::Entry * em = (PIConfig::Entry * )e_main; PIConfig::Entry * ep = (PIConfig::Entry * )e_parent; setDevice(readDeviceSetting("device", device(), em, ep)); - setSpeed((PISerial::Speed)(readDeviceSetting("speed", (int)ospeed, em, ep))); + setSpeed((PISerial::Speed)(readDeviceSetting("speed", (int)outSpeed(), em, ep))); setDataBitsCount(readDeviceSetting("dataBitsCount", dataBitsCount(), em, ep)); setParameter(PISerial::ParityControl, readDeviceSetting("parityControl", isParameterSet(PISerial::ParityControl), em, ep)); setParameter(PISerial::ParityOdd, readDeviceSetting("parityOdd", isParameterSet(PISerial::ParityOdd), em, ep)); @@ -505,6 +519,25 @@ bool PISerial::configureDevice(const void * e_main, const void * e_parent) { } +void PISerial::configureFromFullPath(const PIString & full_path) { + PIStringList pl = full_path.split(":"); + for (int i = 0; i < pl.size_s(); ++i) { + PIString p(pl[i]); + switch (i) { + case 0: setPath(p); break; + case 1: setSpeed((Speed)(p.toInt())); break; + case 2: setDataBitsCount(p.toInt()); break; + case 3: + p = p.toLowerCase(); + if (p != "n") setParameter(ParityControl); + if (p == "o") setParameter(ParityOdd); + break; + case 4: if (p.toInt() == 2) setParameter(TwoStopBits); break; + } + } +} + + PIVector PISerial::availableSpeeds() { PIVector spds; spds << 50 << 75 << 110 << 300 << 600 << 1200 << 2400 << 4800 << @@ -518,11 +551,11 @@ PIStringList PISerial::availableDevices(bool test) { PIStringList dl; #ifdef WINDOWS HKEY key = 0; - RegOpenKey(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", &key); + RegOpenKey(HKEY_LOCAL_MACHINE, (LPCTSTR)"HARDWARE\\DEVICEMAP\\SERIALCOMM", &key); if (key != 0) { char name[256], data[1024]; DWORD name_len = 256, data_len = 1024, type = 0, index = 0; - while (RegEnumValue(key, index, name, &name_len, NULL, &type, (uchar * )data, &data_len) == ERROR_SUCCESS) { + while (RegEnumValue(key, index, (LPTSTR)name, &name_len, NULL, &type, (uchar * )data, &data_len) == ERROR_SUCCESS) { dl << PIString(data); index++; } diff --git a/piserial.h b/piserial.h index 4bca94a1..d2738b52 100644 --- a/piserial.h +++ b/piserial.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives COM - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -91,7 +91,9 @@ #endif -class PIP_EXPORT PISerial: public PIIODevice { +class PIP_EXPORT PISerial: public PIIODevice +{ + PIIODEVICE(PISerial) public: //! Contructs an empty %PISerial @@ -134,36 +136,36 @@ public: //! Set both input and output speed to "speed" - void setSpeed(PISerial::Speed speed) {ospeed = ispeed = speed; applySettings();} + void setSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); setProperty("inSpeed", (int)speed); applySettings();} //! Set output speed to "speed" - void setOutSpeed(PISerial::Speed speed) {ospeed = speed; applySettings();} + void setOutSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); applySettings();} //! Set input speed to "speed" - void setInSpeed(PISerial::Speed speed) {ispeed = speed; applySettings();} + void setInSpeed(PISerial::Speed speed) {setProperty("inSpeed", (int)speed); applySettings();} //! Set device name to "dev" - void setDevice(const PIString & dev) {path_ = dev; if (isOpened()) {close(); open();};} + void setDevice(const PIString & dev) {setPath(dev); if (isOpened()) {close(); open();};} //! Set parameters to "parameters_" - void setParameters(PIFlags parameters_) {params = parameters_; applySettings();} + void setParameters(PIFlags parameters_) {setProperty("parameters", (int)parameters_); applySettings();} //! Set parameter "parameter" to "on" state - void setParameter(PISerial::Parameters parameter, bool on = true) {params.setFlag(parameter, on); applySettings();} + void setParameter(PISerial::Parameters parameter, bool on = true); //! Returns if parameter "parameter" is set - bool isParameterSet(PISerial::Parameters parameter) const {return params[parameter];} + bool isParameterSet(PISerial::Parameters parameter) const; //! Returns parameters - PIFlags parameters() const {return params;} + PIFlags parameters() const {return (PIFlags)(property("parameters").toInt());} //! Set data bits count. Valid range is from 5 to 8, befault is 8 - void setDataBitsCount(int bits) {dbits = bits; applySettings();} + void setDataBitsCount(int bits) {setProperty("dataBitsCount", bits); applySettings();} //! Returns data bits count - int dataBitsCount() const {return dbits;} + int dataBitsCount() const {return property("dataBitsCount").toInt();} //! Set pin number "number" to logic level "on". Valid numbers are 4 (DTR) and 7 (RTS) @@ -200,13 +202,13 @@ public: //! Returns device name - const PIString & device() const {return path_;} + PIString device() const {return path();} //! Returns output speed - PISerial::Speed outSpeed() const {return ospeed;} + PISerial::Speed outSpeed() const {return (PISerial::Speed)(property("outSpeed").toInt());} //! Returns input speed - PISerial::Speed inSpeed() const {return ispeed;} + PISerial::Speed inSpeed() const {return (PISerial::Speed)(property("inSpeed").toInt());} int VTime() const {return vtime;} @@ -271,17 +273,19 @@ public: //! \} protected: + PIString fullPathPrefix() const {return "ser";} + void configureFromFullPath(const PIString & full_path); bool configureDevice(const void * e_main, const void * e_parent = 0); int write(const void * data, int max_size) {return write(data, max_size, true);} //! Executes when any read function was successful. Default implementation does nothing virtual void received(const void * data, int size) {;} + void _init(); void applySettings(); int convertSpeed(PISerial::Speed speed); bool setBit(int bit, bool on, const PIString & bname); bool isBit(int bit, const PIString & bname) const; - static bool headerValidate(void * d, uchar * src, uchar * rec, int size) {for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} bool openDevice(); bool closeDevice(); @@ -295,11 +299,9 @@ protected: termios desc, sdesc; uint readed; #endif - int fd, vtime, dbits; + int fd, vtime; bool block_read; - PISerial::Speed ospeed, ispeed; PITimer timer; - PIFlags params; }; diff --git a/pisignals.cpp b/pisignals.cpp index 1336baab..b67ec964 100644 --- a/pisignals.cpp +++ b/pisignals.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Signals - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pisignals.h b/pisignals.h index 881d7e04..859cf35d 100644 --- a/pisignals.h +++ b/pisignals.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Signals - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pistack.h b/pistack.h index 3857aa26..113de2ca 100644 --- a/pistack.h +++ b/pistack.h @@ -6,7 +6,7 @@ /* PIP - Platform Independent Primitives Stack container - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pistatemachine.h b/pistatemachine.h index dd23ae37..8f54de3c 100644 --- a/pistatemachine.h +++ b/pistatemachine.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives State machine - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pistring.cpp b/pistring.cpp index 5e837af3..491345aa 100644 --- a/pistring.cpp +++ b/pistring.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives String - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -356,6 +356,44 @@ int PIString::findLast(const PIString str, const int start) const { } +int PIString::findWord(const PIString & word, const int start) const { + int f = start - 1, tl = length(), wl = word.length(); + while ((f = find(word, f + 1)) >= 0) { + bool ok = true; + PIChar c; + if (f > 0) {c = (*this)[f - 1]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {ok = false; continue;}} + if (f + wl < tl) {c = (*this)[f + wl]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {ok = false; continue;}} + if (ok) return f; + } + return -1; +} + + +int PIString::findCWord(const PIString & word, const int start) const { + int f = start - 1, tl = length(), wl = word.length(); + while ((f = find(word, f + 1)) >= 0) { + bool ok = true; + PIChar c; + if (f > 0) {c = (*this)[f - 1]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {ok = false; continue;}} + if (f + wl < tl) {c = (*this)[f + wl]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {ok = false; continue;}} + if (ok) return f; + } + return -1; +} + + +bool PIString::startsWith(const PIString & str) const { + if (size() < str.size()) return false; + return str == left(str.size()); +} + + +bool PIString::endsWith(const PIString & str) const { + if (size() < str.size()) return false; + return str == right(str.size()); +} + + PIString PIString::takeSymbol() { PIString ret; int sz = size_s(), ss = -1; diff --git a/pistring.h b/pistring.h index 430f1153..fd1a1f95 100644 --- a/pistring.h +++ b/pistring.h @@ -6,7 +6,7 @@ /* PIP - Platform Independent Primitives String - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,7 +35,7 @@ class PIP_EXPORT PIString: public PIVector { public: //! Contructs an empty string - PIString(): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--;} + PIString(): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--;} //inline PIString & operator +=(const char c) {push_back(c); return *this;} PIString & operator +=(const PIChar & c) {push_back(c); return *this;} @@ -49,63 +49,63 @@ public: #endif //PIString(const char c) {*this += c;} + PIString(const PIString & o): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += o;} + //! Contructs string with single symbol "c" - PIString(const PIChar & c): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += c;} - PIString(const char c): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += PIChar(c);} + PIString(const PIChar & c): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += c;} + PIString(const char c): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += PIChar(c);} /*! \brief Contructs string from c-string "str" * \details "str" should be null-terminated\n * Example: \snippet pistring.cpp PIString(char * ) */ - PIString(const char * str): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;} + PIString(const char * str): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} /*! \brief Contructs string from \c wchar_t c-string "str" * \details "str" should be null-terminated\n * Example: \snippet pistring.cpp PIString(wchar_t * ) */ - PIString(const wchar_t * str): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;} + PIString(const wchar_t * str): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} //! Contructs string from std::string "str" - PIString(const string & str): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;} + PIString(const string & str): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} #ifdef HAS_LOCALE - PIString(const wstring & str): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;} + PIString(const wstring & str): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} #endif //! Contructs string from byte array "ba" - PIString(const PIByteArray & ba): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += ba;} + PIString(const PIByteArray & ba): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += ba;} /*! \brief Contructs string from "len" characters of buffer "str" * \details Example: \snippet pistring.cpp PIString(char * , int) */ - PIString(const char * str, const int len): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += string(str, len);} + PIString(const char * str, const int len): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += string(str, len);} /*! \brief Contructs string as sequence of characters "c" of buffer with length "len" * \details Example: \snippet pistring.cpp PIString(int, char) */ - PIString(const int len, const char c): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} + PIString(const int len, const char c): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} /*! \brief Contructs string as sequence of symbols "c" of buffer with length "len" * \details Example: \snippet pistring.cpp PIString(int, PIChar) */ - PIString(const int len, const PIChar & c): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} + PIString(const int len, const PIChar & c): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} - PIString(const short & value): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const ushort & value): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const int & value): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const uint & value): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const long & value): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const ulong & value): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const llong & value): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const ullong & value): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const float & value): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const double & value): PIVector() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const short & value): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const ushort & value): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const int & value): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const uint & value): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const long & value): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const ulong & value): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const llong & value): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const ullong & value): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const float & value): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const double & value): PIVector() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - /* - //! Contructs string from other string "str" - PIString(const PIString & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; uint len = str.size(); for (uint i = 0; i < len; ++i) push_back(str[i]);} -*/ - ~PIString() {piMonitor.strings--; piMonitor.containers++;} + //~PIString() {piMonitor.strings--; piMonitor.containers++;} + PIString & operator =(const PIString & o) {clear(); *this += o; return *this;} + /*! \brief Return c-string representation of string * \details Converts content of string to c-string and return * pointer to first char. This buffer is valid until new convertion @@ -369,6 +369,21 @@ public: PIString reversed() const {PIString str(*this); str.reverse(); return str;} + /*! \brief Take a part of string from symbol at index "start" and maximum length "len" and return it + * \details Example: \snippet pistring.cpp PIString::takeMid + * \sa \a takeLeft, \a takeRight() */ + PIString takeMid(const int start, const int len = -1) {PIString ret(mid(start, len)); cutMid(start, len); return ret;} + + /*! \brief Take a part from the begin of string with maximum length "len" and return it + * \details Example: \snippet pistring.cpp PIString::takeLeft + * \sa \a takeMid(), \a takeRight() */ + PIString takeLeft(const int len) {PIString ret(left(len)); cutLeft(len); return ret;} + + /*! \brief Take a part from the end of string with maximum length "len" and return it + * \details Example: \snippet pistring.cpp PIString::takeRight + * \sa \a takeMid(), \a takeLeft() */ + PIString takeRight(const int len) {PIString ret(right(len)); cutRight(len); return ret;} + /*! \brief Take a symbol from the begin of this string and return it * \details Example: \snippet pistring.cpp PIString::takeSymbol * \sa \a takeWord(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */ @@ -422,7 +437,7 @@ public: const char * data() const; //! \brief Return \c std::string representation of this string - const string stdString() const {return convertToStd();} + std::string stdString() const {return convertToStd();} #ifdef HAS_LOCALE wstring stdWString() const {return convertToWString();} #endif @@ -478,7 +493,20 @@ public: //! \brief Search substring "str" from symbol at index "start" and return last occur position //! \details Example: \snippet pistring.cpp PIString::findLast int findLast(const string str, const int start = 0) const {return findLast(PIString(str), start);} - + + //! \brief Search word "word" from symbol at index "start" and return last occur position. + //! \details Example: \snippet pistring.cpp PIString::findWord + int findWord(const PIString & word, const int start = 0) const; + + //! \brief Search C-style word "word" from symbol at index "start" and return last occur position. + //! \details Example: \snippet pistring.cpp PIString::findCWord + int findCWord(const PIString & word, const int start = 0) const; + + //! \brief Return if string starts with "str" + bool startsWith(const PIString & str) const; + + //! \brief Return if string ends with "str" + bool endsWith(const PIString & str) const; //! \brief Return symbols length of string int length() const {return size();} @@ -640,6 +668,9 @@ public: //! \details Example: \snippet pistring.cpp PIString::readableSize static PIString readableSize(llong bytes) {PIString s; s.setReadableSize(bytes); return s;} + PIString & removeAll(char v) {replaceAll(v, ""); return *this;} + PIString & removeAll(const PIString & v) {replaceAll(v, ""); return *this;} + private: static const char toBaseN[]; static const int fromBaseN[]; @@ -699,8 +730,8 @@ private: if (cs < 0 || cs >= base) break; digits << cs; } - piForeachRC (int & i, digits) { - ret += i * m; + for (int i = digits.size_s() - 1; i >= 0; --i) { + ret += digits[i] * m; m *= base; } if (neg) ret = -ret; @@ -788,6 +819,8 @@ public: //! Contructs empty strings list with strings "s0", "s1", "s2" and "s3" PIStringList(const PIString & s0, const PIString & s1, const PIString & s2, const PIString & s3) {push_back(s0); push_back(s1); push_back(s2); push_back(s3);} + + PIStringList(const PIStringList & o): PIVector() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];} //! \brief Join all strings in one with delimiter "delim" and return it @@ -812,6 +845,8 @@ public: //! Return sum of lengths of all strings uint contentSize() {uint s = 0; for (uint i = 0; i < size(); ++i) s += at(i).size(); return s;} + PIStringList & operator =(const PIStringList & o) {clear(); for (uint i = 0; i < o.size(); ++i) *this << o[i]; return *this;} + PIStringList & operator <<(const PIString & str) {push_back(str); return *this;} PIStringList & operator <<(const PIStringList & sl) {piForeachC (PIString & i, sl) push_back(i); return *this;} //inline PIStringList & operator <<(const char c) {push_back(PIString(c)); return *this;} diff --git a/pisystemmonitor.cpp b/pisystemmonitor.cpp index 8b95d689..0f4d97dc 100644 --- a/pisystemmonitor.cpp +++ b/pisystemmonitor.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Process resource monitor - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pisystemmonitor.h b/pisystemmonitor.h index 51ed5068..d74cd200 100644 --- a/pisystemmonitor.h +++ b/pisystemmonitor.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Process resource monitor - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pisystemtests.cpp b/pisystemtests.cpp index a70ec08f..dcc1a8c6 100644 --- a/pisystemtests.cpp +++ b/pisystemtests.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives System tests results (see system_test folder) - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pisystemtests.h b/pisystemtests.h index eea34196..ddf602d9 100644 --- a/pisystemtests.h +++ b/pisystemtests.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives System tests results (see system_test folder) - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pithread.cpp b/pithread.cpp index 92d597cf..38774cf2 100644 --- a/pithread.cpp +++ b/pithread.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Thread - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pithread.h b/pithread.h index b3e565d1..a05cacd7 100644 --- a/pithread.h +++ b/pithread.h @@ -6,7 +6,7 @@ /* PIP - Platform Independent Primitives Thread - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pitime.cpp b/pitime.cpp index 8a0a4e97..93a46ae6 100644 --- a/pitime.cpp +++ b/pitime.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Timer - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pitime.h b/pitime.h index 7ed2da7b..d8a00680 100644 --- a/pitime.h +++ b/pitime.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Time structs - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pitimer.cpp b/pitimer.cpp index 5518b6b9..e7afed4a 100644 --- a/pitimer.cpp +++ b/pitimer.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Timer - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pitimer.h b/pitimer.h index 8e6979eb..a7130a22 100644 --- a/pitimer.h +++ b/pitimer.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives Timer - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piusb.cpp b/piusb.cpp index 6fe9b780..393e27b1 100644 --- a/piusb.cpp +++ b/piusb.cpp @@ -9,16 +9,19 @@ # endif #endif +REGISTER_DEVICE(PIUSB); -PIUSB::PIUSB(ushort vid, ushort pid): PIIODevice("", ReadWrite, false) { + +PIUSB::PIUSB(ushort vid, ushort pid): PIIODevice("", ReadWrite) { vid_ = vid; pid_ = pid; - path_ = PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0"); - dev_num = 1; intefrace_ = 0; hdev = 0; interface_claimed = -1; - timeout_r = timeout_w = 1000; + setPath(PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0")); + setDeviceNumber(1); + setTimeoutRead(1000); + setTimeoutWrite(1000); } @@ -145,9 +148,9 @@ bool PIUSB::configureDevice(const void * e_main, const void * e_parent) { bool PIUSB::openDevice() { #ifdef PIP_USB - if (path_.size_s() >= 8) { - vid_ = path_.left(4).toInt(16); - pid_ = path_.right(4).toInt(16); + if (path().size_s() >= 8) { + vid_ = path().left(4).toInt(16); + pid_ = path().right(4).toInt(16); } if (hdev != 0) closeDevice(); hdev = 0; @@ -172,7 +175,7 @@ bool PIUSB::openDevice() { for (bus = usb_get_busses(); bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { if (dev->descriptor.idVendor == vid_ && dev->descriptor.idProduct == pid_) { - if (cur_num == dev_num) { + if (cur_num == deviceNumber()) { struct usb_device_descriptor & dd(dev->descriptor); desc_.usb_spec_number = dd.bcdUSB; desc_.device_class = dd.bDeviceClass; @@ -383,3 +386,18 @@ PICout operator<<(PICout s, const PIUSB::Endpoint & v) { s.restoreControl(); return s; } + + +void PIUSB::configureFromFullPath(const PIString & full_path) { + PIStringList pl = full_path.split(":"); + for (int i = 0; i < pl.size_s(); ++i) { + PIString p(pl[i]); + switch (i) { + case 0: setVendorID(p.toUShort(16)); break; + case 1: setProductID(p.toUShort(16)); break; + case 2: setDeviceNumber(p.toInt()); break; + case 3: setEndpointRead(Endpoint(p.toInt())); break; + case 4: setEndpointWrite(Endpoint(p.toInt())); break; + } + } +} diff --git a/piusb.h b/piusb.h index d5fed372..0e68924f 100644 --- a/piusb.h +++ b/piusb.h @@ -4,7 +4,7 @@ /* PIP - Platform Independent Primitives USB, based on libusb - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,7 +27,9 @@ struct usb_dev_handle; -class PIP_EXPORT PIUSB: public PIIODevice { +class PIP_EXPORT PIUSB: public PIIODevice +{ + PIIODEVICE(PIUSB) public: PIUSB(ushort vid = 0, ushort pid = 0); @@ -58,7 +60,7 @@ public: ushort class_code; ushort subclass_code; ushort protocol_code; - PIVector endpoints; + PIVector endpoints; }; struct Configuration { @@ -69,7 +71,7 @@ public: ushort max_power; // mA bool self_powered; bool remote_wakeup; - PIVector interfaces; + PIVector interfaces; }; struct Descriptor { @@ -85,37 +87,38 @@ public: uchar index_manufacturer; uchar index_product; uchar index_serial; - PIVector configurations; + PIVector configurations; }; - const Descriptor & currentDescriptor() const {return desc_;} - const Configuration & currentConfiguration() const {return conf_;} - const Interface & currentInterface() const {return iface_;} + const PIUSB::Descriptor & currentDescriptor() const {return desc_;} + const PIUSB::Configuration & currentConfiguration() const {return conf_;} + const PIUSB::Interface & currentInterface() const {return iface_;} ushort vendorID() const {return vid_;} ushort productID() const {return pid_;} - int deviceNumber() const {return dev_num;} + int deviceNumber() const {return property("deviceNumber").toInt();} + int timeoutRead() const {return property("timeoutRead").toInt();} + int timeoutWrite() const {return property("timeoutWrite").toInt();} + const PIUSB::Endpoint & endpointRead() {return ep_read;} + const PIUSB::Endpoint & endpointWrite() {return ep_write;} - const PIVector & endpoints() const {return eps;} - PIVector endpointsRead(); - PIVector endpointsWrite(); - Endpoint getEndpointByAddress(uchar address); + const PIVector & endpoints() const {return eps;} + PIVector endpointsRead(); + PIVector endpointsWrite(); + PIUSB::Endpoint getEndpointByAddress(uchar address); - const Endpoint & endpointRead() {return ep_read;} - const Endpoint & endpointWrite() {return ep_write;} - - void setVendorID(ushort vid) {vid_ = vid; path_ = PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0");} - void setProductID(ushort pid) {pid_ = pid; path_ = PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0");} + void setVendorID(ushort vid) {vid_ = vid; setPath(PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0"));} + void setProductID(ushort pid) {pid_ = pid; setPath(PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0"));} bool setConfiguration(uchar value); bool setInterface(uchar value); - void setEndpointRead(const Endpoint & ep) {ep_read = ep;} - void setEndpointWrite(const Endpoint & ep) {ep_write = ep;} - void setDeviceNumber(int dn) {dev_num = dn;} - void setTimeoutRead(int t) {timeout_r = t;} - void setTimeoutWrite(int t) {timeout_w = t;} + void setEndpointRead(const PIUSB::Endpoint & ep) {ep_read = ep;} + void setEndpointWrite(const PIUSB::Endpoint & ep) {ep_write = ep;} + void setDeviceNumber(int dn) {setProperty("deviceNumber", dn);} + void setTimeoutRead(int t) {setProperty("timeoutRead", t);} + void setTimeoutWrite(int t) {setProperty("timeoutWrite", t);} int read(void * read_to, int max_size); int write(const void * data, int max_size); @@ -124,16 +127,18 @@ public: void flush(); protected: + PIString fullPathPrefix() const {return "usb";} + void configureFromFullPath(const PIString & full_path); bool configureDevice(const void * e_main, const void * e_parent = 0); //bool init(); bool openDevice(); bool closeDevice(); - PIVector eps; + PIVector eps; ushort vid_, pid_; - int dev_num, intefrace_, timeout_r, timeout_w; + int intefrace_, timeout_r, timeout_w; int interface_claimed; - Endpoint ep_read, ep_write; + PIUSB::Endpoint ep_read, ep_write; Descriptor desc_; Configuration conf_; Interface iface_; diff --git a/pivariant.cpp b/pivariant.cpp index eaf24e81..f1761236 100644 --- a/pivariant.cpp +++ b/pivariant.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Variant type - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,9 +33,10 @@ void PIVariant::operator =(const PIVariant & v) { _vbitarray = v._vbitarray; _vstring = v._vstring; _vstringlist = v._vstringlist; + _vcustom = v._vcustom; } -/* + bool PIVariant::operator ==(const PIVariant & v) const { if (type_ != v.type_) return false; switch (type_) { @@ -67,7 +68,7 @@ bool PIVariant::operator ==(const PIVariant & v) const { }; return false; } -*/ + PIVariant::Type PIVariant::typeFromName(const PIString & tname) { PIString s = tname.trimmed().toLowerCase().replaceAll(" ", ""); @@ -126,6 +127,7 @@ PIString PIVariant::typeName(PIVariant::Type type) { case PIVariant::Date: return "Date"; case PIVariant::DateTime: return "DateTime"; case PIVariant::SystemTime: return "SystemTime"; + case PIVariant::Custom: return "Custom"; default: break; } return "Invalid"; diff --git a/pivariant.h b/pivariant.h index 4eecd0d3..cf234639 100644 --- a/pivariant.h +++ b/pivariant.h @@ -47,6 +47,7 @@ #define _vvsystime(v) (*((PISystemTime*)v._vraw)) class PIP_EXPORT PIVariant { + friend PICout operator <<(PICout s, const PIVariant & v); public: enum Type { Invalid = 0, @@ -73,8 +74,8 @@ public: Time, Date, DateTime, - SystemTime/*, - Custom = 0xFF*/ + SystemTime, + Custom = 0xFF }; PIVariant(); @@ -147,6 +148,35 @@ public: PIBitArray toBitArray() const; PIByteArray toByteArray() const; + template + T toValue() const {if (_vcustom.size() != sizeof(T)) return T(); return *((T*)_vcustom.data());} + /* + operator bool() const {return toBool();} + operator char() const {return toInt();} + operator uchar() const {return toInt();} + operator short() const {return toInt();} + operator ushort() const {return toInt();} + operator int() const {return toInt();} + operator uint() const {return toInt();} + operator long() const {return toInt();} + operator ulong() const {return toInt();} + operator llong() const {return toLLong();} + operator ullong() const {return (ullong)toLLong();} + operator float() const {return toFloat();} + operator double() const {return toDouble();} + operator ldouble() const {return toLDouble();} + operator complexd() const {return toComplexd();} + operator complexld() const {return toComplexld();} + operator PITime() const {return toTime();} + operator PIDate() const {return toDate();} + operator PIDateTime() const {return toDateTime();} + operator PIString() const {return toString();} + operator PIStringList() const {return toStringList();} + operator PIBitArray() const {return toBitArray();} + operator PIByteArray() const {return toByteArray();} + operator const char*() const {return toString().data();} + operator void*() const {return (void*)(toLLong());} + */ void operator =(const PIVariant & v); void operator =(const char * v) {setValue(PIString(v));} void operator =(const bool v) {setValue(v);} @@ -177,15 +207,21 @@ public: bool operator ==(const PIVariant & v) const; bool operator !=(const PIVariant & v) const {return !(*this == v);} + PIVariant::Type type() const {return type_;} PIString typeName() const {return typeName(type_);} bool isValid() const {return type_ != PIVariant::Invalid;} + template + static PIVariant fromValue(const T & v) {PIVariant ret; ret._vcustom.resize(sizeof(T)); new((T*)(ret._vcustom.data()))T(v); ret.type_ = PIVariant::Custom; return ret;} + static PIVariant::Type typeFromName(const PIString & tname); static PIString typeName(PIVariant::Type type); private: + void destroy() {_vcustom.clear();} + union { int _vint; llong _vllong; @@ -204,12 +240,71 @@ private: PIByteArray _vbytearray; PIString _vstring; PIStringList _vstringlist; + PIByteArray _vcustom; PIVariant::Type type_; }; +template<> inline bool PIVariant::toValue() const {return toBool();} +template<> inline char PIVariant::toValue() const {return (char)toInt();} +template<> inline uchar PIVariant::toValue() const {return (uchar)toInt();} +template<> inline short PIVariant::toValue() const {return (short)toInt();} +template<> inline ushort PIVariant::toValue() const {return (ushort)toInt();} +template<> inline int PIVariant::toValue() const {return toInt();} +template<> inline uint PIVariant::toValue() const {return (uint)toInt();} +template<> inline long PIVariant::toValue() const {return (long)toInt();} +template<> inline ulong PIVariant::toValue() const {return (ulong)toInt();} +template<> inline llong PIVariant::toValue() const {return toLLong();} +template<> inline ullong PIVariant::toValue() const {return (ullong)toLLong();} +template<> inline float PIVariant::toValue() const {return toFloat();} +template<> inline double PIVariant::toValue() const {return toDouble();} +template<> inline ldouble PIVariant::toValue() const {return toLDouble();} +template<> inline complexd PIVariant::toValue() const {return toComplexd();} +template<> inline complexld PIVariant::toValue() const {return toComplexld();} +template<> inline void* PIVariant::toValue() const {return (void*)toLLong();} +template<> inline const char* PIVariant::toValue() const {return toString().data();} +template<> inline PITime PIVariant::toValue() const {return toTime();} +template<> inline PIDate PIVariant::toValue() const {return toDate();} +template<> inline PIDateTime PIVariant::toValue() const {return toDateTime();} +template<> inline PIString PIVariant::toValue() const {return toString();} +template<> inline PIStringList PIVariant::toValue() const {return toStringList();} +template<> inline PIBitArray PIVariant::toValue() const {return toBitArray();} +template<> inline PIByteArray PIVariant::toValue() const {return toByteArray();} -inline PICout operator <<(PICout s, const PIVariant & v) {s.space(); s.setControl(0, true); s << "PIVariant(" << PIVariant::typeName(v.type()) << ", " << v.toString() << ")"; s.restoreControl(); return s;} +//template<> inline PIVariant PIVariant::fromValue(const char * v) {return PIVariant(PIString(v));} +template<> inline PIVariant PIVariant::fromValue(const bool & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const char & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const uchar & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const short & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const ushort & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const int & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const uint & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const long & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const ulong & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const llong & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const ullong & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const float & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const double & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const ldouble & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const complexd & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const complexld & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIBitArray & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIByteArray & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIString & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIStringList & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PITime & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIDate & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIDateTime & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PISystemTime & v) {return PIVariant(v);} + +inline PICout operator <<(PICout s, const PIVariant & v) { + s.space(); s.setControl(0, true); + s << "PIVariant(" << PIVariant::typeName(v.type()) << ", "; + if (v.type() == PIVariant::Custom) s << v._vcustom.size() << " bytes"; + else s << v.toString(); + s << ")"; + s.restoreControl(); return s; +} #endif // PIVARIANT_H diff --git a/pivector.h b/pivector.h index 4082da7f..3c3beb6e 100644 --- a/pivector.h +++ b/pivector.h @@ -6,7 +6,7 @@ /* PIP - Platform Independent Primitives Dynamic array of any type - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -201,7 +201,7 @@ public: return *this; } PIVector & assign(const T & f = T()) {return fill(f);} - PIVector & assign(size_t new_size, const T & f) {resize(new_size); fill(f);} + PIVector & assign(size_t new_size, const T & f) {resize(new_size); return fill(f);} PIVector & resize(size_t new_size, const T & f = T()) { if (new_size < piv_size) { T * de = &(piv_data[new_size]); @@ -261,6 +261,13 @@ public: PIVector & push_back(const T & v) {alloc(piv_size + 1); new(piv_data + piv_size - 1)T(v); return *this;} PIVector & append(const T & v) {return push_back(v);} PIVector & operator <<(const T & v) {return push_back(v);} + PIVector & operator <<(const PIVector & t) { + size_t ps = piv_size; + alloc(piv_size + t.piv_size); + for (int i = 0; i < t.piv_size; ++i) + new(piv_data + ps + i)T(t.piv_data[i]); + return *this; + } PIVector & push_front(const T & v) {insert(0, v); return *this;} PIVector & prepend(const T & v) {return push_front(v);} diff --git a/remote_console/main.cpp b/remote_console/main.cpp index 39f97a2e..db43c449 100644 --- a/remote_console/main.cpp +++ b/remote_console/main.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Remote console viewer - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/system_test/main.cpp b/system_test/main.cpp index 91e87ca3..9022d54b 100644 --- a/system_test/main.cpp +++ b/system_test/main.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives System tests program - Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by