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