29.04.2014 - Version 0.4.0_prealpha. PICodeParser, namespace PICodeInfo, new tool "pip_cmg" in dir "code_model_generator". New feature in PIIODevice - "createFromFullPath", all parameters of all I/O devices now works with PIObjects`s properties.

This commit is contained in:
peri4
2014-04-29 11:50:13 +04:00
parent 77abb0bbea
commit 2e5e75c4c4
98 changed files with 2545 additions and 768 deletions

View File

@@ -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)

4
clean
View File

@@ -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 ..

View File

@@ -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 ()

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <output_file> [-I<include_dir1>] [-I<include_dir1>] [...] [-D<define1>] [-D<define1>] [...] <file1> [<file2>] [<file3>] [...]\"" << NewLine;
piCout << Green << Bold << "Details:";
piCout << "-h " << Green << "- display this message and exit";
piCout << "-o <output_file> " << Green << "- output file for code model without extension (e.g. \"ccm\" - files \"ccm.h\" and \"ccm.cpp\" will be created)";
piCout << "-I<include_dir> " << Green << "- add include dir (e.g. -I.. -I../some_dir -I/usr/include)";
piCout << "-D<define> " << Green << "- add define to preprocessor, define PICODE is always defined (e.g. -DMY_DEFINE will add MY_DEFINE define)";
piCout << "<file> " << 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<const PICodeParser::Entity * > ventities;
PIString defname = out.replaceAll(".", "_").replaceAll("/", "_").toUpperCase() + "_H";
PISet<PIString> 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 <string.h>\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<PICodeParser::Member> & 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;
};

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<TimerEvent>(event));
execFunction(&tm, "start", 200);
piMSleep(1000);
execFunction(&tm, "addDelimiter", 2);
piMSleep(1000);
execFunction(&tm, "stop");
execFunction(&tm, "stop_");
piMSleep(1000);*/
typedef std::pair<PIString, PICodeInfo::ClassInfo * > mpair;
piForeachC (mpair & i, *(PICodeInfo::classesInfo))
piCout << *i.second;
piCout << "\n\n";
typedef std::pair<PIString, PICodeInfo::EnumInfo * > epair;
piForeachC (epair & i, *(PICodeInfo::enumsInfo))
piCout << *i.second;
return 0;
};

140
main.cpp
View File

@@ -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<T> newVariant(const T & v) {return Test::PIVariant<T>(v);}
template <typename T>
Test::PIVariant<T> * castVariant(Test::__PIVariantBase * v, const T & t) {return static_cast<Test::PIVariant<T> * >(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<TypeFlag> TypeFlags;
struct TypeInfo {
TypeInfo() {flags = 0;}
PIString name;
PIString type;
TypeFlags flags;
};
struct FunctionInfo {
PIString name;
TypeInfo return_type;
PIVector<TypeInfo> arguments;
};
struct ClassInfo {
PIString name;
PIStringList parents;
PIVector<TypeInfo> variables;
PIVector<FunctionInfo> 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<float>();
//piCout << v.toType<float>().toType<PIString>();
//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();
}

View File

@@ -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;
}
}
}

View File

@@ -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<int> 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];
};

View File

@@ -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

View File

@@ -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

View File

@@ -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<void * >(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;}

View File

@@ -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

View File

@@ -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;
}

12
picli.h
View File

@@ -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 {

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<PIString, PIString> 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;
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<PIString, PIString> Define;
typedef PIPair<PIString, PIString> 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<Entity * > children;
};
PIVector<Define> defines;
PIVector<Macro> macros;
PIVector<Typedef> typedefs;
PIVector<Entity> entities;
PIVector<Entity * > tree;
};
#endif // PIPACKETEXTRACTOR_H

View File

@@ -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

View File

@@ -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

26
picodeinfo.cpp Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#include "picodeinfo.h"
PIMap<PIString, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo;
PIMap<PIString, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo;
bool __PICodeInfoInitializer__::_inited_ = false;

147
picodeinfo.h Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<PICodeInfo::TypeFlag> 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<PICodeInfo::TypeInfo> arguments;
};
struct ClassInfo {
PIString name;
PIStringList parents;
PIVector<PICodeInfo::TypeInfo> variables;
PIVector<PICodeInfo::FunctionInfo> functions;
};
struct EnumeratorInfo {
EnumeratorInfo(const PIString & n = PIString(), int v = 0) {name = n; value = v;}
PIString name;
int value;
};
struct EnumInfo {
PIString name;
PIVector<PICodeInfo::EnumeratorInfo> 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<PIString, PICodeInfo::ClassInfo * > * classesInfo;
extern PIMap<PIString, PICodeInfo::EnumInfo * > * enumsInfo;
}
class __PICodeInfoInitializer__ {
public:
__PICodeInfoInitializer__() {
if (_inited_) return;
_inited_ = true;
PICodeInfo::classesInfo = new PIMap<PIString, PICodeInfo::ClassInfo * >;
PICodeInfo::enumsInfo = new PIMap<PIString, PICodeInfo::EnumInfo * >;
}
static bool _inited_;
};
static __PICodeInfoInitializer__ __picodeinfoinitializer__;
#endif // PICODEINFO_H

762
picodeparser.cpp Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<PIString, PIString> 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<Entity * > 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;
}

148
picodeparser.h Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<Attribute> Attributes;
typedef PIPair<PIString, PIString> Define;
typedef PIPair<PIString, PIString> Typedef;
typedef PIPair<PIString, int> 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<Entity * > parents;
//PIVector<Entity * > children;
PIVector<Member> functions;
PIVector<Member> members;
PIVector<Typedef> typedefs;
};
struct PIP_EXPORT Enum {
Enum(const PIString & n = PIString()) {
name = n;
}
PIString name;
PIVector<Enumerator> 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<Define> defines, custom_defines;
PIVector<Macro> macros;
PIVector<Enum> enums;
PIVector<Typedef> typedefs;
PIVector<Entity * > 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<Entity * > tree;
PISet<PIString> proc_files;
PIString cur_file;
PIStringList includes;
Entity root_;
Visibility cur_def_vis;
PIString cur_namespace;
PIMap<PIString, PIString> tmp_temp;
};
#endif // PICODEPARSER_H

View File

@@ -14,14 +14,14 @@
PIStringList PICollection::groups() {
PIStringList sl;
piForeachC (Group & g, _groups)
piForeachC (Group & g, *_groups)
sl << g.name;
return sl;
}
PIVector<const PIObject * > PICollection::groupElements(const PIString & group) {
piForeachC (Group & g, _groups)
piForeachC (Group & g, *_groups)
if (g.name == group)
return g.elements;
return PIVector<const PIObject * >();
@@ -29,18 +29,21 @@ PIVector<const PIObject * > 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::Group> PICollection::_groups;
bool __PICollectionInitializer::_inited_(false);
PIVector<PICollection::Group> * PICollection::_groups;

View File

@@ -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<const PIObject * > elements;
};
static PIVector<Group> _groups;
static PIVector<Group> * _groups;
};
class PIP_EXPORT __PICollectionInitializer {
public:
__PICollectionInitializer() {
if (_inited_) return;
_inited_ = true;
PICollection::_groups = new PIVector<PICollection::Group>();
}
static bool _inited_;
};
static __PICollectionInitializer __picollectioninitializer;
#endif // PICOLLECTION_H

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<typename Type0, typename Type1>
inline bool operator <(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return value0.first < value1.first;}
template<typename Type0, typename Type1>
inline bool operator ==(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first == value1.first) && (value0.second == value1.second);}
template<typename Type0, typename Type1>
inline bool operator !=(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first != value1.first) || (value0.second != value1.second);}
template<typename Type0, typename Type1>
inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> & v) {s << "(" << v.first << ", " << v.second << ")"; return s;}
template<typename Type0, typename Type1>
inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & 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<Type> toVector() {PIVector<Type> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}

View File

@@ -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

44
pidevicepool.cpp Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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();
}*/
}

65
pidevicepool.h Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@@ -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

View File

@@ -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

View File

@@ -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::DirEntry> PIDir::entries() {
struct stat fs;
PIVector<DirEntry> 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];
}

View File

@@ -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

View File

@@ -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<PIEthernet::Parameters> params_): PIIODevice(ip_port, ReadWrite) {
PIEthernet::PIEthernet(PIEthernet::Type type_, const PIString & ip_port, const PIFlags<PIEthernet::Parameters> 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<Parameters> 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<Parameters> 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<Parameters> cp = (PIFlags<Parameters>)(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<Parameters> 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<Parameters> 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;

View File

@@ -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<PIEthernet::Parameters> parameters_) {params = parameters_;}
void setParameters(PIFlags<PIEthernet::Parameters> 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<PIEthernet::Parameters>)(property("parameters").toInt()))[parameter];}
//! Returns parameters
PIFlags<PIEthernet::Parameters> parameters() const {return params;}
PIFlags<PIEthernet::Parameters> parameters() const {return (PIFlags<PIEthernet::Parameters>)(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<PIEthernet * > clients_;
PIQueue<PIString> mcast_queue;
PIStringList mcast_groups;
#ifdef WINDOWS
PIMap<PIString, SOCKET> leafs;
#endif
PIFlags<PIEthernet::Parameters> 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

View File

@@ -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<ldouble>(rand()) / RAND_MAX;
stmp = value(ci.operators[1]) - value(ci.operators[0]);

View File

@@ -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<int> 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);}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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

View File

@@ -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

View File

@@ -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 <ctime>
#include <csignal>
#include <cassert>
#include <cmath>
//#include <signal.h>
#include <typeinfo>
#include <algorithm>
@@ -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<wchar_t> wstring;
typedef std::basic_string<wchar_t> wstring;
#endif
/*! \brief Templated function for swap two values
@@ -458,8 +479,8 @@ template<typename T> 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
};
};

View File

@@ -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://<path>"
* * PIBinaryLog: "binlog://<logDir>[:<filePrefix>][:<defaultID>]"
* * PISerial: "ser://<device>:<speed(50|...|115200)>[:<dataBitsCount(6|7|8)>][:<parity(N|E|O)>][:<stopBits(1|2)>]"
* * PIEthernet: "eth://<type(UDP|TCP)>:<readIP>:<readPort>[:<multicast(mcast:<ip>)>]"
* * PIUSB: "usb://<vid>:<pid>[:<deviceNumber>][:<readEndpointNumber>][:<writeEndpointNumber>]"
* \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<const PIObject * > 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;
}

View File

@@ -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();}

View File

@@ -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_);
}
}

View File

@@ -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;

13
pimap.h
View File

@@ -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<Key, Type> 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<Key> keys() const {
PIVector<Key> 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();}
};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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<PIString, PIVariant> & 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<T0, T1, T2, T3>(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<PIString, PIVariant> properties_;
static PIVector<PIObject * > objects;
static PIObject * findByName(const PIString & name) {
piForeach (PIObject * i, PIObject::objects) {
if (i->name_ != name) continue;
return i;
}
return 0;
};
};

4
pip.h
View File

@@ -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"

18
pip.pro
View File

@@ -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 {

View File

@@ -1,38 +0,0 @@
# if defined(UNDER_CE)
# include <winbase.h>
# else
# include <winver.h>
# 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 */

View File

@@ -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"

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<PeerInfo> 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]);

View File

@@ -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<PeerInfo> & allPeers() const {return peers;}
const PIVector<PIPeer::PeerInfo> & 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);

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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<PISerial::Parameters> 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<Parameters> cp = (PIFlags<Parameters>)(property("parameters").toInt());
cp.setFlag(parameter, on);
setParameters(cp);
}
bool PISerial::isParameterSet(PISerial::Parameters parameter) const {
PIFlags<Parameters> cp = (PIFlags<Parameters>)(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, &times) == -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<Parameters> 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<Parameters> 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<PIString>("device", device(), em, ep));
setSpeed((PISerial::Speed)(readDeviceSetting<int>("speed", (int)ospeed, em, ep)));
setSpeed((PISerial::Speed)(readDeviceSetting<int>("speed", (int)outSpeed(), em, ep)));
setDataBitsCount(readDeviceSetting<int>("dataBitsCount", dataBitsCount(), em, ep));
setParameter(PISerial::ParityControl, readDeviceSetting<bool>("parityControl", isParameterSet(PISerial::ParityControl), em, ep));
setParameter(PISerial::ParityOdd, readDeviceSetting<bool>("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<int> PISerial::availableSpeeds() {
PIVector<int> 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++;
}

View File

@@ -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<PISerial::Parameters> parameters_) {params = parameters_; applySettings();}
void setParameters(PIFlags<PISerial::Parameters> 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<PISerial::Parameters> parameters() const {return params;}
PIFlags<PISerial::Parameters> parameters() const {return (PIFlags<Parameters>)(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<PISerial::Parameters> params;
};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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<PIChar>
{
public:
//! Contructs an empty string
PIString(): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--;}
PIString(): PIVector<PIChar>() {/*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<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += o;}
//! Contructs string with single symbol "c"
PIString(const PIChar & c): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += c;}
PIString(const char c): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += PIChar(c);}
PIString(const PIChar & c): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += c;}
PIString(const char c): PIVector<PIChar>() {/*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<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
PIString(const char * str): PIVector<PIChar>() {/*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<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
PIString(const wchar_t * str): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;}
//! Contructs string from std::string "str"
PIString(const string & str): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
PIString(const string & str): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;}
#ifdef HAS_LOCALE
PIString(const wstring & str): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
PIString(const wstring & str): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;}
#endif
//! Contructs string from byte array "ba"
PIString(const PIByteArray & ba): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += ba;}
PIString(const PIByteArray & ba): PIVector<PIChar>() {/*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<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += string(str, len);}
PIString(const char * str, const int len): PIVector<PIChar>() {/*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<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
PIString(const int len, const char c): PIVector<PIChar>() {/*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<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
PIString(const int len, const PIChar & c): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
PIString(const short & value): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ushort & value): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const int & value): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const uint & value): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const long & value): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ulong & value): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const llong & value): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ullong & value): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const float & value): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const double & value): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const short & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ushort & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const int & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const uint & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const long & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ulong & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const llong & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ullong & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const float & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const double & value): PIVector<PIChar>() {/*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<PIString>() {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;}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}
}

57
piusb.h
View File

@@ -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<Endpoint> endpoints;
PIVector<PIUSB::Endpoint> endpoints;
};
struct Configuration {
@@ -69,7 +71,7 @@ public:
ushort max_power; // mA
bool self_powered;
bool remote_wakeup;
PIVector<Interface> interfaces;
PIVector<PIUSB::Interface> interfaces;
};
struct Descriptor {
@@ -85,37 +87,38 @@ public:
uchar index_manufacturer;
uchar index_product;
uchar index_serial;
PIVector<Configuration> configurations;
PIVector<PIUSB::Configuration> 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<Endpoint> & endpoints() const {return eps;}
PIVector<Endpoint> endpointsRead();
PIVector<Endpoint> endpointsWrite();
Endpoint getEndpointByAddress(uchar address);
const PIVector<PIUSB::Endpoint> & endpoints() const {return eps;}
PIVector<PIUSB::Endpoint> endpointsRead();
PIVector<PIUSB::Endpoint> 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<Endpoint> eps;
PIVector<PIUSB::Endpoint> 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_;

View File

@@ -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";

View File

@@ -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<typename T>
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 <typename T>
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

View File

@@ -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<T> & assign(const T & f = T()) {return fill(f);}
PIVector<T> & assign(size_t new_size, const T & f) {resize(new_size); fill(f);}
PIVector<T> & assign(size_t new_size, const T & f) {resize(new_size); return fill(f);}
PIVector<T> & 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<T> & push_back(const T & v) {alloc(piv_size + 1); new(piv_data + piv_size - 1)T(v); return *this;}
PIVector<T> & append(const T & v) {return push_back(v);}
PIVector<T> & operator <<(const T & v) {return push_back(v);}
PIVector<T> & operator <<(const PIVector<T> & 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<T> & push_front(const T & v) {insert(0, v); return *this;}
PIVector<T> & prepend(const T & v) {return push_front(v);}

View File

@@ -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

View File

@@ -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