From 29190ea465bea795b69c53a653cd2220024047bb Mon Sep 17 00:00:00 2001 From: peri4 Date: Fri, 29 Jul 2011 08:17:24 +0400 Subject: [PATCH] 29.07.2011 - fundamental new --- .kdev4/_custom.kdev4 | 28 ++ .kdev4/pip.kdev4 | 5 +- CMakeLists.txt | 10 +- Makefile_qnx | 240 ++++++++++ main.cpp | 41 +- make_install.sh | 8 + pibitarray.h | 2 +- pibytearray.h | 5 +- pichar.h | 102 +++++ picli.cpp | 63 +++ picli.h | 60 +++ picodec.cpp | 22 + picodec.h | 31 ++ piconfig.cpp | 583 ++++++++++++++++-------- piconfig.h | 235 +++++++--- piconsole.cpp | 254 +++++++---- piconsole.h | 146 +++--- picontainers.h | 226 +++++++++ pidir.cpp | 142 +++++- pidir.h | 42 +- piethernet.cpp | 59 ++- piethernet.h | 24 +- pievaluator.cpp | 1033 ++++++++++++++++++++++++++++++++++++++++++ pievaluator.h | 148 ++++++ pifile.cpp | 38 +- pifile.h | 58 ++- pigeometry.h | 2 + piincludes.h | 112 ++--- pikbdlistener.cpp | 41 +- pikbdlistener.h | 21 +- pimath.cpp | 20 +- pimath.h | 59 ++- pimutex.h | 1 + pip.h | 5 +- pip.pro | 47 ++ piprocess.cpp | 124 +++++ piprocess.h | 62 +++ piprotocol.cpp | 411 +++++++++++------ piprotocol.h | 149 +++--- piserial.cpp | 58 ++- piserial.h | 36 +- pistring.cpp | 234 ++++++++-- pistring.h | 236 ++++++---- pithread.cpp | 61 ++- pithread.h | 16 +- pitimer.cpp | 52 ++- pitimer.h | 16 +- pivariable.cpp | 246 ++++++---- pivariable.h | 142 ++++-- 49 files changed, 4704 insertions(+), 1052 deletions(-) create mode 100644 .kdev4/_custom.kdev4 create mode 100644 Makefile_qnx create mode 100755 make_install.sh create mode 100644 pichar.h create mode 100644 picli.cpp create mode 100644 picli.h create mode 100644 picodec.cpp create mode 100644 picodec.h create mode 100644 picontainers.h create mode 100644 pievaluator.cpp create mode 100644 pievaluator.h create mode 100644 pip.pro create mode 100644 piprocess.cpp create mode 100644 piprocess.h 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)**/