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