diff --git a/.kdev4/_custom.kdev4 b/.kdev4/_custom.kdev4 new file mode 100644 index 00000000..0c4c24e1 --- /dev/null +++ b/.kdev4/_custom.kdev4 @@ -0,0 +1,28 @@ +[Containments][1] +ActionPluginsSource=Global +ExpandAllApplets=false +activity=pip +activityId= +desktop=-1 +formfactor=0 +immutability=1 +lastDesktop=-1 +lastScreen=0 +location=0 +orientation=2 +plugin=newspaper +screen=0 +wallpaperplugin=color +wallpaperpluginmode= + +[Containments][1][Wallpaper][color] +backgroundMode=0 +color1=255,255,255 +color2=0,0,0 + +[General] +immutability=1 + +[Project] +Manager=KDevCMakeManager +Name=pip diff --git a/.kdev4/pip.kdev4 b/.kdev4/pip.kdev4 index 66546cad..6f91f02d 100644 --- a/.kdev4/pip.kdev4 +++ b/.kdev4/pip.kdev4 @@ -24,7 +24,10 @@ Arguments= Dependencies=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00p\x00i\x00p) Dependency Action=Build EnvironmentGroup=default -Project Target=pip,pip +Executable= +External Terminal=konsole --noclose --workdir %workdir -e %exe +Project Target=pip,pip_test +Use External Terminal=false Working Directory= isExecutable=false diff --git a/CMakeLists.txt b/CMakeLists.txt index 66350215..6fa514c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,17 @@ project(pip) cmake_minimum_required(VERSION 2.6) include_directories(${CMAKE_CURRENT_SOURCE_DIR} .) -file(GLOB CPPS "*.cpp") +file(GLOB CPPS "pi*.cpp") add_definitions(-O2 -g3 -Wall) -add_executable(pip ${CPPS}) +add_library(pip SHARED ${CPPS}) if (${WIN32}) target_link_libraries(pip pthread ws2_32) else (${WIN32}) target_link_libraries(pip pthread rt) endif (${WIN32}) +add_executable(pip_test "main.cpp") +if (${WIN32}) + target_link_libraries(pip_test pip pthread ws2_32) +else (${WIN32}) + target_link_libraries(pip_test pip pthread rt) +endif (${WIN32}) diff --git a/Makefile_qnx b/Makefile_qnx new file mode 100644 index 00000000..be2f61d8 --- /dev/null +++ b/Makefile_qnx @@ -0,0 +1,240 @@ +####### Compiler, tools and options + +TARGET = pip +CC = gcc +CXX = g++ +CFLAGS = -pipe -D_REENTRANT +CXXFLAGS = $(CFLAGS) +INCPATH = -I. +LINK = g++ +LFLAGS = -Wl,-O2 +LIBS = -lsocket +DEL_FILE = rm -f +DEL_DIR = rmdir + +####### Output directory + +OBJECTS_DIR = ./ + +####### Files + +SOURCES = main.cpp \ + pibytearray.cpp \ + piconfig.cpp \ + piconsole.cpp \ + pidir.cpp \ + piethernet.cpp \ + pievaluator.cpp \ + pifile.cpp \ + pikbdlistener.cpp \ + pimath.cpp \ + piprotocol.cpp \ + piserial.cpp \ + pistring.cpp \ + pithread.cpp \ + pitimer.cpp \ + pivariable.cpp +OBJECTS = main.o \ + pibytearray.o \ + piconfig.o \ + piconsole.o \ + pidir.o \ + piethernet.o \ + pievaluator.o \ + pifile.o \ + pikbdlistener.o \ + pimath.o \ + piprotocol.o \ + piserial.o \ + pistring.o \ + pithread.o \ + pitimer.o \ + pivariable.o + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile $(TARGET) + +$(TARGET): $(OBJECTS) + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) *~ core *.core + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile + +compiler_clean: + +####### Compile + +main.o: main.cpp pip.h \ + pitimer.h \ + pithread.h \ + piincludes.h \ + pimutex.h \ + pivariable.h \ + piconfig.h \ + pifile.h \ + pistring.h \ + pibytearray.h \ + pibitarray.h \ + pichar.h \ + piconsole.h \ + pikbdlistener.h \ + pievaluator.h \ + pimath.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o main.cpp + +pibytearray.o: pibytearray.cpp pibytearray.h \ + pibitarray.h \ + piincludes.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o pibytearray.o pibytearray.cpp + +piconfig.o: piconfig.cpp piconfig.h \ + pifile.h \ + piincludes.h \ + pistring.h \ + pibytearray.h \ + pibitarray.h \ + pichar.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o piconfig.o piconfig.cpp + +piconsole.o: piconsole.cpp piconsole.h \ + pikbdlistener.h \ + pithread.h \ + piincludes.h \ + pimutex.h \ + pistring.h \ + pibytearray.h \ + pibitarray.h \ + pichar.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o piconsole.o piconsole.cpp + +pidir.o: pidir.cpp pidir.h \ + pifile.h \ + piincludes.h \ + pistring.h \ + pibytearray.h \ + pibitarray.h \ + pichar.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o pidir.o pidir.cpp + +piethernet.o: piethernet.cpp piethernet.h \ + pithread.h \ + piincludes.h \ + pimutex.h \ + pistring.h \ + pibytearray.h \ + pibitarray.h \ + pichar.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o piethernet.o piethernet.cpp + +pievaluator.o: pievaluator.cpp pievaluator.h \ + pistring.h \ + pibytearray.h \ + pibitarray.h \ + piincludes.h \ + pichar.h \ + pimath.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o pievaluator.o pievaluator.cpp + +pifile.o: pifile.cpp pifile.h \ + piincludes.h \ + pistring.h \ + pibytearray.h \ + pibitarray.h \ + pichar.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o pifile.o pifile.cpp + +pikbdlistener.o: pikbdlistener.cpp pikbdlistener.h \ + pithread.h \ + piincludes.h \ + pimutex.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o pikbdlistener.o pikbdlistener.cpp + +pimath.o: pimath.cpp pimath.h \ + piincludes.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o pimath.o pimath.cpp + +piprotocol.o: piprotocol.cpp piprotocol.h \ + piserial.h \ + pithread.h \ + piincludes.h \ + pimutex.h \ + pistring.h \ + pibytearray.h \ + pibitarray.h \ + pichar.h \ + piethernet.h \ + pitimer.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o piprotocol.o piprotocol.cpp + +piserial.o: piserial.cpp piserial.h \ + pithread.h \ + piincludes.h \ + pimutex.h \ + pistring.h \ + pibytearray.h \ + pibitarray.h \ + pichar.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o piserial.o piserial.cpp + +pistring.o: pistring.cpp pistring.h \ + pibytearray.h \ + pibitarray.h \ + piincludes.h \ + pichar.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o pistring.o pistring.cpp + +pithread.o: pithread.cpp pithread.h \ + piincludes.h \ + pimutex.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o pithread.o pithread.cpp + +pitimer.o: pitimer.cpp pitimer.h \ + pithread.h \ + piincludes.h \ + pimutex.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o pitimer.o pitimer.cpp + +pivariable.o: pivariable.cpp pivariable.h \ + piconfig.h \ + pifile.h \ + piincludes.h \ + pistring.h \ + pibytearray.h \ + pibitarray.h \ + pichar.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o pivariable.o pivariable.cpp + +####### Install + +install: FORCE + +uninstall: FORCE + +FORCE: + diff --git a/main.cpp b/main.cpp index 9eccf944..5abab5a7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,26 +1,21 @@ -#include "pip.h" +#include int main(int argc, char * argv[]) { - /*PIString s("I love Kusia! <3"); - PIByteArray c(s.data(), s.size()); - c.compressHuffman(); - cout << s << endl << c << endl; - //c.decompressRLE(128); - cout << c << endl;*/ - PIBitArray a(0xFFF00Fu); - //cout << a << endl; - a.setBit(31); - cout << a << endl; - a.push_back(true); - cout << a << endl; - a.push_front(true); - cout << a << endl; - a.push_front(false); - cout << a << endl; - a.pop_front(); - cout << a << endl; - a.pop_front(); - cout << a << endl; - a.pop_front(); - cout << a << endl; + PIString s("sos№⚒№хуй"/*☢⚒SOŮ*/); + /*cout << s << endl; + cout << s.length() << endl; + cout << s.stdWString().length() << endl;*/ + //system("cd /"); + PIProcess p; + //p.setWorkingDirectory("/"); + //p.setEnvironmentVariable("PWD", "/"); + //cout << p.environment().join("\n") << endl; + p.exec("cd"); + p.waitForFinish(); + + //cout << s << endl; + /*wchar_t wc; + cout << (int)(uchar)("№"[0]) << ", " << (int)(uchar)("№"[1]) << endl; + cout << isascii("№"[0]) << endl; + cout << mbtowc(&wc, "№", 4) << endl;*/ }; diff --git a/make_install.sh b/make_install.sh new file mode 100755 index 00000000..195f1dc5 --- /dev/null +++ b/make_install.sh @@ -0,0 +1,8 @@ +#! /bin/bash +cmake . +make -j3 +if [ $@ != "" ] ; then + chown -v $@ /usr/lib/ /usr/include/ +fi +cp -vf *.h /usr/include/ +cp -vf libpip.so /usr/lib/libpip.so diff --git a/pibitarray.h b/pibitarray.h index 7446e049..a929ba85 100644 --- a/pibitarray.h +++ b/pibitarray.h @@ -1,7 +1,7 @@ #ifndef PIBITARRAY_H #define PIBITARRAY_H -#include "piincludes.h" +#include "picontainers.h" class PIBitArray { public: diff --git a/pibytearray.h b/pibytearray.h index 435ca46f..1e61f595 100644 --- a/pibytearray.h +++ b/pibytearray.h @@ -74,8 +74,9 @@ private: class PIByteArray: public PIVector { public: PIByteArray() {;} - PIByteArray(const char * data, uint size) {for (uint i = 0; i < size; ++i) push_back(data[i]);} - PIByteArray(const uchar * data, uint size) {for (uint i = 0; i < size; ++i) push_back(data[i]);} + PIByteArray(const uint size) {resize(size);} + PIByteArray(const char * data, const uint size) {for (uint i = 0; i < size; ++i) push_back(data[i]);} + PIByteArray(const uchar * data, const uint size) {for (uint i = 0; i < size; ++i) push_back(data[i]);} PIByteArray & convertToBase64(); PIByteArray & convertFromBase64(); diff --git a/pichar.h b/pichar.h new file mode 100644 index 00000000..008c2d05 --- /dev/null +++ b/pichar.h @@ -0,0 +1,102 @@ +#ifndef PICHAR_H +#define PICHAR_H + +#include "piincludes.h" + +class PIChar +{ + friend class PIString; +public: + PIChar(const char c) {ch = c; ch &= 0xFF;} + PIChar(const short c) {ch = c; ch &= 0xFFFF;} + PIChar(const int c = 0) {ch = c;} + PIChar(const uchar c) {ch = c; ch &= 0xFF;} + PIChar(const ushort c) {ch = c; ch &= 0xFFFF;} + PIChar(const uint c) {ch = c;} + PIChar(const char * c) {ch = *reinterpret_cast(c);} + + //inline operator const int() {return static_cast(ch);} + //inline operator const char() {return toAscii();} + + inline PIChar & operator =(const char v) {ch = v; return *this;} + /*inline PIChar & operator =(const short v) {ch = v; return *this;} + inline PIChar & operator =(const int v) {ch = v; return *this;} + inline PIChar & operator =(const uchar v) {ch = v; return *this;} + inline PIChar & operator =(const ushort v) {ch = v; return *this;} + inline PIChar & operator =(const uint v) {ch = v; return *this;}*/ + + inline bool operator ==(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) == 0;} + /*inline bool operator ==(const PIChar & o) const {if (o.isAscii() ^ isAscii()) return false; + if (isAscii()) return (o.toAscii() == toAscii()); + return (o.toInt() == toInt());} + inline bool operator ==(const char o) const {return (PIChar(o) == *this);} + inline bool operator ==(const short o) const {return (PIChar(o) == *this);} + inline bool operator ==(const int o) const {return (PIChar(o) == *this);} + inline bool operator ==(const uchar o) const {return (PIChar(o) == *this);} + inline bool operator ==(const ushort o) const {return (PIChar(o) == *this);} + inline bool operator ==(const uint o) const {return (PIChar(o) == *this);}*/ + + inline bool operator !=(const PIChar & o) const {return !(o == *this);} + /*inline bool operator !=(const char o) const {return (PIChar(o) != *this);} + inline bool operator !=(const short o) const {return (PIChar(o) != *this);} + inline bool operator !=(const int o) const {return (PIChar(o) != *this);} + inline bool operator !=(const uchar o) const {return (PIChar(o) != *this);} + inline bool operator !=(const ushort o) const {return (PIChar(o) != *this);} + inline bool operator !=(const uint o) const {return (PIChar(o) != *this);}*/ + + inline bool operator >(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) < 0;} + inline bool operator <(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) > 0;} + inline bool operator >=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) <= 0;} + inline bool operator <=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) >= 0;} + + inline bool isDigit() const {return isdigit(ch);} + inline bool isHex() const {return isxdigit(ch);} + inline bool isGraphical() const {return isgraph(ch);} + inline bool isControl() const {return iscntrl(ch);} + inline bool isLower() const {return islower(ch);} + inline bool isUpper() const {return isupper(ch);} + inline bool isPrint() const {return isprint(ch);} + inline bool isSpace() const {return isspace(ch);} + inline bool isAlpha() const {return isalpha(ch);} + inline bool isAscii() const {return isascii(ch);} + + inline int toInt() const {return static_cast(ch);} + inline const wchar_t * toWCharPtr() const {return &ch;} + inline const char * toCharPtr() const {return reinterpret_cast(&ch);} + inline const wchar_t toWChar() const {return ch;} + inline char toAscii() const {return ch % 256;} + inline int unicode16Code() const {wchar_t wc; if (mbtowc(&wc, toCharPtr(), 4) > 0) return wc; return 0;} +#ifdef WINDOWS + inline PIChar toUpper() const __attribute__ ((optimize(0))) {return PIChar(toupper(ch));} + inline PIChar toLower() const __attribute__ ((optimize(0))) {return PIChar(tolower(ch));} +#else + inline PIChar toUpper() const {return PIChar(toupper(ch));} + inline PIChar toLower() const {return PIChar(tolower(ch));} +#endif + +private: + wchar_t ch; + +}; + +inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;} + +inline bool operator ==(const char v, const PIChar & c) {return (PIChar(v) == c);} +inline bool operator >(const char v, const PIChar & c) {return (PIChar(v) > c);} +inline bool operator <(const char v, const PIChar & c) {return (PIChar(v) < c);} +inline bool operator >=(const char v, const PIChar & c) {return (PIChar(v) >= c);} +inline bool operator <=(const char v, const PIChar & c) {return (PIChar(v) <= c);} + +inline bool operator ==(const char * v, const PIChar & c) {return (PIChar(v) == c);} +inline bool operator >(const char * v, const PIChar & c) {return (PIChar(v) > c);} +inline bool operator <(const char * v, const PIChar & c) {return (PIChar(v) < c);} +inline bool operator >=(const char * v, const PIChar & c) {return (PIChar(v) >= c);} +inline bool operator <=(const char * v, const PIChar & c) {return (PIChar(v) <= c);} + +inline bool operator ==(const int v, const PIChar & c) {return (PIChar(v) == c);} +inline bool operator >(const int v, const PIChar & c) {return (PIChar(v) > c);} +inline bool operator <(const int v, const PIChar & c) {return (PIChar(v) < c);} +inline bool operator >=(const int v, const PIChar & c) {return (PIChar(v) >= c);} +inline bool operator <=(const int v, const PIChar & c) {return (PIChar(v) <= c);} + +#endif // PICHAR_H diff --git a/picli.cpp b/picli.cpp new file mode 100644 index 00000000..722a59e4 --- /dev/null +++ b/picli.cpp @@ -0,0 +1,63 @@ +#include "picli.h" + + +PICLI::PICLI(int argc, char * argv[]) { + needParse = true; + _prefix_short = "-"; + _prefix_full = "--"; + _count_opt = 0; + _count_mand = 1; + for (int i = 0; i < argc; ++i) + _args_raw << argv[i]; +} + + +void PICLI::parse() { + if (!needParse) return; + PIString cra, full; + Argument * last = 0; + for (int i = 1; i < _args_raw.size_s(); ++i) { + cra = _args_raw[i]; + if (cra.left(2) == _prefix_full) { + last = 0; + full = cra.right(cra.length() - 2); + piForeachA (a, _args) { + if (a.full_key == full) { + a.found = true; + last = &a; + break; + } + } + } else { + if (cra.left(1) == _prefix_short) { + last = 0; + for (int j = 1; j < cra.length(); ++j) { + piForeachA (a, _args) { + if (a.short_key == cra[j]) { + a.found = true; + last = &a; + break; + } + } + } + } else { + if (last == 0 ? true : !last->has_value) { + if (_args_mand.size_s() < _count_mand) { + _args_mand << cra; + continue; + } + if (_args_opt.size_s() < _count_opt) { + _args_opt << cra; + continue; + } + cout << "[PICli] Arguments overflow, \"" << cra << "\" ignored" << endl; + } + if (last == 0 ? false : last->has_value) { + last->value = cra; + last = 0; + } + } + } + } + needParse = false; +} diff --git a/picli.h b/picli.h new file mode 100644 index 00000000..73f01210 --- /dev/null +++ b/picli.h @@ -0,0 +1,60 @@ +#ifndef PICLI_H +#define PICLI_H + +#include "pistring.h" + +class PICLI +{ +public: + PICLI(int argc, char * argv[]); + + inline void addArgument(const PIString & name, bool value = false) {_args << Argument(name, name[0], name, value); needParse = true;} + inline void addArgument(const PIString & name, const PIChar & shortKey, bool value = false) {_args << Argument(name, shortKey, name, value); needParse = true;} + inline void addArgument(const PIString & name, const char * shortKey, bool value = false) {_args << Argument(name, PIChar(shortKey), name, value); needParse = true;} + inline void addArgument(const PIString & name, const PIChar & shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, shortKey, fullKey, value); needParse = true;} + inline void addArgument(const PIString & name, const char * shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, PIChar(shortKey), fullKey, value); needParse = true;} + + inline PIString rawArgument(int index) {return _args_raw[index];} + inline PIString mandatoryArgument(int index) {return _args_mand[index];} + inline PIString optionalArgument(int index) {return _args_opt[index];} + inline const PIStringList & rawArguments() const {return _args_raw;} + inline const PIStringList & mandatoryArguments() const {return _args_mand;} + inline const PIStringList & optionalArguments() const {return _args_opt;} + inline const PIString programCommand() const {return _args_raw.size() > 0 ? _args_raw.front() : PIString();} + inline bool hasArgument(const PIString & name) {parse(); piForeachA (i, _args) if (i.name == name && i.found) return true; return false;} + inline PIString argumentValue(const PIString & name) {parse(); piForeachA (i, _args) if (i.name == name && i.found) return i.value; return PIString();} + inline PIString argumentShortKey(const PIString & name) {piForeachA (i, _args) if (i.name == name) return i.short_key; return PIString();} + inline PIString argumentFullKey(const PIString & name) {piForeachA (i, _args) if (i.name == name) return i.full_key; return PIString();} + + inline const PIString & shortKeyPrefix() const {return _prefix_short;} + inline const PIString & fullKeyPrefix() const {return _prefix_full;} + inline const int mandatoryArgumentsCount() const {return _count_mand;} + inline const int optionalArgumentsCount() const {return _count_opt;} + inline void setShortKeyPrefix(const PIString & prefix) {_prefix_short = prefix;} + inline void setFullKeyPrefix(const PIString & prefix) {_prefix_full = prefix;} + inline void setMandatoryArgumentsCount(const int count) {_count_mand = count;} + inline void setOptionalArgumentsCount(const int count) {_count_opt = count;} + +private: + struct Argument { + Argument() {has_value = found = false;} + Argument(const PIString & n, const PIChar & s, const PIString & f, bool v) {name = n; short_key = s; full_key = f; has_value = v; found = false;} + PIString name; + PIChar short_key; + PIString full_key; + PIString value; + bool has_value, found; + }; + + void parse(); + + PIString _prefix_short, _prefix_full; + PIStringList _args_raw, _args_mand, _args_opt; + PISet keys_full, keys_short; + PIVector _args; + int _count_mand, _count_opt; + bool needParse; + +}; + +#endif // PICLI_H diff --git a/picodec.cpp b/picodec.cpp new file mode 100644 index 00000000..d97eb3c0 --- /dev/null +++ b/picodec.cpp @@ -0,0 +1,22 @@ +#include "picodec.h" + + +PIStringList PICodec::availableCodecs() { + exec("iconv", "-l"); + waitForFinish(); + PIString str(readOutput()); + str.cutLeft(str.find("\n ")); + str.replaceAll("\n", ""); + return str.split("//"); +} + + +PIByteArray PICodec::exec_iconv(const PIString & from, const PIString & to, const PIByteArray & str) { + tf.open(); + tf.clear(); + tf << str; + tf.close(); + exec("iconv", ("-f=" + from), ("-t=" + to), tf.path()); + waitForFinish(); + return readOutput(); +} diff --git a/picodec.h b/picodec.h new file mode 100644 index 00000000..07f10cc9 --- /dev/null +++ b/picodec.h @@ -0,0 +1,31 @@ +#ifndef PICODEC_H +#define PICODEC_H + +#include "piprocess.h" + +class PICodec: private PIProcess +{ +public: + PICodec(): PIProcess() {setGrabOutput(true); tf = PIFile::openTemporary(PIFile::New | PIFile::Read | PIFile::Write); tf.open();} + PICodec(const PIString & from, const PIString & to): PIProcess() {setCodings(from, to); tf = PIFile::openTemporary(PIFile::New | PIFile::Read | PIFile::Write);} + ~PICodec() {tf.remove();} + + void setFromCoding(const PIString & from) {c_from = from;} + void setToCoding(const PIString & to) {c_to = to;} + void setCodings(const PIString & from, const PIString & to) {c_from = from; c_to = to;} + + PIStringList availableCodecs(); + PIString encode(PIString & str) {return PIString(exec_iconv(c_from, c_to, str.toByteArray()));} + PIString encode(const PIByteArray & str) {return PIString(exec_iconv(c_from, c_to, str));} + PIString decode(PIString & str) {return PIString(exec_iconv(c_to, c_from, str.toByteArray()));} + PIString decode(const PIByteArray & str) {return PIString(exec_iconv(c_to, c_from, str));} + +private: + PIByteArray exec_iconv(const PIString & from, const PIString & to, const PIByteArray & str); + + PIString c_from, c_to; + PIFile tf; + +}; + +#endif // PICODEC_H diff --git a/piconfig.cpp b/piconfig.cpp index 8983907d..965efed1 100644 --- a/piconfig.cpp +++ b/piconfig.cpp @@ -1,259 +1,474 @@ #include "piconfig.h" -PIConfig::PIConfig(const PIString & path, Flags mode): PIFile(path, mode) { +PIConfig::Entry PIConfig::Branch::_empty; +PIConfig::Entry PIConfig::Entry::_empty; + + +PIConfig::Branch PIConfig::Branch::allLeaves() { + Branch b; + b.delim = delim; + piForeachCA (i, *this) { + if (i->isLeaf()) b << i; + else allLeaves(b, i); + } + return b; +} + + +PIConfig::Entry & PIConfig::Branch::getValue(const PIString & vname, const PIString & def, bool * exist) { + if (vname.isEmpty()) { + _empty.clear(); + _empty.delim = delim; + if (exist != 0) *exist = false; + return _empty; + } + PIStringList tree = vname.split(delim); + PIString name = tree.front(); + tree.pop_front(); + Entry * ce = 0; + piForeachCA (i, *this) + if (i->_name == name) { + ce = i; + break; + } + if (ce == 0) { + _empty._name = vname; + _empty._value = def; + _empty.delim = delim; + if (exist != 0) *exist = false; + return _empty; + } + piForeachCA (i, tree) { + ce = ce->findChild(i); + if (ce == 0) { + _empty._name = vname; + _empty._value = def; + _empty.delim = delim; + if (exist != 0) *exist = false; + return _empty; + } + } + if (exist != 0) *exist = true; + return *ce; +} + + +PIConfig::Branch PIConfig::Branch::getValues(const PIString & name) { + Branch b; + b.delim = delim; + piForeachA (i, *this) { + if (i->isLeaf()) { + if (i->_name.find(name) >= 0) + b << i; + } else { + piForeachA (j, i->_children) + if (j->_name.find(name) >= 0) + b << j; + } + } + return b; +} + + +PIConfig::Branch PIConfig::Branch::getLeaves() { + Branch b; + b.delim = delim; + piForeachA (i, *this) + if (i->isLeaf()) + b << i; + return b; +} + + +PIConfig::Branch PIConfig::Branch::getBranches() { + Branch b; + b.delim = delim; + piForeachA (i, *this) + if (!i->isLeaf()) + b << i; + return b; +} + + +PIConfig::Branch & PIConfig::Branch::filter(const PIString & f) { + for (int i = 0; i < size_s(); ++i) { + if (at(i)->_name.find(f) < 0) { + remove(i); + --i; + } + } + return *this; +} + + +bool PIConfig::Branch::entryExists(const Entry * e, const PIString & name) const { + if (e->_children.isEmpty()) { + if (e->_name == name) return true; + else return false; + } + piForeachCA (i, e->_children) + if (entryExists(i, name)) return true; + return false; +} + + +PIConfig::Entry & PIConfig::Entry::getValue(const PIString & vname, const PIString & def, bool * exist) { + PIStringList tree = vname.split(delim); + Entry * ce = this; + piForeachCA (i, tree) { + ce = ce->findChild(i); + if (ce == 0) { + _empty._name = vname; + _empty._value = def; + _empty.delim = delim; + if (exist != 0) *exist = false; + return _empty; + } + } + if (exist != 0) *exist = true; + return *ce; +} + + +PIConfig::Branch PIConfig::Entry::getValues(const PIString & vname) { + Branch b; + b.delim = delim; + piForeachA (i, _children) + if (i->_name.find(vname) >= 0) + b << i; + return b; +}; + + +bool PIConfig::Entry::entryExists(const Entry * e, const PIString & name) const { + if (e->_children.isEmpty()) { + if (e->_name == name) return true; + else return false; + } + piForeachCA (i, e->_children) + if (entryExists(i, name)) return true; + return false; +} + + +PIConfig::PIConfig(const PIString & path, PIFlags mode): PIFile(path, mode) { + delim = "."; + root.delim = delim; + empty.delim = delim; + empty._parent = 0; if (!isOpened() && (mode[Write] || mode[New])) open(path, Read | Write | New); parse(); } -PIStringList PIConfig::getValue(const PIString & vname, const PIStringList & def, bool * exist) const { - return getValue(vname, def.join("%|%"), exist).split("%|%");} -bool PIConfig::getValue(const PIString & vname, const bool def, bool * exist) const { - return atob(getValue(vname, btos(def), exist));} -char PIConfig::getValue(const PIString & vname, const char def, bool * exist) const { - return getValue(vname, PIString(def), exist)[0];} -short PIConfig::getValue(const PIString & vname, const short def, bool * exist) const { - return getValue(vname, itos(def), exist).toShort();} -int PIConfig::getValue(const PIString & vname, const int def, bool * exist) const { - return getValue(vname, itos(def), exist).toInt();} -long PIConfig::getValue(const PIString & vname, const long def, bool * exist) const { - return getValue(vname, ltos(def), exist).toLong();} -uchar PIConfig::getValue(const PIString & vname, const uchar def, bool * exist) const { - return getValue(vname, uitos(def), exist).toInt();} -ushort PIConfig::getValue(const PIString & vname, const ushort def, bool * exist) const { - return getValue(vname, uitos(def), exist).toShort();} -uint PIConfig::getValue(const PIString & vname, const uint def, bool * exist) const { - return getValue(vname, uitos(def), exist).toInt();} -ulong PIConfig::getValue(const PIString & vname, const ulong def, bool * exist) const { - return getValue(vname, ultos(def), exist).toLong();} -float PIConfig::getValue(const PIString & vname, const float def, bool * exist) const { - return getValue(vname, ftos(def), exist).toFloat();} -double PIConfig::getValue(const PIString & vname, const double def, bool * exist) const { - return getValue(vname, dtos(def), exist).toDouble();} - - -void PIConfig::setValue(const PIString & name, const PIStringList & value, bool write) { - setValue(name, value.join("%|%"), "l", write);} -void PIConfig::setValue(const PIString & name, const char * value, bool write) { - setValue(name, PIString(value), "s", write);} -void PIConfig::setValue(const PIString & name, const bool value, bool write) { - setValue(name, btos(value), "b", write);} -void PIConfig::setValue(const PIString & name, const char value, bool write) { - setValue(name, PIString(1, value), "s", write);} -void PIConfig::setValue(const PIString & name, const short value, bool write) { - setValue(name, itos(value), "n", write);} -void PIConfig::setValue(const PIString & name, const int value, bool write) { - setValue(name, itos(value), "n", write);} -void PIConfig::setValue(const PIString & name, const long value, bool write) { - setValue(name, ltos(value), "n", write);} -void PIConfig::setValue(const PIString & name, const uchar value, bool write) { - setValue(name, uitos(value), "n", write);} -void PIConfig::setValue(const PIString & name, const ushort value, bool write) { - setValue(name, uitos(value), "n", write);} -void PIConfig::setValue(const PIString & name, const uint value, bool write) { - setValue(name, uitos(value), "n", write);} -void PIConfig::setValue(const PIString & name, const ulong value, bool write) { - setValue(name, ultos(value), "n", write);} -void PIConfig::setValue(const PIString & name, const float value, bool write) { - setValue(name, ftos(value), "f", write);} -void PIConfig::setValue(const PIString & name, const double value, bool write) { - setValue(name, dtos(value), "f", write);} - - -PIString PIConfig::getValue(const PIString & vname, const PIString & def, bool * exist) const { - for (uint i = 0; i < settname.size(); i++) { - if (settname[i] == vname) { - if (exist != 0) *exist = true; - return settval[i]; +PIConfig::Entry & PIConfig::getValue(const PIString & vname, const PIString & def, bool * exist) { + PIStringList tree = vname.split(delim); + Entry * ce = &root; + piForeachCA (i, tree) { + ce = ce->findChild(i); + if (ce == 0) { + if (exist != 0) *exist = false; + empty._name = vname; + empty._value = def; + empty.delim = delim; + return empty; } } - if (exist != 0) *exist = false; - return def; + if (exist != 0) *exist = true; + return *ce; +} + + +PIConfig::Branch PIConfig::getValues(const PIString & vname) { + Branch b; + b.delim = delim; + piForeachA (i, root._children) + if (i->_name.find(vname) >= 0) + b << i; + return b; +}; + + +void PIConfig::addEntry(const PIString & name, const PIString & value, const PIString & type, bool write) { + if (getValue(name)._parent != 0) + return; + bool toRoot = false; + PIStringList tree = name.split(delim); + PIString ename = tree.back(); + tree.pop_back(); + Entry * te, * ce, * entry = &root; + if (tree.isEmpty()) toRoot = true; + piForeachA (i, tree) { + te = entry->findChild(i); + if (te == 0) { + ce = new Entry(); + ce->delim = delim; + ce->_tab = entry->_tab; + ce->_line = entry->_line; + ce->_name = i; + ce->_parent = entry; + entry->_children << ce; + entry = ce; + } else entry = te; + } + PIConfig::Branch ch = entry->_children; + std::sort(ch.begin(), ch.end(), PIConfig::Entry::compare); + te = (entry->isLeaf() ? 0 : ch.back()); + ce = new Entry(); + ce->delim = delim; + ce->_name = ename; + ce->_value = value; + ce->_type = type; + if (te == 0) { + ce->_tab = entry->_tab; + if (toRoot) ce->_line = other.size_s() - 1; + else ce->_line = entry->_line; + } else { + ce->_tab = te->_tab; + if (toRoot) ce->_line = other.size_s() - 1; + else { + ch = entry->_parent->_children; + std::sort(ch.begin(), ch.end(), PIConfig::Entry::compare); + ce->_line = ch.back()->_line + 1; + } + } + ce->_parent = entry; + entry->_children << ce; + other.insert(ce->_line, ""); + Branch b = allLeaves(); + bool found = false; + for (int i = 0; i < b.size_s(); ++i) { + if (found) { + b[i]->_line++; + continue; + } + if (b[i] == ce) { + found = true; + if (i > 0) + if (b[i - 1]->_line == b[i]->_line) + b[i - 1]->_line++; + } + } + if (write) writeAll(); } void PIConfig::setValue(const PIString & name, const PIString & value, const PIString & type, bool write) { - int number = getNumber(name); - if (number == -1) { - addLine(name, value, type); + Entry & e(getValue(name)); + if (&e == &empty) { + addEntry(name, value, type); return; } - PIString tmp = settname[number] + " = " + value + " #" + setttype[number] + " " + settcom[number]; - settval[number] = value; - all[settlines[number]] = tmp; + e._value = value; + e._type = type; if (write) writeAll(); } -bool PIConfig::existsValue(const PIString & name) { - for (uint i = 0; i < settname.size(); i++) - if (settname[i] == name) return true; - return false; -} - - -void PIConfig::addLine(const PIString & name, const PIString & value, const PIString & type) { - if (setttab.size() > 0) *this << setttab[setttab.size() - 1] << name << " = " << value << " #" << type << "\n"; - else *this << name << " = " << value << " #" << type << "\n"; - settname.push_back(name); - settval.push_back(value); - settcom.push_back(""); - setttype.push_back(type); - if (setttab.size() > 0) setttab.push_back(setttab[setttab.size() - 1]); - else setttab.push_back("\t"); - settlines.push_back(all.size()); - all.push_back(name + " = " + value + " #" + type); - flush(); -} - - -void PIConfig::insertLine(uint number, const PIString & name, const PIString & value, const PIString & type) { - if (number >= settname.size()) { - addLine(name, value, type); - return; +int PIConfig::entryIndex(const PIString & name) { + PIStringList tree = name.split(delim); + Entry * ce = &root; + piForeachCA (i, tree) { + ce = ce->findChild(i); + if (ce == 0) + return -1; } - settname.insert(number, name); - settval.insert(number, value); - settcom.insert(number, ""); - setttab.insert(number, setttab[number]); - setttype.insert(number, type); - settlines.insert(number, settlines[number]); - for (uint i = number + 1; i < settlines.size(); i++) settlines[i]++; - all.insert(settlines[number], name + " = " + value + " #" + type); - flush(); - writeAll(); -} - - -int PIConfig::getNumber(const PIString & name) { - for (uint i = 0; i < settname.size(); i++) - if (settname[i] == name) - return i; - return -1; + Branch b = allLeaves(); + return allLeaves().indexOf(ce); } void PIConfig::setValue(uint number, const PIString & value, bool write) { - PIString tmp = settname[number] + " = " + value + " #" + setttype[number] + " " + settcom[number]; - settval[number] = value; - all[settlines[number]] = tmp; + Entry & e(entryByIndex(number)); + if (&e == &empty) return; + e._value = value; if (write) writeAll(); } -void PIConfig::setName(uint number, const PIString & name) { - PIString tmp = name + " = " + settval[number] + " #" + setttype[number] + " " + settcom[number]; - settname[number] = name; - all[settlines[number]] = tmp; - writeAll(); +void PIConfig::setName(uint number, const PIString & name, bool write) { + Entry & e(entryByIndex(number)); + if (&e == &empty) return; + e._name = name; + if (write) writeAll(); } -void PIConfig::setType(uint number, const PIString & type) { - PIString tmp = settname[number] + " = " + settval[number] + " #" + type + " " + settcom[number]; - setttype[number] = type; - all[settlines[number]] = tmp; - writeAll(); +void PIConfig::setType(uint number, const PIString & type, bool write) { + Entry & e(entryByIndex(number)); + if (&e == &empty) return; + e._type = type; + if (write) writeAll(); } -void PIConfig::setComment(uint number, const PIString & comment) { - PIString tmp = settname[number] + " = " + settval[number] + " #" + setttype[number] + " " + comment; - settcom[number] = comment; - all[settlines[number]] = tmp; - writeAll(); +void PIConfig::setComment(uint number, const PIString & comment, bool write) { + Entry & e(entryByIndex(number)); + if (&e == &empty) return; + e._comment = comment; + if (write) writeAll(); } -void PIConfig::deleteLine(const PIString & name) { - bool exist = false; - uint i; - for (i = 0; i < settname.size(); i++) { - if (settname[i] == name) { - exist = true; - break; - } +void PIConfig::removeEntry(const PIString & name, bool write) { + Entry & e(getValue(name)); + if (&e == &empty) return; + Branch b = allLeaves(); + removeEntry(b, &e); + if (write) writeAll(); +} + + +void PIConfig::removeEntry(uint number, bool write) { + Entry & e(entryByIndex(number)); + if (&e == &empty) return; + Branch b = allLeaves(); + removeEntry(b, &e); + if (write) writeAll(); +} + + +void PIConfig::removeEntry(Branch & b, PIConfig::Entry * e) { + bool leaf = true; + if (!e->isLeaf() && !e->_value.isEmpty()) { + e->_value.clear(); + leaf = false; + } else { + int cc = e->_children.size_s(); + piForTimes (cc) + removeEntry(b, e->_children.back()); } - if (!exist) return; - deleteLine(i); -} - - -void PIConfig::deleteLine(uint number) { - settname.erase(settname.begin() + number); - settval.erase(settval.begin() + number); - settcom.erase(settcom.begin() + number); - setttab.erase(setttab.begin() + number); - setttype.erase(setttype.begin() + number); - all.erase(all.begin() + settlines[number]); - for (uint i = number; i < settlines.size(); i++) settlines[i]--; - settlines.erase(settlines.begin() + number); - writeAll(); + bool found = false; + for (int i = 0; i < b.size_s(); ++i) { + if (found) { + b[i]->_line--; + continue; + } + if (b[i] == e) found = true; + } + if (!leaf) return; + e->_parent->_children.remove(e); + b.remove(e); + other.remove(e->_line); + delete e; } void PIConfig::writeAll() { clear(); - uint c = 0; - for (uint i = 0; i < all.size() - 1; i++) { - if (c < settlines.size() && c < setttab.size()) { - if (settlines[c] == i) { - *this << setttab[c]; - c++; + //writeEntry(&root); + buildFullNames(&root); + Branch b = allLeaves(); + int j = 0; + for (int i = 0; i < other.size_s(); ++i) { + //cout << j << endl; + if (j >= 0 && j < b.size_s()) { + if (b[j]->_line == i) { + b[j]->buildLine(); + *this << b[j]->_all << '\n'; + ++j; + } else { + *this << other[i]; + if (i < other.size_s() - 1) *this << '\n'; } + } else { + *this << other[i]; + if (i < other.size_s() - 1) *this << '\n'; } - *this << all[i] << "\n"; } + flush(); readAll(); } void PIConfig::readAll() { - settname.clear(); - settval.clear(); - settcom.clear(); - setttab.clear(); - settlines.clear(); - setttype.clear(); - all.clear(); + root.clear(); flush(); parse(); } +bool PIConfig::entryExists(const Entry * e, const PIString & name) const { + if (e->_children.isEmpty()) { + if (e->_name == name) return true; + else return false; + } + piForeachCA (i, e->_children) + if (entryExists(i, name)) return true; + return false; +} + + void PIConfig::parse() { - PIString str, tab, comm; + PIString src, str, tab, comm, all, name, type; + PIStringList tree; + Entry * entry, * te, * ce; int ind, sind; + bool isNew; if (!isOpened()) return; - seek(0); - lines = 0; + seekToBegin(); + other.clear(); + lines = centry = 0; while (!isEnd()) { - str = readLine(); + other.push_back(PIString()); + src = str = readLine(); //cout << str << endl; tab = str.left(str.find(str.trimmed().left(1))); str.trim(); - all.push_back(str); + all = str; ind = str.find('='); if ((ind > 0) && !(str[0] == '#')) { sind = str.find('#'); if (sind > 0) { - comm = str.right(str.size() - sind - 1).trimmed(); - if (comm.length() > 0) setttype.push_back(comm[0]); - else setttype.push_back("s"); - comm = comm.right(comm.size() - 1).trimmed(); - settcom.push_back(comm); + comm = str.right(str.length() - sind - 1).trimmed(); + if (comm.length() > 0) type = comm[0]; + else type = "s"; + comm = comm.right(comm.length() - 1).trimmed(); str = str.left(sind); } else { - setttype.push_back("s"); - settcom.push_back(""); + type = "s"; + comm = ""; } - settname.push_back(str.left(ind).trimmed()); - settval.push_back(str.right(str.size() - ind - 1).trimmed()); - setttab.push_back(tab); - settlines.push_back(lines); - } + //name = str.left(ind).trimmed(); + tree = str.left(ind).trimmed().split(delim); + name = tree.back(); + tree.pop_back(); + entry = &root; + piForeachA (i, tree) { + te = entry->findChild(i); + if (te == 0) { + ce = new Entry(); + ce->delim = delim; + ce->_tab = tab; + ce->_line = lines; + ce->_name = i; + ce->_parent = entry; + entry->_children << ce; + entry = ce; + } else entry = te; + } + isNew = false; + ce = entry->findChild(name); + if (ce == 0) { + ce = new Entry(); + isNew = true; + } + ce->delim = delim; + ce->_tab = tab; + ce->_name = name; + ce->_value = str.right(str.length() - ind - 1).trimmed(); + ce->_type = type; + ce->_comment = comm; + ce->_line = lines; + ce->_all = all; + if (isNew) { + ce->_parent = entry; + entry->_children << ce; + } + } else other.back() = src; lines++; } + setEntryDelim(&root, delim); } diff --git a/piconfig.h b/piconfig.h index 6e738895..8fb4505d 100644 --- a/piconfig.h +++ b/piconfig.h @@ -3,72 +3,205 @@ #include "pifile.h" +#define PICONFIG_GET_VALUE \ + inline Entry & getValue(const PIString & vname, const char * def, bool * exist = 0) {return getValue(vname, PIString(def), exist);} \ + inline Entry & getValue(const PIString & vname, const PIStringList & def, bool * exist = 0) {return getValue(vname, def.join("%|%"), exist);} \ + inline Entry & getValue(const PIString & vname, const bool def, bool * exist = 0) {return getValue(vname, PIString::fromBool(def), exist);} \ + inline Entry & getValue(const PIString & vname, const short def, bool * exist = 0) {return getValue(vname, itos(def), exist);} \ + inline Entry & getValue(const PIString & vname, const int def, bool * exist = 0) {return getValue(vname, itos(def), exist);} \ + inline Entry & getValue(const PIString & vname, const long def, bool * exist = 0) {return getValue(vname, ltos(def), exist);} \ + inline Entry & getValue(const PIString & vname, const uchar def, bool * exist = 0) {return getValue(vname, uitos(def), exist);} \ + inline Entry & getValue(const PIString & vname, const ushort def, bool * exist = 0) {return getValue(vname, uitos(def), exist);} \ + inline Entry & getValue(const PIString & vname, const uint def, bool * exist = 0) {return getValue(vname, uitos(def), exist);} \ + inline Entry & getValue(const PIString & vname, const ulong def, bool * exist = 0) {return getValue(vname, ultos(def), exist);} \ + inline Entry & getValue(const PIString & vname, const float def, bool * exist = 0) {return getValue(vname, ftos(def), exist);} \ + inline Entry & getValue(const PIString & vname, const double def, bool * exist = 0) {return getValue(vname, dtos(def), exist);} + class PIConfig: public PIFile { + friend class Entry; + friend class Branch; public: - PIConfig(const PIString & path, Flags mode = Read | Write); + PIConfig(const PIString & path, PIFlags mode = Read | Write); ~PIConfig() {;} + + class Entry; + + class Branch: public PIVector { + friend class PIConfig; + friend class Entry; + friend std::ostream & operator <<(std::ostream & s, const Branch & v); + public: + inline Branch() {;} + + Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0); + PICONFIG_GET_VALUE + + Branch allLeaves(); + Branch getValues(const PIString & name); + Branch getLeaves(); + Branch getBranches(); + Branch & filter(const PIString & f); + inline bool isEntryExists(const PIString & name) const {piForeachCA (i, *this) if (entryExists(i, name)) return true; return false;} + inline int indexOf(const Entry * e) {for (int i = 0; i < size_s(); ++i) if (at(i) == e) return i; return -1;} + + inline void clear() {piForeachA (i, *this) delete i; PIVector::clear();} + + private: + bool entryExists(const Entry * e, const PIString & name) const; + inline void allLeaves(Branch & b, Entry * e) {piForeachCA (i, e->_children) {if (i->isLeaf()) b << i; else allLeaves(b, i);}} + inline void coutt(std::ostream & s, const PIString & p) const {piForeachCA (i, *this) i->coutt(s, p);} + + static Entry _empty; + PIString delim; + + }; + + class Entry { + friend class PIConfig; + friend class Branch; + public: + inline Entry() {_parent = 0;} + + inline Entry * parent() const {return _parent;} + inline int childCount() {return _children.size_s();} + inline Branch & children() {_children.delim = delim; return _children;} + inline Entry * child(const int index) const {return _children[index];} + inline Entry * findChild(const PIString & name) {piForeachCA (i, _children) if (i->_name == name) return i; return 0;} + inline const Entry * findChild(const PIString & name) const {piForeachCA (i, _children) if (i->_name == name) return i; return 0;} + inline bool isLeaf() const {return _children.isEmpty();} + + inline const PIString & name() const {return _name;} + inline const PIString & value() const {return _value;} + inline const PIString & type() const {return _type;} + inline const PIString & comment() const {return _comment;} + + inline Entry & setName(const PIString & value) {_name = value; return *this;} + inline Entry & setType(const PIString & value) {_type = value; return *this;} + inline Entry & setComment(const PIString & value) {_comment = value; return *this;} + inline Entry & setValue(const PIString & value) {_value = value; return *this;} + inline Entry & setValue(const PIStringList & value) {setValue(value.join("%|%")); setType("l"); return *this;} + inline Entry & setValue(const char * value) {setValue(PIString(value)); setType("s"); return *this;} + inline Entry & setValue(const bool value) {setValue(btos(value)); setType("b"); return *this;} + inline Entry & setValue(const char value) {setValue(PIString(1, value)); setType("s"); return *this;} + inline Entry & setValue(const short value) {setValue(itos(value)); setType("n"); return *this;} + inline Entry & setValue(const int value) {setValue(itos(value)); setType("n"); return *this;} + inline Entry & setValue(const long value) {setValue(ltos(value)); setType("n"); return *this;} + inline Entry & setValue(const uchar value) {setValue(uitos(value)); setType("n"); return *this;} + inline Entry & setValue(const ushort value) {setValue(uitos(value)); setType("n"); return *this;} + inline Entry & setValue(const uint value) {setValue(uitos(value)); setType("n"); return *this;} + inline Entry & setValue(const ulong value) {setValue(ultos(value)); setType("n"); return *this;} + inline Entry & setValue(const float value) {setValue(ftos(value)); setType("f"); return *this;} + inline Entry & setValue(const double value) {setValue(dtos(value)); setType("f"); return *this;} + + Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0); + PICONFIG_GET_VALUE + + Branch getValues(const PIString & vname); + + inline bool isEntryExists(const PIString & name) const {return entryExists(this, name);} + + operator bool() {return _value.toBool();} + operator char() {return (_value.isEmpty() ? 0 : _value[0].toAscii());} + operator short() {return _value.toShort();} + operator int() {return _value.toInt();} + operator long() {return _value.toLong();} + operator uchar() {return _value.toInt();} + operator ushort() {return _value.toShort();} + operator uint() {return _value.toInt();} + operator ulong() {return _value.toLong();} + operator float() {return _value.toFloat();} + operator double() {return _value.toDouble();} + operator PIString() {return _value;} + operator PIStringList() {return _value.split("%|%");} + + private: + inline static bool compare(const PIConfig::Entry * f, const PIConfig::Entry * s) {return f->_line < s->_line;} + bool entryExists(const Entry * e, const PIString & name) const; + inline void buildLine() {_all = _tab + _full_name + " = " + _value + " #" + _type + " " + _comment;} + inline void clear() {_children.clear(); _name = _value = _type = _comment = _all = PIString(); _line = 0; _parent = 0;} + inline void coutt(std::ostream & s, const PIString & p) const {PIString nl = p + " "; if (!_value.isEmpty()) s << p << _name << " = " << _value << endl; else cout << p << _name << endl; piForeachCA (i, _children) i->coutt(s, nl);} + + static Entry _empty; + Entry * _parent; + Branch _children; + PIString _tab; + PIString _name; + PIString _value; + PIString _type; + PIString _comment; + PIString _all; + PIString _full_name; + PIString delim; + int _line; + }; - PIString getValue(const PIString & vname, const PIString & def = "", bool * exist = 0) const; - PIString getValue(const PIString & vname, const char * def = "", bool * exist = 0) const {return getValue(vname, PIString(def), exist);} - PIStringList getValue(const PIString & vname, const PIStringList & def = PIStringList(), bool * exist = 0) const; - bool getValue(const PIString & vname, const bool def = false, bool * exist = 0) const; - char getValue(const PIString & vname, const char def = 0, bool * exist = 0) const; - short getValue(const PIString & vname, const short def = 0, bool * exist = 0) const; - int getValue(const PIString & vname, const int def = 0, bool * exist = 0) const; - long getValue(const PIString & vname, const long def = 0, bool * exist = 0) const; - uchar getValue(const PIString & vname, const uchar def = 0, bool * exist = 0) const; - ushort getValue(const PIString & vname, const ushort def = 0, bool * exist = 0) const; - uint getValue(const PIString & vname, const uint def = 0, bool * exist = 0) const; - ulong getValue(const PIString & vname, const ulong def = 0, bool * exist = 0) const; - float getValue(const PIString & vname, const float def = 0., bool * exist = 0) const; - double getValue(const PIString & vname, const double def = 0., bool * exist = 0) const; + Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0); + PICONFIG_GET_VALUE + + Branch getValues(const PIString & vname); void setValue(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); - void setValue(const PIString & name, const PIStringList & value, bool write = true); - void setValue(const PIString & name, const char * value, bool write = true); - void setValue(const PIString & name, const bool value, bool write = true); - void setValue(const PIString & name, const char value, bool write = true); - void setValue(const PIString & name, const short value, bool write = true); - void setValue(const PIString & name, const int value, bool write = true); - void setValue(const PIString & name, const long value, bool write = true); - void setValue(const PIString & name, const uchar value, bool write = true); - void setValue(const PIString & name, const ushort value, bool write = true); - void setValue(const PIString & name, const uint value, bool write = true); - void setValue(const PIString & name, const ulong value, bool write = true); - void setValue(const PIString & name, const float value, bool write = true); - void setValue(const PIString & name, const double value, bool write = true); + inline void setValue(const PIString & name, const PIStringList & value, bool write = true) {setValue(name, value.join("%|%"), "l", write);} + inline void setValue(const PIString & name, const char * value, bool write = true) {setValue(name, PIString(value), "s", write);} + inline void setValue(const PIString & name, const bool value, bool write = true) {setValue(name, btos(value), "b", write);} + inline void setValue(const PIString & name, const short value, bool write = true) {setValue(name, itos(value), "n", write);} + inline void setValue(const PIString & name, const int value, bool write = true) {setValue(name, itos(value), "n", write);} + inline void setValue(const PIString & name, const long value, bool write = true) {setValue(name, ltos(value), "n", write);} + inline void setValue(const PIString & name, const uchar value, bool write = true) {setValue(name, uitos(value), "n", write);} + inline void setValue(const PIString & name, const ushort value, bool write = true) {setValue(name, uitos(value), "n", write);} + inline void setValue(const PIString & name, const uint value, bool write = true) {setValue(name, uitos(value), "n", write);} + inline void setValue(const PIString & name, const ulong value, bool write = true) {setValue(name, ultos(value), "n", write);} + inline void setValue(const PIString & name, const float value, bool write = true) {setValue(name, ftos(value), "f", write);} + inline void setValue(const PIString & name, const double value, bool write = true) {setValue(name, dtos(value), "f", write);} - PIString getValue(uint number) const {return settval[number];} - PIString getName(uint number) const {return settname[number];} - PIString getComment(uint number) const {return settcom[number];} + inline Entry & rootEntry() {return root;} + inline int entriesCount() const {return childCount(&root);} + inline bool isEntryExists(const PIString & name) const {return entryExists(&root, name);} + + inline Branch allTree() {Branch b; piForeachCA (i, root._children) b << i; return b;} + inline Branch allLeaves() {Branch b; allLeaves(b, &root); std::sort(b.begin(), b.end(), Entry::compare); return b;} + int entryIndex(const PIString & name); + + inline PIString getName(uint number) {return entryByIndex(number)._name;} + inline PIString getValue(uint number) {return entryByIndex(number)._value;} + inline PIChar getType(uint number) {return entryByIndex(number)._type[0];} + inline PIString getComment(uint number) {return entryByIndex(number)._comment;} + + void addEntry(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); + void setName(uint number, const PIString & name, bool write = true); void setValue(uint number, const PIString & value, bool write = true); - bool existsValue(const PIString & name); - char getType(uint number) const {return setttype[number][0];} - int getNumber(const PIString & name); - void setName(uint number, const PIString & name); - void setType(uint number, const PIString & type); - void setComment(uint number, const PIString & comment); - int numValues() const {return settval.size();} - void addLine(const PIString & name, const PIString & value, const PIString & type = "s"); - void insertLine(uint number, const PIString & name, const PIString & value, const PIString & type = "s"); - void deleteLine(const PIString & name); - void deleteLine(uint number); + void setType(uint number, const PIString & type, bool write = true); + void setComment(uint number, const PIString & comment, bool write = true); + + void removeEntry(const PIString & name, bool write = true); + void removeEntry(uint number, bool write = true); + void readAll(); void writeAll(); + const PIString & delimiter() const {return delim;} + void setDelimiter(const PIString & d) {delim = d; setEntryDelim(&root, d); readAll();} + private: + int childCount(const Entry * e) const {int c = 0; piForeachCA (i, e->_children) c += childCount(i); c += e->_children.size_s(); return c;} + bool entryExists(const Entry * e, const PIString & name) const; + void buildFullNames(Entry * e) {piForeachCA (i, e->_children) {if (e != &root) i->_full_name = e->_full_name + delim + i->_name; else i->_full_name = i->_name; buildFullNames(i);}} + void allLeaves(Branch & b, Entry * e) {piForeachCA (i, e->_children) {if ((!i->_value.isEmpty() && !i->isLeaf()) || i->isLeaf()) b << i; allLeaves(b, i);}} + void setEntryDelim(Entry * e, const PIString & d) {piForeachCA (i, e->_children) setEntryDelim(i, d); e->delim = d;} + inline Entry & entryByIndex(const int index) {Branch b = allLeaves(); if (index < 0 || index >= b.size_s()) return empty; return *(b[index]);} + void removeEntry(Branch & b, Entry * e); void parse(); - - PIVector settname; - PIVector settval; - PIVector settcom; - PIVector setttab; - PIVector setttype; - PIVector all; - PIVector settlines; + + int centry; + PIString delim; + Entry root, empty; uint lines; - + PIStringList other; + }; +inline std::ostream & operator <<(std::ostream & s, const PIConfig::Branch & v) {v.coutt(s, ""); return s;} +inline std::ostream & operator <<(std::ostream & s, const PIConfig::Entry & v) {s << v.value(); return s;} + #endif // PICONFIG_H diff --git a/piconsole.cpp b/piconsole.cpp index bd465e98..b8766dfb 100644 --- a/piconsole.cpp +++ b/piconsole.cpp @@ -6,7 +6,7 @@ PIConsole::PIConsole(bool startNow, KBFunc slot): PIThread() { needLockRun(true); ret_func = slot; num_format = 0; - cur_tab = width = height = my = 0; + cur_tab = width = height = pwidth = pheight = my = 0; #ifdef WINDOWS ulcoord.X = ulcoord.Y = 0; hOut = GetStdHandle(STD_OUTPUT_HANDLE); @@ -17,29 +17,25 @@ PIConsole::PIConsole(bool startNow, KBFunc slot): PIThread() { GetConsoleMode(hOut, &smode); GetConsoleCursorInfo(hOut, &curinfo); #endif - addTab(PIString("main")); + addTab("main"); listener = new PIKbdListener(key_event, this); - if (startNow) start(40); + if (startNow) start(); } PIConsole::~PIConsole() { - if (isRunning()) { + if (isRunning()) stop(); - waitForFinish(); - moveTo(0, my + 4); - showCursor(); - } - delete listener; clearTabs(false); #ifdef WINDOWS SetConsoleMode(hOut, smode); SetConsoleTextAttribute(hOut, dattr); #endif + delete listener; } -int PIConsole::addTab(PIString name, char bind_key) { +int PIConsole::addTab(const PIString & name, char bind_key) { tabs.push_back(Tab(name, bind_key)); cur_tab = tabs.size() - 1; return tabs.size(); @@ -53,7 +49,7 @@ void PIConsole::removeTab(uint index) { } -void PIConsole::removeTab(PIString name) { +void PIConsole::removeTab(const PIString & name) { uint index = tabs.size() + 1; for (uint i = 0; i < tabs.size(); ++i) { if (tabs[i].name == name) { @@ -66,7 +62,7 @@ void PIConsole::removeTab(PIString name) { bool PIConsole::setTab(uint index) { - if (index >= tabs.size() || index < 0) + if (index >= tabs.size()) return false; cur_tab = index; if (!isRunning()) return true; @@ -78,7 +74,7 @@ bool PIConsole::setTab(uint index) { } -bool PIConsole::setTab(PIString name) { +bool PIConsole::setTab(const PIString & name) { uint index = tabs.size() + 1; for (uint i = 0; i < tabs.size(); ++i) { if (tabs[i].name == name) { @@ -91,14 +87,14 @@ bool PIConsole::setTab(PIString name) { bool PIConsole::setTabBindKey(uint index, char bind_key) { - if (index < 0 || index >= tabs.size()) + if (index >= tabs.size()) return false; tabs[index].key = bind_key; return true; } -bool PIConsole::setTabBindKey(PIString name, char bind_key) { +bool PIConsole::setTabBindKey(const PIString & name, char bind_key) { uint index =tabs.size() + 1; for (uint i = 0; i < tabs.size(); ++i) { if (tabs[i].name == name) { @@ -122,15 +118,28 @@ void PIConsole::key_event(char key, void * t) { } -PIString PIConsole::fstr(Flags f) { +void PIConsole::stop(bool clear) { + PIThread::stop(true); + if (clear) clearScreen(); + moveTo(0, my + 4); + showCursor(); + couts(fstr(Normal).stdString()); +#ifdef WINDOWS + SetConsoleMode(hOut, smode); + SetConsoleTextAttribute(hOut, dattr); +#endif + fflush(0); +} + + +PIString PIConsole::fstr(PIFlags f) { if (f[PIConsole::Dec]) num_format = 0; if (f[PIConsole::Hex]) num_format = 1; - -if (f[PIConsole::Oct]) num_format = 2; + if (f[PIConsole::Oct]) num_format = 2; if (f[PIConsole::Scientific]) num_format = 3; #ifdef WINDOWS - WORD attr = dattr; + WORD attr = 0; if (f[PIConsole::Inverse]) { if (f[PIConsole::Red]) attr |= BACKGROUND_RED; @@ -140,7 +149,13 @@ if (f[PIConsole::Oct]) num_format = 2; if (f[PIConsole::Magenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE); if (f[PIConsole::Cyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE); if (f[PIConsole::White]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); - attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + if (f[PIConsole::BackRed]) attr |= FOREGROUND_RED; + if (f[PIConsole::BackGreen]) attr |= FOREGROUND_GREEN; + if (f[PIConsole::BackBlue]) attr |= FOREGROUND_BLUE; + if (f[PIConsole::BackYellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN); + if (f[PIConsole::BackMagenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE); + if (f[PIConsole::BackCyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE); + if (f[PIConsole::BackWhite]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } else { if (f[PIConsole::Red]) attr |= FOREGROUND_RED; if (f[PIConsole::Green]) attr |= FOREGROUND_GREEN; @@ -149,6 +164,13 @@ if (f[PIConsole::Oct]) num_format = 2; if (f[PIConsole::Magenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE); if (f[PIConsole::Cyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE); if (f[PIConsole::White]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + if (f[PIConsole::BackRed]) attr |= BACKGROUND_RED; + if (f[PIConsole::BackGreen]) attr |= BACKGROUND_GREEN; + if (f[PIConsole::BackBlue]) attr |= BACKGROUND_BLUE; + if (f[PIConsole::BackYellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN); + if (f[PIConsole::BackMagenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE); + if (f[PIConsole::BackCyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE); + if (f[PIConsole::BackWhite]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); } if (f[PIConsole::Bold]) attr |= FOREGROUND_INTENSITY; @@ -172,7 +194,16 @@ if (f[PIConsole::Oct]) num_format = 2; if (f[PIConsole::Magenta]) ts += ";35"; if (f[PIConsole::Cyan]) ts += ";36"; if (f[PIConsole::White]) ts += ";37"; - + + if (f[PIConsole::BackBlack]) ts += ";40"; + if (f[PIConsole::BackRed]) ts += ";41"; + if (f[PIConsole::BackGreen]) ts += ";42"; + if (f[PIConsole::BackYellow]) ts += ";43"; + if (f[PIConsole::BackBlue]) ts += ";44"; + if (f[PIConsole::BackMagenta]) ts += ";45"; + if (f[PIConsole::BackCyan]) ts += ";46"; + if (f[PIConsole::BackWhite]) ts += ";47"; + return ts + "m"; #endif } @@ -181,6 +212,7 @@ if (f[PIConsole::Oct]) num_format = 2; #define iprint(x) switch (num_format) {case (1): return printf("0x%.8X", x); break; case (2): return printf("%o", x); break; default: return printf("%d", x); break;} #define liprint(x) switch (num_format) {case (1): return printf("0x%.16lX", x); break; case (2): return printf("%lo", x); break; default: return printf("%ld", x); break;} #define lliprint(x) switch (num_format) {case (1): return printf("0x%.16LX", x); break; case (2): return printf("%Lo", x); break; default: return printf("%Ld", x); break;} +#define cuprint(x) switch (num_format) {case (1): return printf("0x%.2X", x); break; case (2): return printf("%o", x); break; default: return printf("%u", x); break;} #define suprint(x) switch (num_format) {case (1): return printf("0x%.4hX", x); break; case (2): return printf("%o", x); break; default: return printf("%hd", x); break;} #define uprint(x) switch (num_format) {case (1): return printf("0x%.8X", x); break; case (2): return printf("%o", x); break; default: return printf("%u", x); break;} #define luprint(x) switch (num_format) {case (1): return printf("0x%.16lX", x); break; case (2): return printf("%lo", x); break; default: return printf("%lu", x); break;} @@ -196,7 +228,7 @@ inline int PIConsole::couts(const short v) {siprint(v);} inline int PIConsole::couts(const int v) {iprint(v);} inline int PIConsole::couts(const long v) {liprint(v);} inline int PIConsole::couts(const llong v) {lliprint(v);} -inline int PIConsole::couts(const uchar v) {uprint(v);} +inline int PIConsole::couts(const uchar v) {cuprint(v);} inline int PIConsole::couts(const ushort v) {suprint(v);} inline int PIConsole::couts(const uint v) {uprint(v);} inline int PIConsole::couts(const ulong v) {luprint(v);} @@ -217,7 +249,6 @@ void PIConsole::begin() { void PIConsole::run() { uint cx, clen = 0; - string ts; #ifdef WINDOWS GetConsoleScreenBufferInfo(hOut, &sbi); width = sbi.srWindow.Right - sbi.srWindow.Left; @@ -228,19 +259,20 @@ void PIConsole::run() { width = ws.ws_col; height = ws.ws_row; #endif + if (pwidth != width || pheight != height) { + clearScreen(); + fillLabels(); + } + pwidth = width; + pheight = height; col_cnt = vars().size(); col_wid = (col_cnt > 0) ? width / col_cnt : width; for (uint i = 0; i < col_cnt; ++i) { cx = col_wid * i; toUpperLeft(); - for (uint j = 0; j < vars()[i].size(); ++j) { - if (my < j) my = j; - tv = vars()[i][j]; + if (my < vars()[i].size()) my = vars()[i].size(); + piForeachCA (tv, vars()[i]) { moveRight(cx); - if (tv.name.size() == 0) { - newLine(); - continue; - } if (tv.type == 0 && tv.s == 0) { newLine(); continue; @@ -261,10 +293,10 @@ void PIConsole::run() { case 11: clen = printValue(*tv.uc, tv.format); break; case 12: clen = printValue(*tv.ll, tv.format); break; case 13: clen = printValue(*tv.ull, tv.format); break; - case 14: clen = printValue(bitsValue(tv.uc, tv.bitFrom, tv.bitCount), tv.format); break; + case 14: clen = printValue(bitsValue(tv.ptr, tv.bitFrom, tv.bitCount), tv.format); break; } if (clen + tv.offset < (uint)col_wid) { - ts = PIString(col_wid - clen - tv.offset, ' ').stdString(); + string ts = PIString(col_wid - clen - tv.offset, ' ').stdString(); printf("%s", ts.c_str()); } newLine(); @@ -275,7 +307,7 @@ void PIConsole::run() { void PIConsole::fillLabels() { - uint cx, my = 0; + uint cx, cy, my = 0; #ifdef WINDOWS GetConsoleScreenBufferInfo(hOut, &sbi); width = sbi.srWindow.Right - sbi.srWindow.Left; @@ -290,27 +322,43 @@ void PIConsole::fillLabels() { col_wid = (col_cnt > 0) ? width / col_cnt : width; for (uint i = 0; i < col_cnt; ++i) { cx = col_wid * i; + cy = 1; toUpperLeft(); for (uint j = 0; j < vars()[i].size(); ++j) { if (my < j) my = j; moveRight(cx); tv = vars()[i][j]; + vars()[i][j].nx = cx; + vars()[i][j].ny = cy; if (tv.name.size() == 0) { + vars()[i][j].offset = 0; + clearLine(); newLine(); + cy++; continue; } clearLine(); if (tv.type == 0 && tv.s == 0) { + vars()[i][j].offset = vars()[i][j].name.length(); + vars()[i][j].nx += vars()[i][j].offset; printLine(tv.name, cx, tv.format); newLine(); + cy++; continue; } - vars()[i][j].offset = printValue(tv.name + ": ", tv.format); + vars()[i][j].offset = (tv.name + ": ").length(); + vars()[i][j].nx += vars()[i][j].offset; + printValue(tv.name + ": ", tv.format); newLine(); + cy++; } } +#ifdef WINDOWS + moveTo(0, my + 1); +#else moveTo(0, my + 2); - if (tabs[cur_tab].status.length() > 0) { +#endif + if (!tabs[cur_tab].status.isEmpty()) { printValue(tabs[cur_tab].status); newLine(); } @@ -325,24 +373,24 @@ void PIConsole::status() { for (uint i = 0; i < tabsCount(); ++i) { ctab = &tabs[i]; if (ctab->key == 0) continue; - printValue(ctab->key, PIConsole::Bold); + printValue(ctab->key, PIConsole::White | PIConsole::Bold); printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse); - printValue(PIString(" "), PIConsole::Normal); + printValue(" "); } newLine(); } -int PIConsole::bitsValue(unsigned char * src, int offset, int count) { +int PIConsole::bitsValue(void * src, int offset, int count) { int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8; - char cbyte = src[stbyte]; + char cbyte = reinterpret_cast(src)[stbyte]; for (int i = 0; i < count; i++) { ret |= ((cbyte >> cbit & 1) << i); cbit++; if (cbit == 8) { cbit = 0; stbyte++; - cbyte = src[stbyte]; + cbyte = reinterpret_cast(src)[stbyte]; } } return ret; @@ -350,77 +398,109 @@ int PIConsole::bitsValue(unsigned char * src, int offset, int count) { #define ADD_VAR_BODY tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; checkColumn(column); -void PIConsole::addString(PIString name, int column, Flags format) { +void PIConsole::addString(const PIString & name, int column, PIFlags format) { ADD_VAR_BODY tv.type = 0; tv.s = 0; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, PIString* ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, PIString* ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 0; tv.s = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, bool * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, bool * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 1; tv.b = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, int * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, int * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 2; tv.i = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, long * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, long * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 3; tv.l = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, char * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, char * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 4; tv.c = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, float * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, float * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 5; tv.f = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, double * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, double * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 6; tv.d = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, short * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, short * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 7; tv.sh = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, uint * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, uint * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 8; tv.ui = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, ulong * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, ulong * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 9; tv.ul = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, ushort * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, ushort * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 10; tv.ush = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, uchar * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, uchar * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 11; tv.uc = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, llong * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, llong * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 12; tv.ll = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addVariable(PIString name, ullong * ptr, int column, Flags format) { +void PIConsole::addVariable(const PIString & name, ullong * ptr, int column, PIFlags format) { ADD_VAR_BODY tv.type = 13; tv.ull = ptr; vars()[column - 1].push_back(tv);} -void PIConsole::addBitVariable(PIString name, uchar * ptr, int fromBit, int bitCount, int column, Flags format) { - tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.uc = ptr; tv.format = format; +void PIConsole::addBitVariable(const PIString & name, void * ptr, int fromBit, int bitCount, int column, PIFlags format) { + tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = format; checkColumn(column); vars()[column - 1].push_back(tv);} -void PIConsole::addEmptyLine(int column) { +void PIConsole::addEmptyLine(int column, uint count) { tv.name = ""; tv.type = 0; tv.d = 0; tv.format = Normal; - checkColumn(column); vars()[column - 1].push_back(tv);} + for (uint i = 0; i < count; ++i) { + checkColumn(column); + vars()[column - 1].push_back(tv); + } +} -#define PRINT_VAR_BODY couts(fstr(format).stdString()); int ret = couts(value); fstr(PIConsole::Dec); return ret; -inline void PIConsole::printLine(const PIString & value, int dx, Flags format) { +PIString PIConsole::getString(int x, int y) { + bool run = isRunning(); + if (run) PIThread::stop(true); + listener->terminate(); + msleep(10); + listener->setActive(false); + moveTo(x, y); + showCursor(); + PIByteArray ba(4096); + fflush(0); + scanf("%s", ba.data()); + //fflush(0); + listener->start(); + msleep(10); + if (run) start(); + msleep(10); + listener->setActive(true); + return PIString(ba); +} + + +PIString PIConsole::getString(const PIString & name) { + piForeachCA (i, tabs[cur_tab].variables) + piForeachCA (j, i) + if (j.name == name) + return getString(j.nx + 1, j.ny); + return PIString(); +} + + +#define PRINT_VAR_BODY couts(fstr(format).stdString()); int ret = couts(value); couts(fstr(PIConsole::Dec).stdString()); return ret; + +inline void PIConsole::printLine(const PIString & value, int dx, PIFlags format) { int i = width - value.length() - dx; #ifdef QNX --i; #endif - string ts = fstr(format).stdString(); - couts(ts); - if (i >= 0) ts = (value + PIString(i, ' ')).stdString(); - else ts = value.left(value.size() + i).stdString(); - couts(ts); - ts = fstr(Dec).stdString(); - couts(ts); + PIString ts = fstr(format); + couts(ts.stdString()); + if (i >= 0) ts = value + PIString(i, ' '); + else ts = value.left(value.size() + i); + couts(ts.stdString()); + couts(fstr(Dec).stdString()); } -inline int PIConsole::printValue(const PIString & value, Flags format) { - string ts = fstr(format).stdString(); - couts(ts); - ts = value.stdString(); - int ret = couts(ts); +inline int PIConsole::printValue(const PIString & value, PIFlags format) { + couts(fstr(format).stdString()); + int ret = couts(value.stdString()); fstr(PIConsole::Dec); return ret; } -inline int PIConsole::printValue(const char * value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const bool value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const int value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const long value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const llong value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const float value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const double value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const char value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const short value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const uchar value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const ushort value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const uint value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const ulong value, Flags format) {PRINT_VAR_BODY} -inline int PIConsole::printValue(const ullong value, Flags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const char * value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const bool value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const int value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const long value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const llong value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const float value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const double value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const char value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const short value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const uchar value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const ushort value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const uint value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const ulong value, PIFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const ullong value, PIFlags format) {PRINT_VAR_BODY} diff --git a/piconsole.h b/piconsole.h index ace72614..18b2b4d0 100644 --- a/piconsole.h +++ b/piconsole.h @@ -29,42 +29,73 @@ public: Magenta = 0x2000, Cyan = 0x4000, White = 0x8000, - Dec = 0x10000, - Hex = 0x20000, - Oct = 0x40000, - Scientific = 0x80000}; + BackBlack = 0x10000, + BackRed = 0x20000, + BackGreen = 0x40000, + BackYellow = 0x80000, + BackBlue = 0x100000, + BackMagenta = 0x200000, + BackCyan = 0x400000, + BackWhite = 0x800000, + Dec = 0x1000000, + Hex = 0x2000000, + Oct = 0x4000000, + Scientific = 0x8000000}; - void addString(PIString name, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, PIString * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, char * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, bool * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, short * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, int * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, long * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, llong * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, uchar * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, ushort * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, uint * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, ulong * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, ullong * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, float * ptr, int column = 1, Flags format = PIConsole::Normal); - void addVariable(PIString name, double * ptr, int column = 1, Flags format = PIConsole::Normal); - void addBitVariable(PIString name, uchar * ptr, int fromBit, int bitCount, int column = 1, Flags format = PIConsole::Normal); - void addEmptyLine(int column = 1); - int addTab(PIString name, char bind_key = 0); - void removeTab(uint index); - void removeTab(PIString name); + void addString(const PIString & name, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, PIString * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, char * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, bool * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, short * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, int * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, long * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, llong * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, uchar * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, ushort * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, uint * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, ulong * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, ullong * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, float * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, double * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addBitVariable(const PIString & name, void * ptr, int fromBit, int bitCount, int column = 1, PIFlags format = PIConsole::Normal); + void addEmptyLine(int column = 1, uint count = 1); + + PIString getString(int x, int y); + short getShort(int x, int y) {return getString(x, y).toShort();} + int getInt(int x, int y) {return getString(x, y).toInt();} + float getFloat(int x, int y) {return getString(x, y).toFloat();} + double getDouble(int x, int y) {return getString(x, y).toDouble();} + PIString getString(const PIString & name); + short getShort(const PIString & name) {return getString(name).toShort();} + int getInt(const PIString & name) {return getString(name).toInt();} + float getFloat(const PIString & name) {return getString(name).toFloat();} + double getDouble(const PIString & name) {return getString(name).toDouble();} + uint tabsCount() const {return tabs.size();} - bool setTab(uint index); - bool setTab(PIString name); - bool setTabBindKey(uint index, char bind_key); - bool setTabBindKey(PIString name, char bind_key); - void addCustomStatus(PIString str) {tabs[cur_tab].status = str;} - void clearCustomStatus() {tabs[cur_tab].status = "";} - void clearVariables(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} vars().clear();} - void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();} - PIString fstr(Flags f); PIString currentTab() const {return tabs[cur_tab].name;} + int addTab(const PIString & name, char bind_key = 0); + void removeTab(uint index); + void removeTab(const PIString & name); + bool setTab(uint index); + bool setTab(const PIString & name); + bool setTabBindKey(uint index, char bind_key); + bool setTabBindKey(const PIString & name, char bind_key); + void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();} + + void addCustomStatus(const PIString & str) {tabs[cur_tab].status = str;} + void clearCustomStatus() {tabs[cur_tab].status.clear();} + + void clearVariables(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} vars().clear();} + + inline void waitForFinish() {WAIT_FOR_EXIT} + inline void start() {PIThread::start(40);} + void stop(bool clear = false); + PIString fstr(PIFlags f); + + inline void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);} + inline void disableExitCapture() {listener->disableExitCapture();} + inline bool exitCaptured() const {return listener->exitCaptured();} + inline char exitKey() const {return listener->exitKey();} private: void begin(); @@ -101,28 +132,30 @@ private: #endif void status(); void checkColumn(uint col) {if (vars().size() < col) {vars().resize(col);}} - int bitsValue(unsigned char * src, int offset, int count); - inline void printLine(const PIString & str, int dx = 0, Flags format = PIConsole::Normal); - inline int printValue(const PIString & str, Flags format = PIConsole::Normal); - inline int printValue(const char * str, Flags format = PIConsole::Normal); - inline int printValue(const bool value, Flags format = PIConsole::Normal); - inline int printValue(const int value, Flags format = PIConsole::Normal); - inline int printValue(const long value, Flags format = PIConsole::Normal); - inline int printValue(const llong value, Flags format = PIConsole::Normal); - inline int printValue(const float value, Flags format = PIConsole::Normal); - inline int printValue(const double value, Flags format = PIConsole::Normal); - inline int printValue(const char value, Flags format = PIConsole::Normal); - inline int printValue(const short value, Flags format = PIConsole::Normal); - inline int printValue(const uchar value, Flags format = PIConsole::Normal); - inline int printValue(const ushort value, Flags format = PIConsole::Normal); - inline int printValue(const uint value, Flags format = PIConsole::Normal); - inline int printValue(const ulong value, Flags format = PIConsole::Normal); - inline int printValue(const ullong value, Flags format = PIConsole::Normal); + int bitsValue(void * src, int offset, int count); + inline void printLine(const PIString & str, int dx = 0, PIFlags format = PIConsole::Normal); + inline int printValue(const PIString & str, PIFlags format = PIConsole::Normal); + inline int printValue(const char * str, PIFlags format = PIConsole::Normal); + inline int printValue(const bool value, PIFlags format = PIConsole::Normal); + inline int printValue(const int value, PIFlags format = PIConsole::Normal); + inline int printValue(const long value, PIFlags format = PIConsole::Normal); + inline int printValue(const llong value, PIFlags format = PIConsole::Normal); + inline int printValue(const float value, PIFlags format = PIConsole::Normal); + inline int printValue(const double value, PIFlags format = PIConsole::Normal); + inline int printValue(const char value, PIFlags format = PIConsole::Normal); + inline int printValue(const short value, PIFlags format = PIConsole::Normal); + inline int printValue(const uchar value, PIFlags format = PIConsole::Normal); + inline int printValue(const ushort value, PIFlags format = PIConsole::Normal); + inline int printValue(const uint value, PIFlags format = PIConsole::Normal); + inline int printValue(const ulong value, PIFlags format = PIConsole::Normal); + inline int printValue(const ullong value, PIFlags format = PIConsole::Normal); static void key_event(char key, void * t); struct Variable { PIString name; - Flags format; + PIFlags format; + int nx; + int ny; int type; int offset; int bitFrom; @@ -142,13 +175,14 @@ private: uint * ui; ulong * ul; ullong * ull; + void * ptr; }; void operator =(const Variable & src) {name = src.name; format = src.format; type = src.type; offset = src.offset; - bitFrom = src.bitFrom; bitCount = src.bitCount; c = src.c;} + bitFrom = src.bitFrom; bitCount = src.bitCount; c = src.c; nx = src.nx; ny = src.ny;} }; struct Tab { - vector > variables; + PIVector > variables; PIString name; PIString status; char key; @@ -156,7 +190,7 @@ private: Tab(PIString n, char k) {name = n; key = k;} }; - inline vector > & vars() {return tabs[cur_tab].variables;} + inline PIVector > & vars() {return tabs[cur_tab].variables;} inline int couts(const string v); inline int couts(const char * v); inline int couts(const bool v); @@ -183,11 +217,11 @@ private: #else struct termios sterm, vterm; #endif - vector tabs; + PIVector tabs; Variable tv; PIKbdListener * listener; KBFunc ret_func; - int width, height, ret, col_wid, num_format; + int width, height, pwidth, pheight, ret, col_wid, num_format; uint my; uint cur_tab, col_cnt; diff --git a/picontainers.h b/picontainers.h new file mode 100644 index 00000000..35aa65fd --- /dev/null +++ b/picontainers.h @@ -0,0 +1,226 @@ +#ifndef PICONTAINERS_H +#define PICONTAINERS_H + +#include "piincludes.h" + +template +class _PIForeachC { +public: + _PIForeachC(const Type & t, bool i = false): _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin(); _break = false;} + typename Type::value_type _var; + typename Type::const_iterator _it; + typename Type::const_reverse_iterator _rit; + const Type & _t; + bool _break, _inv; + inline bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();} + inline void operator ++() {if (_inv) _rit++; else _it++; _break = false;} +}; + +template +class _PIForeach { +public: + _PIForeach(Type & t, bool i = false): _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin(); _break = false;} + typename Type::value_type _var; + typename Type::iterator _it; + typename Type::reverse_iterator _rit; + Type & _t; + bool _break, _inv; + inline bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();} + inline void operator ++() {if (_inv) _rit++; else _it++; _break = false;} +}; + +#define piForTimes(c) for(int i = 0; i < c; ++i) + +#define piForeach(i,c) for(_PIForeach _for(c); !_for.isEnd(); ++_for) for(i = *_for._it; !_for._break; _for._break = true) +#define piForeachR(i,c) for(_PIForeach _for(c, true); !_for.isEnd(); ++_for) for(i = *_for._rit; !_for._break; _for._break = true) +#define piForeachA(i,c) for(_PIForeach _for(c); !_for.isEnd(); ++_for) for(typeof(_for._var) & i(*_for._it); !_for._break; _for._break = true) +#define piForeachAR(i,c) for(_PIForeach _for(c, true); !_for.isEnd(); ++_for) for(typeof(_for._var) & i(*_for._rit); !_for._break; _for._break = true) +#define piForeachC(i,c) for(_PIForeachC _for(c); !_for.isEnd(); ++_for) for(const i = *_for._it; !_for._break; _for._break = true) +#define piForeachCR(i,c) for(_PIForeachC _for(c, true); !_for.isEnd(); ++_for) for(const i = *_for._rit; !_for._break; _for._break = true) +#define piForeachCA(i,c) for(_PIForeachC _for(c); !_for.isEnd(); ++_for) for(const typeof(_for._var) & i(*_for._it); !_for._break; _for._break = true) +#define piForeachCAR(i,c) for(_PIForeachC _for(c, true); !_for.isEnd(); ++_for) for(const typeof(_for._var) & i(*_for._rit); !_for._break; _for._break = true) + +#define piForeachRA piForeachAR +#define piForeachRC piForeachCR +#define piForeachAC piForeachCA +#define piForeachCRA piForeachCAR +#define piForeachARC piForeachCAR +#define piForeachACR piForeachCAR +#define piForeachRCA piForeachCAR +#define piForeachRAC piForeachCAR + +template +class PIFlags { +public: + inline PIFlags(): flags(0) {;} + inline PIFlags(Enum e): flags(e) {;} + inline PIFlags(const PIFlags & f): flags(f.flags) {;} + inline PIFlags(const int i): flags(i) {;} + inline void operator =(const PIFlags & f) {flags = f.flags;} + inline void operator =(const Enum & e) {flags = e;} + inline void operator =(const int & i) {flags = i;} + inline void operator |=(const PIFlags & f) {flags = flags | f.flags;} + inline void operator |=(const Enum & e) {flags = flags | e;} + inline void operator |=(const int i) {flags = flags | i;} + inline void operator &=(const PIFlags & f) {flags = flags & f.flags;} + inline void operator &=(const Enum & e) {flags = flags & e;} + inline void operator &=(const int i) {flags = flags & i;} + inline PIFlags & operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;} + inline PIFlags & operator |(Enum e) const {PIFlags tf(flags | e); return tf;} + inline PIFlags & operator |(int i) const {PIFlags tf(flags | i); return tf;} + inline PIFlags & operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;} + inline PIFlags & operator &(Enum e) const {PIFlags tf(flags & e); return tf;} + inline PIFlags & operator &(int i) const {PIFlags tf(flags & i); return tf;} + inline bool operator [](Enum e) {return (flags & e) == e;} + inline operator int() const {return flags;} +private: + int flags; +}; + +template > +class PIVector: public vector { + typedef PIVector _CVector; + typedef vector _stlc; +public: + inline PIVector() {;} + inline PIVector(const Type & value) {_stlc::push_back(value);} + inline PIVector(const Type & v0, const Type & v1) {_stlc::push_back(v0); _stlc::push_back(v1);} + inline PIVector(const Type & v0, const Type & v1, const Type & v2) {_stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);} + inline PIVector(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {_stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);} + inline PIVector(uint size, const Type & value = Type()) {_stlc::resize(size, value);} + inline const Type & at(uint index) const {return (*this)[index];} + inline Type & at(uint index) {return (*this)[index];} + inline const Type * data(uint index = 0) const {return &(*this)[index];} + inline Type * data(uint index = 0) {return &(*this)[index];} + inline int size_s() const {return static_cast(_stlc::size());} + inline bool isEmpty() const {return _stlc::empty();} + inline _CVector & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;} + inline _CVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;} + inline _CVector & push_front(const Type & t) {_stlc::insert(_stlc::begin(), t); return *this;} + inline _CVector & remove(uint num) {_stlc::erase(_stlc::begin() + num); return *this;} + inline _CVector & remove(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + count); return *this;} + inline _CVector & remove(const Type & t) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) {_stlc::erase(i); --i;} return *this;} + inline _CVector & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;} + inline _CVector & operator <<(const Type & t) {_stlc::push_back(t); return *this;} + inline bool contain(const Type & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;} +}; + +template +inline std::ostream & operator <<(std::ostream & s, const PIVector & v) {s << "{"; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;} + +template > +class PIList: public list { + typedef PIList _CList; + typedef list _stlc; +public: + inline PIList() {;} + inline PIList(const Type & value) {_stlc::resize(1, value);} + inline PIList(const Type & v0, const Type & v1) {_stlc::push_back(v0); _stlc::push_back(v1);} + inline PIList(const Type & v0, const Type & v1, const Type & v2) {_stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);} + inline PIList(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {_stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);} + inline PIList(uint size, const Type & value = Type()) {_stlc::resize(size, value);} + inline const Type * data(uint index = 0) const {return &(*this)[index];} + inline Type * data(uint index = 0) {return &(*this)[index];} + inline int size_s() const {return static_cast(_stlc::size());} + inline bool isEmpty() const {return _stlc::empty();} + inline _CList & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;} + inline _CList & remove(uint num) {_stlc::erase(_stlc::begin() + num); return *this;} + inline _CList & remove(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + count); return *this;} + inline _CList & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;} + inline _CList & operator <<(const Type & t) {_stlc::push_back(t); return *this;} + inline PIVector toVector() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} +}; + +template, typename Allocator = std::allocator > +class PISet: public set { + typedef PISet _CSet; + typedef set _stlc; +public: + inline PISet() {;} + inline PISet(const Type & value) {_stlc::resize(1, value);} + inline PISet(const Type & v0, const Type & v1) {_stlc::insert(v0); _stlc::insert(v1);} + inline PISet(const Type & v0, const Type & v1, const Type & v2) {_stlc::insert(v0); _stlc::insert(v1); _stlc::insert(v2);} + inline PISet(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {_stlc::insert(v0); _stlc::insert(v1); _stlc::insert(v2); _stlc::insert(v3);} + inline int size_s() const {return static_cast(_stlc::size());} + inline bool isEmpty() const {return _stlc::empty();} + inline _CSet & remove(uint num) {_stlc::erase(_stlc::begin() + num); return *this;} + inline _CSet & remove(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + count); return *this;} + inline _CSet & operator <<(const Type & t) {_stlc::insert(t); return *this;} + inline bool operator [](const Type & t) {return _stlc::find(t);} + inline PIVector toVector() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} +}; + +template +class PIStack: public PIVector { + typedef PIStack _CStack; +public: + inline PIStack() {;} + inline PIStack(const Type & value) {_CStack::resize(1, value);} + inline PIStack(const Type & v0, const Type & v1) {_CStack::push_back(v0); _CStack::push_back(v1);} + inline PIStack(const Type & v0, const Type & v1, const Type & v2) {_CStack::push_back(v0); _CStack::push_back(v1); _CStack::push_back(v2);} + inline PIStack(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {_CStack::push_back(v0); _CStack::push_back(v1); _CStack::push_back(v2); _CStack::push_back(v3);} + inline _CStack & push(const Type & v) {_CStack::push_back(v); return *this;} + inline Type pop() {Type t = Type(); if (_CStack::size() == 0) return t; t = _CStack::back(); _CStack::pop_back(); return t;} + inline Type & top() {return _CStack::back();} + inline const Type & top() const {return _CStack::back();} + inline PIVector toVector() {PIVector v; for (typename _CStack::const_iterator i = _CStack::begin(); i != _CStack::end(); ++i) v << *i; return v;} +}; + +template > +class PIDeque: public deque { + typedef PIDeque _CDeque; + typedef deque _stlc; +public: + inline PIDeque() {;} + inline PIDeque(const Type & value) {_stlc::resize(1, value);} + inline PIDeque(const Type & v0, const Type & v1) {_stlc::push_back(v0); _stlc::push_back(v1);} + inline PIDeque(const Type & v0, const Type & v1, const Type & v2) {_stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);} + inline PIDeque(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {_stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);} + inline int size_s() const {return static_cast(_stlc::size());} + inline bool isEmpty() const {return _stlc::empty();} + inline _CDeque & operator <<(const Type & t) {_CDeque::push_back(t); return *this;} + inline PIVector toVector() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} +}; + +template +class PIQueue: public PIDeque { + typedef PIQueue _CQueue; +public: + inline PIQueue() {;} + inline PIQueue(const Type & value) {_CQueue::resize(1, value);} + inline PIQueue(const Type & v0, const Type & v1) {_CQueue::push_front(v0); _CQueue::push_front(v1);} + inline PIQueue(const Type & v0, const Type & v1, const Type & v2) {_CQueue::push_front(v0); _CQueue::push_front(v1); _CQueue::push_front(v2);} + inline PIQueue(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {_CQueue::push_front(v0); _CQueue::push_front(v1); _CQueue::push_front(v2); _CQueue::push_front(v3);} + inline _CQueue & enqueue(const Type & v) {_CQueue::push_front(v); return *this;} + inline Type dequeue() {Type t = Type(); if (_CQueue::size() == 0) return t; t = _CQueue::back(); _CQueue::pop_back(); return t;} + inline Type & head() {return _CQueue::back();} + inline const Type & head() const {return _CQueue::back();} + inline PIVector toVector() {PIVector v; for (typename _CQueue::const_iterator i = _CQueue::begin(); i != _CQueue::end(); ++i) v << *i; return v;} +}; + + +template +class PIPair { +public: + inline PIPair() {first = Type0(); second = Type1();} + inline PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;} + Type0 first; + Type1 second; +}; +template +inline bool operator <(const PIPair & value0, const PIPair & value1) {return value0.first < value1.first;} + + +template +class PIHash: public PISet > { + typedef PIHash _CHash; + typedef PISet > _CSet; +public: + inline PIHash() {;} + inline PIHash(const Type & value, const Key & key) {insert(value, key);} + inline _CHash & insert(const Type & value, const Key & key) {_CSet::insert(PIPair(key, value));} + inline Type value(Key key) {piForeachCA (i, *this) if (i.first == key) return i.second;; return Key();} + inline Type operator[](Key key) {return value(key);} +}; + +#endif // PICONTAINERS_H diff --git a/pidir.cpp b/pidir.cpp index 23eae4af..655d0799 100644 --- a/pidir.cpp +++ b/pidir.cpp @@ -1,5 +1,19 @@ #include "pidir.h" +#ifndef WINDOWS +#ifdef WINDOWS + const PIChar PIDir::separator = '\\'; +#else + const PIChar PIDir::separator = '/'; +#endif + + +PIDir::PIDir() { + path_ = PIDir::current().path_; + dir_ = 0; + open(); +} + PIDir::PIDir(const PIString & dir) { path_ = dir.stdString(); @@ -8,7 +22,7 @@ PIDir::PIDir(const PIString & dir) { } -bool PIDir::operator==(const PIDir & d) const { +bool PIDir::operator ==(const PIDir & d) const { return true; } @@ -17,7 +31,7 @@ bool PIDir::open() { if (dir_ != 0) if (!close()) return false; - dir_ = opendir(path_.c_str()); + dir_ = opendir(path_.data()); return (dir_ != 0); } @@ -38,6 +52,118 @@ PIString PIDir::absolutePath() { } +PIDir & PIDir::cleanPath() { + PIString p(path_); + if (p.size() == 0) { + path_ = "."; + open(); + return *this; + } + bool isAbs = isAbsolute(); + for (uint i = p.size() - 1; i > 0; --i) { + if (p[i] == separator && p[i - 1] == separator) { + p.cutLeft(i); + isAbs = true; + break; + } + } + PIStringList l = PIString(p).split(separator); + l.removeStrings("."); + l.removeStrings(""); + bool found = true; + while (found) { + found = false; + for (uint i = 0; i < l.size() - 1; ++i) { + if (l.size() < 2) break; + if (l[i] != ".." && l[i + 1] == "..") { + if (l.size() + i > 2) l.remove(i, 2); + else l.remove(i, 1); + --i; + found = true; + } + } + } + found = true; + while (found) { + found = false; + if (l.size() > 0) if (l[0] == "..") + {l.pop_front(); found = true;} + } + path_ = separator + l.join(separator); + if (!isAbs) path_.insert(0, "."); + if (path_.size() == 0) path_ = "./"; + open(); + return *this; +} + + +PIDir & PIDir::cd(const PIString & path) { + if (path_.size() == 0) return *this; + if (path_[path_.size() - 1] == separator) path_ << path; + else path_ << separator << path; + return cleanPath(); +} + + +bool PIDir::mkDir(bool withParents) { + PIDir d = cleanedPath(); + string p = d.path_; + PIString tp; + int ret; + bool isAbs = isAbsolute(); + if (withParents) { + PIStringList l = PIString(p).split(separator); + for (int i = l.size_s() - 1; i >= 0; --i) { + if (i > 1) tp = PIStringList(l).remove(i, l.size_s() - i).join(separator); + else { + tp = separator; + if (!isAbs) tp.push_front('.'); + } + //cout << tp << endl; + if (isExists(tp)) { + for (int j = i + 1; j <= l.size_s(); ++j) { + tp = PIStringList(l).remove(j, l.size_s() - j).join(separator); + //cout << tp << endl; + p = tp.stdString(); + ret = mkdir(p.c_str(), 16877); + if (ret == 0) continue; + printf("[PIDir] mkDir(\"%s\") error: %s\n", p.c_str(), strerror(errno)); + return false; + } + break; + }; + } + } else { + ret = mkdir(p.c_str(), 16877); + if (ret == 0) return true; + printf("[PIDir] mkDir(\"%s\") error: %s\n", p.c_str(), strerror(errno)); + } + return false; +} + + +PIVector PIDir::entries() { + PIDir d = cleanedPath(); + PIString p = d.path_; + dirent ** list; +#ifndef QNX + int cnt = scandir(const_cast(p.data()), &list, 0, alphasort); +#else + int cnt = scandir(const_cast(p.data()), 0, 0, alphasort); +#endif + struct stat fs; + PIVector l; + for (int i = 0; i < cnt; ++i) { + stat((p + separator + list[i]->d_name).data(), &fs); + l.push_back(DirEntry(list[i]->d_name, fs.st_mode, fs.st_size)); + delete list[i]; + } + delete list; + return l; +} + + + PIDir PIDir::current() { char rc[1024]; if (getcwd(rc, 1024) == 0) return PIString(); @@ -58,12 +184,10 @@ PIDir PIDir::temporary() { } -bool PIDir::mkDir(const PIString & path) { - string s = path.stdString(); - int ret = mkdir(s.c_str(), 16877); - if (ret == 0) return true; - printf("[PIDir] mkDir(\"%s\") error: %s\n", s.c_str(), strerror(errno)); - return false; +bool PIDir::mkDir(const PIString & path, bool withParents) { + PIDir d(path); + if (d.isExists()) return true; + return d.mkDir(withParents); } @@ -74,3 +198,5 @@ bool PIDir::rmDir(const PIString & path) { printf("[PIDir] rmDir(\"%s\") error: %s\n", s.c_str(), strerror(errno)); return false; } + +#endif diff --git a/pidir.h b/pidir.h index 35b53867..b991ebbc 100644 --- a/pidir.h +++ b/pidir.h @@ -2,41 +2,67 @@ #define PIDIR_H #include "pifile.h" +#ifndef WINDOWS #include +#include class PIDir { public: - PIDir() {dir_ = 0;} + PIDir(); PIDir(const PIString & dir); ~PIDir() {close();} + struct DirEntry { + DirEntry() {;} + DirEntry(const PIString & name_, const int & mode_, const int & size_) { + name = name_; mode = mode_; size = size_;} + + PIString name; + int mode; + int size; + + bool isDir() const {return (mode & S_IFDIR);} + bool isFile() const {return (mode & S_IFREG);} + bool isSymLink() const {return (mode & S_IFLNK);} + bool isBlkDevice() const {return (mode & S_IFBLK);} + bool isChrDevice() const {return (mode & S_IFCHR);} + bool isSocket() const {return (mode & S_IFSOCK);} + }; + inline const bool isExists() {return (dir_ != 0);} + inline const bool isAbsolute() {if (path_.size() == 0) return false; return (path_[0] == separator);} inline PIString path() {return PIString(path_);} + PIDir & cleanPath(); + inline PIDir cleanedPath() {PIDir d(path_); d.cleanPath(); return d;} PIString absolutePath(); + bool mkDir(bool withParents = true); + PIVector entries(); + + PIDir & cd(const PIString & path); + inline PIDir & up() {return cd("..");} bool operator ==(const PIDir & d) const; -#ifdef WINDOWS - static const char separator = '\\'; -#else - static const char separator = '/'; -#endif + static const PIChar separator; static PIDir current(); static PIDir home(); static PIDir temporary(); - static bool mkDir(const PIString & path); + static bool mkDir(const PIString & path, bool withParents = true); static bool rmDir(const PIString & path); + static bool isExists(const PIString & path) {return PIDir(path).isExists();} //static bool rmDir(const PIString & path); private: bool open(); bool close(); - string path_; + PIString path_; + DIR * dir_; }; +#endif #endif // PIDIR_H diff --git a/piethernet.cpp b/piethernet.cpp index 13a0046e..f2c8dcb4 100644 --- a/piethernet.cpp +++ b/piethernet.cpp @@ -8,7 +8,8 @@ PIEthernet::PIEthernet(PIString ip, int port, void * data_, EthernetFunc slot): port_ = port_s = port; sock = sock_s = -1; ret_func = slot; - buffer = new char[BUFFER_SIZE]; + tries = 0; + //buffer_ = new char[BUFFER_SIZE]; #ifdef WINDOWS WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); @@ -22,26 +23,36 @@ PIEthernet::~PIEthernet() { #ifdef WINDOWS WSACleanup(); #endif - delete buffer; if (sock != -1) { shutdown(sock, SHUT_RDWR); +#ifdef WINDOWS + closesocket(sock); +#else close(sock); +#endif sock = -1; } if (sock_s != -1) { shutdown(sock_s, SHUT_RDWR); +#ifdef WINDOWS + closesocket(sock_s); +#else close(sock_s); +#endif sock_s = -1; } + //if (buffer_ != 0) delete buffer_; + //buffer_ = 0; } void PIEthernet::terminate() { - if (!initialized()) return; + if (!receiverInitialized()) return; if (isRunning()) { stop(); pthread_cancel(thread); } + tries = 0; /*if (sock != -1) { shutdown(sock, SHUT_RDWR); shutdown(sock, SHUT_RDWR); @@ -63,20 +74,20 @@ void PIEthernet::begin() { void PIEthernet::run() { #ifdef WINDOWS - int addr_len; + int addr_len = sizeof(sockaddr_storage); #else - socklen_t addr_len; + socklen_t addr_len = sizeof(sockaddr_storage); #endif - //cout << "[PIEthernet] reading ... "; - readed = recvfrom(sock, buffer, BUFFER_SIZE, 0, (sockaddr * )&addr_, &addr_len); + //cout << "[PIEthernet] reading from " << &addr_ << endl; + readed = recvfrom(sock, buffer_, BUFFER_SIZE, 0, (sockaddr * )&addr_, &addr_len); //cout << WSAGetLastError() << endl; if (readed < 0) { - //cout << "[PIEthernet] Error while reading" << endl; + cout << "[PIEthernet] Error while reading, " << errorString() << endl; //stop(); //init(); return; } - if (ret_func != 0) ret_func(data, buffer); + if (ret_func != 0) ret_func(data, buffer_, readed); } @@ -86,13 +97,23 @@ void PIEthernet::end() { bool PIEthernet::init() { - addr_.sin_addr.s_addr = inet_addr(ip_.stdString().data()); + addr_.sin_addr.s_addr = inet_addr(ip_.data()); addr_.sin_family = PF_INET; addr_.sin_port = htons(port_); +#ifdef WINDOWS + closesocket(sock); +#else close(sock); +#endif sock = socket(PF_INET, SOCK_DGRAM, 0); if (bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) { - cout << "[PIEthernet] Cant`t bind to " << ip_.stdString() << ":" << port_ << endl; + if (tries < 10) { + if (init()) { + tries = 0; + return true; + } else return false; + } else + cout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << errorString() << endl; return false; } return true; @@ -100,10 +121,20 @@ bool PIEthernet::init() { bool PIEthernet::initSend() { +#ifdef WINDOWS + closesocket(sock_s); +#else close(sock_s); +#endif sock_s = socket(PF_INET, SOCK_DGRAM, 0); if (sock_s == -1) { - cout << "[PIEthernet] Unable to create socket" << endl; + if (tries < 10) { + if (init()) { + tries = 0; + return true; + } else return false; + } else + cout << "[PIEthernet] Unable to create socket, " << errorString() << endl; return false; } return true; @@ -116,7 +147,7 @@ bool PIEthernet::send(PIString ip, int port, char * data, int size) { return false; } saddr_.sin_port = htons(port); - saddr_.sin_addr.s_addr = inet_addr(ip.stdString().data()); + saddr_.sin_addr.s_addr = inet_addr(ip.data()); saddr_.sin_family = PF_INET; wrote = sendto(sock_s, data, size, 0, (sockaddr * )&saddr_, sizeof(saddr_)); if (wrote != size) { @@ -134,7 +165,7 @@ bool PIEthernet::send(char * data, int size) { return false; } saddr_.sin_port = htons(port_s); - saddr_.sin_addr.s_addr = inet_addr(ip_s.stdString().data()); + saddr_.sin_addr.s_addr = inet_addr(ip_s.data()); saddr_.sin_family = PF_INET; //cout << "[PIEthernet] sending in " << sock_s << endl; wrote = sendto(sock_s, data, size, 0, (sockaddr * )&saddr_, sizeof(saddr_)); diff --git a/piethernet.h b/piethernet.h index 287432ca..ac920d38 100644 --- a/piethernet.h +++ b/piethernet.h @@ -4,22 +4,22 @@ #include "pithread.h" #include "pistring.h" #ifndef WINDOWS -# include -# include -# include +# include +# include +# include #else -# include -# define SHUT_RDWR SD_BOTH +# include +# define SHUT_RDWR SD_BOTH #endif #define BUFFER_SIZE 4096 -typedef bool (*EthernetFunc)(void * , char * ); +typedef bool (*EthernetFunc)(void * , char * , int ); class PIEthernet: public PIThread { public: - // slot is any function format "bool (void*, char*)" + // slot is any function format "bool (void*, char*, int)" PIEthernet(PIString ip = "", int port = 0, void * data = 0, EthernetFunc slot = 0); ~PIEthernet(); @@ -32,22 +32,22 @@ public: bool send(char * data, int size); bool init(); bool initSend(); - bool initialized() const {return sock != -1;} + bool receiverInitialized() const {return sock != -1;} + bool senderInitialized() const {return sock_s != -1;} void terminate(); + inline const char * buffer() const {return buffer_;} private: void begin(); void run(); void end(); - - int sock, sock_s, port_, port_s, wrote; + int sock, sock_s, port_, port_s, wrote, readed, tries; sockaddr_in addr_, saddr_; PIString ip_, ip_s; EthernetFunc ret_func; - char * buffer; void * data; - int readed; + char buffer_[BUFFER_SIZE]; }; diff --git a/pievaluator.cpp b/pievaluator.cpp new file mode 100644 index 00000000..2f6206e2 --- /dev/null +++ b/pievaluator.cpp @@ -0,0 +1,1033 @@ +#include "pievaluator.h" + + +PIEvaluatorContent::PIEvaluatorContent() { + addFunction("arcsin", 1); + addFunction("arccos", 1); + addFunction("arctg", 1); + addFunction("arcctg", 1); + addFunction("random", 2); + addFunction("sin", 1); + addFunction("cos", 1); + addFunction("ctg", 1); + addFunction("tg", 1); + addFunction("exp", 1); + addFunction("cth", 1); + addFunction("sh", 1); + addFunction("ch", 1); + addFunction("th", 1); + addFunction("sqrt", 1); + addFunction("sqr", 1); + addFunction("pow", 2); + addFunction("abs", 1); + addFunction("ln", 1); + addFunction("lg", 1); + addFunction("log", 2); + addFunction("im", 1); + addFunction("re", 1); + addFunction("arg", 1); + addFunction("len", 1); + addFunction("conj", 1); + addFunction("sign", 1); + addFunction("rad", 1); + addFunction("deg", 1); + clearCustomVariables(); + //addVariable("n", 0.); + //addVariable("x1", 123); +} + + +bool PIEvaluatorContent::setVariableValue(int index, complexd new_value) { + if (index < 0 || index >= variables.size_s()) return false; + variables[index].value = new_value; + return true; +} + + +bool PIEvaluatorContent::setVariableName(int index, const PIString & new_name) { + if (index < 0 || index >= variables.size_s()) return false; + variables[index].name = new_name; + return true; +} + + +void PIEvaluatorContent::clearCustomVariables() { + variables.clear(); + addVariable("i", complexd_1); + addVariable("pi", atan(1.) * 4.); + addVariable("e", exp(1.)); + cv_count = variables.size(); +} + + +void PIEvaluatorContent::sortVariables() { + PIEvaluatorTypes::Variable tv; + for (uint i = 0; i < variables.size(); i++) { + for (uint j = variables.size() - 1; j > i; j--) { + if (variables[j].name.length() <= variables[i].name.length()) continue; + piSwap(variables[i], variables[j]); + } + } + /* + * qDebug() << "---"; + * for (int i = 0; i < variables.size(); i++) { + * qDebug() << variables[i].name; + } + */ +} + + +PIEvaluatorTypes::BaseFunctions PIEvaluatorContent::getBaseFunction(const PIString & name) { + if (name == "sin") return PIEvaluatorTypes::bfSin; + if (name == "cos") return PIEvaluatorTypes::bfCos; + if (name == "tg") return PIEvaluatorTypes::bfTg; + if (name == "ctg") return PIEvaluatorTypes::bfCtg; + if (name == "arcsin") return PIEvaluatorTypes::bfArcsin; + if (name == "arccos") return PIEvaluatorTypes::bfArccos; + if (name == "arctg") return PIEvaluatorTypes::bfArctg; + if (name == "arcctg") return PIEvaluatorTypes::bfArcctg; + if (name == "exp") return PIEvaluatorTypes::bfExp; + if (name == "random") return PIEvaluatorTypes::bfRandom; + if (name == "sh") return PIEvaluatorTypes::bfSh; + if (name == "ch") return PIEvaluatorTypes::bfCh; + if (name == "th") return PIEvaluatorTypes::bfTh; + if (name == "cth") return PIEvaluatorTypes::bfCth; + if (name == "sqrt") return PIEvaluatorTypes::bfSqrt; + if (name == "sqr") return PIEvaluatorTypes::bfSqr; + if (name == "pow") return PIEvaluatorTypes::bfPow; + if (name == "abs") return PIEvaluatorTypes::bfAbs; + if (name == "ln") return PIEvaluatorTypes::bfLn; + if (name == "lg") return PIEvaluatorTypes::bfLg; + if (name == "log") return PIEvaluatorTypes::bfLog; + if (name == "im") return PIEvaluatorTypes::bfIm; + if (name == "re") return PIEvaluatorTypes::bfRe; + if (name == "arg") return PIEvaluatorTypes::bfArg; + if (name == "len") return PIEvaluatorTypes::bfLen; + if (name == "conj") return PIEvaluatorTypes::bfConj; + if (name == "sign") return PIEvaluatorTypes::bfSign; + if (name == "rad") return PIEvaluatorTypes::bfRad; + if (name == "deg") return PIEvaluatorTypes::bfDeg; + return PIEvaluatorTypes::bfUnknown; +} + +const PIString & PIEvaluator::prepare(const PIString & string) { + currentString = string.trimmed(); + if (currentString.isEmpty()) currentString = "0"; + replaceOperators(); + removeSpaces(); + checkBrackets(); + while (fillElements()) checkBrackets(); + while (setSignes()) fillElements(); + removeJunk(); + findUnknownVariables(); + return currentString; +} + + +void PIEvaluator::removeSpaces() { + PIString tmps = currentString; + for (int i = 0; i < tmps.length(); i++) { + if (tmps[i] == ' ' || tmps[i] == '\t') { + tmps.remove(i, 1); + i--; + } + } + currentString = tmps; +} + + +void PIEvaluator::removeJunk() { + PIChar cc; + bool junk = true; + int bcnt; + while (junk) { + if (currentString.left(1) != "(" || currentString.right(1) != ")") return; + bcnt = 1; + junk = false; + for (int i = 1; i < currentString.length(); i++) { + cc = currentString[i]; + if (cc == '(') bcnt++; + if (cc == ')') bcnt--; + if (bcnt == 0) { + if (i == currentString.length() - 1) { + currentString = currentString.mid(1, currentString.length() - 2); + elements.pop_front(); + elements.pop_back(); + junk = true; + break; + } else break; + } + } + } +} + + +void PIEvaluator::replaceOperators() { + currentString.replaceAll("==", "="); + currentString.replaceAll("!=", ":"); + currentString.replaceAll(">=", "}"); + currentString.replaceAll("<=", "{"); + currentString.replaceAll("&&", "&"); + currentString.replaceAll("||", "|"); +} + + +void PIEvaluator::makeOutput(PIString & string) { + string.replaceAll(":", "≠"); + string.replaceAll("}", "≥"); + string.replaceAll("{", "≤"); + string.replaceAll("&", "⋀"); + string.replaceAll("|", "⋁"); +} + + +void PIEvaluator::findUnknownVariables() { + PIString cvar; + unknownVars.clear(); + for (int i = 0; i < currentString.length(); i++) { + if (elements[i].var_num == -666) cvar += currentString[i]; + else { + if (cvar.length() == 0) continue; + unknownVars << cvar; + cvar = ""; + } + } + if (cvar.length() > 0) unknownVars << cvar; + unknownVars.removeDuplicates(); +} + + +bool PIEvaluator::isSign(const PIChar & ch) { + return ch == '+' || ch == '-' || + ch == '*' || ch == '/' || + ch == '%' || ch == '^' || + ch == '=' || ch == ':' || + ch == '>' || ch == '<' || + ch == '}' || ch == '{' || + ch == '&' || ch == '|'; +} + + +void PIEvaluator::checkBrackets() { + PIString tmps = currentString; + PIChar fc, sc; + int bcnt = 0, bpos = 0, inserted = 0; + currentString = tmps; + for (int i = 0; i < tmps.length(); i++) { + if (tmps[i] == '(') { + if (bcnt == 0) bpos = i; + bcnt++; + } + if (tmps[i] == ')') { + if (bcnt == 0) { + currentString.insert(bpos + inserted, "("); + inserted++; + } else bcnt--; + } + } + if (bcnt > 0) currentString += PIString(bcnt, ')'); + tmps = currentString; + for (int i = 0; i < tmps.length() - 1; i++) { + fc = tmps[i].toLower(); + sc = tmps[i + 1].toLower(); + if ((fc == ')' && sc == '(') || + (fc == ')' && sc >= '0' && sc <= '9') || + (fc == ')' && sc >= 'a' && sc <= 'z') ) tmps.insert(++i, '*'); + } + currentString = tmps; +} + + +bool PIEvaluator::fillElements() { + int fstart, flen, cnum = 0, cpart = 0, cfunc; + PIChar cc, nc, pc, fc = '!'; + bool numFound = false; + PIString curfind, tmps = currentString; + elements.resize(tmps.length()); + for (uint i = 0; i < elements.size(); i++) { + elements[i].type = PIEvaluatorTypes::etVariable; + elements[i].var_num = -666; + } + currentVariables.clear(); + //qDebug().nospace() << "search for functions ..."; + for (int i = 0; i < content.functionsCount(); i++) { + curfind = content.function(i).identifier; + cfunc = i; //(int)content.function(i).type; + flen = curfind.length(); + fstart = 0; + while (fstart >= 0) { + fstart = tmps.find(curfind, fstart); + if (fstart < 0) break; + if (tmps[fstart + flen] != '(') { + currentString.insert(fstart + flen, "("); + return true; + } + for (int j = fstart; j < fstart + flen; j++) { + elements[j].set(PIEvaluatorTypes::etFunction, cnum, cfunc); + tmps.replace(j, 1, fc); + } + cnum++; + } + } + cnum = 0; + //qDebug().nospace() << "search for variables ..."; + for (int i = 0; i < content.variablesCount(); i++) { + curfind = content.variable(i).name; + flen = curfind.length(); + fstart = 0; + while (fstart >= 0) { + fstart = tmps.find(curfind, fstart); + if (fstart < 0) break; + for (int j = fstart; j < fstart + flen; j++) { + elements[j].set(PIEvaluatorTypes::etVariable, cnum, i); + tmps.replace(j, 1, fc); + } + cnum++; + } + } + curfind = ""; + cnum = 1; + //qDebug().nospace() << "search for numbers ..."; + for (int i = 0; i < tmps.length(); i++) { + cc = tmps[i]; + /*if (cc == " " || cc == "(" || cc == ")") { + curfind = ""; + cpart = 0; + numFound = false; + continue; + }*/ + switch (cpart) { + case 0: + if ((cc >= '0' && cc <= '9')) {// || cc == '-' || cc == '+') { + curfind += cc; + cpart = 1; + continue; + } + if (cc == '.') { + curfind += cc; + cpart = 2; + continue; + } + if (cc == 'E') { + curfind += cc; + cpart = 3; + continue; + } + break; + case 1: + if (cc >= '0' && cc <= '9') { + curfind += cc; + continue; + } + if (cc == '.') { + curfind += cc; + cpart = 2; + continue; + } + if (cc == 'E') { + curfind += cc; + cpart = 3; + continue; + } + numFound = true; + break; + case 2: + if (cc >= '0' && cc <= '9') { + curfind += cc; + continue; + } + if (cc == 'E') { + curfind += cc; + cpart = 3; + continue; + } + numFound = true; + break; + case 3: + if ((cc >= '0' && cc <= '9') || cc == '-' || cc == '+') { + curfind += cc; + cpart = 4; + continue; + } + numFound = true; + break; + case 4: + if (cc >= '0' && cc <= '9') { + curfind += cc; + continue; + } + numFound = true; + break; + } + if (numFound) { + //qDebug().nospace() << "add " << cnum << ": " << curfind << " = " << curfind.toDouble(); + currentVariables.push_back(PIEvaluatorTypes::Variable("tmp" + PIString::fromNumber(cnum), curfind.toDouble())); + for (int j = i - curfind.length(); j < i; j++) { + elements[j].set(PIEvaluatorTypes::etNumber, cnum, -cnum); + tmps.replace(j, 1, fc); + } + curfind = ""; + cnum++; + cpart = 0; + numFound = false; + } + } + if (cpart > 0) { + //qDebug().nospace() << "add " << cnum << ": " << curfind << " = " << curfind.toDouble(); + currentVariables.push_back(PIEvaluatorTypes::Variable("tmp" + PIString::fromNumber(cnum), curfind.toDouble())); + for (int j = tmps.length() - curfind.length(); j < tmps.length(); j++) { + elements[j].set(PIEvaluatorTypes::etNumber, cnum, -cnum); + tmps.replace(j, 1, fc); + } + } + cc = nc = fc; + //qDebug().nospace() << "search for signes ..."; + for (int i = 0; i < tmps.length(); i++) { + cc = tmps[i]; + if (i > 0) pc = tmps[i - 1]; + else pc = fc; + if (i < tmps.length() - 1) nc = tmps[i + 1]; + else nc = fc; + if (cc == '(' || cc == ')' || cc == ',') { + elements[i].set(PIEvaluatorTypes::etOperator, -1); + continue; + } + if (cc == '-' || cc == '+') { + elements[i].set(PIEvaluatorTypes::etOperator, -1); + if (i < tmps.length() - 1) if (elements[i + 1].type == PIEvaluatorTypes::etVariable || + elements[i + 1].type == PIEvaluatorTypes::etFunction) continue; + if ((pc == '(' || isSign(pc) || i == 0) && i < tmps.length() - 1) { + if (elements[i + 1].type != PIEvaluatorTypes::etOperator) { + cnum = elements[i + 1].num; + elements[i].set(PIEvaluatorTypes::etNumber, cnum); + tmps.replace(i, 1, fc); + ///cout << "found sign " << cc << " :" << cnum - 1 << endl; + if (cc == '-' && currentVariables.size_s() >= cnum) + currentVariables[cnum - 1].value = -currentVariables[cnum - 1].value; + //i++; + continue; + } + } + } + if (isSign(cc)) { + elements[i].set(PIEvaluatorTypes::etOperator, -1); + continue; + } + } + /* + qDebug().nospace() << tmps; + cout << " "; + for (int i = 0; i < elements.size(); i++) { + switch (elements[i].type) { + case etFunction: cout << "f"; break; + case etNumber: cout << "n"; break; + case etOperator: cout << "o"; break; + case etVariable: cout << "v"; break; + } + } + cout << endl; + */ + return false; + //for (int i = 0; i < currentVariables.size(); i++) qDebug() << "var " << i << ": " << currentVariables[i].value.real(); +} + + +bool PIEvaluator::setSignes() { + int inserted = 0, ni, pi = 0, needInsert = 0; + PIChar fc, sc, pc; + PIString tmps = currentString; + for (int i = 0; i < tmps.length() - 1; i++) { + needInsert = 0; + ni = i + 1; + if (i > 0) pi = i - 1; + fc = tmps[i].toLower(); + sc = tmps[ni].toLower(); + pc = tmps[pi].toLower(); + //if (elements[i].type == etOperator || elements[ni].type == etVariable) continue; + if (fc == ',' || sc == ',') continue; + if (elements[i].type == PIEvaluatorTypes::etOperator && elements[ni].type == PIEvaluatorTypes::etOperator) continue; + if (fc == ')' && (elements[ni].type == PIEvaluatorTypes::etNumber || elements[ni].type == PIEvaluatorTypes::etVariable || elements[ni].type == PIEvaluatorTypes::etFunction)) needInsert = 1; + if (sc == '(' && (elements[i].type == PIEvaluatorTypes::etNumber || elements[i].type == PIEvaluatorTypes::etVariable)) needInsert = 1; + if (elements[i].type == PIEvaluatorTypes::etNumber && elements[ni].type == PIEvaluatorTypes::etNumber && elements[i].num != elements[ni].num) needInsert = 1; + if (elements[i].type == PIEvaluatorTypes::etVariable && elements[ni].type == PIEvaluatorTypes::etVariable && elements[i].num != elements[ni].num) needInsert = 1; + if ((elements[i].type == PIEvaluatorTypes::etNumber && elements[ni].type == PIEvaluatorTypes::etVariable) || (elements[i].type == PIEvaluatorTypes::etVariable && elements[ni].type == PIEvaluatorTypes::etNumber)) needInsert = 1; + if ((elements[i].type == PIEvaluatorTypes::etNumber || elements[i].type == PIEvaluatorTypes::etVariable) && elements[ni].type == PIEvaluatorTypes::etFunction) needInsert = 1; + if (elements[i].type == PIEvaluatorTypes::etFunction && elements[ni].type == PIEvaluatorTypes::etFunction && elements[i].num != elements[ni].num) needInsert = 2; + if (elements[i].type == PIEvaluatorTypes::etFunction && elements[ni].type != PIEvaluatorTypes::etFunction && sc != '(') needInsert = 2; + if (elements[pi].type == PIEvaluatorTypes::etOperator && (elements[ni].type == PIEvaluatorTypes::etFunction || elements[ni].type == PIEvaluatorTypes::etVariable) && fc == '-') needInsert = 3; + switch (needInsert) { + case 1: + currentString.insert(ni + inserted, "*"); + elements.insert(ni + inserted, PIEvaluatorTypes::Element(PIEvaluatorTypes::etOperator, -1)); + //inserted++; + //i++; + return true; + /*case 2: + currentString.insert(ni + inserted, ")"); + currentString.insert(ni + inserted, "("); + elements.insert(ni + inserted, Element(etOperator, -1)); + elements.insert(ni + inserted, Element(etOperator, -1)); + inserted++; + i++; + return true;*/ + case 3: + currentString.insert(ni + inserted, "1*"); + elements.insert(ni + inserted, PIEvaluatorTypes::Element(PIEvaluatorTypes::etOperator, -1)); + //inserted; + //i++; + return true; + } + } + /*if (elements[tmps.length() - 1].type == etFunction) { + currentString.insert(tmps.length() + inserted, ")"); + currentString.insert(tmps.length() + inserted, "("); + elements.insert(tmps.length() + inserted, Element(etOperator, -1)); + elements.insert(tmps.length() + inserted, Element(etOperator, -1)); + return true; + }*/ + return false; +} + + +void PIEvaluator::convert() { + int j; + PIEvaluatorTypes::Element ce, pe; + for (int i = 0; i < currentString.length(); i++) { + pe = elements[i]; + if (pe.type != PIEvaluatorTypes::etFunction) continue; + j = i + 1; + while (j < currentString.length()) { + ce = elements[j]; + if (ce != pe) break; + j++; + } + currentString.replace(i, j - i, " "); + for (int k = i + 1; k < j; k++) elements.remove(i); + //i++; + } + for (int i = 0; i < currentString.length(); i++) { + pe = elements[i]; + if (pe.type != PIEvaluatorTypes::etNumber) continue; + j = i + 1; + while (j < currentString.length()) { + ce = elements[j]; + if (ce != pe) break; + j++; + } + currentString.replace(i, j - i, " "); + for (int k = i + 1; k < j; k++) elements.remove(i); + //i++; + } + for (int i = 0; i < currentString.length(); i++) { + pe = elements[i]; + if (pe.type != PIEvaluatorTypes::etVariable) continue; + j = i + 1; + while (j < currentString.length()) { + ce = elements[j]; + if (ce != pe) break; + j++; + } + currentString.replace(i, j - i, " "); + for (int k = i + 1; k < j; k++) elements.remove(i); + //i++; + } + /*qDebug().nospace() << currentString; + cout << " "; + for (int i = 0; i < elements.size(); i++) { + switch (elements[i].type) { + case etFunction: cout << "f"; break; + case etNumber: cout << "n"; break; + case etOperator: cout << "o"; break; + case etVariable: cout << "v"; break; + } + } + cout << endl;*/ +} + + + +const PIString & PIEvaluator::preprocess(const PIString & string) { + static PIString ret; + int lind; + ret = prepare(string); + convert(); + instructions.clear(); + //qDebug() << preproc->currentString; + variables = currentVariables; + lind = parse(currentString); + if (instructions.size() == 0) { + variables.push_back(PIEvaluatorTypes::Variable()); + instructions.push_back(PIEvaluatorTypes::Instruction(PIEvaluatorTypes::oNone, PIVector(1, lind), -variables.size())); + } + kvars = &(content.variables); + /* + cout << endl << "variables:" << endl; + for (int i = 0; i < variables.size(); i++) + cout << i << " value = " << variables[i].value << endl; + + cout << endl << "instructions:" << endl; + for (int i = 0; i < instructions.size(); i++) { + cout << i << endl; + cout << " operation " << instructions[i].operation << endl; + cout << " operators: "; + for (int j = 0; j < instructions[i].operators.size(); j++) + cout << instructions[i].operators[j] << "; "; + cout << endl << " function " << instructions[i].function << endl; + cout << " out " << instructions[i].out << endl; + } + */ + makeOutput(ret); + return ret; +} + + +PIEvaluatorTypes::Operation PIEvaluator::operationInOrder(const int & index) { + switch (index) { + case 0: return PIEvaluatorTypes::oPower; + case 1: return PIEvaluatorTypes::oMultiply; + case 2: return PIEvaluatorTypes::oDivide; + case 3: return PIEvaluatorTypes::oResidue; + case 4: return PIEvaluatorTypes::oAdd; + case 5: return PIEvaluatorTypes::oSubtract; + case 6: return PIEvaluatorTypes::oEqual; + case 7: return PIEvaluatorTypes::oNotEqual; + case 8: return PIEvaluatorTypes::oGreaterEqual; + case 9: return PIEvaluatorTypes::oSmallerEqual; + case 10: return PIEvaluatorTypes::oGreater; + case 11: return PIEvaluatorTypes::oSmaller; + case 12: return PIEvaluatorTypes::oAnd; + case 13: return PIEvaluatorTypes::oOr; + default: return PIEvaluatorTypes::oNone; + } +} + + +int PIEvaluator::parse(const PIString & string, int offset) { + int slen = string.length(), facnt, farg, bcnt, k; + PIChar cc; + PIEvaluatorTypes::Element ce; + PIEvaluatorTypes::Function cfunc; + PIEvaluatorTypes::Operation coper; + PIString sbrackets, carg; + PIVector args, atmp; + PIVector opers; + + ///qDebug() << "to parse :" + string; + ///cout << " "; for (int i = 0; i < slen; i++) cout << preproc->elements[i + offset].type; cout << endl; + + for (int i = 0; i < slen; i++) { + ce = elements[i + offset]; + cc = string[i]; + switch (ce.type) { + case PIEvaluatorTypes::etNumber: + args.push_back(ce.var_num); + continue; + case PIEvaluatorTypes::etVariable: + args.push_back(ce.var_num); + continue; + case PIEvaluatorTypes::etFunction: + i++; + cfunc = content.function(ce.var_num); + facnt = cfunc.arguments; + atmp.clear(); + bcnt = farg = 1; + ///qDebug() << "function: " + cfunc.identifier; + //for (int k = 0; k < facnt; k++) { + bcnt = 1; + carg = ""; + k = i + 1; + //if (string.size_s() <= k || k < 0) return -666; + while (bcnt > 0) { + //if (k < facnt - 1) fcomma = string.indexOf(',', j); + cc = string[k]; + switch (cc.toAscii()) { + case '(': bcnt++; break; + case ')': + bcnt--; + if (bcnt == 0) { + ///qDebug() << "arument: " << carg; + atmp.push_back(parse(carg, k + offset - carg.length())); + k++; + carg = ""; + if (atmp.size_s() > 0) if (atmp.back() < 0 && farg > 0) farg = atmp.back(); + continue; + } + break; + case ',': + if (bcnt == 1) { + ///qDebug() << "arument: " << carg; + atmp.push_back(parse(carg, k + offset - carg.length())); + k++; + carg = ""; + if (atmp.size_s() > 0) if (atmp.back() < 0 && farg > 0) farg = atmp.back(); + continue; + } + break; + } + carg += cc; + k++; + } + i = k - 1; + if (farg > 0) { + variables.push_back(PIEvaluatorTypes::Variable()); + farg = -variables.size_s(); + } + instructions.push_back(PIEvaluatorTypes::Instruction(PIEvaluatorTypes::oFunction, atmp, farg, ce.var_num)); + args.push_back(farg); + //for (int i = 0; i < args.size_s(); i++) cout << preproc->currentVariables[-args[i]].value << endl; + //i = j + 1; + continue; + case PIEvaluatorTypes::etOperator: + //qDebug() << "operator: " << cc; + if (cc == '(') { + sbrackets = inBrackets(string.right(slen - i)); + args.push_back(parse(sbrackets, i + offset + 1)); + i += sbrackets.length() + 1; + continue; + } + if (cc == '+') {opers.push_back(PIEvaluatorTypes::oAdd); continue;} + if (cc == '-') {opers.push_back(PIEvaluatorTypes::oSubtract); continue;} + if (cc == '*') {opers.push_back(PIEvaluatorTypes::oMultiply); continue;} + if (cc == '/') {opers.push_back(PIEvaluatorTypes::oDivide); continue;} + if (cc == '%') {opers.push_back(PIEvaluatorTypes::oResidue); continue;} + if (cc == '^') {opers.push_back(PIEvaluatorTypes::oPower); continue;} + if (cc == '=') {opers.push_back(PIEvaluatorTypes::oEqual); continue;} + if (cc == ':') {opers.push_back(PIEvaluatorTypes::oNotEqual); continue;} + if (cc == '}') {opers.push_back(PIEvaluatorTypes::oGreaterEqual); continue;} + if (cc == '{') {opers.push_back(PIEvaluatorTypes::oSmallerEqual); continue;} + if (cc == '>') {opers.push_back(PIEvaluatorTypes::oGreater); continue;} + if (cc == '<') {opers.push_back(PIEvaluatorTypes::oSmaller); continue;} + if (cc == '&') {opers.push_back(PIEvaluatorTypes::oAnd); continue;} + if (cc == '|') {opers.push_back(PIEvaluatorTypes::oOr); continue;} + } + } + /* + cout << "stack: " << endl << "args: "; + for (int i = 0; i < args.size_s(); i++) cout << args[i] << ", "; + cout << endl << "opers: "; + for (int i = 0; i < opers.size_s(); i++) cout << opers[i] << ", "; + */ + if (opers.size_s() == 0) { + if (args.size_s() > 0) return args.back(); + else return -666; + } + for (int i = 0; i < PIEvaluatorTypes::operationCount; i++) { + coper = operationInOrder(i); + for (int j = 0; j < opers.size_s(); j++) { + if (coper == PIEvaluatorTypes::oDivide || coper == PIEvaluatorTypes::oMultiply) { + if (opers[j] != PIEvaluatorTypes::oDivide && opers[j] != PIEvaluatorTypes::oMultiply) continue; + } else { + if (opers[j] != coper) continue; + } + atmp.clear(); + if (j < args.size_s() && j >= 0) atmp.push_back(args[j]); + else atmp.push_back(-666); + if (j + 1 < args.size_s() && j >= -1) atmp.push_back(args[j + 1]); + else atmp.push_back(-666); + farg = 1; + if (atmp[0] < 0) farg = atmp[0]; + else { + if (atmp[1] < 0) farg = atmp[1]; + else { + variables.push_back(PIEvaluatorTypes::Variable()); + farg = -variables.size_s(); + } + } + instructions.push_back(PIEvaluatorTypes::Instruction(opers[j], atmp, farg)); + if (j >= 0 && j < args.size_s()) { + args.remove(j); + if (j < args.size_s()) args[j] = farg; + } + opers.remove(j); + j--; + } + } + return instructions.back().out; + ///cout << endl; +} + + +bool PIEvaluator::check() { + PIEvaluatorTypes::Instruction ci; + bool error; + if (unknownVars.size_s() > 0) { + lastError = "Unknown variables: \"" + unknownVars.join("\", \"") + "\""; + return false; + } + for (int i = 0; i < instructions.size_s(); i++) { + error = false; + ci = instructions[i]; + switch (ci.operation) { + case PIEvaluatorTypes::oNone: break; + case PIEvaluatorTypes::oFunction: + for (int j = 0; j < ci.operators.size_s(); j++) { + if (ci.operators[j] == -666) { //(ci.operators[j] < -variables.size_s() || ci.operators[j] >= kvars->size()) { + error = true; + break; + } + } + if (ci.operators.size_s() != content.function(ci.function).arguments || error) { + lastError = "Invalid arguments count for function \"" + content.function(ci.function).identifier + "\""; + return false; + } + break; + default: + if (ci.operators[0] == -666 || ci.operators[1] == -666) error = true; + if (ci.operators.size_s() != 2 || error) { + lastError = "Invalid arguments count for operation \" " + operationChar(ci.operation) + " \""; + return false; + } + break; + } + if (ci.out < -variables.size_s()) { + lastError = "Invalid variable index \"" + PIString::fromNumber(ci.out) + "\""; + return false; + } + for (int j = 0; j < ci.operators.size_s(); j++) { + if (ci.operators[j] < -variables.size_s() || ci.operators[j] >= kvars->size_s()) { + lastError = "Invalid variable index \"" + PIString::fromNumber(ci.operators[j]) + "\""; + return false; + } + } + } + return true; +} + + +PIString PIEvaluator::inBrackets(const PIString & string) { + int slen = string.length(), bcnt = 0; + PIChar cc; + for (int i = 0; i < slen; i++) { + cc = string[i]; + if (cc == '(') bcnt++; + if (cc == ')') { + bcnt--; + if (bcnt == 0) return string.mid(1, i - 1); + } + } + return PIString(); +} + + +PIString PIEvaluator::operationChar(const PIEvaluatorTypes::Operation & operation) { + switch (operation) { + case PIEvaluatorTypes::oAdd: return "+"; + case PIEvaluatorTypes::oSubtract: return "-"; + case PIEvaluatorTypes::oMultiply: return "*"; + case PIEvaluatorTypes::oDivide: return "/"; + case PIEvaluatorTypes::oPower: return "^"; + case PIEvaluatorTypes::oResidue: return "%"; + case PIEvaluatorTypes::oEqual: return "="; + case PIEvaluatorTypes::oNotEqual: return ("≠"); + case PIEvaluatorTypes::oGreaterEqual: return ("≥"); + case PIEvaluatorTypes::oSmallerEqual: return ("≤"); + case PIEvaluatorTypes::oGreater: return ">"; + case PIEvaluatorTypes::oSmaller: return "<"; + case PIEvaluatorTypes::oAnd: return ("⋀"); + case PIEvaluatorTypes::oOr: return ("⋁"); + default: return "???"; + } +} + + +inline complexd PIEvaluator::residue(const complexd & f, const complexd & s) { + complexd ret; + if (s.real() != 0.) ret = complexd(f.real() - ((int)(f.real() / s.real())) * s.real(), 0.); + if (s.imag() != 0.) ret = complexd(ret.real(), f.imag() - ((int)(f.imag() / s.imag())) * s.imag()); + return ret; +} + + +inline void PIEvaluator::execFunction(const PIEvaluatorTypes::Instruction & ci) { + PIEvaluatorTypes::Function cfunc = content.function(ci.function); + int oi = -ci.out - 1; + complexd tmp, stmp; + ldouble ldtmp; + //qDebug() << "function " << (int)cfunc.type; + switch (cfunc.type) { + case PIEvaluatorTypes::bfSin: + tmpvars[oi].value = sin(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfCos: + tmpvars[oi].value = cos(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfTg: + tmpvars[oi].value = tan(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfCtg: + tmp = tan(value(ci.operators[0])); + if (tmp == complexd_0) tmpvars[oi].value = 0.; + else tmpvars[oi].value = complexd_1 / tmp; + break; + case PIEvaluatorTypes::bfArcsin: + tmpvars[oi].value = asinc(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfArccos: + tmpvars[oi].value = acosc(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfArctg: + tmpvars[oi].value = atanc(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfArcctg: + tmp = atanc(value(ci.operators[0])); + if (tmp == complexd_0) tmpvars[oi].value = 0.; + else tmpvars[oi].value = complexd_1 / tmp; + break; + case PIEvaluatorTypes::bfSh: + tmpvars[oi].value = sinh(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfCh: + tmpvars[oi].value = cosh(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfTh: + tmpvars[oi].value = tanh(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfCth: + tmp = tanh(value(ci.operators[0])); + if (tmp == complexd_0) tmpvars[oi].value = 0.; + else tmpvars[oi].value = complexd_1 / tmp; + break; + case PIEvaluatorTypes::bfAbs: + tmpvars[oi].value = abs(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfSqrt: + tmpvars[oi].value = sqrt(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfSqr: + tmpvars[oi].value = value(ci.operators[0]) * value(ci.operators[0]); + break; + case PIEvaluatorTypes::bfExp: + tmpvars[oi].value = exp(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfPow: + tmpvars[oi].value = pow(value(ci.operators[0]), value(ci.operators[1])); + break; + case PIEvaluatorTypes::bfLn: + tmpvars[oi].value = log(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfLg: + tmpvars[oi].value = log10(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfLog: + tmp = log(value(ci.operators[1])); + if (tmp == complexd_0) tmpvars[oi].value = 0.; + else tmpvars[oi].value = log(value(ci.operators[0])) / tmp; + break; + case PIEvaluatorTypes::bfRe: + tmpvars[oi].value = value(ci.operators[0]).real(); + break; + case PIEvaluatorTypes::bfIm: + tmpvars[oi].value = value(ci.operators[0]).imag(); + break; + case PIEvaluatorTypes::bfArg: + tmpvars[oi].value = arg(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfLen: + tmpvars[oi].value = abs(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfConj: + tmpvars[oi].value = conj(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfSign: + ldtmp = value(ci.operators[0]).real(); + tmpvars[oi].value = ldtmp >= 0. ? complexd_1 : -complexd_1; + break; + case PIEvaluatorTypes::bfRad: + tmpvars[oi].value = value(ci.operators[0]) * complexd(deg2rad, 0.); + break; + case PIEvaluatorTypes::bfDeg: + tmpvars[oi].value = value(ci.operators[0]) * complexd(rad2deg, 0.); + break; + case PIEvaluatorTypes::bfRandom: + tmp = static_cast(rand()) / RAND_MAX; + stmp = value(ci.operators[1]) - value(ci.operators[0]); + tmpvars[oi].value = value(ci.operators[0]) + tmp * stmp; + break; + default: break; + } +} + + +inline bool PIEvaluator::execInstructions() { + PIEvaluatorTypes::Instruction ci; + int oi; + complexd tmp; + tmpvars = variables; + //cout << "var count " << tmpvars.size_s() << endl; + for (int i = 0; i < instructions.size_s(); i++) { + ci = instructions[i]; + oi = -ci.out - 1; + //cout << value(ci.operators[0]) << operationChar(ci.operation) << value(ci.operators[1]) << ", " << oi << endl; + switch (ci.operation) { + case PIEvaluatorTypes::oAdd: + tmpvars[oi].value = value(ci.operators[0]) + value(ci.operators[1]); + break; + case PIEvaluatorTypes::oSubtract: + tmpvars[oi].value = value(ci.operators[0]) - value(ci.operators[1]); + break; + case PIEvaluatorTypes::oMultiply: + tmpvars[oi].value = value(ci.operators[0]) * value(ci.operators[1]); + break; + case PIEvaluatorTypes::oDivide: + tmp = value(ci.operators[1]); + if (tmp == complexd(0., 0.)) tmpvars[oi].value = 0.; + else tmpvars[oi].value = value(ci.operators[0]) / tmp; + break; + case PIEvaluatorTypes::oResidue: + tmpvars[oi].value = residue(value(ci.operators[0]), value(ci.operators[1])); + break; + case PIEvaluatorTypes::oPower: + tmpvars[oi].value = pow(value(ci.operators[0]), value(ci.operators[1])); + break; + case PIEvaluatorTypes::oEqual: + tmpvars[oi].value = value(ci.operators[0]) == value(ci.operators[1]); + break; + case PIEvaluatorTypes::oNotEqual: + tmpvars[oi].value = value(ci.operators[0]) != value(ci.operators[1]); + break; + case PIEvaluatorTypes::oGreaterEqual: + tmpvars[oi].value = value(ci.operators[0]).real() >= value(ci.operators[1]).real(); + break; + case PIEvaluatorTypes::oSmallerEqual: + tmpvars[oi].value = value(ci.operators[0]).real() <= value(ci.operators[1]).real(); + break; + case PIEvaluatorTypes::oGreater: + tmpvars[oi].value = value(ci.operators[0]).real() > value(ci.operators[1]).real(); + break; + case PIEvaluatorTypes::oSmaller: + tmpvars[oi].value = value(ci.operators[0]).real() < value(ci.operators[1]).real(); + break; + case PIEvaluatorTypes::oAnd: + tmpvars[oi].value = value(ci.operators[0]).real() > 0. && value(ci.operators[1]).real() > 0.; + break; + case PIEvaluatorTypes::oOr: + tmpvars[oi].value = value(ci.operators[0]).real() > 0. || value(ci.operators[1]).real() > 0.; + break; + case PIEvaluatorTypes::oFunction: + execFunction(ci); + break; + case PIEvaluatorTypes::oNone: + tmpvars[oi].value = value(ci.operators[0]); + break; + } + } + out = value(instructions.back().out); + return true; +} + + +bool PIEvaluator::check(const PIString & string) { + currentString = preprocess(string); + if (!check()) + return false; + lastError = "Correct"; + return true; +} + + +complexd PIEvaluator::evaluate() { + if (!execInstructions()) out = 0.; + if (fabs(out.real()) < 1E-300) out = complexd(0., out.imag()); + if (fabs(out.imag()) < 1E-300) out = complexd(out.real(), 0.); + return out; +} diff --git a/pievaluator.h b/pievaluator.h new file mode 100644 index 00000000..55ffe9e3 --- /dev/null +++ b/pievaluator.h @@ -0,0 +1,148 @@ +#ifndef PIEVALUATOR_H +#define PIEVALUATOR_H + +#include "pistring.h" +#include "pimath.h" + +namespace PIEvaluatorTypes { + static const int operationCount = 14; + + enum eType {etNumber, etOperator, etVariable, etFunction}; + enum Operation {oNone, oAdd, oSubtract, oMultiply, oDivide, oResidue, oPower, + oEqual, oNotEqual, oGreater, oSmaller, oGreaterEqual, oSmallerEqual, + oAnd, oOr, oFunction}; + enum BaseFunctions {bfUnknown, bfSin, bfCos, bfTg, bfCtg, + bfArcsin, bfArccos, bfArctg, bfArcctg, + bfExp, bfRandom, bfSh, bfCh, bfTh, bfCth, + bfSqrt, bfSqr, bfPow, bfAbs, + bfLn, bfLg, bfLog, bfSign, + bfIm, bfRe, bfArg, bfLen, bfConj, + bfRad, bfDeg}; + + struct Instruction { + Instruction() {;} + Instruction(Operation oper, PIVector opers, int out_ind, int func = -1) { + operation = oper; operators = opers; out = out_ind; function = func;} + Operation operation; + PIVector operators; + int out; + int function;}; + struct Element { + Element() {;} + Element(eType new_type, int new_num, int new_var_num = -1) {set(new_type, new_num, new_var_num);} + void set(eType new_type, int new_num, int new_var_num = -1) {type = new_type; num = new_num; var_num = new_var_num;} + eType type; + int num; + int var_num;}; + struct Function { + Function() {arguments = 0; type = bfUnknown;} + Function(const PIString & name, int args, BaseFunctions ftype) {identifier = name; arguments = args; type = ftype;} + PIString identifier; + BaseFunctions type; + int arguments;}; + struct Variable { + Variable() {value = 0.;} + Variable(const PIString & var_name, complexd val) {name = var_name; value = val;} + PIString name; + complexd value;}; +}; +/* + ≠ : + ≥ } + ≤ { + ⋀ & + ⋁ | +*/ +class PIEvaluatorContent +{ + friend class PIEvaluator; +public: + PIEvaluatorContent(); + ~PIEvaluatorContent() {;} + + inline void addFunction(const PIString & name, int args = 1) {functions.push_back(PIEvaluatorTypes::Function(name, args, getBaseFunction(name)));} + inline void addVariable(const PIString & name, const complexd & val = 0.) {variables.push_back(PIEvaluatorTypes::Variable(name, val)); sortVariables();} + inline int functionsCount() const {return functions.size();} + inline int variablesCount() const {return variables.size();} + inline int customVariablesCount() const {return variables.size() - cv_count;} + inline int findFunction(const PIString & name) const {for (uint i = 0; i < functions.size(); i++) if (functions[i].identifier == name) return i; return -1;} + inline int findVariable(const PIString & var_name) const {for (uint i = 0; i < variables.size(); i++) if (variables[i].name == var_name) return i; return -1;} + inline PIEvaluatorTypes::Function function(int index) {if (index < 0 || index >= functions.size_s()) return PIEvaluatorTypes::Function(); return functions[index];} + inline PIEvaluatorTypes::Variable variable(int index) {if (index < 0 || index >= variables.size_s()) return PIEvaluatorTypes::Variable(); return variables[index];} + inline PIEvaluatorTypes::Function function(const PIString & name) {return function(findFunction(name));} + inline PIEvaluatorTypes::Variable variable(const PIString & name) {return variable(findVariable(name));} + inline PIEvaluatorTypes::Variable customVariable(int index) {if (index < cv_count || index >= variables.size_s() + cv_count) return PIEvaluatorTypes::Variable(); return variables[index + cv_count];} + bool setVariableValue(int index, complexd new_value); + bool setVariableName(int index, const PIString & new_name); + inline bool setVariableValue(const PIString & var_name, const complexd & new_value) {return setVariableValue(findVariable(var_name), new_value);} + inline bool setVariableName(const PIString & var_name, const PIString & new_name) {return setVariableName(findVariable(var_name), new_name);} + inline void removeVariable(int index) {variables.remove(index);} + inline void removeVariable(const PIString & var_name) {removeVariable(findVariable(var_name));} + void clearCustomVariables(); + void sortVariables(); + PIEvaluatorTypes::BaseFunctions getBaseFunction(const PIString & name); + +private: + PIVector functions; + PIVector variables; + int cv_count; + +}; + +class PIEvaluator +{ +public: + PIEvaluator() {;} + ~PIEvaluator() {;} + + bool check(const PIString & string); + inline int setVariable(const PIString & name, complexd value = 0.) {if (content.findVariable(name) < 0) content.addVariable(name, value); else content.setVariableValue(name, value); return content.findVariable(name);} + inline void setVariable(int index, complexd value = 0.) {if (index >= 0 && index < content.variablesCount()) content.setVariableValue(index, value);} + inline void setCustomVariableValue(int index, complexd value = 0.) {content.variables[index + content.cv_count].value = value;} + complexd evaluate(); + inline void removeVariable(const PIString & name) {content.removeVariable(name);} + inline void clearCustomVariables() {content.clearCustomVariables();} + inline int variableIndex(const PIString & name) const {return content.findVariable(name);} + inline const PIStringList & unknownVariables() {return unknownVars;} + inline const PIString & expression() {return currentString;} + inline const PIString & error() {return lastError;} + inline const complexd & lastResult() {return out;} + + PIEvaluatorContent content; + +private: + const PIString & prepare(const PIString & string); + const PIString & preprocess(const PIString & string); + int parse(const PIString & string, int offset = 0); + void convert(); + void checkBrackets(); + void removeSpaces(); + void findUnknownVariables(); + void removeJunk(); + void replaceOperators(); + void makeOutput(PIString & string); + bool fillElements(); + bool setSignes(); + bool isSign(const PIChar & ch); + inline PIString inverse(const PIString & string) {int len = string.length(); PIString s; for (int i = 0; i < len; i++) s += string[len - i - 1]; return s;} + bool check(); + bool execInstructions(); + PIString inBrackets(const PIString & string); + PIString operationChar(const PIEvaluatorTypes::Operation & operation); + PIEvaluatorTypes::Operation operationInOrder(const int & index); + inline complexd value(const int & index) {if (index < 0) return tmpvars[-index - 1].value; else return kvars->at(index).value;} + inline complexd residue(const complexd & f, const complexd & s); + inline void execFunction(const PIEvaluatorTypes::Instruction & ci); + + PIVector elements; + PIVector currentVariables, variables, tmpvars, * kvars; + PIVector instructions; + PIStringList unknownVars; + PIString currentString, lastError; + complexd out; +}; + +inline bool operator ==(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {return (e1.type == e2.type && e1.num == e2.num);} +inline bool operator !=(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {return (e1.type != e2.type || e1.num != e2.num);} + +#endif // PIEVALUATOR_H diff --git a/pifile.cpp b/pifile.cpp index 669c4ea1..64d009cf 100644 --- a/pifile.cpp +++ b/pifile.cpp @@ -1,7 +1,7 @@ #include "pifile.h" -bool PIFile::open(const PIString & path_, Flags mode_) { +bool PIFile::open(const PIString & path_, PIFlags mode_) { cpath = path_; cmode = mode_; string st = cpath.stdString(); @@ -18,7 +18,26 @@ bool PIFile::open(const PIString & path_, Flags mode_) { PIString PIFile::readLine() { char * buff = new char[4096]; stream.getline(buff, 4096); - return string(buff); + return PIString(buff); +} + + +int PIFile::readAll(void * data) { + int cp = pos(), s = size(); + stream.seekg(0); + stream.read((char * )data, s); + seek(cp); + return s; +} + + +PIByteArray PIFile::readAll() { + int s = size(); + if (s < 0) return PIByteArray(); + PIByteArray a(s); + s = readAll(a.data()); + if (s >= 0) a.resize(s); + return a; } @@ -26,17 +45,11 @@ int PIFile::size() { int s, cp = stream.tellg(); stream.seekg(0, fstream::end); s = stream.tellg(); - stream.seekg(cp); + stream.seekg(cp, fstream::beg); return s; } -void PIFile::seek(int position) { - if (cmode[Read]) stream.seekg(position); - if (cmode[Write]) stream.seekp(position); -} - - void PIFile::resize(int new_size, char fill_) { int ds = new_size - size(); if (ds == 0) return; @@ -56,3 +69,10 @@ int PIFile::pos() { if (cmode[Write]) return stream.tellp(); return -1; } + + +PIFile PIFile::openTemporary(PIFlags mode) { + char * rc; + rc = tmpnam(0); + return PIFile(PIString(rc), mode); +} diff --git a/pifile.h b/pifile.h index 7899bb73..c66ccd72 100644 --- a/pifile.h +++ b/pifile.h @@ -1,7 +1,6 @@ #ifndef PIFILE_H #define PIFILE_H -#include "piincludes.h" #include "pistring.h" #include @@ -11,33 +10,46 @@ class PIFile { public: PIFile() {;} - + enum Mode {Read = fstream::in, Write = fstream::out, Truncate = fstream::trunc, New = fstream::app}; - - PIFile(const PIString & path, Flags mode = Read | Write) {open(path, mode);} + + PIFile(const PIString & path, PIFlags mode = Read | Write) {open(path, mode);} PIFile(const PIFile & file) {cpath = file.cpath; cmode = file.cmode;} ~PIFile() {if (isOpened()) close();} - bool open(const PIString & path, Flags mode = Read | Write); - inline void close() {stream.close();} - inline void clear() {string st = cpath.stdString(); close(); stream.open(st.c_str(), fstream::trunc | fstream::binary | (fstream::openmode)(int)cmode);} - void seek(int position); - inline void seekToEnd() {stream.seekg(0, fstream::end);} + PIFile & operator =(const PIFile & f) {cpath = f.cpath; cmode = f.cmode; return *this;} + + bool open(const PIString & path, PIFlags mode); + bool open(PIFlags mode) {return open(cpath, mode);} + bool open(const PIString & path) {return open(path, cmode);} + bool open() {return open(cpath, cmode);} + void close() {stream.close();} + void clear() {string st = cpath.stdString(); close(); stream.open(st.c_str(), fstream::trunc | fstream::binary | (fstream::openmode)(int)cmode);} + void seek(int position) {stream.clear(); stream.seekg(position); stream.seekp(position);} + void seekToBegin() {stream.clear(); stream.seekg(0, fstream::beg); stream.seekp(0, fstream::beg);} + void seekToEnd() {stream.clear(); stream.seekg(0, fstream::end); stream.seekp(0, fstream::end);} + void seekToLine(int line) {stream.clear(); seekToBegin(); piForTimes (line) readLine();} // line 0 - begin of file void resize(int new_size, char fill = 0); - inline void fill(char c) {stream.fill(c);} - inline void flush() {stream.flush();} + void fill(char c) {stream.fill(c);} + void flush() {stream.flush();} PIString readLine(); - + int readAll(void * data); + PIByteArray readAll(); + void remove() {if (isOpened()) close(); std::remove(cpath.data());} + PIString path() const {return cpath;} - Flags mode() const {return cmode;} + void setPath(const PIString & path) {cpath = path;} + PIFlags mode() const {return cmode;} int size(); int pos(); - bool isOpened() const {return stream.is_open();} - bool isEnd() const {return stream.eof();} - + bool isOpened() {return stream.is_open();} + bool isEnd() {return stream.eof();} + bool isEmpty() {return (size() == 0);} + PIFile & writeData(const void * data, int size_) {stream.write((char * )data, size_); return *this;} PIFile & readData(void * data, int size_) {stream.read((char * )data, size_); return *this;} - + PIFile & writeToBinLog(ushort id, const void * data, int size) {writeBinary(id).writeBinary((ushort)size).writeData(data, size); flush(); return *this;} + PIFile & writeBinary(const char v) {stream.write((char * )&v, sizeof(v)); return *this;} PIFile & writeBinary(const short v) {stream.write((char * )&v, sizeof(v)); return *this;} PIFile & writeBinary(const int v) {stream.write((char * )&v, sizeof(v)); return *this;} @@ -48,10 +60,10 @@ public: PIFile & writeBinary(const ulong v) {stream.write((char * )&v, sizeof(v)); return *this;} PIFile & writeBinary(const float v) {stream.write((char * )&v, sizeof(v)); return *this;} PIFile & writeBinary(const double v) {stream.write((char * )&v, sizeof(v)); return *this;} - + PIFile & operator <<(const char & v) {stream.write(&v, 1); return *this;} //PIFile & operator <<(const string & v) {stream.write(v.c_str(), v.size()); return *this;} - PIFile & operator <<(const PIString & v) {stream.write(v.data(), v.size()); return *this;} + PIFile & operator <<(const PIString & v) {string s = v.stdString(); stream.write(s.c_str(), s.size()); return *this;} PIFile & operator <<(const PIByteArray & v) {stream.write((char * )v.data(), v.size()); return *this;} PIFile & operator <<(const short & v) {stream << v; return *this;} PIFile & operator <<(const int & v) {stream << v; return *this;} @@ -62,7 +74,7 @@ public: PIFile & operator <<(const ulong & v) {stream << v; return *this;} PIFile & operator <<(const float & v) {stream << v; return *this;} PIFile & operator <<(const double & v) {stream << v; return *this;} - + PIFile & operator >>(char & v) {stream >> v; return *this;} PIFile & operator >>(short & v) {stream >> v; return *this;} PIFile & operator >>(int & v) {stream >> v; return *this;} @@ -74,11 +86,13 @@ public: PIFile & operator >>(float & v) {stream >> v; return *this;} PIFile & operator >>(double & v) {stream >> v; return *this;} + static PIFile openTemporary(PIFlags mode = PIFile::Read | PIFile::Write); + private: fstream stream; PIString cpath; - Flags cmode; - + PIFlags cmode; + }; #endif // PIFILE_H diff --git a/pigeometry.h b/pigeometry.h index 5ebdd898..138d9ec0 100644 --- a/pigeometry.h +++ b/pigeometry.h @@ -17,6 +17,8 @@ public: inline PIPoint & move(const PIPoint & p) {x += p.x; y += p.y; return *this;} inline double angleRad() const {return atan2(y, x);} inline int angleDeg() const {return round(atan2(y, x) * 180. / M_PI);} + inline PIPoint toPolar(bool isDeg = false) const {return PIPoint(sqrt(x*x + y*y), isDeg ? angleDeg() : angleRad());} + inline static PIPoint fromPolar(const PIPoint & p) {return PIPoint(p.y * cos(p.x), p.y * sin(p.x));} inline PIPoint operator +(const PIPoint & p) {return PIPoint(x + p.x, y + p.y);} inline PIPoint operator +(const Type & p) {return PIPoint(x + p, y + p);} diff --git a/piincludes.h b/piincludes.h index 86de29c8..c0d39887 100644 --- a/piincludes.h +++ b/piincludes.h @@ -7,33 +7,48 @@ #if __QNX__ # define QNX #endif +#ifndef WINDOWS +# ifndef QNX +# define LINUX +# endif +#endif #include #include +#include +#include #ifndef QNX -# include -# include +# include +# include +# include #else -# include -# include +# include +# include #endif +#include #include #include #include +#include +#include +#include #include #include #include #include +#include #include +#include +#include #ifdef WINDOWS -#include -#include -#include +# include +# include +# include #endif #define FOREVER for (;;) -#define FOREVER_WAIT FOREVER msleep(10); +#define FOREVER_WAIT FOREVER msleep(1); typedef long long llong; typedef unsigned char uchar; @@ -49,60 +64,46 @@ using std::endl; using std::flush; using std::vector; using std::list; +using std::queue; using std::deque; +using std::stack; +using std::set; using std::string; +#ifndef QNX +using std::wstring; +# ifndef WINDOWS +static locale_t currentLocale_t = 0; +# endif +#else +typedef std::basic_string wstring; +#endif -template > -class PIVector: public vector { +static bool isPIInit = false; + +class piInit { public: - inline const Type & at(uint index) const {return (*this)[index];} - inline Type & at(uint index) {return (*this)[index];} - inline const Type * data(uint index = 0) const {return &(*this)[index];} - inline Type * data(uint index = 0) {return &(*this)[index];} - inline void fill(const Type & t) {vector::assign(vector::size(), t);} - inline void pop_front() {vector::erase(vector::begin());} - inline void push_front(const Type & t) {vector::insert(vector::begin(), t);} - inline void remove(uint num) {vector::erase(vector::begin() + num);} - inline void remove(uint num, uint count) {vector::erase(vector::begin() + num, vector::begin() + num + count);} - inline void insert(uint pos, const Type & t) {vector::insert(vector::begin() + pos, t);} + piInit() { + if (isPIInit) return; + isPIInit = true; +#ifdef LINUX + if (currentLocale_t != 0) { + freelocale(currentLocale_t); + currentLocale_t = 0; + } + currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0); +#else + setlocale(LC_ALL, ""); +#endif + } + ~piInit() { + //if (currentLocale_t != 0) freelocale(currentLocale_t); + } }; -template > -class PIList: public list { -public: - inline const Type * data(uint index = 0) const {return &(*this)[index];} - inline Type * data(uint index = 0) {return &(*this)[index];} - inline void fill(const Type & t) {list::assign(list::size(), t);} - inline void remove(uint num) {list::erase(list::begin() + num);} - inline void remove(uint num, uint count) {list::erase(list::begin() + num, list::begin() + num + count);} - inline void insert(uint pos, const Type & t) {list::insert(list::begin() + pos, t);} -}; +static piInit __pi_init; +static lconv * currentLocale = std::localeconv(); -template -class Flags { -private: - int flags; -public: - inline Flags(): flags(0) {;} - inline Flags(Enum e): flags(e) {;} - inline Flags(const Flags & f): flags(f.flags) {;} - inline Flags(const int i): flags(i) {;} - inline void operator =(const Flags & f) {flags = f.flags;} - inline void operator |=(const Flags & f) {flags = flags | f.flags;} - inline void operator |=(const Enum & e) {flags = flags | e;} - inline void operator |=(const int i) {flags = flags | i;} - inline void operator &=(const Flags & f) {flags = flags & f.flags;} - inline void operator &=(const Enum & e) {flags = flags & e;} - inline void operator &=(const int i) {flags = flags & i;} - inline Flags & operator |(Flags f) const {Flags tf(flags | f.flags); return tf;} - inline Flags & operator |(Enum e) const {Flags tf(flags | e); return tf;} - inline Flags & operator |(int i) const {Flags tf(flags | i); return tf;} - inline Flags & operator &(Flags f) const {Flags tf(flags & f.flags); return tf;} - inline Flags & operator &(Enum e) const {Flags tf(flags & e); return tf;} - inline Flags & operator &(int i) const {Flags tf(flags & i); return tf;} - inline bool operator [](Enum e) {return (flags & e) == e;} - inline operator int() const {return flags;} -}; +inline const char * errorString() {return strerror(errno);} #ifdef WINDOWS inline int random() {return rand();} @@ -113,6 +114,7 @@ template inline Type piMin(const Type & f, const Type & s) {retur template inline Type piMax(const Type & f, const Type & s) {return (f < s) ? s : f;} template inline Type piMin(const Type & f, const Type & s, const Type & t) {return (f < s && f < t) ? f : ((s < t) ? s : t);} template inline Type piMax(const Type & f, const Type & s, const Type & t) {return (f > s && f > t) ? f : ((s > t) ? s : t);} +inline ushort letobe_s(ushort v) {return v = (v << 8) | (v >> 8);} inline bool atob(const string & str) { return str == "1" ? true : false;}; inline string btos(const bool num) { return num ? "0" : "1";}; inline string itos(const int num) { diff --git a/pikbdlistener.cpp b/pikbdlistener.cpp index 1f36eb69..cf7bafbc 100644 --- a/pikbdlistener.cpp +++ b/pikbdlistener.cpp @@ -1,9 +1,27 @@ #include "pikbdlistener.h" +bool PIKbdListener::exiting; + PIKbdListener::PIKbdListener(KBFunc slot, void * data_): PIThread() { +#ifdef __WIN32__ + hIn = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(hIn, &smode); +#else + struct termios term; + tcgetattr(0, &term); + sterm = term; +#endif + is_active = true; ret_func = slot; data = data_; + PIKbdListener::exiting = exit_enabled = false; + start(); +} + + +void PIKbdListener::begin() { + //cout << "list begin" << endl; #ifdef __WIN32__ hIn = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(hIn, &smode); @@ -11,19 +29,8 @@ PIKbdListener::PIKbdListener(KBFunc slot, void * data_): PIThread() { #else struct termios term; tcgetattr(0, &term); - sterm = term; term.c_lflag &= ~(ECHO | ICANON) | NOFLSH; tcsetattr(0, TCSAFLUSH, &term); -#endif - start(); -} - - -PIKbdListener::~PIKbdListener() { -#ifdef __WIN32__ - SetConsoleMode(hIn, smode); -#else - tcsetattr(0, TCSANOW, &sterm); #endif } @@ -34,6 +41,16 @@ void PIKbdListener::run() { #else ret = read(0, &rc, 1); #endif - if (ret_func != 0 && ret > 0) ret_func(rc, data); + if (exit_enabled && rc == exit_key) PIKbdListener::exiting = true; + if (ret_func != 0 && ret > 0 && is_active) ret_func(rc, data); } + +void PIKbdListener::end() { + //cout << "list end" << endl; +#ifdef __WIN32__ + SetConsoleMode(hIn, smode); +#else + tcsetattr(0, TCSANOW, &sterm); +#endif +} diff --git a/pikbdlistener.h b/pikbdlistener.h index de3589c5..59dfe1d3 100644 --- a/pikbdlistener.h +++ b/pikbdlistener.h @@ -3,22 +3,37 @@ #include "pithread.h" #ifndef __WIN32__ -#include +# include #endif +#define WAIT_FOR_EXIT while (!PIKbdListener::exiting) msleep(1); + typedef void (*KBFunc)(char, void * ); class PIKbdListener: public PIThread { + friend class PIConsole; public: // slot is any function format "void (char, void * )" PIKbdListener(KBFunc slot = 0, void * data = 0); - ~PIKbdListener(); + ~PIKbdListener() {terminate(); end();} + + inline void enableExitCapture(char key = 'Q') {exit_enabled = true; exit_key = key;} + inline void disableExitCapture() {exit_enabled = false;} + inline bool exitCaptured() const {return exit_enabled;} + inline char exitKey() const {return exit_key;} + inline bool isActive() {return is_active;} + inline void setActive(bool yes = true) {is_active = yes;} + + static bool exiting; private: + void begin(); void run(); + void end(); KBFunc ret_func; - char rc; + char rc, exit_key, is_active; + bool exit_enabled; void * data; #ifdef __WIN32__ DWORD ret; diff --git a/pimath.cpp b/pimath.cpp index d83ffaa7..8ccb91c2 100644 --- a/pimath.cpp +++ b/pimath.cpp @@ -155,7 +155,7 @@ void fft(complexd * x, int T, bool complement) } -const char Solver::methods_desc[] = "Methods:\ +const char Solver::methods_desc[] = "b{Methods:}\ \n -1 - Global settings\ \n 01 - Eyler 1\ \n 02 - Eyler 2\ @@ -167,15 +167,15 @@ const char Solver::methods_desc[] = "Methods:\ \n 34 - Polynomial Approximation 4\ \n 35 - Polynomial Approximation 5"; -Solver::Method Solver::method_global = Solver::AdamsBashfortMoulton_4; +Solver::Method Solver::method_global = Solver::Eyler_2; void Solver::solve(double u, double h) { switch (method) { case Global: switch (method_global) { - case Eyler1: solveEyler1(u, h); break; - case Eyler2: solveEyler2(u, h); break; + case Eyler_1: solveEyler1(u, h); break; + case Eyler_2: solveEyler2(u, h); break; case RungeKutta_4: solveRK4(u, h); break; case AdamsBashfortMoulton_2: solveABM2(u, h); break; case AdamsBashfortMoulton_3: solveABM3(u, h); break; @@ -186,8 +186,8 @@ void Solver::solve(double u, double h) { case PolynomialApproximation_5: solvePA5(u, h); break; } break; - case Eyler1: solveEyler1(u, h); break; - case Eyler2: solveEyler2(u, h); break; + case Eyler_1: solveEyler1(u, h); break; + case Eyler_2: solveEyler2(u, h); break; case RungeKutta_4: solveRK4(u, h); break; case AdamsBashfortMoulton_2: solveABM2(u, h); break; case AdamsBashfortMoulton_3: solveABM3(u, h); break; @@ -273,12 +273,14 @@ void Solver::solveEyler2(double u, double h) { void Solver::solveRK4(double u, double h) { + td = X[0] - F[0][0]; k1 = A * X + d * u; xx = k1 * h / 2.; XX = X + xx; - k2 = A * (XX + k1 * h / 2.) + d * (u + xx[0]); xx = k2 * h / 2.; XX += xx; - k3 = A * (XX + k2 * h / 2.) + d * (u + xx[0]); xx = k3 * h; XX += xx; - k4 = A * (XX + k3 * h) + d * (u + xx[0]); + k2 = A * (XX + k1 * h / 2.) + d * (u + td/3.); xx = k2 * h / 2.; XX += xx; + k3 = A * (XX + k2 * h / 2.) + d * (u + td*2./3.); xx = k3 * h; XX += xx; + k4 = A * (XX + k3 * h) + d * (u + td); //cout << k1 << k2 << k3 << k4 << endl; X += (k1 + k2 * 2. + k3 * 2. + k4) * h / 6.; + F[0] = X; } diff --git a/pimath.h b/pimath.h index 0f7215c5..57a6769f 100644 --- a/pimath.h +++ b/pimath.h @@ -1,27 +1,52 @@ #ifndef PIMATH_H #define PIMATH_H -#include -#include -#include "piincludes.h" +#include "picontainers.h" #ifndef QNX -# include +# include +# include #else -# include +# include +# include #endif +#define M_2PI 6.28318530717958647692 +#define M_PI_3 1.04719755119659774615 + using std::complex; typedef complex complexi; typedef complex complexf; typedef complex complexd; typedef complex complexld; +const complexld complexld_i(0., 1.); +const complexld complexld_0(0.); +const complexld complexld_1(1.); +const complexd complexd_i(0., 1.); +const complexd complexd_0(0.); +const complexd complexd_1(1.); const double deg2rad = atan(1.) / 45.; const double rad2deg = 45. / atan(1.); -inline int pow2(int p) {return (int)1 << p;} +inline int pow2(int p) {return 1 << p;} inline double sqr(const double & v) {return v * v;} +inline double sinc(const double & v) {double t = M_PI * v; return sin(t) / t;} +inline complexd atanc(const complexd & c) {return -complexd(-0.5, 1.) * log((complexd_1 + complexd_i * c) / (complexd_1 - complexd_i * c));} +inline complexd asinc(const complexd & c) {return -complexd_i * log(complexd_i * c + sqrt(complexd_1 - c * c));} +inline complexd acosc(const complexd & c) {return -complexd_i * log(c + complexd_i * sqrt(complexd_1 - c * c));} +#ifdef QNX +inline complexd tan(const complexd & c) {return sin(c) / cos(c);} +inline complexd tanh(const complexd & c) {return sinh(c) / cosh(c);} +inline complexd log2(const complexd & c) {return log(c) / M_LN2;} +inline complexd log10(const complexd & c) {return log(c) / M_LN10;} +inline double j0(const double & v) {v;} +inline double j1(const double & v) {v;} +inline double jn(const int & n, const double & v) {v;} +inline double y0(const double & v) {v;} +inline double y1(const double & v) {v;} +inline double yn(const int & n, const double & v) {v;} +#endif template class PIMathMatrixT; @@ -35,13 +60,15 @@ class PIMathVectorT { typedef PIMathVectorT _CVector; public: PIMathVectorT() {resize(Size);} + //PIMathVectorT(Type val) {resize(Size); PIMV_FOR(i, 0) c[i] = val;} PIMathVectorT(Type fval, ...) {resize(Size); c[0] = fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) c[i] = va_arg(vl, Type); va_end(vl);} PIMathVectorT(const PIVector & val) {resize(Size); PIMV_FOR(i, 0) c[i] = val[i];} - PIMathVectorT(const _CVector & st, const _CVector & fn) {resize(Size); PIMV_FOR(i, 0) c[i] = fn[i] - st[i];} + PIMathVectorT(const _CVector & st, const _CVector & fn) {resize(Size); set(st, fn);} inline uint size() const {return Size;} inline _CVector & fill(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;} inline _CVector & set(Type fval, ...) {c[0] = fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) c[i] = va_arg(vl, Type); va_end(vl); return *this;} + inline _CVector & set(const _CVector & st, const _CVector & fn) {PIMV_FOR(i, 0) c[i] = fn[i] - st[i]; return *this;} inline _CVector & move(const Type & v) {PIMV_FOR(i, 0) c[i] += v; return *this;} inline _CVector & move(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i]; return *this;} inline _CVector & move(Type fval, ...) {c[0] += fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) c[i] += va_arg(vl, Type); va_end(vl); return *this;} @@ -71,12 +98,12 @@ public: inline void operator *=(const _CVector & v) {PIMV_FOR(i, 0) c[i] *= v[i];} inline void operator /=(const Type & v) {PIMV_FOR(i, 0) c[i] /= v;} inline void operator /=(const _CVector & v) {PIMV_FOR(i, 0) c[i] /= v[i];} - inline _CVector operator -() {_CVector tv; PIMV_FOR(i, 0) tv[i] = -c[i]; return tv;} - inline _CVector operator +(const _CVector & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] += v[i]; return tv;} - inline _CVector operator -(const _CVector & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] -= v[i]; return tv;} - inline _CVector operator *(const Type & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v; return tv;} - inline _CVector operator /(const Type & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v; return tv;} - inline _CVector operator *(const _CVector & v) {if (Size < 3) return _CVector(); _CVector tv; tv.fill(Type(1)); tv[0] = c[1]*v[2] - v[1]*c[2]; tv[1] = v[0]*c[2] - c[0]*v[2]; tv[2] = c[0]*v[1] - v[0]*c[1]; return tv;} + inline _CVector operator -() const {_CVector tv; PIMV_FOR(i, 0) tv[i] = -c[i]; return tv;} + inline _CVector operator +(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] += v[i]; return tv;} + inline _CVector operator -(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] -= v[i]; return tv;} + inline _CVector operator *(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v; return tv;} + inline _CVector operator /(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v; return tv;} + inline _CVector operator *(const _CVector & v) const {if (Size > 3) return _CVector(); _CVector tv; tv.fill(Type(1)); tv[0] = c[1]*v[2] - v[1]*c[2]; tv[1] = v[0]*c[2] - c[0]*v[2]; tv[2] = c[0]*v[1] - v[0]*c[1]; return tv;} inline Type operator ^(const _CVector & v) const {Type tv(0); PIMV_FOR(i, 0) tv += c[i] * v[i]; return tv;} inline operator PIMathMatrixT<1, Size, Type>() {return PIMathMatrixT<1, Size, Type>(c);} @@ -96,6 +123,8 @@ private: template inline std::ostream & operator <<(std::ostream & s, const PIMathVectorT & v) {s << '{'; PIMV_FOR(i, 0) {s << v[i]; if (i < Size - 1) s << ", ";} s << '}'; return s;} +template +inline const bool operator ||(const PIMathVectorT & f, const PIMathVectorT & s) {return (f * s).isNull();} //template /// vector {Size0, Type0} to vector {Size1, Type1} //inline operator PIMathVectorT(const PIMathVectorT & v) {PIMathVectorT tv; uint sz = piMin(Size0, Size1); for (uint i = 0; i < sz; ++i) tv[i] = v[i]; return tv;} @@ -637,8 +666,8 @@ class Solver { public: enum Method {Global = -1, - Eyler1 = 01, - Eyler2 = 02, + Eyler_1 = 01, + Eyler_2 = 02, EylerKoshi = 03, RungeKutta_4 = 14, AdamsBashfortMoulton_2 = 22, diff --git a/pimutex.h b/pimutex.h index fe1e1118..e6f63c2a 100644 --- a/pimutex.h +++ b/pimutex.h @@ -11,6 +11,7 @@ public: pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_PROCESS_SHARED); + //pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&mutex, &attr); pthread_mutexattr_destroy(&attr); } diff --git a/pip.h b/pip.h index da53d67c..afb03fb8 100644 --- a/pip.h +++ b/pip.h @@ -1,6 +1,7 @@ #include "pitimer.h" #include "pivariable.h" #include "piconsole.h" -#include "pimath.h" -#include "pidir.h" +#include "picli.h" +#include "pievaluator.h" #include "piprotocol.h" +#include "picodec.h" diff --git a/pip.pro b/pip.pro new file mode 100644 index 00000000..d10d9bd2 --- /dev/null +++ b/pip.pro @@ -0,0 +1,47 @@ +###################################################################### +# Automatically generated by qmake (2.01a) ?? ???. 18 21:49:21 2011 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +HEADERS += pibitarray.h \ + pibytearray.h \ + pichar.h \ + piconfig.h \ + piconsole.h \ + pidir.h \ + piethernet.h \ + pievaluator.h \ + pifile.h \ + pigeometry.h \ + piincludes.h \ + pikbdlistener.h \ + pimath.h \ + pimutex.h \ + pip.h \ + piprotocol.h \ + piserial.h \ + pistring.h \ + pithread.h \ + pitimer.h \ + pivariable.h +SOURCES += main.cpp \ + pibytearray.cpp \ + piconfig.cpp \ + piconsole.cpp \ + pidir.cpp \ + piethernet.cpp \ + pievaluator.cpp \ + pifile.cpp \ + pikbdlistener.cpp \ + pimath.cpp \ + piprotocol.cpp \ + piserial.cpp \ + pistring.cpp \ + pithread.cpp \ + pitimer.cpp \ + pivariable.cpp diff --git a/piprocess.cpp b/piprocess.cpp new file mode 100644 index 00000000..8ac7f2cd --- /dev/null +++ b/piprocess.cpp @@ -0,0 +1,124 @@ +#include "piprocess.h" + + +PIProcess::PIProcess(): PIThread() { + exit_code = -1; + pid = 0; + is_exec = false; + g_in = g_out = g_err = false; + t_in = t_out = t_err = false; + env = PIProcess::currentEnvironment(); +} + + +PIProcess::~PIProcess() { + if (t_in) f_in.remove(); + if (t_out) f_out.remove(); + if (t_err) f_err.remove(); +} + + +void PIProcess::exec_() { + is_exec = false; + startOnce(); + //cout << "exec wait" << endl; + while (!is_exec) + msleep(1); + //cout << "exec end" << endl; +} + + +void PIProcess::run() { + //cout << "run" << endl; + string str; + /// arguments convertion + char * a[args.size_s() + 1]; + for (int i = 0; i < args.size_s(); ++i) { + str = args[i].stdString(); + a[i] = new char[str.size() + 1]; + memcpy(a[i], str.c_str(), str.size()); + a[i][str.size()] = 0; + //cout << a[i] << endl; + } + a[args.size_s()] = 0; + /// environment convertion + char * e[env.size_s() + 1]; + for (int i = 0; i < env.size_s(); ++i) { + str = env[i].stdString(); + e[i] = new char[str.size() + 1]; + memcpy(e[i], str.c_str(), str.size()); + e[i][str.size()] = 0; + //cout << e[i] << endl; + } + e[env.size_s()] = 0; + /// files for stdin/out/err + t_in = t_out = t_err = false; + if (f_in.path().isEmpty()) { + f_in = PIFile::openTemporary(PIFile::New | PIFile::Read); + t_in = true; + } + f_in.open(PIFile::New | PIFile::Read); f_in.close(); + if (f_out.path().isEmpty()) { + f_out = PIFile::openTemporary(PIFile::New | PIFile::Write); + t_out = true; + } + f_out.open(PIFile::New | PIFile::Write); f_out.close(); + if (f_err.path().isEmpty()) { + f_err = PIFile::openTemporary(PIFile::New | PIFile::Write); + t_err = true; + } + f_err.open(PIFile::New | PIFile::Write); f_err.close(); + + str = args.front().stdString(); + is_exec = true; + pid = fork(); + if (pid == 0) { + FILE * tf; + //cout << "exec" << endl; + //cout << f_out.path() << endl; + if (g_in) tf = freopen(f_in.path().data(), "r", stdin); + if (g_out) tf = freopen(f_out.path().data(), "w", stdout); + if (g_err) tf = freopen(f_err.path().data(), "w", stderr); + if (!wd.isEmpty()) system(("cd " + wd).data()); + if (execvpe(str.c_str(), a, e) < 0) + cout << "[PIProcess] \"execvpe\" error, " << errorString() << endl; + } else { + msleep(1); + //cout << "wait" << endl; + wait(&exit_code); + pid = 0; + //cout << "wait done" << endl; + } + is_exec = false; + for (int i = 0; i < env.size_s(); ++i) + delete e[i]; + for (int i = 0; i < args.size_s(); ++i) + delete a[i]; + //cout << "end" << endl; +} + + +void PIProcess::removeEnvironmentVariable(const PIString & variable) { + PIString s; + for (int i = 0; i < env.size_s(); ++i) { + s = env[i]; + if (s.left(s.find("=")).trimmed() == variable) { + env.remove(i); + --i; + } + } +} + + +void PIProcess::setEnvironmentVariable(const PIString & variable, const PIString & value) { + PIString s, v; + for (int i = 0; i < env.size_s(); ++i) { + s = env[i]; + v = s.left(s.find("=")).trimmed(); + if (v == variable) { + env[i] = v + "=" + value; + return; + } + } + env << variable + "=" + value; +} diff --git a/piprocess.h b/piprocess.h new file mode 100644 index 00000000..5f6cac31 --- /dev/null +++ b/piprocess.h @@ -0,0 +1,62 @@ +#ifndef PIPROCESS_H +#define PIPROCESS_H + +#include "pithread.h" +#include "pifile.h" +#include + +/// TODO workind dir + +class PIProcess: private PIThread +{ +public: + PIProcess(); + ~PIProcess(); + + int exitCode() const {return exit_code;} + int pID() const {return pid;} + + void setGrabInput(bool yes) {g_in = yes;} + void setGrabOutput(bool yes) {g_out = yes;} + void setGrabError(bool yes) {g_err = yes;} + void setInputFile(const PIString & path) {f_in.setPath(path);} + void setOutputFile(const PIString & path) {f_out.setPath(path);} + void setErrorFile(const PIString & path) {f_err.setPath(path);} + void unsetInputFile() {f_in.setPath("");} + void unsetOutputFile() {f_out.setPath("");} + void unsetErrorFile() {f_err.setPath("");} + void setWorkingDirectory(const PIString & path) {wd = path;} + void resetWorkingDirectory() {wd.clear();} + void exec(const PIString & program) {args.clear(); args << program; exec_();} + void exec(const PIString & program, const PIString & arg) {args.clear(); args << program << arg; exec_();} + void exec(const PIString & program, const PIString & arg1, const PIString & arg2) {args.clear(); args << program << arg1 << arg2; exec_();} + void exec(const PIString & program, const PIString & arg1, const PIString & arg2, const PIString & arg3) {args.clear(); args << program << arg1 << arg2 << arg3; exec_();} + void exec(const PIString & program, const PIStringList & args_) {args = args_; exec_();} + void terminate() {if (is_exec) ::kill(pid, SIGKILL); pid = 0;} + bool waitForFinish(int timeout_msecs = 60000) {return PIThread::waitForFinish(timeout_msecs);} + PIByteArray readOutput() {f_out.open(PIFile::Read); return f_out.readAll();} + PIByteArray readError() {f_err.open(PIFile::Read); return f_err.readAll();} + + PIStringList environment() {return env;} + void clearEnvironment() {env.clear();} + void removeEnvironmentVariable(const PIString & variable); + void setEnvironmentVariable(const PIString & variable, const PIString & value); + + static PIStringList currentEnvironment() {PIStringList l; int i = 0; while (environ[i] != 0) {l << environ[i]; ++i;} return l;} + +private: + virtual void run(); + void exec_(); + + PIStringList args, env; + PIString wd; + PIByteArray out; + PIFile f_in, f_out, f_err; + bool g_in, g_out, g_err, t_in, t_out, t_err; + pid_t pid; + int exit_code, sz; + bool is_exec; + +}; + +#endif // PIPROCESS_H diff --git a/piprotocol.cpp b/piprotocol.cpp index 00b26b6e..2d3447b9 100644 --- a/piprotocol.cpp +++ b/piprotocol.cpp @@ -1,180 +1,327 @@ #include "piprotocol.h" -PIProtocol::PIProtocol(PIString devName, int speed, void * headerPtr, int headerSize, void * dataPtr, int dataSize) { - init(); - type = PIProtocol::Serial; - serial = new PISerial(devName, this, received); - serial->setReadData(headerPtr, headerSize, dataSize); - this->devName = devName; - this->headerPtr = (unsigned char * )headerPtr; - this->headerSize = headerSize; - this->dataPtr = (unsigned char * )dataPtr; - this->dataSize = dataSize; - packet = new char[headerSize + dataSize]; -} - - -PIProtocol::PIProtocol(PIString ip, int port, void * dataPtr, int dataSize) { - init(); - type = PIProtocol::Ethernet; - ether = new PIEthernet(ip, port, this, received); - this->devName = ip + ":" + itos(port); - this->dataPtr = (unsigned char * )dataPtr; - this->dataSize = dataSize; - packet = new char[dataSize]; +PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr, int recHeaderSize, void * recDataPtr, int recDataSize, void * sendDataPtr_, int sendDataSize_) { + init(); + PIConfig conf(config, PIFile::Read); + if (!conf.isOpened()) { + cout << "[PIProtocol \"" << name << "\"] Can`t open \"" << config << "\"!" << endl; + devReceiverState = devSenderState = "Config error"; + return; + } + int ps; + bool ok; + PIFlags pp; + PIConfig::Entry b = conf.getValue(name), + rb = b.getValue("receiver"), + sb = b.getValue("sender"); + PIString dev; + + /// receiver section + if (rb.isEntryExists("ip") && rb.isEntryExists("device")) { + cout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl; + devReceiverState = "Config error"; + return; + } + dev = rb.getValue("ip", "", &ok); + if (ok) { + ps = rb.getValue("port", 0, &ok); + if (!ok) { + type_rec = PIProtocol::None; + cout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.port\" in \"" << config << "\"!" << endl; + devReceiverState = "Config error"; + return; + } + type_rec = PIProtocol::Ethernet; + eth = new PIEthernet(dev, ps, this, receiveEvent); + devReceiverName = dev + ":" + PIString::fromNumber(ps); + } + dev = rb.getValue("device", "", &ok); + if (ok) { + ps = rb.getValue("speed", 0, &ok); + if (!ok) { + cout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.speed\" in \"" << config << "\"!" << endl; + devReceiverState = "Config error"; + return; + } + if (rb.getValue("parity", false)) pp |= PISerial::ParityControl; + if (rb.getValue("twoStopBits", false)) pp |= PISerial::TwoStopBits; + type_rec = PIProtocol::Serial; + ser = new PISerial(dev, this, receiveEvent); + ser->setInSpeed((PISerial::Speed)ps); + ser->setParameters(pp); + ser->setReadData(recHeaderPtr, recHeaderSize, recDataSize); + devReceiverName = dev; + } + + /// sender section + if (sb.isEntryExists("ip") && sb.isEntryExists("device")) { + cout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl; + devSenderState = "Config error"; + return; + } + dev = sb.getValue("ip", "", &ok); + if (ok) { + ps = sb.getValue("port", 0, &ok); + if (!ok) { + type_send = PIProtocol::None; + cout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.port\" in \"" << config << "\"!" << endl; + devSenderState = "Config error"; + return; + } + type_send = PIProtocol::Ethernet; + if (eth == 0) eth = new PIEthernet(dev, ps, this, receiveEvent); + setSenderAddress(dev, ps); + devSenderName = dev + ":" + PIString::fromNumber(ps); + } + dev = sb.getValue("device", "", &ok); + if (ok) { + ps = sb.getValue("speed", 0, &ok); + if (!ok) { + cout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" in \"" << config << "\"!" << endl; + devSenderState = "Config error"; + return; + } + if (sb.getValue("parity", false)) pp |= PISerial::ParityControl; + if (sb.getValue("twoStopBits", false)) pp |= PISerial::TwoStopBits; + type_send = PIProtocol::Serial; + if (ser == 0) ser = new PISerial(dev, this, receiveEvent); + ser->setOutSpeed((PISerial::Speed)ps); + ser->setParameters(pp); + ser->setReadData(recHeaderPtr, recHeaderSize, recDataSize); + devSenderName = dev; + } + + float fr = rb.getValue("frequency", 0.f, &ok); + if (ok) setExpectedFrequency(fr); + fr = sb.getValue("frequency", 0.f, &ok); + if (ok) setSenderFrequency(fr); + headerPtr = (uchar * )recHeaderPtr; + headerSize = recHeaderSize; + dataPtr = (uchar * )recDataPtr; + dataSize = recDataSize; + sendDataPtr = (uchar * )sendDataPtr_; + sendDataSize = sendDataSize_; + if (type_rec == PIProtocol::Ethernet) { + if (recHeaderPtr != 0) { + dataPtr = (uchar * )recHeaderPtr; + dataSize = recHeaderSize + recDataSize; + if (dataSize > 0) packet = new char[dataSize]; + } else if (recDataSize > 0) packet = new char[recDataSize]; + } else if (recHeaderSize + recDataSize > 0) packet = new char[recHeaderSize + recDataSize]; } PIProtocol::~PIProtocol() { - delete sendtimer; - if (timer != 0) delete timer; - if (type == PIProtocol::Serial) delete serial; - if (type == PIProtocol::Ethernet) delete ether; + delete diagTimer; + delete sendTimer; + if (packet != 0) delete packet; + if (eth != 0) delete eth; + if (ser != 0) delete ser; } void PIProtocol::init() { - work = false; - net_diag = PIProtocol::Unknown; - cur_pckt = 0; - timer = 0; - sendtimer = new PITimer(run, this); - wrong_count = receive_count = send_count = 0; - immediateFreq = integralFreq = 0.f; - headerPtr = dataPtr = sendDataPtr = 0; - headerSize = dataSize = sendDataSize = 0; - exp_freq = 20.f; - devState = "Unknown"; + work = false; + ret_func = 0; + net_diag = PIProtocol::Unknown; + cur_pckt = 0; + diagTimer = 0; + packet = 0; + sendTimer = new PITimer(sendEvent, this); + diagTimer = new PITimer(diagEvent, this); + wrong_count = receive_count = send_count = 0; + send_freq = -1.f; + immediateFreq = integralFreq = exp_freq = 0.f; + headerPtr = dataPtr = sendDataPtr = 0; + headerSize = dataSize = sendDataSize = 0; + eth = 0; + ser = 0; + type_rec = type_send = PIProtocol::None; + devSenderState = devReceiverState = "Unknown"; } -void PIProtocol::setDevice(const PIString & dev_ip, int speed_port) { - if (type == PIProtocol::Serial) { - serial->setDevice(dev_ip); - serial->setSpeed(speed_port); - devName = dev_ip; - } - if (type == PIProtocol::Ethernet) { - ether->setReadAddress(dev_ip, speed_port); - devName = dev_ip + ":" + itos(speed_port); +void PIProtocol::setReceiverDevice(const PIString & device, PISerial::Speed speed) { + if (type_rec == PIProtocol::Serial) { + ser->setDevice(device); + ser->setSpeed(speed); + devReceiverName = device; } } -void PIProtocol::setExpectedFrequency(float frequency) -{ - exp_freq = frequency; - if (exp_freq < 3.33) pckt_cnt_max = 10; - else pckt_cnt_max = 3 * (int)exp_freq; - last_packets.resize(pckt_cnt_max); - timer = new PITimer(diag_event, this); - timer->start(1000. / exp_freq); - timer->reset(); +void PIProtocol::setReceiverDevice(const PIString & ip, int port) { + if (type_rec == PIProtocol::Ethernet) { + eth->setReadAddress(ip, port); + devReceiverName = ip + ":" + PIString::fromNumber(port); + } } -void PIProtocol::startReceive() -{ - if (type == PIProtocol::Serial) serial->start(); - if (type == PIProtocol::Ethernet) ether->start(); +void PIProtocol::setSenderDevice(const PIString & device, PISerial::Speed speed) { + if (type_send == PIProtocol::Serial) { + ser->setDevice(device); + ser->setSpeed(speed); + devSenderName = device; + } } -void PIProtocol::stopReceive() -{ - if (type == PIProtocol::Serial) serial->stop(); - if (type == PIProtocol::Ethernet) ether->stop(); +void PIProtocol::setSenderDevice(const PIString & ip, int port) { + if (type_send == PIProtocol::Ethernet) { + eth->setReadAddress(ip, port); + devSenderName = ip + ":" + PIString::fromNumber(port); + } } -bool PIProtocol::received(void * t, char * data) { - PIProtocol * p = (PIProtocol * )t; - memcpy(p->dataPtr, data, p->dataSize); - p->work = true; - //p->lock(); - if (p->validate()) - { - //p->unlock(); - p->receive_count++; - p->cur_pckt = 1; - return true; - } - //p->unlock(); - p->wrong_count++; - return false; +void PIProtocol::setExpectedFrequency(float frequency) { + exp_freq = frequency; + if (exp_freq < 10.f / 3.f) pckt_cnt_max = 10; + else pckt_cnt_max = round(3.f * exp_freq); + last_packets.resize(pckt_cnt_max); } -void PIProtocol::diag_event(void * t) { - PIProtocol * p = (PIProtocol * )t; - p->calc_freq(); - p->calc_diag(); - p->check_state(); +void PIProtocol::startReceive(float exp_frequency) { + if (exp_frequency > 0.f) exp_freq = exp_frequency; + if (type_rec == PIProtocol::Serial) ser->start(); + if (type_rec == PIProtocol::Ethernet) eth->start(); + if (exp_freq <= 0.f) return; + setExpectedFrequency(exp_freq); + diagTimer->start(1000. / exp_freq); + diagTimer->reset(); +} + + +void PIProtocol::startSend(float frequency) { + if (frequency > 0.f) send_freq = frequency; + if (send_freq <= 0.f) return; + sendTimer->start(1000. / send_freq); +} + + +void PIProtocol::stopReceive() { + if (type_rec == PIProtocol::Serial) ser->stop(); + if (type_rec == PIProtocol::Ethernet) eth->stop(); + diagTimer->stop(); +} + + +bool PIProtocol::receiveEvent(void * t, char * data, int size) { + PIProtocol * p = (PIProtocol * )t; + if (!p->receive(data, size)) return false; + p->work = true; + //p->lock(); + if (p->validate()) + { + //p->unlock(); + p->receive_count++; + p->cur_pckt = 1; + if (p->ret_func != 0) p->ret_func(p); + return true; + } + //p->unlock(); + p->wrong_count++; + return false; +} + + +void PIProtocol::diagEvent(void * t) { + PIProtocol * p = (PIProtocol * )t; + p->calc_freq(); + p->calc_diag(); + p->check_state(); } void PIProtocol::calc_diag() { - PIProtocol::Quality diag; - if (!work) { - diag = PIProtocol::Unknown; - return; - } - if (pckt_cnt < pckt_cnt_max) { - last_packets[pckt_cnt] = cur_pckt; - pckt_cnt++; - } else { - packets[(int)last_packets.back()]--; - last_packets.pop_back(); - last_packets.push_front(cur_pckt); - } - packets[(int)cur_pckt]++; - cur_pckt = 0; - float good_percents; - good_percents = (float)packets[1] / pckt_cnt * 100.0f; - if (good_percents == 0.0) diag = PIProtocol::Failure; - else if (good_percents <= 20.0) diag = PIProtocol::Bad; - else if (good_percents > 20.0 && good_percents <= 80.0) diag = PIProtocol::Average; - else diag = PIProtocol::Good; - if (diag != net_diag) net_diag = diag; + PIProtocol::Quality diag; + if (!work) { + diag = PIProtocol::Unknown; + return; + } + if (pckt_cnt < pckt_cnt_max) { + last_packets[pckt_cnt] = cur_pckt; + pckt_cnt++; + } else { + packets[(int)last_packets.back()]--; + last_packets.pop_back(); + last_packets.push_front(cur_pckt); + } + packets[(int)cur_pckt]++; + cur_pckt = 0; + float good_percents; + good_percents = (float)packets[1] / pckt_cnt * 100.f; + if (good_percents == 0.f) diag = PIProtocol::Failure; + else if (good_percents <= 20.f) diag = PIProtocol::Bad; + else if (good_percents > 20.f && good_percents <= 80.f) diag = PIProtocol::Average; + else diag = PIProtocol::Good; + if (diag != net_diag) net_diag = diag; } void PIProtocol::calc_freq() { - tf = 1000. / timer->elapsed_m(); - timer->reset(); - if (cur_pckt != 1) tf = 0.; - immediateFreq = tf; - if (last_freq.size() >= pckt_cnt_max) last_freq.pop_front(); - last_freq.push_back(tf); - tf = last_freq[0]; - for (uint i = 1; i < last_freq.size(); ++i) - tf += last_freq[i]; - integralFreq = tf / last_freq.size(); + tf = 1000.f / diagTimer->elapsed_m(); + diagTimer->reset(); + if (cur_pckt != 1) tf = 0.f; + immediateFreq = tf; + if (last_freq.size() >= pckt_cnt_max) last_freq.pop_front(); + last_freq.push_back(tf); + tf = last_freq[0]; + for (uint i = 1; i < last_freq.size(); ++i) + tf += last_freq[i]; + integralFreq = tf / last_freq.size(); } void PIProtocol::check_state() { - if (type == PIProtocol::Serial) { - if (serial->initialized()) devState = "Initialized"; - else devState = "Uninitialized"; - } - if (type == PIProtocol::Ethernet) { - if (ether->initialized()) devState = "Initialized"; - else devState = "Uninitialized"; - } + if (type_send == PIProtocol::Serial) { + if (ser->initialized()) devSenderState = "Initialized"; + else devSenderState = "Uninitialized"; + return; + } + if (type_send == PIProtocol::Ethernet) { + if (eth->senderInitialized()) devSenderState = "Initialized"; + else devSenderState = "Uninitialized"; + return; + } + if (type_rec == PIProtocol::Serial) { + if (ser->initialized()) devReceiverState = "Initialized"; + else devReceiverState = "Uninitialized"; + return; + } + if (type_rec == PIProtocol::Ethernet) { + if (eth->receiverInitialized()) devReceiverState = "Initialized"; + else devReceiverState = "Uninitialized"; + return; + } } +void PIProtocol::send(const void * data, int size) { + if (data == 0 || size == 0) return; + if (!aboutSend()) return; + if (type_rec == PIProtocol::Serial) + if (ser->send((char * )data, size)) + send_count++; + if (type_rec == PIProtocol::Ethernet) + if (eth->send((char * )data, size)) + send_count++; +} + void PIProtocol::send() { - //lock(); - memcpy(packet, sendDataPtr, sendDataSize); - //unlock(); - if (type == PIProtocol::Serial) - if (serial->send(packet, sendDataSize)) - send_count++; - if (type == PIProtocol::Ethernet) - if (ether->send(packet, sendDataSize)) - send_count++; + //lock(); + //memcpy(packet, sendDataPtr, sendDataSize); + //unlock(); + if (sendDataPtr == 0 || sendDataSize == 0) return; + if (!aboutSend()) return; + if (type_rec == PIProtocol::Serial) + if (ser->send((char * )sendDataPtr, sendDataSize)) + send_count++; + if (type_rec == PIProtocol::Ethernet) + if (eth->send((char * )sendDataPtr, sendDataSize)) + send_count++; } diff --git a/piprotocol.h b/piprotocol.h index 84d5e7fb..7d2552a7 100644 --- a/piprotocol.h +++ b/piprotocol.h @@ -4,77 +4,108 @@ #include "piserial.h" #include "piethernet.h" #include "pitimer.h" +#include "piconfig.h" +#include "math.h" + +typedef void (*ReceiveFunc)(void * ); class PIProtocol { - enum Type {Serial, Ethernet}; + enum Type {None, Serial, Ethernet}; + enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5}; + public: - PIProtocol(PIString devName, int speed, void * headerPtr, int headerSize, void * dataPtr, int dataSize); // for RS - PIProtocol(PIString ip, int port, void * dataPtr, int dataSize); // for Ethernet - ~PIProtocol(); + PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0, + void * recDataPtr = 0, int recDataSize = 0, void * sendDataPtr = 0, int sendDataSize = 0); // from config + ~PIProtocol(); + + void startReceive(float exp_frequency = -1.f); // if "frequency = -1" used last passed value + void stopReceive(); + void setExpectedFrequency(float frequency); // for connection quality diagnostic + void setReceiverDevice(const PIString & device, PISerial::Speed speed); // for Serial + void setReceiverDevice(const PIString & ip, int port); // for Ethernet + void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize;} + void setReceiverAddress(const PIString & ip, int port) {if (type_send == PIProtocol::Ethernet && eth != 0) eth->setSendAddress(ip, port);} // for Ethernet + void setReceiverParameters(PIFlags parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial + void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;} + + void startSend(float frequency = -1.f); // if "frequency = -1" used last passed value + void stopSend() {sendTimer->stop();} + void setSenderFrequency(float frequency) {send_freq = frequency;} + void setSenderDevice(const PIString & device, PISerial::Speed speed); // for Serial + void setSenderDevice(const PIString & ip, int port); // for Ethernet + void setSenderData(void * dataPtr, int dataSize) {sendDataPtr = (uchar * )dataPtr; sendDataSize = dataSize;} + void setSenderAddress(const PIString & ip, int port) {if (type_send == PIProtocol::Ethernet && eth != 0) eth->setSendAddress(ip, port);} // for Ethernet + void setSenderParameters(PIFlags parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial + + void send(); + void send(const void * data, int size); - enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5}; - - void startReceive(); // start receive - void stopReceive(); // stop receive - void startSend(float frequency = 20.f) {sendtimer->start(frequency > 0 ? 1000.f / frequency : 1000);} // start sending - void stopSend() {sendtimer->stop();} // stop sending - void setDevice(const PIString & dev_ip, int speed_port); - void setSendData(void * dataPtr, int dataSize) {sendDataPtr = (unsigned char * )dataPtr; sendDataSize = dataSize;} - void setReceiveData(void * dataPtr, int dataSize) {this->dataPtr = (unsigned char * )dataPtr; this->dataSize = dataSize;} - void setSendAddress(const PIString & ip, int port) {if (type == PIProtocol::Ethernet) ether->setSendAddress(ip, port);} // for Ethernet - void setParameters(Flags parameters) {if (type == PIProtocol::Serial) serial->setParameters(parameters);} // for RS - - void setExpectedFrequency(float frequency); // for start diagnostic connection quality - float * immediateFrequency_ptr() {return &immediateFreq;} - float * integralFrequency_ptr() {return &integralFreq;} - unsigned long long int * wrongCount_ptr() {return &wrong_count;} - unsigned long long int * receiveCount_ptr() {return &receive_count;} - unsigned long long int * sendCount_ptr() {return &send_count;} - PIProtocol::Quality * quality_ptr() {return &net_diag;} - PIString * deviceState_ptr() {return &devState;} - PIString deviceName() {return devName;} + float immediateFrequency() {return immediateFreq;} + float integralFrequency() {return integralFreq;} + float * immediateFrequency_ptr() {return &immediateFreq;} + float * integralFrequency_ptr() {return &integralFreq;} + ullong receiveCount() {return receive_count;} + ullong * receiveCount_ptr() {return &receive_count;} + ullong wrongCount() {return wrong_count;} + ullong * wrongCount_ptr() {return &wrong_count;} + ullong sendCount() {return send_count;} + ullong * sendCount_ptr() {return &send_count;} + PIProtocol::Quality quality() {return net_diag;} // receive quality + int * quality_ptr() {return (int * )&net_diag;} // receive quality pointer + PIString receiverDeviceName() {return devReceiverName;} + PIString senderDeviceName() {return devSenderName;} + PIString receiverDeviceState() {return devReceiverState;} + PIString * receiverDeviceState_ptr() {return &devReceiverState;} + PIString senderDeviceState() {return devSenderState;} + PIString * senderDeviceState_ptr() {return &devSenderState;} protected: - virtual bool validate() {return true;} // function for validate algorithm and save data from dataPtr to external struct - virtual unsigned int checksum(unsigned char * data, int size) // function for checksum - { - unsigned char c = 0; - for (int i = 0; i < size; ++i) - c += data[i]; - c = ~(c + 1); - return c; - } - virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending + virtual bool receive(char * data, int size) {memcpy(dataPtr, data, size); return true;} // executed when raw data received, break if 'false' return + virtual bool validate() {return true;} // function for validate algorithm and save data from dataPtr to external struct + virtual uint checksum_i(void * data, int size) { // function for checksum (uint) + uint c = 0; + for (int i = 0; i < size; ++i) + c += ((uchar*)data)[i]; + c = ~(c + 1); + return c; + } + virtual uchar checksum_c(void * data, int size) { // function for checksum (uchar) + uchar c = 0; + for (int i = 0; i < size; ++i) + c += ((uchar*)data)[i]; + c = ~(c + 1); + return c; + } + virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending - void init(); - void send(); - void check_state(); - void calc_freq(); - void calc_diag(); - static bool received(void * t, char * data); - static void diag_event(void * t); + void init(); + void check_state(); + void calc_freq(); + void calc_diag(); - PISerial * serial; - PIEthernet * ether; - unsigned int dataSize, headerSize, sendDataSize; - unsigned char * dataPtr, * headerPtr, * sendDataPtr; + PISerial * ser; + PIEthernet * eth; + uint dataSize, headerSize, sendDataSize; + uchar * dataPtr, * headerPtr, * sendDataPtr; private: - static void run(void * e) {PIProtocol* p = (PIProtocol*)e; if (p->aboutSend()) p->send();} - PITimer * timer, * sendtimer; - PIProtocol::Type type; - PIProtocol::Quality net_diag; - deque last_freq; - deque last_packets; - PIString devState, devName; - bool work; - float exp_freq, immediateFreq, integralFreq, tf; - int packets[2]; + static void sendEvent(void * e) {((PIProtocol * )e)->send();} + static bool receiveEvent(void * t, char * data, int size); + static void diagEvent(void * t); + ReceiveFunc ret_func; + PITimer * diagTimer, * sendTimer; + PIProtocol::Type type_send, type_rec; + PIProtocol::Quality net_diag; + deque last_freq; + deque last_packets; + PIString devReceiverName, devReceiverState, devSenderName, devSenderState; + bool work; + float exp_freq, send_freq, immediateFreq, integralFreq, tf; + int packets[2]; uint pckt_cnt, pckt_cnt_max; - char * packet; - char cur_pckt; - unsigned long long int wrong_count, receive_count, send_count; + char * packet, cur_pckt; + ullong wrong_count, receive_count, send_count; }; #endif // PIPROTOCOL_H diff --git a/piserial.cpp b/piserial.cpp index 10c08f5e..d5639784 100644 --- a/piserial.cpp +++ b/piserial.cpp @@ -9,19 +9,21 @@ PISerial::PISerial(PIString name, void * data_, SerialFunc slot): PIThread() { dataSize = headerSize = 0; headerPtr = 0; ret_func = slot; - buffer = new char[BUFFER_SIZE]; - sbuffer = new char[BUFFER_SIZE]; + //buffer = new char[BUFFER_SIZE]; + //sbuffer = new char[BUFFER_SIZE]; #ifdef WINDOWS hCom = 0; #endif - ispeed = ospeed = B115200; + ispeed = ospeed = S115200; } PISerial::~PISerial() { terminate(); - delete buffer; - delete sbuffer; + /*if (buffer != 0) delete buffer; + buffer = 0; + if (sbuffer != 0) delete sbuffer; + sbuffer = 0;*/ } @@ -48,6 +50,24 @@ void PISerial::terminate() { } +int PISerial::convertSpeed(PISerial::Speed speed) { + switch (speed) { + case S110: return B110; + case S300: return B300; + case S600: return B600; + case S1200: return B1200; + case S2400: return B2400; + case S4800: return B4800; + case S9600: return B9600; + case S19200: return B19200; + case S38400: return B38400; + case S57600: return B57600; + case S115200: return B115200; + } + return B115200; +} + + void PISerial::begin() { sbuffIndex = 0; startIndex = 0; @@ -89,7 +109,7 @@ void PISerial::run() { { //cout << "vsdfgvb" << endl; memcpy(pbuffer,&sbuffer[startIndex+headerSize],dataSize); - if (ret_func(data, pbuffer)) + if (ret_func(data, pbuffer, dataSize)) { startIndex = 0; sbuffIndex = -1; @@ -143,7 +163,7 @@ void PISerial::run() { b = buffer[i]; sbuffer[sbuffIndex] = b; if (sbuffIndex == dataSize - 1) { - if (ret_func != 0) ret_func(data, sbuffer); + if (ret_func != 0) ret_func(data, sbuffer, dataSize); sbuffIndex = -1; } sbuffIndex++; @@ -163,7 +183,7 @@ bool PISerial::init() { #ifdef WINDOWS hCom = CreateFileA(devName.stdString().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); if(hCom == INVALID_HANDLE_VALUE) { - cout << "[PISerial] Unable to open " << devName << endl; + cout << "[PISerial] Unable to open \"" << devName << "\"" << endl; return false; } fd = 0; @@ -174,7 +194,7 @@ bool PISerial::init() { times.WriteTotalTimeoutConstant = 0; times.WriteTotalTimeoutMultiplier = 1; if (SetCommTimeouts(hCom, ×) == -1) { - cout << "[PISerial] Unable to set timeouts for " << devName << endl; + cout << "[PISerial] Unable to set timeouts for \"" << devName << "\"" << endl; CloseHandle(hCom); fd = -1; return false; @@ -184,12 +204,12 @@ bool PISerial::init() { GetCommState(hCom, &sdesc); desc = sdesc; desc.DCBlength = sizeof(desc); - desc.BaudRate = ispeed; + desc.BaudRate = convertSpeed(ispeed); desc.ByteSize = 8; desc.fParity = params[PISerial::IgnoreParityControl] ? 0 : 1; desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT; if (SetCommState(hCom, &desc) == -1) { - cout << "[PISerial] Unable to set comm state for " << devName << endl; + cout << "[PISerial] Unable to set comm state for \"" << devName << "\"" << endl; CloseHandle(hCom); fd = -1; return false; @@ -197,7 +217,7 @@ bool PISerial::init() { #else fd = open(devName.data(), O_NOCTTY | O_RDWR); if(fd == -1) { - cout << "[PISerial] Unable to open " << devName << endl; + cout << "[PISerial] Unable to open \"" << devName << "\"" << endl; return false; } fcntl(fd, F_SETFL, 0); @@ -206,16 +226,20 @@ bool PISerial::init() { sdesc = desc; desc.c_iflag = desc.c_oflag = desc.c_lflag = 0; desc.c_cflag = CLOCAL | CREAD | CSIZE; - if (params[PISerial::TwoStopBits]) desc.c_cflag &= CSTOPB; - if (params[PISerial::IgnoreParityControl]) desc.c_iflag &= IGNPAR ; // | INPCK | IGNBRK | IGNCR; + if (params[PISerial::TwoStopBits]) desc.c_cflag |= CSTOPB; + if (!params[PISerial::ParityControl]) { + desc.c_iflag |= INPCK; + desc.c_cflag |= PARENB; + if (!params[PISerial::ParityOdd]) desc.c_cflag |= PARODD; + } desc.c_cc[VMIN] = 0; desc.c_cc[VTIME] = 1; - cfsetispeed(&desc, ispeed); - cfsetospeed(&desc, ospeed); + cfsetispeed(&desc, convertSpeed(ispeed)); + cfsetospeed(&desc, convertSpeed(ospeed)); if(tcsetattr(fd, TCSANOW, &desc) < 0) { - cout << "[PISerial] Can`t set attributes for " << devName << endl; + cout << "[PISerial] Can`t set attributes for \"" << devName << "\"" << endl; close(fd); return false; } diff --git a/piserial.h b/piserial.h index 0e7185ec..6497db24 100644 --- a/piserial.h +++ b/piserial.h @@ -25,23 +25,36 @@ #define BUFFER_SIZE 4096 -typedef bool (*SerialFunc)(void * , char * ); +typedef bool (*SerialFunc)(void * , char * , int ); class PISerial: public PIThread { public: - // slot is any function format "bool (void*, char*)" + // slot is any function format "bool (void*, char*, int)" PISerial(PIString name = "serial", void * data = 0, SerialFunc slot = 0); ~PISerial(); - enum Parameters {IgnoreParityControl = 0x01, TwoStopBits = 0x02}; + enum Parameters {ParityControl = 0x01, ParityOdd = 0x02, TwoStopBits = 0x04}; + enum Speed { + S110 = 110, + S300 = 300, + S600 = 600, + S1200 = 1200, + S2400 = 2400, + S4800 = 4800, + S9600 = 9600, + S19200 = 19200, + S38400 = 38400, + S57600 = 57600, + S115200 = 115200 + }; void setSlot(SerialFunc func) {ret_func = func;} - void setSpeed(int speed) {ospeed = ispeed = speed;} - void setOutSpeed(int speed) {ospeed = speed;} - void setInSpeed(int speed) {ispeed = speed;} + void setSpeed(PISerial::Speed speed) {ospeed = ispeed = speed;} + void setOutSpeed(PISerial::Speed speed) {ospeed = speed;} + void setInSpeed(PISerial::Speed speed) {ispeed = speed;} void setDevice(const PIString & dev) {devName = dev;} - void setParameters(Flags parameters) {params = parameters;} + void setParameters(PIFlags parameters) {params = parameters;} void setData(void * d) {data = d;} void setReadData(void * headerPtr, int headerSize, int dataSize) {this->headerPtr = headerPtr; this->headerSize = headerSize; @@ -53,6 +66,8 @@ public: void terminate(); private: + int convertSpeed(PISerial::Speed speed); + void begin(); void run(); void end(); @@ -65,13 +80,14 @@ private: termios desc, sdesc; uint readed; #endif - int fd, ospeed, ispeed; + int fd; + PISerial::Speed ospeed, ispeed; PIString devName; SerialFunc ret_func; - char * buffer, * sbuffer, * hbuffer, * pbuffer; + char buffer[BUFFER_SIZE], sbuffer[BUFFER_SIZE], * hbuffer, * pbuffer; void * headerPtr, * data; int dataSize, headerSize, sbuffIndex, startIndex, backIndex; - Flags params; + PIFlags params; bool first, tryagain; }; diff --git a/pistring.cpp b/pistring.cpp index e43cf32a..6b16db2a 100644 --- a/pistring.cpp +++ b/pistring.cpp @@ -1,14 +1,46 @@ #include "pistring.h" +void PIString::appendFromChars(const char * c, int s) { + int sz; + wchar_t wc; + for (int i = 0; i < s; ++i) { + if (isascii(c[i])) { + push_back(PIChar(c[i])); + continue; + } + sz = mbtowc(&wc, &c[i], 4); + switch (sz) { + case 4: + push_back(PIChar(*(int*)&(c[i]))); + i += 3; + continue; + case 3: + push_back(PIChar(*(int*)&(c[i]))); + back().ch &= 0xFFFFFF; + i += 2; + continue; + case 2: + push_back(PIChar(*(short * )&(c[i]))); + ++i; + continue; + default: + push_back(PIChar(c[i])); + break; + } + } +} + + PIString & PIString::operator +=(const char * str) { - uint i = 0; - while (str[i] != '\0') push_back(str[i++]); + int l = 0; + while (str[l] != '\0') ++l; + appendFromChars(str, l); return *this; } -PIString & PIString::operator +=(const string & str) { +PIString & PIString::operator +=(const wstring & str) { uint l = str.size(); for (uint i = 0; i < l; ++i) push_back(str[i]); return *this; @@ -22,13 +54,6 @@ PIString & PIString::operator +=(const PIString & str) { } -PIString & PIString::operator +=(const PIByteArray & ba) { - uint l = ba.size(); - for (uint i = 0; i < l; ++i) push_back(ba[i]); - return *this; -} - - bool PIString::operator ==(const PIString & str) const { uint l = str.size(); if (size() != l) return false; @@ -49,6 +74,32 @@ bool PIString::operator !=(const PIString & str) const { } +bool PIString::operator <(const PIString & str) const { + uint l = str.size(); + if (size() < l) return true; + if (size() > l) return false; + for (uint i = 0; i < l; ++i) { + if (str[i] == at(i)) continue; + if (str[i] < at(i)) return true; + else return false; + } + return false; +} + + +bool PIString::operator >(const PIString & str) const { + uint l = str.size(); + if (size() < l) return false; + if (size() > l) return true; + for (uint i = 0; i < l; ++i) { + if (str[i] == at(i)) continue; + if (str[i] < at(i)) return false; + else return true; + } + return false; +} + + PIString PIString::mid(const int start, const int len) const { PIString str; int s = start, l = len; @@ -82,24 +133,12 @@ PIString & PIString::cutMid(const int start, const int len) { else { if (l > length() - s) l = length() - s; - remove(s, s + l); + remove(s, l); } return *this; } -PIString PIString::trimmed() const { - int st = 0, fn = 0; - for (int i = 0; i < length(); ++i) - if (at(i) != ' ' && at(i) != '\t') - {st = i; break;} - for (int i = length() - 1; i >= 0; --i) - if (at(i) != ' ' && at(i) != '\t') - {fn = i; break;} - return mid(st, fn - st + 1); -} - - PIString & PIString::trim() { int st = 0, fn = 0; for (int i = 0; i < length(); ++i) @@ -113,9 +152,53 @@ PIString & PIString::trim() { } -PIStringList PIString::split(const PIString & delim) { - PIString ts(*this); +PIString PIString::trimmed() const { + int st = 0, fn = 0; + for (int i = 0; i < length(); ++i) + if (at(i) != ' ' && at(i) != '\t') + {st = i; break;} + for (int i = length() - 1; i >= 0; --i) + if (at(i) != ' ' && at(i) != '\t') + {fn = i; break;} + return mid(st, fn - st + 1); +} + + +PIString & PIString::replace(int from, int count, const PIString & with) { + if (count < length() - from) remove(from, count); + else remove(from, length() - from); + uint c = with.length(); + for (uint i = 0; i < c; ++i) insert(from + i, with[i]); + return *this; +} + + +PIString & PIString::replace(const PIString & what, const PIString & with, bool * ok) { + int s = find(what); + if (s >= 0) replace(s, what.length(), with); + if (ok != 0) *ok = (s >= 0); + return *this; +} + + +PIString & PIString::replaceAll(const PIString & what, const PIString & with) { + bool ok = true; + while (ok) replace(what, with, &ok); + return *this; +} + + +PIString & PIString::insert(int index, const PIString & str) { + uint c = str.length(); + for (uint i = 0; i < c; ++i) insert(index + i, str[i]); + return *this; +} + + +PIStringList PIString::split(const PIString & delim) const { PIStringList sl; + if (isEmpty() || delim.isEmpty()) return sl; + PIString ts(*this); int ci = ts.find(delim); while (ci >= 0) { sl << ts.left(ci); @@ -127,7 +210,7 @@ PIStringList PIString::split(const PIString & delim) { } -int PIString::find(const char str, const int start) { +int PIString::find(const char str, const int start) const { for (int i = start; i < length(); ++i) if (at(i) == str) return i; @@ -135,7 +218,7 @@ int PIString::find(const char str, const int start) { } -int PIString::find(const PIString str, const int start) { +int PIString::find(const PIString str, const int start) const { int l = str.length(); for (int i = start; i < length() - l + 1; ++i) if (mid(i, l) == str) @@ -144,7 +227,7 @@ int PIString::find(const PIString str, const int start) { } -int PIString::findLast(const char str, const int start) { +int PIString::findLast(const char str, const int start) const { for (int i = length() - 1; i >= start; --i) if (at(i) == str) return i; @@ -152,7 +235,7 @@ int PIString::findLast(const char str, const int start) { } -int PIString::findLast(const PIString str, const int start) { +int PIString::findLast(const PIString str, const int start) const { int l = str.length(); for (int i = length() - l; i >= start; --i) if (mid(i, l) == str) @@ -164,7 +247,7 @@ int PIString::findLast(const PIString str, const int start) { PIString PIString::toUpperCase() const { PIString str(*this); int l = str.size(); - for (int i = 0; i < l; ++i) str[i] = chrUpr(str[i]); + for (int i = 0; i < l; ++i) str[i] = str[i].toUpper(); return str; } @@ -172,11 +255,78 @@ PIString PIString::toUpperCase() const { PIString PIString::toLowerCase() const { PIString str(*this); int l = str.size(); - for (int i = 0; i < l; ++i) str[i] = chrLwr(str[i]); + for (int i = 0; i < l; ++i) str[i] = str[i].toLower(); return str; } +string PIString::convertToStd() const { + string s; + if (size() > 0) { + for (int i = 0; i < length(); ++i) { + if (at(i).isAscii()) + s.push_back(at(i).toAscii()); + else { + s.push_back(at(i).toCharPtr()[0]); + s.push_back(at(i).toCharPtr()[1]); + } + } + } + return s; +} + + +char PIString::toChar() const { + PIString s(toNativeDecimalPoints()); + char v; + sscanf(s.data(), "%c", &v); + return v; +} + + +short PIString::toShort() const { + PIString s(trimmed().toNativeDecimalPoints()); + int i; + short v; + if (s.left(2) == "0x") {sscanf(s.data(), "%x", &i); return (short)i;} + if (s.left(1) == "0") {sscanf(s.data(), "%o", &i); return (short)i;} + sscanf(s.data(), "%hd", &v); + return v; +} + + +int PIString::toInt() const { + PIString s(trimmed().toNativeDecimalPoints()); + int v; + if (s.left(2) == "0x") {sscanf(s.data(), "%x", &v); return v;} + if (s.left(1) == "0") {sscanf(s.data(), "%o", &v); return v;} + sscanf(s.data(), "%d", &v); + return v; +} + + +long PIString::toLong() const { + PIString s(trimmed().toNativeDecimalPoints()); + int i; + long v; + if (s.left(2) == "0x") {sscanf(s.data(), "%x", &i); return (long)i;} + if (s.left(1) == "0") {sscanf(s.data(), "%o", &i); return (long)i;} + sscanf(s.data(), "%ld", &v); + return v; +} + + +llong PIString::toLLong() const { + PIString s(trimmed().toNativeDecimalPoints()); + int i; + llong v; + if (s.left(2) == "0x") {sscanf(s.data(), "%x", &i); return (llong)i;} + if (s.left(1) == "0") {sscanf(s.data(), "%o", &i); return (llong)i;} + sscanf(s.data(), "%Ld", &v); + return v; +} + + char chrUpr(char c) { if (c >= 'a' && c <= 'z') return c + 'A' - 'a'; //if (c >= 'а' && c <= 'я') return c + 'А' - 'а'; @@ -189,3 +339,25 @@ char chrLwr(char c) { //if (c >= 'А' && c <= 'Я') return c + 'а' - 'А'; return c; } + + +PIStringList& PIStringList::removeDuplicates() { + PIStringList l; + PIString s; + bool ae; + for (uint i = 0; i < size(); ++i) { + ae = false; + s = at(i); + for (uint j = 0; j < l.size(); ++j) { + if (s != l[j]) continue; + ae = true; break; + } + if (!ae) { + l << s; + continue; + } + remove(i); + --i; + } + return *this; +} diff --git a/pistring.h b/pistring.h index 87828d21..557ac732 100644 --- a/pistring.h +++ b/pistring.h @@ -2,112 +2,179 @@ #define PISTRING_H #include "pibytearray.h" +#include "pichar.h" class PIStringList; -class PIString: public PIVector +class PIString: public PIVector { public: PIString() {;} - PIString(const char & c) {*this += c;} + + //inline PIString & operator +=(const char c) {push_back(c); return *this;} + PIString & operator +=(const PIChar c) {push_back(c); return *this;} + PIString & operator +=(const char * str); + PIString & operator +=(const string & str) {appendFromChars(str.c_str(), str.length()); return *this;} + PIString & operator +=(const PIByteArray & ba) {appendFromChars((const char * )ba.data(), ba.size_s()); return *this;} + PIString & operator +=(const PIString & str); + PIString & operator +=(const wstring & str); + + //PIString(const char c) {*this += c;} + PIString(const PIChar c) {*this += c;} PIString(const char * str) {*this += str;} PIString(const string & str) {*this += str;} + PIString(const wstring & str) {*this += str;} PIString(const PIString & str) {*this += str;} PIString(const PIByteArray & ba) {*this += ba;} - PIString(const int len, const char c = ' ') {for (int i = 0; i < len; ++i) push_back(c);} + PIString(const char * str, const int len) {*this += string(str, len);} + PIString(const int len, const char c) {for (int i = 0; i < len; ++i) push_back(c);} + PIString(const int len, const PIChar & c) {for (int i = 0; i < len; ++i) push_back(c);} operator const char*() {return data();} - operator const string() {return (size() == 0) ? string() : string(&at(0), size());} - inline char & operator [](const int pos) {return at(pos);} - inline const char operator [](const int pos) const {return at(pos);} - - PIString & operator +=(const PIString & str); - PIString & operator +=(const PIByteArray & ba); - inline PIString & operator +=(const char & c) {push_back(c); return *this;} - PIString & operator +=(const char * str); - PIString & operator +=(const string & str); + operator const string() {if (size() == 0) return string(); string s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toAscii()); return s;} +#ifdef WINDOWS + PIChar operator [](const int pos) const __attribute__ ((optimize(0))) {return at(pos);} +#else + PIChar operator [](const int pos) const {return at(pos);} +#endif + PIChar & operator [](const int pos) {return at(pos);} bool operator ==(const PIString & str) const; - inline bool operator ==(const PIByteArray & ba) const {return *this == PIString(ba);} - inline bool operator ==(const char & c) const {return *this == PIString(c);} - inline bool operator ==(const char * str) const {return *this == PIString(str);} - inline bool operator ==(const string & str) const {return *this == PIString(str);} + bool operator ==(const PIChar c) const {return *this == PIString(c);} + //inline bool operator ==(const char c) const {return *this == PIString(c);} + bool operator ==(const char * str) const {return *this == PIString(str);} + bool operator ==(const string & str) const {return *this == PIString(str);} bool operator !=(const PIString & str) const; - inline bool operator !=(const PIByteArray & ba) const {return *this != PIString(ba);} - inline bool operator !=(const char & c) const {return *this != PIString(c);} - inline bool operator !=(const char * str) const {return *this != PIString(str);} - inline bool operator !=(const string & str) const {return *this != PIString(str);} + bool operator !=(const PIChar c) const {return *this != PIString(c);} + //inline bool operator !=(const char c) const {return *this != PIString(c);} + bool operator !=(const char * str) const {return *this != PIString(str);} + bool operator !=(const string & str) const {return *this != PIString(str);} - inline PIString & operator <<(const PIString & str) {*this += str; return *this;} - inline PIString & operator <<(const PIByteArray & ba) {*this += ba; return *this;} - inline PIString & operator <<(const char & c) {*this += c; return *this;} - inline PIString & operator <<(const char * str) {*this += str; return *this;} - inline PIString & operator <<(const string & str) {*this += str; return *this;} - inline PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;} - inline PIString & operator <<(const short & num) {*this += PIString::fromNumber(num); return *this;} - inline PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;} - inline PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;} - inline PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;} + bool operator <(const PIString & str) const; + bool operator <(const PIChar c) const {return *this < PIString(c);} + //inline bool operator <(const char c) const {return *this < PIString(c);} + bool operator <(const char * str) const {return *this < PIString(str);} + bool operator <(const string & str) const {return *this < PIString(str);} + + bool operator >(const PIString & str) const; + bool operator >(const PIChar c) const {return *this > PIString(c);} + //inline bool operator >(const char c) const {return *this > PIString(c);} + bool operator >(const char * str) const {return *this > PIString(str);} + bool operator >(const string & str) const {return *this > PIString(str);} + + bool operator <=(const PIString & str) const {return !(*this > str);} + bool operator <=(const PIChar c) const {return *this <= PIString(c);} + //inline bool operator <=(const char c) const {return *this <= PIString(c);} + bool operator <=(const char * str) const {return *this <= PIString(str);} + bool operator <=(const string & str) const {return *this <= PIString(str);} + + bool operator >=(const PIString & str) const {return !(*this < str);} + bool operator >=(const PIChar c) const {return *this >= PIString(c);} + //inline bool operator >=(const char c) const {return *this >= PIString(c);} + bool operator >=(const char * str) const {return *this >= PIString(str);} + bool operator >=(const string & str) const {return *this >= PIString(str);} + + PIString & operator <<(const PIString & str) {*this += str; return *this;} + //inline PIString & operator <<(const char c) {*this += c; return *this;} + PIString & operator <<(const PIChar c) {*this += c; return *this;} + PIString & operator <<(const char * str) {*this += str; return *this;} + PIString & operator <<(const string & str) {*this += str; return *this;} + PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;} + PIString & operator <<(const short & num) {*this += PIString::fromNumber(num); return *this;} + PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;} + PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;} + PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;} PIString mid(const int start, const int len = -1) const; - inline PIString left(const int len) const {return len <= 0 ? PIString() : mid(0, len);} - inline PIString right(const int len) const {return len <= 0 ? PIString() : mid(size() - len, len);} + PIString left(const int len) const {return len <= 0 ? PIString() : mid(0, len);} + PIString right(const int len) const {return len <= 0 ? PIString() : mid(size() - len, len);} PIString & cutMid(const int start, const int len); - inline PIString & cutLeft(const int len) {return len <= 0 ? *this : cutMid(0, len);} - inline PIString & cutRight(const int len) {return len <= 0 ? *this : cutMid(size() - len, len);} - PIString trimmed() const; + PIString & cutLeft(const int len) {return len <= 0 ? *this : cutMid(0, len);} + PIString & cutRight(const int len) {return len <= 0 ? *this : cutMid(size() - len, len);} PIString & trim(); - const char * data() const {return stdString().c_str();} - string stdString() const {return (size() == 0) ? string() : string(&at(0), size());} - PIStringList split(const PIString & delim); + PIString trimmed() const; + PIString & replace(const int from, const int count, const PIString & with); + PIString replaced(const int from, const int count, const PIString & with) const {PIString str(*this); str.replace(from, count, with); return str;} + PIString & replace(const PIString & what, const PIString & with, bool * ok = 0); + PIString replaced(const PIString & what, const PIString & with, bool * ok = 0) const {PIString str(*this); str.replace(what, with, ok); return str;} + PIString & replaceAll(const PIString & what, const PIString & with); + PIString replaceAll(const PIString & what, const PIString & with) const {PIString str(*this); str.replaceAll(what, with); return str;} + PIString & insert(const int index, const PIChar & c) {PIVector::insert(index, c); return *this;} + PIString & insert(const int index, const char & c) {return insert(index, PIChar(c));} + PIString & insert(const int index, const PIString & str); + PIString & insert(const int index, const char * c) {return insert(index, PIString(c));} + PIString & expandRightTo(const int len, const PIChar & c) {if (len > length()) resize(len, c); return *this;} + PIString & expandLeftTo(const int len, const PIChar & c) {if (len > length()) insert(0, PIString(len - length(), c)); return *this;} + + const char * data() {std_string = convertToStd(); return std_string.c_str();} + const string stdString() const {return convertToStd();} + wstring stdWString() const {return convertToWString();} + PIByteArray toByteArray() {convertToStd(); return PIByteArray(std_string.c_str(), std_string.length());} + PIStringList split(const PIString & delim) const; PIString toUpperCase() const; PIString toLowerCase() const; + PIString toNativeDecimalPoints() const {PIString s(*this); if (currentLocale == 0) return s; return s.replaceAll(".", currentLocale->decimal_point);} - int find(const char str, const int start = 0); - int find(const PIString str, const int start = 0); - inline int find(const char * str, const int start = 0) {return find(PIString(str), start);} - inline int find(const string str, const int start = 0) {return find(PIString(str), start);} - int findLast(const char str, const int start = 0); - int findLast(const PIString str, const int start = 0); - inline int findLast(const char * str, const int start = 0) {return findLast(PIString(str), start);} - inline int findLast(const string str, const int start = 0) {return findLast(PIString(str), start);} + int find(const char str, const int start = 0) const; + int find(const PIString str, const int start = 0) const; + int find(const char * str, const int start = 0) const {return find(PIString(str), start);} + int find(const string str, const int start = 0) const {return find(PIString(str), start);} + int findLast(const char str, const int start = 0) const; + int findLast(const PIString str, const int start = 0) const; + int findLast(const char * str, const int start = 0) const {return findLast(PIString(str), start);} + int findLast(const string str, const int start = 0) const {return findLast(PIString(str), start);} - inline int length() const {return size();} - inline bool isEmpty() const {return size() == 0;} + int length() const {return size();} + bool isEmpty() const {return (size() == 0 || *this == "");} - int toInt() const {return atoi(data());} - short toShort() const {return (short)atoi(data());} - long toLong() const {return atol(data());} - float toFloat() const {return (float)atof(data());} - double toDouble() const {return atof(data());} - inline PIByteArray toBase64() {return PIByteArray(data(), size()).toBase64();} + bool toBool() const {PIString s(*this); if (atof(s.toNativeDecimalPoints().data()) > 0. || s.trimmed().toLowerCase() == "true") return true; return false;} + char toChar() const; + short toShort() const; + int toInt() const; + long toLong() const; + llong toLLong() const; + float toFloat() const {PIString s(*this); return (float)atof(s.toNativeDecimalPoints().data());} + double toDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());} + ldouble toLDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());} - inline PIString & setNumber(const int value) {clear(); *this += itos(value); return *this;} - inline PIString & setNumber(const short value) {clear(); *this += itos(value); return *this;} - inline PIString & setNumber(const long value) {clear(); *this += ltos(value); return *this;} - inline PIString & setNumber(const float value) {clear(); *this += ftos(value); return *this;} - inline PIString & setNumber(const double value) {clear(); *this += dtos(value); return *this;} + //inline PIString & setNumber(const char value) {clear(); *this += itos(value); return *this;} + PIString & setNumber(const int value) {clear(); *this += itos(value); return *this;} + PIString & setNumber(const short value) {clear(); *this += itos(value); return *this;} + PIString & setNumber(const long value) {clear(); *this += ltos(value); return *this;} + PIString & setNumber(const float value) {clear(); *this += ftos(value); return *this;} + PIString & setNumber(const double value) {clear(); *this += dtos(value); return *this;} + PIString & setNumber(const ldouble value) {clear(); *this += dtos(value); return *this;} - inline static PIString fromNumber(const int value) {return PIString(itos(value));} - inline static PIString fromNumber(const uint value) {return PIString(itos(value));} - inline static PIString fromNumber(const short value) {return PIString(itos(value));} - inline static PIString fromNumber(const long value) {return PIString(ltos(value));} - inline static PIString fromNumber(const float value) {return PIString(ftos(value));} - inline static PIString fromNumber(const double value) {return PIString(dtos(value));} + //inline static PIString fromNumber(const char value) {return PIString(itos(value));} + static PIString fromNumber(const int value) {return PIString(itos(value));} + static PIString fromNumber(const uint value) {return PIString(itos(value));} + static PIString fromNumber(const short value) {return PIString(itos(value));} + static PIString fromNumber(const long value) {return PIString(ltos(value));} + static PIString fromNumber(const float value) {return PIString(ftos(value));} + static PIString fromNumber(const double value) {return PIString(dtos(value));} + static PIString fromNumber(const ldouble value) {return PIString(dtos(value));} + static PIString fromBool(const bool value) {return PIString(value ? "true" : "false");} + +private: + void appendFromChars(const char * c, int s); + string convertToStd() const; + wstring convertToWString() const {wstring s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toWChar()); return s;} + + string std_string; }; +inline std::ostream & operator <<(std::ostream & s, const PIString & v) {for (int i = 0; i < v.length(); ++i) s << v[i]; return s;} + inline PIString operator +(const PIString & str, const PIString & f) {PIString s(str); s += f; return s;} -inline PIString operator +(const PIString & f, const PIByteArray & ba) {PIString s(f); s += ba; return s;} -inline PIString operator +(const PIString & f, const char & c) {PIString s(f); s.push_back(c); return s;} +//inline PIString operator +(const PIString & f, const char c) {PIString s(f); s.push_back(c); return s;} inline PIString operator +(const PIString & f, const char * str) {PIString s(f); s += str; return s;} inline PIString operator +(const PIString & f, const string & str) {PIString s(f); s += str; return s;} -inline PIString operator +(const PIByteArray & ba, const PIString & f) {return PIString(ba) + f;} -inline PIString operator +(const char & c, const PIString & f) {return PIString(c) + f;} +//inline PIString operator +(const char c, const PIString & f) {return PIString(c) + f;} inline PIString operator +(const char * str, const PIString & f) {return PIString(str) + f;} inline PIString operator +(const string & str, const PIString & f) {return PIString(str) + f;} @@ -119,20 +186,29 @@ class PIStringList: public PIVector public: PIStringList() {;} PIStringList(const PIString & str) {push_back(str);} + PIStringList(const PIString & s0, const PIString & s1) {push_back(s0); push_back(s1);} + PIStringList(const PIString & s0, const PIString & s1, const PIString & s2) {push_back(s0); push_back(s1); push_back(s2);} + 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);} - inline PIString join(const PIString & delim) const {PIString s; for (uint i = 0; i < size(); ++i) {s += at(i); if (i < size() - 1) s += delim;} return s;} + PIString join(const PIString & delim) const {PIString s; for (uint i = 0; i < size(); ++i) {s += at(i); if (i < size() - 1) s += delim;} return s;} + PIStringList & removeStrings(const PIString & value) {for (uint i = 0; i < size(); ++i) {if (at(i) == value) {remove(i); --i;}} return *this;} + PIStringList & remove(uint num) {PIVector::remove(num); return *this;} + PIStringList & remove(uint num, uint count) {PIVector::remove(num, count); return *this;} + PIStringList & removeDuplicates(); + uint contentSize() {uint s = 0; for (uint i = 0; i < size(); ++i) s += at(i).size(); return s;} - inline PIStringList & operator <<(const PIString & str) {push_back(str); return *this;} - inline PIStringList & operator <<(const PIByteArray & ba) {push_back(ba); return *this;} - inline PIStringList & operator <<(const char & c) {push_back(PIString(c)); return *this;} - inline PIStringList & operator <<(const char * str) {push_back(PIString(str)); return *this;} - inline PIStringList & operator <<(const string & str) {push_back(str); return *this;} - inline PIStringList & operator <<(const int & num) {push_back(PIString::fromNumber(num)); return *this;} - inline PIStringList & operator <<(const short & num) {push_back(PIString::fromNumber(num)); return *this;} - inline PIStringList & operator <<(const long & num) {push_back(PIString::fromNumber(num)); return *this;} - inline PIStringList & operator <<(const float & num) {push_back(PIString::fromNumber(num)); return *this;} - inline PIStringList & operator <<(const double & num) {push_back(PIString::fromNumber(num)); return *this;} + PIStringList & operator <<(const PIString & str) {push_back(str); return *this;} + //inline PIStringList & operator <<(const char c) {push_back(PIString(c)); return *this;} + PIStringList & operator <<(const char * str) {push_back(PIString(str)); return *this;} + PIStringList & operator <<(const string & str) {push_back(str); return *this;} + PIStringList & operator <<(const int & num) {push_back(PIString::fromNumber(num)); return *this;} + PIStringList & operator <<(const short & num) {push_back(PIString::fromNumber(num)); return *this;} + PIStringList & operator <<(const long & num) {push_back(PIString::fromNumber(num)); return *this;} + PIStringList & operator <<(const float & num) {push_back(PIString::fromNumber(num)); return *this;} + PIStringList & operator <<(const double & num) {push_back(PIString::fromNumber(num)); return *this;} }; +inline std::ostream & operator <<(std::ostream & s, const PIStringList & v) {s << "{"; for (uint i = 0; i < v.size(); ++i) {s << '\"' << v[i] << '\"'; if (i < v.size() - 1) s << ", ";} s << "}"; return s;} + #endif // PISTRING_H diff --git a/pithread.cpp b/pithread.cpp index 9483def5..ddd04853 100644 --- a/pithread.cpp +++ b/pithread.cpp @@ -17,7 +17,7 @@ PIThread::~PIThread() { bool PIThread::start(int timer_delay) { pthread_attr_t attr; - terminating = false; + terminating = running = false; timer = timer_delay; pthread_attr_init(&attr); pthread_attr_setschedparam(&attr, &sparam); @@ -29,13 +29,25 @@ bool PIThread::start(int timer_delay) { } +bool PIThread::startOnce() { + pthread_attr_t attr; + terminating = running = false; + pthread_attr_init(&attr); + pthread_attr_setschedparam(&attr, &sparam); + if (pthread_create(&thread, &attr, thread_function_once, this) == 0) + return true; + return false; +} + + void * PIThread::thread_function(void * t) { PIThread * ct = (PIThread * )t; + ct->running = true; ct->begin(); while (!ct->terminating) { if (ct->lockRun) ct->mutex_.lock(); ct->run(); - if (ct->lockRun) ct->mutex_.unlock();; + if (ct->lockRun) ct->mutex_.unlock(); if (ct->timer > 0) msleep(ct->timer); } ct->end(); @@ -46,9 +58,24 @@ void * PIThread::thread_function(void * t) { } +void * PIThread::thread_function_once(void * t) { + PIThread * ct = (PIThread * )t; + ct->running = true; + ct->begin(); + if (ct->lockRun) ct->mutex_.lock(); + ct->run(); + if (ct->lockRun) ct->mutex_.unlock(); + ct->end(); + ct->running = false; + //cout << "thread " << t << " exiting ... " << endl; + pthread_exit(0); + return 0; +} + + void PIThread::setPriority(PIThread::Priority prior) { priority_ = prior; -#if __QNX__ || __WIN32__ +#ifndef LINUX sparam.sched_priority = (int)priority_; #else sparam.__sched_priority = (int)priority_; @@ -59,3 +86,31 @@ void PIThread::setPriority(PIThread::Priority prior) { } +bool PIThread::waitForFinish(int timeout_msecs) { + if (timeout_msecs < 0) { + while (running) + msleep(1); + return true; + } + int cnt = 0; + while (running && cnt < timeout_msecs) { + msleep(1); + ++cnt; + } + return cnt < timeout_msecs; +} + + +bool PIThread::waitForStart(int timeout_msecs) { + if (timeout_msecs < 0) { + while (!running) + msleep(1); + return true; + } + int cnt = 0; + while (!running && cnt < timeout_msecs) { + msleep(1); + ++cnt; + } + return cnt < timeout_msecs; +} diff --git a/pithread.h b/pithread.h index c491cdb2..e161b8ed 100644 --- a/pithread.h +++ b/pithread.h @@ -2,13 +2,13 @@ #define PITHREAD_H #include -#include "piincludes.h" +#include #include "pimutex.h" #ifdef WINDOWS - inline void msleep(int msecs) {Sleep(msecs);} +inline void msleep(int msecs) {Sleep(msecs);} #else - inline void msleep(int msecs) {usleep(msecs * 1000);} +inline void msleep(int msecs) {usleep(msecs * 1000);} #endif class PIThread { @@ -31,13 +31,16 @@ public: #endif bool start(int timer_delay = -1); - void stop() {terminating = true;} + bool startOnce(); + void stop(bool wait = false) {terminating = true; if (wait) waitForFinish();} + void terminate() {kill(thread, SIGKILL); end(); running = false;} void setPriority(PIThread::Priority prior); PIThread::Priority priority() const {return priority_;} bool isRunning() const {return running;} - void waitForFinish() {while (running) msleep(1);} + bool waitForFinish(int timeout_msecs = -1); + bool waitForStart(int timeout_msecs = -1); void needLockRun(bool need) {lockRun = need;} - void lock() {mutex_.lock();;} + void lock() {mutex_.lock();} void unlock() {mutex_.unlock();} PIMutex & mutex() {return mutex_;} @@ -48,6 +51,7 @@ private: protected: static void * thread_function(void * t); + static void * thread_function_once(void * t); volatile bool terminating, running, lockRun; int timer, policy; diff --git a/pitimer.cpp b/pitimer.cpp index 39cad182..75fed155 100644 --- a/pitimer.cpp +++ b/pitimer.cpp @@ -4,19 +4,20 @@ PITimer::PITimer(TimerEvent slot, void * data_) { ret_func = slot; data = data_; -#ifndef __WIN32__ +#ifndef WINDOWS ti = -1; running = false; se.sigev_notify = SIGEV_THREAD; se.sigev_value.sival_ptr = this; se.sigev_notify_function = timer_event; se.sigev_notify_attributes = 0; + lockRun = false; #endif reset(); } -#ifndef __WIN32__ +#ifndef WINDOWS void PITimer::start(double msecs) { spec.it_interval.tv_nsec = ((int)(msecs * 1000) % 1000000) * 1000; spec.it_interval.tv_sec = (time_t)(msecs / 1000); @@ -29,13 +30,17 @@ void PITimer::start(double msecs) { void PITimer::timer_event(sigval e) { PITimer * ct = (PITimer * )e.sival_ptr; - if (ct->ret_func != 0) ct->ret_func(ct->data); + if (ct->ret_func != 0) { + if (ct->lockRun) ct->lock(); + ct->ret_func(ct->data); + if (ct->lockRun) ct->unlock(); + } } #endif double PITimer::elapsed_n() { -#ifdef __WIN32__ +#ifdef WINDOWS t_cur = GetCurrentTime(); return (t_cur * 1000000. - t_st * 1000000.); #else @@ -47,7 +52,7 @@ double PITimer::elapsed_n() { double PITimer::elapsed_u() { -#ifdef __WIN32__ +#ifdef WINDOWS t_cur = GetCurrentTime(); return (t_cur * 1000. - t_st * 1000.); #else @@ -59,7 +64,7 @@ double PITimer::elapsed_u() { double PITimer::elapsed_m() { -#ifdef __WIN32__ +#ifdef WINDOWS t_cur = GetCurrentTime(); return (double)(t_cur - t_st); #else @@ -71,7 +76,7 @@ double PITimer::elapsed_m() { double PITimer::elapsed_s() { -#ifdef __WIN32__ +#ifdef WINDOWS t_cur = GetCurrentTime(); return (t_cur / 1000. - t_st / 1000.); #else @@ -104,25 +109,26 @@ PIDate currentDate() { } -string time2string(const PITime & time, const string & format) { - string ts = format; - int i = ts.find_first_of('h'); - if (i >= 0) ts = ts.replace(i, 1, itos(time.hours)); - i = ts.find_first_of('m'); - if (i >= 0) ts = ts.replace(i, 1, itos(time.minutes)); - i = ts.find_first_of('s'); - if (i >= 0) ts = ts.replace(i, 1, itos(time.seconds)); +PIString time2string(const PITime & time, const PIString & format) { + PIString ts = format; + ts.replace("hh", PIString::fromNumber(time.hours).expandLeftTo(2, '0')); + ts.replace("h", PIString::fromNumber(time.hours)); + ts.replace("mm", PIString::fromNumber(time.minutes).expandLeftTo(2, '0')); + ts.replace("m", PIString::fromNumber(time.minutes)); + ts.replace("ss", PIString::fromNumber(time.seconds).expandLeftTo(2, '0')); + ts.replace("s", PIString::fromNumber(time.seconds)); return ts; } -string date2string(const PIDate & date, const string & format) { - string ts = format; - int i = ts.find_first_of('y'); - if (i >= 0) ts = ts.replace(i, 1, itos(date.year)); - i = ts.find_first_of('m'); - if (i >= 0) ts = ts.replace(i, 1, itos(date.month)); - i = ts.find_first_of('d'); - if (i >= 0) ts = ts.replace(i, 1, itos(date.day)); +PIString date2string(const PIDate & date, const PIString & format) { + PIString ts = format; + ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0')); + ts.replace("yy", PIString::fromNumber(date.year).expandLeftTo(2, '0')); + ts.replace("y", PIString::fromNumber(date.year)); + ts.replace("mm", PIString::fromNumber(date.month).expandLeftTo(2, '0')); + ts.replace("m", PIString::fromNumber(date.month)); + ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0')); + ts.replace("d", PIString::fromNumber(date.day)); return ts; } diff --git a/pitimer.h b/pitimer.h index 169be8f6..eaf866ed 100644 --- a/pitimer.h +++ b/pitimer.h @@ -4,6 +4,7 @@ #include #include #include "pithread.h" +#include "pistring.h" typedef void (*TimerEvent)(void * ); @@ -20,20 +21,23 @@ struct PIDate { }; class PITimer -#ifdef __WIN32__ +#ifdef WINDOWS : public PIThread #endif { public: PITimer(TimerEvent slot = 0, void * data = 0); ~PITimer() {stop();} -#ifdef __WIN32__ +#ifdef WINDOWS void reset() {t_st = GetCurrentTime();} #else void reset() {clock_gettime(0, &t_st);} void start(double msecs); void stop() {if (ti == 0) timer_delete(timer); ti = -1; running = false;} bool isRunning() const {return running;} + void needLockRun(bool need) {lockRun = need;} + void lock() {mutex_.lock();} + void unlock() {mutex_.unlock();} #endif double elapsed_n(); // nanoseconds double elapsed_u(); // microseconds @@ -41,7 +45,7 @@ public: double elapsed_s(); // seconds private: -#ifdef __WIN32__ +#ifdef WINDOWS void run() {if (ret_func != 0) ret_func(data);} long int t_st, t_cur; @@ -49,6 +53,8 @@ private: static void timer_event(sigval e); bool running; + volatile bool lockRun; + PIMutex mutex_; int ti; itimerspec spec; timespec t_st, t_cur; @@ -63,7 +69,7 @@ private: PITime currentTime(); PIDate currentDate(); -string time2string(const PITime & time, const string & format = "h:m:s"); -string date2string(const PIDate & date, const string & format = "d.m.y"); +PIString time2string(const PITime & time, const PIString & format = "h:mm:ss"); +PIString date2string(const PIDate & date, const PIString & format = "d.mm.yyyy"); #endif // PITIMER_H diff --git a/pivariable.cpp b/pivariable.cpp index 028a62a9..e299bd33 100644 --- a/pivariable.cpp +++ b/pivariable.cpp @@ -1,111 +1,195 @@ #include "pivariable.h" -void PIVariable::setVariable(const PIString & str) { - type_ = PIVariable::fromString(str); - size_ = PIVariable::variableSize(type_); +bool PIVariant::operator ==(const PIVariant & v) const { + if (type != v.type) return false; + switch (type) { + case PIVariant::Bool: return vBool == v.vBool; + case PIVariant::Char: return vChar == v.vChar; + case PIVariant::Short: return vShort == v.vShort; + case PIVariant::Int: return vInt == v.vInt; + case PIVariant::Long: return vLong == v.vLong; + case PIVariant::LLong: return vLLong == v.vLLong; + case PIVariant::UChar: return vUChar == v.vUChar; + case PIVariant::UShort: return vUShort == v.vUShort; + case PIVariant::UInt: return vUInt == v.vUInt; + case PIVariant::ULong: return vULong == v.vULong; + case PIVariant::ULLong: return vULLong == v.vULLong; + case PIVariant::Float: return vFloat == v.vFloat; + case PIVariant::Double: return vDouble == v.vDouble; + case PIVariant::LDouble: return vLDouble == v.vLDouble; + case PIVariant::String: return vString == v.vString; + case PIVariant::StringList: return vStringList == v.vStringList; + }; } -PIVariable::Type PIVariable::fromString(const PIString & str) { - PIString s = str.trimmed().toLowerCase(); - if (s == "char" || s == "sbyte") return PIVariable::Char; - if (s == "short" || s == "short int" || s == "signed short" || s == "signed short int" || s == "sword") return PIVariable::Short; - if (s == "int" || s == "signed" || s == "signed int") return PIVariable::Int; - if (s == "long" || s == "long int" || s == "signed long" || s == "signed long int" || s == "sdword") return PIVariable::Long; - if (s == "llong" || s == "long long" || s == "long long int" || s == "signed long long" || s == "signed long long int" || s == "sqword") return PIVariable::LLong; - if (s == "uchar" || s == "byte") return PIVariable::UChar; - if (s == "ushort" || s == "unsigned short" || s == "unsigned short int" || s == "word") return PIVariable::UShort; - if (s == "uint" || s == "unsigned" || s == "unsigned int") return PIVariable::UInt; - if (s == "ulong" || s == "unsigned long" || s == "unsigned long int" || s == "dword") return PIVariable::ULong; - if (s == "ullong" || s == "unsigned long long" || s == "unsigned long long int" || s == "qword") return PIVariable::ULLong; - if (s == "float") return PIVariable::Float; - if (s == "double" || s == "real") return PIVariable::Double; - if (s == "ldouble" || s == "long double") return PIVariable::LDouble; - if (s == "bool") return PIVariable::Bool; - return PIVariable::Double; +void PIVariant::setValueOnly(const PIString & s) { + switch (type) { + case PIVariant::Bool: vBool = s.toBool(); break; + case PIVariant::Char: vChar = s.toChar(); break; + case PIVariant::Short: vShort = s.toShort(); break; + case PIVariant::Int: vInt = s.toInt(); break; + case PIVariant::Long: vLong = s.toLong(); break; + case PIVariant::LLong: vLLong = s.toLLong(); break; + case PIVariant::UChar: vUChar = s.toChar(); break; + case PIVariant::UShort: vUShort = s.toShort(); break; + case PIVariant::UInt: vUInt = s.toInt(); break; + case PIVariant::ULong: vULong = s.toLong(); break; + case PIVariant::ULLong: vULLong = s.toLLong(); break; + case PIVariant::Float: vFloat = s.toFloat(); break; + case PIVariant::Double: vDouble = s.toDouble(); break; + case PIVariant::LDouble: vLDouble = s.toLDouble(); break; + case PIVariant::String: vString = s; break; + case PIVariant::StringList: vStringList = s.split("%|%"); break; + }; } -PIString PIVariable::toString(const PIVariable::Type & var) { +PIString PIVariant::stringValue() const { + switch (type) { + case PIVariant::Bool: return (vBool ? "true" : "false"); + case PIVariant::Char: return PIString::fromNumber(vChar); + case PIVariant::Short: return PIString::fromNumber(vShort); + case PIVariant::Int: return PIString::fromNumber(vInt); + case PIVariant::Long: return PIString::fromNumber(vLong); + case PIVariant::LLong: return PIString::fromNumber(static_cast(vLLong)); + case PIVariant::UChar: return PIString::fromNumber(vUChar); + case PIVariant::UShort: return PIString::fromNumber(vUShort); + case PIVariant::UInt: return PIString::fromNumber(vUInt); + case PIVariant::ULong: return PIString::fromNumber(static_cast(vULong)); + case PIVariant::ULLong: return PIString::fromNumber(static_cast(vULLong)); + case PIVariant::Float: return PIString::fromNumber(vFloat); + case PIVariant::Double: return PIString::fromNumber(vDouble); + case PIVariant::LDouble: return PIString::fromNumber(vLDouble); + case PIVariant::String: return vString; + case PIVariant::StringList: return vStringList.join("%|%"); + }; +} + + +PIVariant PIVariant::readFromString(const PIString & s) { + int i = s.find(':'); + if (i < 0 || s.length() < 2) return PIVariant(s); + PIVariant ret; + ret.type = PIVariant::fromString(s.left(i)); + ret.setValueOnly(s.right(s.length() - i - 1)); + return ret; +} + + +PIVariant::Type PIVariant::fromString(const PIString & str) { + PIString s = str.trimmed().toLowerCase().replace(" ", ""); + if (s == "bool") return PIVariant::Bool; + if (s == "char" || s == "sbyte") return PIVariant::Char; + if (s == "short" || s == "short int" || s == "signed short" || s == "signed short int" || s == "sword") return PIVariant::Short; + if (s == "int" || s == "signed" || s == "signed int") return PIVariant::Int; + if (s == "long" || s == "long int" || s == "signed long" || s == "signed long int" || s == "sdword") return PIVariant::Long; + if (s == "llong" || s == "long long" || s == "long long int" || s == "signed long long" || s == "signed long long int" || s == "sqword") return PIVariant::LLong; + if (s == "uchar" || s == "byte") return PIVariant::UChar; + if (s == "ushort" || s == "unsigned short" || s == "unsigned short int" || s == "word") return PIVariant::UShort; + if (s == "uint" || s == "unsigned" || s == "unsigned int") return PIVariant::UInt; + if (s == "ulong" || s == "unsigned long" || s == "unsigned long int" || s == "dword") return PIVariant::ULong; + if (s == "ullong" || s == "unsigned long long" || s == "unsigned long long int" || s == "qword") return PIVariant::ULLong; + if (s == "float") return PIVariant::Float; + if (s == "double" || s == "real") return PIVariant::Double; + if (s == "ldouble" || s == "long double") return PIVariant::LDouble; + if (s == "pistring" || s == "string") return PIVariant::String; + if (s == "pistringlist" || s == "vector" || s == "vector" || s == "pivector" || s == "pivector") return PIVariant::StringList; + return PIVariant::Double; +} + + +PIString PIVariant::toString(const PIVariant::Type & var) { switch (var) { - case PIVariable::Char: return "char"; - case PIVariable::Short: return "short"; - case PIVariable::Int: return "int"; - case PIVariable::Long: return "long"; - case PIVariable::LLong: return "llong"; - case PIVariable::UChar: return "uchar"; - case PIVariable::UShort: return "ushort"; - case PIVariable::UInt: return "uint"; - case PIVariable::ULong: return "ulong"; - case PIVariable::ULLong: return "ullong"; - case PIVariable::Float: return "float"; - case PIVariable::Double: return "double"; - case PIVariable::LDouble: return "ldouble"; - case PIVariable::Bool: return "bool"; + case PIVariant::Bool: return "bool"; + case PIVariant::Char: return "char"; + case PIVariant::Short: return "short"; + case PIVariant::Int: return "int"; + case PIVariant::Long: return "long"; + case PIVariant::LLong: return "llong"; + case PIVariant::UChar: return "uchar"; + case PIVariant::UShort: return "ushort"; + case PIVariant::UInt: return "uint"; + case PIVariant::ULong: return "ulong"; + case PIVariant::ULLong: return "ullong"; + case PIVariant::Float: return "float"; + case PIVariant::Double: return "double"; + case PIVariant::LDouble: return "ldouble"; + case PIVariant::String: return "string"; + case PIVariant::StringList: return "stringlist"; } return "double"; } -uint PIVariable::variableSize(const PIVariable::Type & var) { +uint PIVariant::variableSize(const PIVariant::Type & var) { switch (var) { - case PIVariable::Char: return sizeof(char); - case PIVariable::Short: return sizeof(short); - case PIVariable::Int: return sizeof(int); - case PIVariable::Long: return sizeof(long); - case PIVariable::LLong: return sizeof(llong); - case PIVariable::UChar: return sizeof(uchar); - case PIVariable::UShort: return sizeof(ushort); - case PIVariable::UInt: return sizeof(uint); - case PIVariable::ULong: return sizeof(ulong); - case PIVariable::ULLong: return sizeof(ullong); - case PIVariable::Float: return sizeof(float); - case PIVariable::Double: return sizeof(double); - case PIVariable::LDouble: return sizeof(ldouble); - case PIVariable::Bool: return sizeof(bool); + case PIVariant::Bool: return sizeof(bool); + case PIVariant::Char: return sizeof(char); + case PIVariant::Short: return sizeof(short); + case PIVariant::Int: return sizeof(int); + case PIVariant::Long: return sizeof(long); + case PIVariant::LLong: return sizeof(llong); + case PIVariant::UChar: return sizeof(uchar); + case PIVariant::UShort: return sizeof(ushort); + case PIVariant::UInt: return sizeof(uint); + case PIVariant::ULong: return sizeof(ulong); + case PIVariant::ULLong: return sizeof(ullong); + case PIVariant::Float: return sizeof(float); + case PIVariant::Double: return sizeof(double); + case PIVariant::LDouble: return sizeof(ldouble); + default: break; } - return sizeof(double); + return 0; } -double PIVariable::variableValue(const char * var_ptr, const PIVariable::Type & var) { +double PIVariant::variableValue(const char * var_ptr, const PIVariant::Type & var) { switch (var) { - case PIVariable::Char: return (double)(*((char * )var_ptr)); - case PIVariable::Short: return (double)(*((short * )var_ptr)); - case PIVariable::Int: return (double)(*((int * )var_ptr)); - case PIVariable::Long: return (double)(*((long * )var_ptr)); - case PIVariable::LLong: return (double)(*((llong * )var_ptr)); - case PIVariable::UChar: return (double)(*((uchar * )var_ptr)); - case PIVariable::UShort: return (double)(*((ushort * )var_ptr)); - case PIVariable::UInt: return (double)(*((uint * )var_ptr)); - case PIVariable::ULong: return (double)(*((ulong * )var_ptr)); - case PIVariable::ULLong: return (double)(*((ullong * )var_ptr)); - case PIVariable::Float: return (double)(*((float * )var_ptr)); - case PIVariable::Double: return (double)(*((double * )var_ptr)); - case PIVariable::LDouble: return (ldouble)(*((ldouble * )var_ptr)); - case PIVariable::Bool: return (double)(*((bool * )var_ptr)); + case PIVariant::Bool: return (double)(*((bool * )var_ptr)); + case PIVariant::Char: return (double)(*((char * )var_ptr)); + case PIVariant::Short: return (double)(*((short * )var_ptr)); + case PIVariant::Int: return (double)(*((int * )var_ptr)); + case PIVariant::Long: return (double)(*((long * )var_ptr)); + case PIVariant::LLong: return (double)(*((llong * )var_ptr)); + case PIVariant::UChar: return (double)(*((uchar * )var_ptr)); + case PIVariant::UShort: return (double)(*((ushort * )var_ptr)); + case PIVariant::UInt: return (double)(*((uint * )var_ptr)); + case PIVariant::ULong: return (double)(*((ulong * )var_ptr)); + case PIVariant::ULLong: return (double)(*((ullong * )var_ptr)); + case PIVariant::Float: return (double)(*((float * )var_ptr)); + case PIVariant::Double: return (double)(*((double * )var_ptr)); + case PIVariant::LDouble: return (ldouble)(*((ldouble * )var_ptr)); + default: break; } return 0.; } +void PIVariable::setVariable(const PIString & str) { + type_ = PIVariant::fromString(str); + size_ = PIVariant::variableSize(type_); +} + + void PIVariable::writeVariable(char * dest) { switch (type_) { - case PIVariable::Char: *((char * )((int)dest + offset)) = value_; return; - case PIVariable::Short: *((short * )((int)dest + offset)) = value_; return; - case PIVariable::Int: *((int * )((int)dest + offset)) = value_; return; - case PIVariable::Long: *((long * )((int)dest + offset)) = value_; return; - case PIVariable::LLong: *((llong * )((int)dest + offset)) = value_; return; - case PIVariable::UChar: *((uchar * )((int)dest + offset)) = value_; return; - case PIVariable::UShort: *((ushort * )((int)dest + offset)) = value_; return; - case PIVariable::UInt: *((uint * )((int)dest + offset)) = value_; return; - case PIVariable::ULong: *((ulong * )((int)dest + offset)) = value_; return; - case PIVariable::ULLong: *((ullong * )((int)dest + offset)) = value_; return; - case PIVariable::Float: *((float * )((int)dest + offset)) = value_; return; - case PIVariable::Double: *((double * )((int)dest + offset)) = value_; return; - case PIVariable::LDouble: *((ldouble * )((int)dest + offset)) = value_; return; - case PIVariable::Bool: *((bool * )((int)dest + offset)) = value_; return; + case PIVariant::Bool: *((bool * )((long)dest + offset)) = value_; return; + case PIVariant::Char: *((char * )((long)dest + offset)) = value_; return; + case PIVariant::Short: *((short * )((long)dest + offset)) = value_; return; + case PIVariant::Int: *((int * )((long)dest + offset)) = value_; return; + case PIVariant::Long: *((long * )((long)dest + offset)) = value_; return; + case PIVariant::LLong: *((llong * )((long)dest + offset)) = value_; return; + case PIVariant::UChar: *((uchar * )((long)dest + offset)) = value_; return; + case PIVariant::UShort: *((ushort * )((long)dest + offset)) = value_; return; + case PIVariant::UInt: *((uint * )((long)dest + offset)) = value_; return; + case PIVariant::ULong: *((ulong * )((long)dest + offset)) = value_; return; + case PIVariant::ULLong: *((ullong * )((long)dest + offset)) = value_; return; + case PIVariant::Float: *((float * )((long)dest + offset)) = value_; return; + case PIVariant::Double: *((double * )((long)dest + offset)) = value_; return; + case PIVariant::LDouble: *((ldouble * )((long)dest + offset)) = value_; return; + default: break; } } @@ -116,7 +200,7 @@ void PIStruct::parseFile(const PIString & file) { PIString ts; uint sz = 0; vars.clear(); - for (int i = 0; i < conf.numValues(); ++i) { + for (int i = 0; i < conf.entriesCount(); ++i) { var.setVariable(conf.getValue(i)); var.setName(conf.getName(i)); var.offset = sz; diff --git a/pivariable.h b/pivariable.h index 3a41188f..3f24f31a 100644 --- a/pivariable.h +++ b/pivariable.h @@ -3,6 +3,111 @@ #include "piconfig.h" +class PIVariant { + friend class PIVariable; +public: + enum Type {Bool, Char, Short, Int, Long, LLong, UChar, UShort, UInt, ULong, ULLong, Float, Double, LDouble, String, StringList}; + + PIVariant() {setValue(0.);} + PIVariant(const char * v) {setValue(v);} + PIVariant(const bool & v) {setValue(v);} + PIVariant(const char & v) {setValue(v);} + PIVariant(const short & v) {setValue(v);} + PIVariant(const int & v) {setValue(v);} + PIVariant(const long & v) {setValue(v);} + PIVariant(const llong & v) {setValue(v);} + PIVariant(const uchar & v) {setValue(v);} + PIVariant(const ushort & v) {setValue(v);} + PIVariant(const uint & v) {setValue(v);} + PIVariant(const ulong & v) {setValue(v);} + PIVariant(const ullong & v) {setValue(v);} + PIVariant(const float & v) {setValue(v);} + PIVariant(const double & v) {setValue(v);} + PIVariant(const ldouble & v) {setValue(v);} + PIVariant(const PIString & v) {setValue(v);} + PIVariant(const PIStringList & v) {setValue(v);} + + inline void setValue(const char * v) {setValue(PIString(v));} + inline void setValue(const bool & v) {type = PIVariant::Bool; vBool = v;} + inline void setValue(const char & v) {type = PIVariant::Char; vChar = v;} + inline void setValue(const short & v) {type = PIVariant::Short; vShort = v;} + inline void setValue(const int & v) {type = PIVariant::Int; vInt = v;} + inline void setValue(const long & v) {type = PIVariant::Long; vLong = v;} + inline void setValue(const llong & v) {type = PIVariant::LLong; vLLong = v;} + inline void setValue(const uchar & v) {type = PIVariant::UChar; vUChar = v;} + inline void setValue(const ushort & v) {type = PIVariant::UShort; vUShort = v;} + inline void setValue(const uint & v) {type = PIVariant::UInt; vUInt = v;} + inline void setValue(const ulong & v) {type = PIVariant::ULong; vULong = v;} + inline void setValue(const ullong & v) {type = PIVariant::ULLong; vULLong = v;} + inline void setValue(const float & v) {type = PIVariant::Float; vFloat = v;} + inline void setValue(const double & v) {type = PIVariant::Double; vDouble = v;} + inline void setValue(const ldouble & v) {type = PIVariant::LDouble; vLDouble = v;} + inline void setValue(const PIString & v) {type = PIVariant::String; vString = v;} + inline void setValue(const PIStringList & v) {type = PIVariant::StringList; vStringList = v;} + void setValueOnly(const PIString & v); + inline PIString typeName() const {return PIVariant::toString(type);} + inline double doubleValue() const {return PIVariant::variableValue(&vChar, type);} + PIString stringValue() const; + inline void typeFromString(const PIString & str) {type = PIVariant::fromString(str);} + inline PIString typeToString() const {return PIVariant::toString(type);} + inline uint size() {if (type != PIVariant::String && type != PIVariant::StringList) return PIVariant::variableSize(type); if (type == PIVariant::String) return vString.size(); else return vStringList.contentSize();} + inline PIString writeToString() const {return typeName() + ":" + stringValue();} + +#ifdef QNX + inline void operator =(const PIVariant & v) {type = v.type; vLDouble = v.vLDouble; vString = v.vString; vStringList = v.vStringList;} +#endif + inline void operator =(const char * v) {setValue(PIString(v));} + inline void operator =(const bool & v) {type = PIVariant::Bool; vBool = v;} + inline void operator =(const char & v) {type = PIVariant::Char; vChar = v;} + inline void operator =(const short & v) {type = PIVariant::Short; vShort = v;} + inline void operator =(const int & v) {type = PIVariant::Int; vInt = v;} + inline void operator =(const long & v) {type = PIVariant::Long; vLong = v;} + inline void operator =(const llong & v) {type = PIVariant::LLong; vLLong = v;} + inline void operator =(const uchar & v) {type = PIVariant::UChar; vUChar = v;} + inline void operator =(const ushort & v) {type = PIVariant::UShort; vUShort = v;} + inline void operator =(const uint & v) {type = PIVariant::UInt; vUInt = v;} + inline void operator =(const ulong & v) {type = PIVariant::ULong; vULong = v;} + inline void operator =(const ullong & v) {type = PIVariant::ULLong; vULLong = v;} + inline void operator =(const float & v) {type = PIVariant::Float; vFloat = v;} + inline void operator =(const double & v) {type = PIVariant::Double; vDouble = v;} + inline void operator =(const ldouble & v) {type = PIVariant::LDouble; vLDouble = v;} + inline void operator =(const PIString & v) {type = PIVariant::String; vString = v;} + inline void operator =(const PIStringList & v) {type = PIVariant::StringList; vStringList = v;} + + bool operator ==(const PIVariant & v) const; + inline bool operator !=(const PIVariant & v) const {return !(*this == v);} + + PIVariant::Type type; + union { + bool vBool; + char vChar; + short vShort; + int vInt; + long vLong; + llong vLLong; + uchar vUChar; + ushort vUShort; + uint vUInt; + ulong vULong; + ullong vULLong; + float vFloat; + double vDouble; + ldouble vLDouble; + }; + PIString vString; + PIStringList vStringList; + + static PIVariant readFromString(const PIString & s); + +private: + static PIVariant::Type fromString(const PIString & str); + static PIString toString(const PIVariant::Type & var); + static uint variableSize(const PIVariant::Type & var); + static double variableValue(const char * var_ptr, const PIVariant::Type & var); + +}; + +inline std::ostream & operator <<(std::ostream & s, const PIVariant & v) {s << v.typeName() << ": " << v.stringValue(); return s;} class PIVariable { public: @@ -10,31 +115,10 @@ public: PIVariable(const PIString & str) {setVariable(str);} ~PIVariable() {;} - enum Type {Char, Short, Int, Long, LLong, UChar, UShort, UInt, ULong, ULLong, Float, Double, LDouble, Bool}; - typedef struct { - union { - char vChar; - short vShort; - int vInt; - long vLong; - llong vLLong; - uchar vUChar; - ushort vUShort; - uint vUInt; - ulong vULong; - ullong vULLong; - float vFloat; - double vDouble; - ldouble vLDouble; - bool vBool; - }; - PIVariable::Type type; - } PIVariant; - void setVariable(const PIString & str); void writeVariable(char * dest); - inline void readVariable(const char * var_ptr) {value_ = PIVariable::variableValue((char * )((int)var_ptr + offset), type_);} - inline PIVariable::Type type() const {return type_;} + inline void readVariable(const char * var_ptr) {value_ = PIVariant::variableValue((char * )((long)var_ptr + offset), type_);} + inline PIVariant::Type type() const {return type_;} inline uint size() const {return size_;} inline const PIString & name() {return name_;} inline void setName(const PIString & str) {name_ = str;} @@ -43,13 +127,8 @@ public: int offset; - static PIVariable::Type fromString(const PIString & str); - static PIString toString(const PIVariable::Type & var); - static uint variableSize(const PIVariable::Type & var); - static double variableValue(const char * var_ptr, const PIVariable::Type & var); - private: - PIVariable::Type type_; + PIVariant::Type type_; uint size_; PIString name_; double value_; @@ -95,3 +174,8 @@ private: }; #endif // PIVARIABLE_H + +#/** PhEDIT attribute block +#-11:16777215 +#0:7338:monospace10:-3:-3:0 +#** PhEDIT attribute block ends (-0000117)**/