diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..da8eb4f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +doc + diff --git a/CMakeLists.txt b/CMakeLists.txt index af00ddae..e5e3945d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,50 @@ project(pip) cmake_minimum_required(VERSION 2.6) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} .) +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) include(CheckFunctionExists) -set(VERSION "0.0400") + +# Version +file(READ "src/piversion.h" VERSION_OFFSET LIMIT 4 OFFSET 3) +file(READ "src/piversion.h" VERSION_MAJOR LIMIT 1 OFFSET ${VERSION_OFFSET}) +file(READ "src/piversion.h" VERSION_OFFSET LIMIT 4 OFFSET 7) +file(READ "src/piversion.h" VERSION_MINOR LIMIT 1 OFFSET ${VERSION_OFFSET}) +file(READ "src/piversion.h" VERSION_OFFSET LIMIT 4 OFFSET 11) +file(READ "src/piversion.h" VERSION_REVISION LIMIT 1 OFFSET ${VERSION_OFFSET}) +file(STRINGS "src/piversion.h" VERSION_SUFFIX REGEX "\".*\"") +string(REGEX MATCH "\".*\"" VERSION_SUFFIX ${VERSION_SUFFIX}) +string(LENGTH ${VERSION_SUFFIX} SL) +math(EXPR SL '${SL}-2') +string(SUBSTRING ${VERSION_SUFFIX} 1 ${SL} VERSION_SUFFIX) +string(LENGTH ${VERSION_MAJOR} SL) +math(EXPR SL '${SL}-1') +string(SUBSTRING ${VERSION_MAJOR} 0 ${SL} VERSION_MAJOR) +string(LENGTH ${VERSION_MINOR} SL) +math(EXPR SL '${SL}-1') +string(SUBSTRING ${VERSION_MINOR} 0 ${SL} VERSION_MINOR) +string(LENGTH ${VERSION_REVISION} SL) +math(EXPR SL '${SL}-1') +string(SUBSTRING ${VERSION_REVISION} 0 ${SL} VERSION_REVISION) +set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}") set(SOVERSION ${VERSION}) +message(STATUS "Building PIP version ${VERSION}${VERSION_SUFFIX}") +file(WRITE "src/pip_version_str.h" "#define __PIP_VERSION_STR__ \"${VERSION}${VERSION_SUFFIX}\"\n") set(CMAKE_BUILD_TYPE "Release") set(LIBS) -file(GLOB HDRS "pi*.h") -file(GLOB CPPS "pi*.cpp") +# Sources +set(PIP_FOLDERS "." "code" "containers" "core" "io" "math" "system" "thread") +include_directories("src") +foreach(F ${PIP_FOLDERS}) + include_directories("src/${F}") + file(GLOB HS "src/${F}/*.h") + file(GLOB CS "src/${F}/*.cpp") + list(APPEND HDRS ${HS}) + list(APPEND CPPS ${CS}) +endforeach(F) + # Check Bessel functions set(CMAKE_REQUIRED_INCLUDES math.h) set(CMAKE_REQUIRED_LIBRARIES m) @@ -19,23 +54,41 @@ CHECK_FUNCTION_EXISTS(jn PIP_MATH_JN) CHECK_FUNCTION_EXISTS(y0 PIP_MATH_Y0) CHECK_FUNCTION_EXISTS(y1 PIP_MATH_Y1) CHECK_FUNCTION_EXISTS(yn PIP_MATH_YN) -if (DEFINED PIP_MATH_J0) - add_definitions("-DPIP_MATH_J0") +if (PIP_MATH_J0) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPIP_MATH_J0") endif () -if (DEFINED PIP_MATH_J1) - add_definitions("-DPIP_MATH_J1") +if (PIP_MATH_J1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPIP_MATH_J1") endif () -if (DEFINED PIP_MATH_JN) - add_definitions("-DPIP_MATH_JN") +if (PIP_MATH_JN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPIP_MATH_JN") endif () -if (DEFINED PIP_MATH_Y0) - add_definitions("-DPIP_MATH_Y0") +if (PIP_MATH_Y0) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPIP_MATH_Y0") endif () -if (DEFINED PIP_MATH_Y1) - add_definitions("-DPIP_MATH_Y1") +if (PIP_MATH_Y1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPIP_MATH_Y1") endif () -if (DEFINED PIP_MATH_YN) - add_definitions("-DPIP_MATH_YN") +if (PIP_MATH_YN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPIP_MATH_YN") +endif () + + +# Check if RT timers exists +set(CMAKE_REQUIRED_INCLUDES time.h) +if (DEFINED ENV{QNX_HOST}) + set(CMAKE_REQUIRED_LIBRARIES ) +else () + set(CMAKE_REQUIRED_LIBRARIES rt) +endif () +CHECK_FUNCTION_EXISTS(timer_create PIP_TIMER_RT_0) +CHECK_FUNCTION_EXISTS(timer_settime PIP_TIMER_RT_1) +CHECK_FUNCTION_EXISTS(timer_delete PIP_TIMER_RT_2) +if (PIP_TIMER_RT_0 AND PIP_TIMER_RT_1 AND PIP_TIMER_RT_2) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPIP_TIMER_RT") + message(STATUS "Available timers: Thread, ThreadRT, Pool") +else () + message(STATUS "Available timers: Thread, Pool") endif () @@ -43,85 +96,94 @@ endif () if (DEFINED USB) message(STATUS "Building with USB support") unset(USB) - add_definitions("-DPIP_USB") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPIP_USB") list(APPEND LIBS usb) else () message(STATUS "Building without USB support") endif () -# Check if STL containers is on (to enable use "-DPIP_CONTAINERS_STL=" argument of cmake) -if (DEFINED PIP_CONTAINERS_STL) +# Check if STL containers is on (to enable use "-DSTL=" argument of cmake) +if (DEFINED STL) message(STATUS "Building with STL containers") - unset(PIP_CONTAINERS_STL) - add_definitions("-DPIP_CONTAINERS_STL") + unset(STL) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPIP_CONTAINERS_STL") else () message(STATUS "Building with PIP containers") endif () +# Add library if (${WIN32}) - list(APPEND LIBS ws2_32 Iphlpapi) - execute_process(COMMAND "make_rc_win.bat" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - list(APPEND CPPS "pip_resource_win.o") + list(APPEND LIBS ws2_32 Iphlpapi Psapi) + #execute_process(COMMAND "make_rc_win.bat" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_QUIET) + #list(APPEND CPPS "pip_resource_win.o") + list(APPEND CPPS "pip_resource_win.rc") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPSAPI_VERSION=1") add_library(pip SHARED ${CPPS}) if (${CMAKE_C_COMPILER} STREQUAL "cl") include(GenerateExportHeader) generate_export_header(pip) - add_definitions("/O2 /Ob2 /Ot") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2 /Ob2 /Ot") + #set(${CMAKE_C_FLAGS} "/O2 /Ob2 /Ot") else () - add_definitions("-O2") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") + #set(${CMAKE_CXX_FLAGS} "-O2") endif () else () - add_definitions("-O2") + set(${CMAKE_CXX_FLAGS} "-O2") if (DEFINED ENV{QNX_HOST}) list(APPEND LIBS socket) - add_definitions("-ftemplate-depth-32") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32") add_library(pip STATIC ${CPPS}) else () list(APPEND LIBS pthread) if (NOT APPLE) list(APPEND LIBS rt) endif() - add_definitions("-Wall") - add_definitions("-g3") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") + #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") add_library(pip SHARED ${CPPS}) endif () endif () target_link_libraries(pip ${LIBS}) #install(TARGETS pip DESTINATION bin) - +set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}") # Test program -find_package(Qt4 REQUIRED) -include_directories(${QT_INCLUDES}) +#find_package(Qt4 REQUIRED) +#include_directories(${QT_INCLUDES}) add_executable(pip_test "main.cpp") -target_link_libraries(pip_test pip ${QT_QTCORE_LIBRARY}) +target_link_libraries(pip_test pip)# ${QT_QTCORE_LIBRARY}) #target_link_libraries(pip_test pip) -add_subdirectory(system_test) -add_subdirectory(remote_console) -add_subdirectory(code_model_generator) - +# Install +# Check if system or local install will be used (to system install use "-DLIB=" argument of cmake) if (DEFINED LIB) - unset(LIB) + set(LIB 1) if (${WIN32}) - get_filename_component(MGWDIR ${CMAKE_C_COMPILER} PATH) - find_path(MGWINCLUDE windows.h HINTS ${MGWDIR}/include) - file(RELATIVE_PATH MGWINCLUDE "${MGWDIR}" ${MGWINCLUDE}) - get_filename_component(MGWINCLUDE ${MGWINCLUDE} PATH) - string(SUBSTRING ${MGWINCLUDE} 1 -1 MGWINCLUDE) - message(STATUS "MGWINCLUDE = ${MGWINCLUDE}/include") - set(CMAKE_INSTALL_PREFIX ${MGWDIR}/..) - install(FILES ${HDRS} DESTINATION ${MGWINCLUDE}/include/pip) - install(TARGETS pip DESTINATION ${MGWINCLUDE}/lib) + find_package(MinGW REQUIRED) + set(CMAKE_INSTALL_PREFIX ${MINGW_DIR}) + install(FILES ${HDRS} DESTINATION ${MINGW_INCLUDE}/pip) + install(TARGETS pip DESTINATION ${MINGW_LIB}) else () set(CMAKE_INSTALL_PREFIX /usr) - install(TARGETS pip DESTINATION lib) - install(FILES ${HDRS} DESTINATION include/pip) + install(FILES ${HDRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/pip) + install(TARGETS pip DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) endif () + message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"") + # Precompiled header + #add_custom_target(pip_pch ALL COMMAND ${CMAKE_CXX_COMPILER} -O2 -fPIC -g3 ${CMAKE_INSTALL_PREFIX}/include/pip/pip.h DEPENDS pip SOURCES ${HDRS}) + #list(APPEND HDRS "pip.h.gch") install(FILES "FindPIP.cmake" DESTINATION ${CMAKE_ROOT}/Modules) else () - install(TARGETS pip DESTINATION bin) + install(TARGETS pip DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) + message(STATUS "Install to local \"bin\"") endif () + +# Utils +add_subdirectory("utils/system_test") +add_subdirectory("utils/remote_console") +add_subdirectory("utils/code_model_generator") +add_subdirectory("utils/system_daemon") diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user new file mode 100644 index 00000000..9b254f4d --- /dev/null +++ b/CMakeLists.txt.user @@ -0,0 +1,222 @@ + + + + + + EnvironmentId + {948faa78-0b50-402e-a285-1bca3b08de64} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + false + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + DesktopBuild + DesktopBuild + {3c749452-9483-442d-b011-933a1b5dac10} + 0 + 0 + 0 + + false + C:/libs/pip + + + -j8 + + false + true + Сборка + + CMakeProjectManager.MakeStep + + 1 + Сборка + + ProjectExplorer.BuildSteps.Build + + + + clean + + true + true + Сборка + + CMakeProjectManager.MakeStep + + 1 + Очистка + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + all + + CMakeProjectManager.CMakeBuildConfiguration + + 1 + + + 0 + Установка + + ProjectExplorer.BuildSteps.Deploy + + 1 + Локальная установка + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + pip_test + + false + + 2 + + pip_test + + CMakeProjectManager.CMakeRunConfiguration.pip_test + 3768 + false + true + false + false + true + + + pip_system_test + + false + + 2 + + pip_system_test + + CMakeProjectManager.CMakeRunConfiguration.pip_system_test + 3768 + false + true + false + false + true + + + pip_remote_console + + false + + 2 + + pip_remote_console + + CMakeProjectManager.CMakeRunConfiguration.pip_remote_console + 3768 + false + true + false + false + true + + + pip_cmg + + false + + 2 + + pip_cmg + + CMakeProjectManager.CMakeRunConfiguration.pip_cmg + 3768 + false + true + false + false + true + + + pisd + + true + + 2 + + pisd + + CMakeProjectManager.CMakeRunConfiguration.pisd + 3768 + false + true + false + false + true + + 5 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 16 + + + Version + 16 + + diff --git a/Doxyfile b/Doxyfile index baaafbaa..2c6d54c5 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.8.6 +# Doxyfile 1.8.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -38,7 +38,7 @@ PROJECT_NAME = PIP # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.4.0 +PROJECT_NUMBER = 0.4.1_alpha3 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -70,6 +70,14 @@ OUTPUT_DIRECTORY = doc CREATE_SUBDIRS = NO +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. @@ -274,9 +282,12 @@ OPTIMIZE_OUTPUT_VHDL = NO # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # @@ -532,7 +543,7 @@ FORCE_LOCAL_INCLUDES = NO # documentation for inline members. # The default value is: YES. -INLINE_INFO = YES +INLINE_INFO = NO # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member @@ -682,8 +693,7 @@ LAYOUT_FILE = # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. Do not use file names with spaces, bibtex cannot handle them. See -# also \cite for info how to create references. +# search path. See also \cite for info how to create references. CITE_BIB_FILES = @@ -756,7 +766,7 @@ WARN_LOGFILE = # spaces. # Note: If this tag is empty the current directory is searched. -INPUT = . +INPUT = src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -777,45 +787,17 @@ INPUT_ENCODING = UTF-8 # *.qsf, *.as and *.js. FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ *.cpp \ *.c++ \ - *.d \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ *.h \ - *.hh \ - *.hxx \ *.hpp \ *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ - *.inc \ - *.m \ - *.markdown \ - *.md \ - *.mm \ - *.dox \ - *.py \ - *.f90 \ - *.f \ - *.for \ - *.vhd \ - *.vhdl # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. -RECURSIVE = NO +RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a @@ -1013,6 +995,25 @@ USE_HTAGS = NO VERBATIM_HEADERS = NO +# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# compiled with the --with-libclang option. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- @@ -1105,13 +1106,15 @@ HTML_FOOTER = HTML_STYLESHEET = -# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- -# defined cascading style sheet that is included after the standard style sheets +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. -# Doxygen will copy the style sheet file to the output directory. For an example -# see the documentation. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra stylesheet files is of importance (e.g. the last +# stylesheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = @@ -1276,7 +1279,8 @@ GENERATE_CHI = NO CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( -# YES) or a normal table of contents ( NO) in the .chm file. +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1516,11 +1520,11 @@ SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using Javascript. There -# are two flavours of web server based searching depending on the -# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for -# searching and an index file used by the script. When EXTERNAL_SEARCH is -# enabled the indexing and searching needs to be provided by external tools. See -# the section "External Indexing and Searching" for details. +# are two flavors of web server based searching depending on the EXTERNAL_SEARCH +# setting. When disabled, doxygen will generate a PHP script for searching and +# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing +# and searching needs to be provided by external tools. See the section +# "External Indexing and Searching" for details. # The default value is: NO. # This tag requires that the tag SEARCHENGINE is set to YES. @@ -1648,17 +1652,19 @@ EXTRA_PACKAGES = # # Note: Only use a user-defined header if you know what you are doing! The # following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will -# replace them by respectively the title of the page, the current date and time, -# only the current date, the version number of doxygen, the project name (see -# PROJECT_NAME), or the project number (see PROJECT_NUMBER). +# $datetime, $date, $doxygenversion, $projectname, $projectnumber, +# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string, +# for the replacement values of the other commands the user is refered to +# HTML_HEADER. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the # generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. +# chapter. If it is left blank doxygen will generate a standard footer. See +# LATEX_HEADER for more information on how to generate a default footer and what +# special commands can be used inside the footer. # # Note: Only use a user-defined footer if you know what you are doing! # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1682,7 +1688,7 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate +# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate # the PDF file directly from the LaTeX files. Set this option to YES to get a # higher quality PDF documentation. # The default value is: YES. @@ -1808,6 +1814,13 @@ MAN_OUTPUT = man MAN_EXTENSION = .3 +# The MAN_SUBDIR tag determines the name of the directory created within +# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by +# MAN_EXTENSION with the initial . removed. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_SUBDIR = + # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it # will generate one additional man file for each entity documented in the real # man page(s). These additional files only source the real man page, but without @@ -1835,18 +1848,6 @@ GENERATE_XML = NO XML_OUTPUT = xml -# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a -# validating XML parser to check the syntax of the XML files. -# This tag requires that the tag GENERATE_XML is set to YES. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify a XML DTD, which can be used by a -# validating XML parser to check the syntax of the XML files. -# This tag requires that the tag GENERATE_XML is set to YES. - -XML_DTD = - # If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program # listings (including syntax highlighting and cross-referencing information) to # the XML output. Note that enabling this will significantly increase the size @@ -1874,6 +1875,15 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook +# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the +# program listings (including syntax highlighting and cross-referencing +# information) to the DOCBOOK output. Note that enabling this will significantly +# increase the size of the DOCBOOK output. +# The default value is: NO. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_PROGRAMLISTING = NO + #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- @@ -1956,14 +1966,20 @@ EXPAND_ONLY_PREDEF = NO # The default value is: YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -SEARCH_INCLUDES = NO +SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by the # preprocessor. # This tag requires that the tag SEARCH_INCLUDES is set to YES. -INCLUDE_PATH = +INCLUDE_PATH = src/code \ + src/containers \ + src/core \ + src/io \ + src/math \ + src/system \ + src/thread # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the @@ -1994,9 +2010,9 @@ PREDEFINED = DOXYGEN \ EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will -# remove all refrences to function-like macros that are alone on a line, have an -# all uppercase name, and do not end with a semicolon. Such function macros are -# typically used for boiler-plate code, and will confuse the parser if not +# remove all references to function-like macros that are alone on a line, have +# an all uppercase name, and do not end with a semicolon. Such function macros +# are typically used for boiler-plate code, and will confuse the parser if not # removed. # The default value is: YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. @@ -2016,7 +2032,7 @@ SKIP_FUNCTION_MACROS = NO # where loc1 and loc2 can be relative or absolute paths or URLs. See the # section "Linking to external documentation" for more information about the use # of tag files. -# Note: Each tag file must have an unique name (where the name does NOT include +# Note: Each tag file must have a unique name (where the name does NOT include # the path). If a tag file is not located in the directory in which doxygen is # run, you must also specify the path to the tagfile here. @@ -2094,7 +2110,7 @@ HIDE_UNDOC_RELATIONS = YES # http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO -# The default value is: NO. +# The default value is: YES. HAVE_DOT = YES @@ -2108,7 +2124,7 @@ HAVE_DOT = YES DOT_NUM_THREADS = 8 -# When you want a differently looking font n the dot files that doxygen +# When you want a differently looking font in the dot files that doxygen # generates you can specify the font name using DOT_FONTNAME. You need to make # sure dot is able to find the font, which can be done by putting it in a # standard location or by setting the DOTFONTPATH environment variable or by @@ -2246,7 +2262,9 @@ DIRECTORY_GRAPH = YES # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # to make the SVG files visible in IE 9+ (other browsers do not have this # requirement). -# Possible values are: png, jpg, gif and svg. +# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd, +# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo, +# gif:cairo:gd, gif:gd, gif:gd:gd and svg. # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2289,6 +2307,15 @@ MSCFILE_DIRS = DIAFILE_DIRS = +# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file. If left blank, it is assumed +# PlantUML is not used or called during a preprocessing step. Doxygen will +# generate a warning when it encounters a \startuml command in this case and +# will not generate output for the diagram. +# This tag requires that the tag HAVE_DOT is set to YES. + +PLANTUML_JAR_PATH = + # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes # that will be shown in the graph. If the number of nodes in a graph becomes # larger than this value, doxygen will truncate the graph, which is visualized diff --git a/FindPIP.cmake b/FindPIP.cmake index 401e5f81..0347577f 100644 --- a/FindPIP.cmake +++ b/FindPIP.cmake @@ -1,14 +1,8 @@ if (${WIN32}) - get_filename_component(MGWDIR ${CMAKE_C_COMPILER} PATH) - find_path(MGWINCLUDE windows.h HINTS ${MGWDIR}/include) - get_filename_component(MGWINCLUDE ${MGWINCLUDE} PATH) - #file(RELATIVE_PATH MGWINCLUDE "${MGWDIR}" ${MGWINCLUDE}) - #string(SUBSTRING ${MGWINCLUDE} 1 -1 MGWINCLUDE) - #message(STATUS "MGWINCLUDE = ${MGWINCLUDE}/include") - #get_filename_component(MGWDIR ${CMAKE_C_COMPILER} PATH) - find_library(PIP_LIBRARY pip ${MGWINCLUDE}/lib) - set(PIP_INCLUDES ${MGWINCLUDE}/include/pip) - set(PIP_CMG ${MGWDIR}/pip_cmg.exe) + find_package(MinGW REQUIRED) + find_library(PIP_LIBRARY pip ${MINGW_LIB}) + set(PIP_INCLUDES ${MINGW_INCLUDE}/pip) + set(PIP_CMG ${MINGW_BIN}/pip_cmg.exe) else () find_library(PIP_LIBRARY pip /usr/lib/) if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") @@ -53,7 +47,7 @@ macro (pip_code_model SRC RESULT) endif () if (NEED_PARSE) message(STATUS "Creating code model based on \"${SRC}\", please wait ... ") - execute_process(COMMAND ${PIP_CMG} -qP -o ${PROJECT_NAME}_ccm -I${PIP_INCLUDES} ${SRC} OUTPUT_VARIABLE CMG_OUT) + execute_process(COMMAND ${PIP_CMG} -qPEs -o ${PROJECT_NAME}_ccm -I${PIP_INCLUDES} ${SRC} OUTPUT_VARIABLE CMG_OUT) message(STATUS "Creating code model done, to use it include \"${PROJECT_NAME}_ccm.h\"") string(REPLACE "\n" ";" CMG_LIST ${CMG_OUT}) string(REPLACE "\n" " " CMG_LIST_S ${CMG_OUT}) diff --git a/clean b/clean index 81218f4e..8d1dc6eb 100644 --- a/clean +++ b/clean @@ -2,15 +2,18 @@ VERBOSE=1 make clean rm -rvf ./CMakeFiles rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core -cd system_test +cd utils/system_test +VERBOSE=1 make clean rm -rvf ./CMakeFiles rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core -cd .. -cd remote_console +cd ../../ +cd utils/remote_console +VERBOSE=1 make clean rm -rvf ./CMakeFiles rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core -cd .. -cd code_model_generator +cd ../../ +cd utils/code_model_generator +VERBOSE=1 make clean rm -rvf ./CMakeFiles rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core -cd .. +cd ../../ diff --git a/clean.bat b/clean.bat index 9e0579b0..703d6aa1 100644 --- a/clean.bat +++ b/clean.bat @@ -2,13 +2,21 @@ del /q /f /s CMakeFiles rmdir /q /s CMakeFiles del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *~ *cxx moc_* *.o *.exe *.a *.dll *.lib core -cd system_test +cd utils\system_test del /q /f /s CMakeFiles rmdir /q /s CMakeFiles del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *~ *cxx moc_* *.o *.exe *.a *.dll *.lib core cd .. -cd remote_console +cd .. +cd utils\remote_console del /q /f /s CMakeFiles rmdir /q /s CMakeFiles del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *~ *cxx moc_* *.o *.exe *.a *.dll *.lib core cd .. +cd .. +cd utils\code_model_generator +del /q /f /s CMakeFiles +rmdir /q /s CMakeFiles +del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *~ *cxx moc_* *.o *.exe *.a *.dll *.lib core +cd .. +cd .. diff --git a/main.cpp b/main.cpp index b5adc277..67f01f74 100644 --- a/main.cpp +++ b/main.cpp @@ -1,188 +1,129 @@ -/* - PIP - Platform Independent Primitives - Test program - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -//#define PIP_DEBUG -/*#include "pip.h" - - -class ElementA: public PIObject { - PIOBJECT(ElementA) - // ... -}; -ADD_NEW_TO_COLLECTION(ab_group, ElementA) - -class ElementB: public PIObject { - PIOBJECT(ElementB) - // ... -}; -ADD_NEW_TO_COLLECTION(ab_group, ElementB) - -class ElementC: public PIObject { - PIOBJECT(ElementC) - // ... -}; -ADD_NEW_TO_COLLECTION(c_group, ElementC) - -class ElementD: public PIObject { - PIOBJECT(ElementD) - // ... -}; -*/ #include "pip.h" -#include "pivariant.h" - - - - -#include "picodeparser.h" -#include "pidir.h" -#include "piconnection.h" -#include - -bool readed(void*, uchar * data, int size) { - piCout << Hex << "readed" << PIByteArray(data, size); - //piCout << PIString((char*)data, size); - return true; -} - -class A: public PIObject { - PIOBJECT(A) +class Ob: public PIObject { + PIOBJECT(Ob) public: - EVENT_HANDLER2(void, cr, const PIString &, from, const PIByteArray &, data) { - piCout << "A readed" << from << Hex << data; + Ob() { + sft.setName("sft"); + sft.setDirectory(sft.directory().cd("..\\")); + piCout << "Send File Transfer DIrectory" << sft.directory().absolutePath(); + CONNECTU(&sft, sendRequest, this, ssend); + + rft.setName("rft"); + rft.setDirectory(rft.directory().cd("..\\1")); + piCout << "Receive File Transfer DIrectory" << rft.directory().absolutePath(); + CONNECTU(&rft, sendRequest, this, rsend); } - EVENT_HANDLER2(void, per, uchar *, data, int, size) { - piCout << "A readed" << size << ":\"" << PIString((const char *)data, size) << "\"" << NewLine; - //piCout << "A readed \""; + + void startsend() { + PIDir dir = PIDir::current(); + dir.cd("..\\"); + piCout << dir.absolutePath(); + PIVector des = dir.allEntries(); + piCout << "all entries" << des.size(); + PIDir::DirEntry sde; + piForeachC(PIDir::DirEntry de, des) { + //piCout << (de.isDir() ? "dir:" : "file") << de.name << de.size; + if (de.name == "0") sde = de; + } + //sft.setPacketSize(64096); + sft.send(sde); } + +private: + EVENT_HANDLER1(void, ssend, PIByteArray &, data) { +// piCout << "[sender]" << sft.stateString() << ". datasize =" << data.size() +// << "(" << PIString::readableSize(sft.bytesFileCur()) << "/" << PIString::readableSize(sft.bytesFileAll()) << ", " +// << PIString::readableSize(sft.bytesTotalCur()) << "/" << PIString::readableSize(sft.bytesTotalAll()) << ")"; + if(rand()%100 != 90) rft.received(data); + } + + EVENT_HANDLER1(void, rsend, PIByteArray &, data) { +// piCout << "[receiver]" << rft.stateString() << ". datasize =" << data.size() +// << "(" << PIString::readableSize(rft.bytesFileCur()) << "/" << PIString::readableSize(rft.bytesFileAll()) << ", " +// << PIString::readableSize(rft.bytesTotalCur()) << "/" << PIString::readableSize(rft.bytesTotalAll()) << ")"; + if(rand()%100 != 90) sft.received(data); + } + + PIFileTransfer sft; + PIFileTransfer rft; }; -class TC: public PIConnection { + +class UDPFileTransfer: public PITimer { + PIOBJECT_SUBCLASS(UDPFileTransfer, PITimer) public: - TC() { - PIPacketExtractor * pe = addFilter("h&f", addDevice("file://piiodevice.h", PIIODevice::ReadOnly, false), PIPacketExtractor::HeaderAndFooter); - pe->setHeader(PIString("//!").toByteArray()); - pe->setFooter(PIString("\n").toByteArray()); - pe = addFilter(" h ", "file://piiodevice.h", PIPacketExtractor::Header); - addChannel(pe, addDevice("file://out.txt", PIIODevice::WriteOnly)); - pe->setHeader(PIString("PI").toByteArray()); - pe->setPayloadSize(3); - startAllThreadedReads(); + UDPFileTransfer(const PIString &src_ip_port, const PIString &dst_ip_port) { + eth.setReadAddress(src_ip_port); + eth.setSendAddress(dst_ip_port); + //ft.setPacketSize(65000); + CONNECTU(&ft, sendRequest, this, ftsend); + CONNECTU(&ft, startSend, this, ftevent); + CONNECTU(&ft, finishSend, this, ftevent); + CONNECTU(&ft, startReceive, this, ftevent); + CONNECTU(&ft, finishReceive, this, ftevent); + CONNECTU(ð, threadedReadEvent, this, received); + start(50); + eth.open(); + eth.startThreadedRead(); } - virtual void dataReceived(const PIString & from, const PIByteArray & data) { - piCout << "dataReceived" << from << (data.size()); + + void startSend(const PIString &file) { + ft.send(file); } - virtual void packetReceived(const PIString & from, const PIByteArray & data) { - piCout << "packetReceived" << from << (data.size()) << PIString(data); + + PIFileTransfer ft; + +private: + PIEthernet eth; + + void tick(void *, int) { + if (ft.isSending() || ft.isReceiving()) ftevent(); } - virtual bool filterValidatePayload(const PIString & filter_name, uchar * rec, int size) { - //piCout << "filterValidatePayload" << filter_name << PIString((char*)rec, size); - if (filter_name == " h ") return PIString((char*)rec, size) == "IOD"; - return false; + + EVENT_HANDLER(void, ftevent) { + piCout << ft.stateString() + << "(" << PIString::readableSize(ft.bytesFileCur()) << "/" << PIString::readableSize(ft.bytesFileAll()) << ", " + << PIString::readableSize(ft.bytesTotalCur()) << "/" << PIString::readableSize(ft.bytesTotalAll()) << ")"; + } + + EVENT_HANDLER1(void, ftsend, PIByteArray &, data) { + eth.send(data); + } + + EVENT_HANDLER2(void, received, uchar * , readed, int, size) { + PIByteArray ba(readed, size); + ft.received(ba); } }; int main (int argc, char * argv[]) { - /*A a_; - PIFile file("piiodevice.h", PIIODevice::ReadOnly); - PIByteArray header = PIString("PI").toByteArray(); - PIByteArray footer = PIString("}").toByteArray(); - PIPacketExtractor pe(&file); - //pe.setPacketData(header.data(), header.size_s(), 10); - pe.setSplitMode(PIPacketExtractor::Footer); - pe.setHeader(header); - pe.setFooter(footer); - pe.setPayloadSize(3); - pe.setThreadedReadBufferSize(40); - //pe.setBufferSize(256); - //pe.setPacketData(0, 0, 20); - CONNECT2(void, uchar * , int , &pe, packetReceived, &a_, per) - pe.startThreadedRead(); - piMSleep(500);*/ - - TC tc; - piMSleep(500); - piCout << tc.makeConfig(); - return 0; - - /*tm = PISystemTime::current(); - for (int i = 0; i < 10000000; ++i) { - ql.append(i*10); - ql.prepend(i*10 + 1); + if (!(argc == 3 || argc == 4)) { + piCout << "UDPFileTransfer"; + piCout << "USE: piptest [src_ip_port] [dst_ip_port] {filename}"; + return 0; } - piCout << (PISystemTime::current() - tm).toMicroseconds(); - */ - //tm = PISystemTime::current(); - /*for (int i = 0; i < 100000000; ++i) { - pl.append(i*10); - pl.prepend(i*10 + 1); - }*/ - //PICodeParser cd_; - //cd.includeDirectory("../qpicalculator"); - //cd_.parseFile("piincludes.h"); - //piCout << (PISystemTime::current() - tm).toMilliseconds(); - /*piCout << NewLine; - piForeachCA (i, pl) - piCout << i; - - pl.remove(1, 2).prepend(111).prepend(222); - pl.remove(1, 1); - piCout << NewLine; - piForeachCA (i, pl) - piCout << i;*/ - /*piCout << NewLine; - for (int i = 0; i < pl.size_s(); ++i) - piCout << pl[i]; - */ - - /*PIEthernet eth(PIEthernet::UDP); - eth.setReadAddress("192.168.0.30:4001"); - eth.setSendAddress("192.168.0.50:4001"); - eth.startThreadedRead(readed); - piCout << "Connected"; - //eth.send(PIString("This is test string!\n").toByteArray()); - FOREVER_WAIT*/ - - if (argc < 2) return 0; - PICodeParser cd; - //cd.includeDirectory("../qpicalculator"); - cd.parseFile(argv[1]); - piForeachC (PICodeParser::Enum & e, cd.enums) - piCout << e.name << e.members; - - - //piCout << v.toType(); - //piCout << v.toType().toType(); - //PIFile::remove("ki"); - /*PIConfig conf("protocols_commod.conf"); - piCout << conf.allTree(); - conf.setValue("rmd.123", 456);*/ - - /*PITimer tm; - piCout << tm.debug() << tm.properties(); - tm.setDebug(false); - piCout << tm.debug() << tm.properties(); - tm.setDebug(true); - piCout << tm.debug() << tm.properties();*/ - - //PIObject * ser = (PIObject * )PIIODevice::createFromFullPath("file://OM2:38400:7"); - //piCout << ser << NewLine << ser->properties(); + PIKbdListener kbd; + kbd.enableExitCapture(); + PIString src = argv[1]; + PIString dst = argv[2]; + UDPFileTransfer f(src, dst); + piCout << "work directory" << f.ft.directory().absolutePath() << ", listen on" << src << ",send to" << dst; + if (argc == 4) { + PIString file = argv[3]; + piCout << "send file" << file; + f.startSend(file); + return 0; + } else { + piCout << "wait for receiving"; + } + WAIT_FOR_EXIT + return 0; +// Ob o; +// ft.setPacketSize(65536); +// PITimeMeasurer tm; +// o.startsend(); +// piCout << tm.elapsed_s(); +// return 0; } - diff --git a/main_.cpp b/main_.cpp new file mode 100644 index 00000000..557171f9 --- /dev/null +++ b/main_.cpp @@ -0,0 +1,294 @@ +/* + PIP - Platform Independent Primitives + Test program + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +//#define PIP_DEBUG +#include "pip.h" +//#include "pivariant.h" +//#include "picodeparser.h" +//#include "pidir.h" +#include "piconnection.h" +//#include + +PIMutex mutex; +PIDeque deq; + +void timerE(void * t, int d) { + //PIMutexLocker l(mutex); + /*if (d == 1) + deq.push_back(int(t)); + else + deq.push_front(int(t));*/ + //printf("%d\n", deq.size()); + piCout << "tick" << (int)t << d; +} + + + +class A: public PIObject { + PIOBJECT(A) +public: + A() {} + EVENT_HANDLER1(void, handlerA1, PIString, s) {piCout << "handlerA1 s" << s;} + EVENT_HANDLER1(void, handlerA1, float, f) {piCout << "handlerA1 f" << f;} + //uchar _[0x10]; +}; + + +class B: public PIObject { + PIOBJECT(B) +public: + B() {} + EVENT1(eventB1, float, f); + EVENT1(eventB2, PIString, s); + //uchar _[0x20]; +}; + + +class C: public A, public B { +public: + C() {} +}; + +int main (int argc, char * argv[]) { + PIFile f("test.txt"); + f.clear(); + f << "1234566789\n"; + piCout << f.size(); + f.close(); + piCout << f.size(); + + /*CONNECTU(&b, eventB1, &a, handlerA1) + CONNECTU(&b, eventB2, &a, handlerA1) + a.dump(); + b.dump(); + b.eventB1(0.33); + b.eventB2("str");*/ + + + + //conf.dump(); + /*PIObject * t_o = &timer, * a_o = &a, * b_o = &b; + CONNECTU(t_o, tickEvent, a_o, handlerT) + CONNECTU(b_o, eventB1, &a, handlerA1) + CONNECTU(&b, eventB2, a_o, hAAA) + a_o->dump("* "); + b_o->dump("# "); + //dumpApplication(); + b.eventB(10, "str"); + b.eventB1(10.5); + b.eventB2("test");*/ + + /*PIKbdListener kbd; + PITimer timer(timerE); + timer.start(100); + kbd.enableExitCapture(); + WAIT_FOR_EXIT*/ + + /* + PIMathVectorT3d v(1., -2., 3.); + PIMathMatrixT33d m0; + m0.setCol(0, v.normalized()); + m0.setCol(1, PIMathVectorT3d(v[1], -v[0], 0.).normalized()); + m0.setCol(2, m0.col(1) * m0.col(0)); + + piCout << m0.determinant(); + //m0.setRow(1, PIMathVectorT3d(1., 2., 3.)); + //piCout << m0 << NewLine << NewLine << m0.; + //PIMathMatrixT33d m0_(-1., 2., 3., 4., -5., 6., 7., 8., -9.); + //PIMathMatrixT33d m1_(10., 2., 30., 4., 50., 6., 70., 8., 90.); + //piCout << m0_.determinant() << m1_.determinant(); + */ + + /* + PITimer::TimerImplementation ti_ = PITimer::ThreadRT; + PITimer t_(timerE, 0, ti_); + t_.setData((void*)0x10); + t_.start(100); + piSleep(1); + piCout << "end"; + t_.stop(); + piCout << "end 1"; + t_.waitForFinish(); + piCout << "end 2"; + */ + + /* + PIVector timers; + int tc = PIString(argv[1]).toInt(); + piCout << "create ..."; + for (int i = 0; i < tc; ++i) { + PITimer * t = new PITimer(timerE, 0, PITimer::Thread); + t->setData((void*)i); + //t->dump(); + timers << t; + if (i > 10) t->addDelimiter(i / 10); + t->start(100); + } + piCout << "create ok"; + piSleep(1); + dumpApplication(); + piCout << "delete ..."; + piForeach (PITimer * t, timers) + t->stop(); + piForeach (PITimer * t, timers) + delete t; + piCout << "delete ok"; + */ + + /* + PIConsole console(false); + PISystemMonitor mon; + console.addVariable("", &mon); + mon.startOnSelf(); + console.enableExitCapture(); + console.start(); + console.waitForFinish(); + return 0; + */ + + /*PITimeMeasurer tm_; + piCout << PIIODevice::normalizeFullPath("ser:///dev/ttyS1"); + piCout << tm_.elapsed_u(); + tm_.reset(); + piCout << PIIODevice::normalizeFullPath("ser:///dev/ttyS2"); + piCout << tm_.elapsed_u(); + tm_.reset(); + piCout << PIIODevice::normalizeFullPath("ser:///dev/ttyS3"); + piCout << tm_.elapsed_u(); + tm_.reset(); + piCout << PIIODevice::normalizeFullPath("ser:///dev/ttyS1"); + piCout << tm_.elapsed_u(); + tm_.reset();*/ + //msleep(6000000); + + /*A a_; + PIFile file("piiodevice.h", PIIODevice::ReadOnly); + PIByteArray header = PIString("PI").toByteArray(); + PIByteArray footer = PIString("}").toByteArray(); + PIPacketExtractor pe(&file); + //pe.setPacketData(header.data(), header.size_s(), 10); + pe.setSplitMode(PIPacketExtractor::Footer); + pe.setHeader(header); + pe.setFooter(footer); + pe.setPayloadSize(3); + pe.setThreadedReadBufferSize(40); + //pe.setBufferSize(256); + //pe.setPacketData(0, 0, 20); + CONNECT2(void, uchar * , int , &pe, packetReceived, &a_, per) + pe.startThreadedRead(); + piMSleep(500);*/ + + /*TC tc; + piMSleep(2000); + //piCout << tc.diagnostic("file://piiodevice.h")->receiveBytesPerSec(); + piCout << tc.makeConfig();*/ + + /*PITimer timer; + piForTimes (50) { + piUSleep(10); + piCout << PISystemTime::current() << timer.elapsed_u(); + } + piCout << NewLine; + piForTimes (50) { + piUSleep(100); + piCout << PISystemTime::current(true) << timer.elapsed_u(); + }*/ + + /*PIConsole console; + PIEthernet eth(PIEthernet::TCP_Client); + eth.connect("192.168.20:5006"); + eth.startThreadedRead(readed); + console.enableExitCapture(); + console.start(); + console.waitForFinish();*/ + + /*PIBinaryLog log_; + GPS_Data gps; + log_.open("log_gps__2014_07_03__11_22_18", PIIODevice::ReadOnly); + while (!log_.isEnd()) { + log_.read(&gps, sizeof(gps)); + printf("%f %f\n", gps.lat, gps.lng); + }*/ + return 0; + + /*tm = PISystemTime::current(); + for (int i = 0; i < 10000000; ++i) { + ql.append(i*10); + ql.prepend(i*10 + 1); + } + piCout << (PISystemTime::current() - tm).toMicroseconds(); + */ + //tm = PISystemTime::current(); + /*for (int i = 0; i < 100000000; ++i) { + pl.append(i*10); + pl.prepend(i*10 + 1); + }*/ + //PICodeParser cd_; + //cd.includeDirectory("../qpicalculator"); + //cd_.parseFile("piincludes.h"); + //piCout << (PISystemTime::current() - tm).toMilliseconds(); + /*piCout << NewLine; + piForeachCA (i, pl) + piCout << i; + + pl.remove(1, 2).prepend(111).prepend(222); + pl.remove(1, 1); + piCout << NewLine; + piForeachCA (i, pl) + piCout << i;*/ + /*piCout << NewLine; + for (int i = 0; i < pl.size_s(); ++i) + piCout << pl[i]; + */ + + /*PIEthernet eth(PIEthernet::UDP); + eth.setReadAddress("192.168.0.30:4001"); + eth.setSendAddress("192.168.0.50:4001"); + eth.startThreadedRead(readed); + piCout << "Connected"; + //eth.send(PIString("This is test string!\n").toByteArray()); + FOREVER_WAIT*/ + + /* + if (argc < 2) return 0; + PICodeParser cd; + //cd.includeDirectory("../qpicalculator"); + cd.parseFile(argv[1]); + piForeachC (PICodeParser::Enum & e, cd.enums) + piCout << e.name << e.members; + */ + + //piCout << v.toType(); + //piCout << v.toType().toType(); + //PIFile::remove("ki"); + /*PIConfig conf("protocols_commod.conf"); + piCout << conf.allTree(); + conf.setValue("rmd.123", 456);*/ + + /*PITimer tm; + piCout << tm.debug() << tm.properties(); + tm.setDebug(false); + piCout << tm.debug() << tm.properties(); + tm.setDebug(true); + piCout << tm.debug() << tm.properties();*/ + + //PIObject * ser = (PIObject * )PIIODevice::createFromFullPath("file://OM2:38400:7"); + //piCout << ser << NewLine << ser->properties(); +} + + diff --git a/main_tcp_server.cpp b/main_tcp_server.cpp new file mode 100644 index 00000000..7cfb4162 --- /dev/null +++ b/main_tcp_server.cpp @@ -0,0 +1,93 @@ +#include "pip.h" + +class Client: public PIObject { + PIOBJECT(Client); +public: + Client(PIEthernet * eth_) { + eth = eth_; + eth->startThreadedRead(); + CONNECTU(eth, threadedReadEvent, this, readed); + CONNECTU(eth, disconnected, this, disconnected); + piCoutObj << uint(eth) << "client connected"; + } + ~Client() {} + EVENT_HANDLER2(void, readed, uchar * , data, int, size) { + PIByteArray ba(data, size) + piCoutObj << uint(eth) << "readed" << size << "bytes" << Hex << ba; + eth->write(ba); + } + EVENT_HANDLER1(void, disconnected, bool, withError) { + piCoutObj << uint(eth) << "client disconnected"; + disconnect(this); + } + void send() { + PIByteArray ba; + ba << uchar(0) << uchar(1) << uchar(2); + piCoutObj << uint(eth) << "client send" << ba; + eth->write(ba); + } + PIEthernet * eth; + + EVENT1(disconnect, Client *, client) +}; + +class Server: public PIObject { + PIOBJECT(Server); +public: + Server(int port) { + eth = new PIEthernet(PIEthernet::TCP_Server); + eth->setParameter(PIEthernet::ReuseAddress); + CONNECTU(eth, newConnection, this, newConnection); + PIString path = "0.0.0.0:" + PIString::fromNumber(port); + eth->listen(path, true); + piCoutObj << uint(eth) << "server started" << path; + } + ~Server() { + eth->close(); + piCoutObj << uint(eth) << "server stoped"; + delete eth; + } + EVENT_HANDLER1(void, newConnection, PIEthernet * , cl) { + piCoutObj << uint(eth) << "add client"; + Client * client = new Client(cl); + CONNECTU(client, disconnect, this, disconnect); + clients.push_back(client); + } + EVENT_HANDLER1(void, disconnect, Client *, client) { + piCoutObj << uint(eth) << "remove client"; + delete client; + clients.removeOne(client); + } + PIEthernet * eth; + PIVector clients; + void send() { + for (int i=0; isend(); + } + } +}; + +Server sl(10001); +Server s2(10002); + + +void keyEvent(char key, void*) { + switch (key) { + case '1': sl.send(); break; + case '2': s2.send(); break; + }; +}; + +void timerEvent(void * , int) { + //sl.send(); +}; + +PITimer timer(timerEvent); + +int main(int argc, char * argv[]) { + timer.start(1000.); + PIKbdListener kbd(keyEvent); + kbd.enableExitCapture(); + WAIT_FOR_EXIT; + return 0; +} diff --git a/make.sh b/make.sh deleted file mode 100644 index 64fcb2ab..00000000 --- a/make.sh +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/sh -cmake ./ -make $@ diff --git a/make_lib.bat b/make_lib.bat index 83908120..afe1db57 100644 --- a/make_lib.bat +++ b/make_lib.bat @@ -1 +1 @@ -cmake_mgw -DLIB= && make install +cmake_mgw -DLIB= && make install %* diff --git a/make_rc_win.bat b/make_rc_win.bat deleted file mode 100644 index f6c1b22a..00000000 --- a/make_rc_win.bat +++ /dev/null @@ -1 +0,0 @@ -windres -i pip_resource_win.rc -o pip_resource_win.o --include-dir=. \ No newline at end of file diff --git a/pibinarylog.cpp b/pibinarylog.cpp deleted file mode 100644 index 8746a45e..00000000 --- a/pibinarylog.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* - PIP - Platform Independent Primitives - Class for write binary data to logfile, and read or playback this data - Copyright (C) 2014 Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pibinarylog.h" - - -/*! \class PIBinaryLog - * \brief Class for read and write binary data to logfile, and playback this data in realtime - * - * \section PIBinaryLog_sec0 Synopsis - * Binary Log is a file with simle header, where you can read and write some binary data. - * Any written data include special header with ID, size and timestamp. - * This header provides separation different messages from the one file by choosing different IDs. - * With \a filterID or special functions, like \a readBinLog() you can choose IDs what you want to read. - * With function \a writeBinLog() or \a setDefaultID() you can choose ID that mark you data. - * By default ID = 1, and \a filterID is empty, that mean you read any ID without filtering. - * ThreadedRead provide you playback data, with delay that you write data. - * You can choose realtime playbak or variable speed play back by set \a PlayMode. - * - * \section PIBinaryLog_sec1 Basic usage - * This class provide all functions of \a PIIODevice, such \a open(), \a close(), - * \a read() ,\a write(), and threaded read/write. - * function \a setLogDir() need to set directory for BinLog files - * function \a createNewFile() need to create new binlog file - * function \a restart() need start from the begining of binlog file - * - */ - -REGISTER_DEVICE(PIBinaryLog); - - -PIBinaryLog::PIBinaryLog() { - binlog_sig[0] = 'B'; - binlog_sig[1] = 'I'; - binlog_sig[2] = 'N'; - binlog_sig[3] = 'L'; - binlog_sig[4] = 'O'; - binlog_sig[5] = 'G'; - setThreadedReadBufferSize(65536); - is_started = false; - setPlaySpeed(1.f); - setDefaultID(1); - setPlayMode(PlayVariableSpeed); - setLogDir(PIString()); - setFilePrefix(PIString()); - setRapidStart(false); -} - - -bool PIBinaryLog::openDevice() { - lastrecord.timestamp = PISystemTime(); - lastrecord.id = 0; - is_started = false; - is_thread_ok = true; - if (mode_ == ReadWrite) { - piCoutObj << "Error: ReadWrite mode not supported, use WriteOnly or ReadOnly"; - return false; - } - if (!file.open(path(), mode_)) - return false; - setName(path()); - if (mode_ == WriteOnly) { - file.resize(0); - if (!writeFileHeader()) { - piCoutObj << "Error: Can't write binlog file header"; - return false; - } - is_started = true; - } - if (mode_ == ReadOnly) { - if (file.isEmpty()) { - piCoutObj << "Error: File is null"; - fileError(); - return false; - } - if (!checkFileHeader()) { - fileError(); - return false; - } - if (isEmpty()) piCoutObj << "Error: Empty BinLog file"; - // startlogtime = PISystemTime::current(); - play_time = 0; - // nextrecord = readsRecord(); - if (!rapidStart()) is_started = true; - } - startlogtime = PISystemTime::current(); - return true; -} - - -bool PIBinaryLog::closeDevice() { - if (canWrite() && isEmpty()) { - file.remove(); - return true; - } - return file.close(); -} - - -bool PIBinaryLog::threadedRead(uchar *readed, int size) { - is_thread_ok = false; - PISystemTime pt; - double delay; - switch (playMode()) { - case PlayRealTime: - pt = PISystemTime::current() - startlogtime; -// if (real_speedX > 0) -// for (int i=0; i pt) - (lastrecord.timestamp - pt).sleep(); - } else { - startlogtime = PISystemTime::current() - lastrecord.timestamp; - is_started = true; - } - // int delay = piRoundd(lastread_timestamp.toMilliseconds() - (PISystemTime::current() - startlogtime).toMilliseconds()); - break; - case PlayVariableSpeed: - delay = lastrecord.timestamp.toMilliseconds() - play_time; - delay /= playSpeed(); - if (is_started) { - if (delay > 0) - PISystemTime::fromMilliseconds(delay).sleep(); - } else is_started = true; - play_time = lastrecord.timestamp.toMilliseconds(); - break; - default: - return false; - } - bool res = PIIODevice::threadedRead(readed, size); - is_thread_ok = true; - return res; -} - - -PIString PIBinaryLog::createNewFile() { - if (!file.close()) return PIString(); - if (open(logDir() + "/" + filePrefix() + PIDateTime::current().toString("yyyy_MM_dd__hh_mm_ss.binlog"), PIIODevice::WriteOnly)) - return file.path(); - piCoutObj << "Can't create new file, maybe LogDir is invalid."; - return PIString(); -} - - -int PIBinaryLog::writeBinLog(int id, const void *data, int size) { - if (size <= 0 || !canWrite()) return -1; - PIByteArray logdata; - logdata << id << size << (PISystemTime::current() - startlogtime) << PIByteArray::RawData(data, size); - int res = file.write(logdata.data(), logdata.size()); - file.flush(); - if (res > 0) return size; - else return res; -} - - -PIByteArray PIBinaryLog::readBinLog(int id) { - if (!canRead()) return PIByteArray(); - BinLogRecord br = readRecord(); - if (br.id == -1) { - piCoutObj << "End of BinLog file"; - fileEnd(); - return PIByteArray(); - } - if (id == 0 && br.id > 0) return br.data; - while (br.id != id && !isEnd()) br = readRecord(); - if (br.id == -1) { - piCoutObj << "End of BinLog file"; - fileEnd(); - return PIByteArray(); - } - if (br.id == id) return br.data; - piCoutObj << "Can't find record with id =" << id; - return PIByteArray(); -} - - -int PIBinaryLog::readBinLog(int id, void *read_to, int max_size) { - if (max_size <= 0 || read_to == 0) return -1; - PIByteArray ba = readBinLog(id); - if (ba.isEmpty()) return -1; - int sz = piMini(max_size, ba.size()); - memcpy(read_to, ba.data(), sz); - return sz; -} - - - -int PIBinaryLog::read(void *read_to, int max_size) { - // piCoutObj << "read"; - if (lastrecord.id == -1 || isEnd()) return 0; - if(!is_thread_ok && lastrecord.id > 0) return lastrecord.data.size(); - if (!canRead()) return -1; - if (max_size <= 0 || read_to == 0) return -1; - BinLogRecord br; - br.id = 0; - if (filterID.isEmpty()) br = readRecord(); - else { - while (!filterID.contains(br.id) && !isEnd()) br = readRecord(); - } - if (br.id == -1) { - fileEnd(); - piCoutObj << "End of BinLog file"; - //stopThreadedRead(); - return 0; - } - if (br.id <= 0) { - piCoutObj << "Read record error"; - return -1; - } - int sz = piMini(max_size, br.data.size()); - memcpy(read_to, br.data.data(), sz); - return sz; -} - - -void PIBinaryLog::restart() { - bool th = isRunning(); - if (th) stopThreadedRead(); - if (!canRead()) return; - lastrecord.timestamp = PISystemTime(); - lastrecord.id = 0; - is_thread_ok = true; - if (rapidStart()) is_started = false; - else is_started = true; - play_time = 0; - file.seekToBegin(); - checkFileHeader(); - startlogtime = PISystemTime::current(); - if (th) startThreadedRead(); -} - - -bool PIBinaryLog::writeFileHeader() { - if (file.write(&binlog_sig, PIBINARYLOG_SIGNATURE_SIZE) <= 0) return false; - uchar version = PIBINARYLOG_VERSION; - if (file.write(&version, 1) <= 0) return false; - file.flush(); - return true; -} - - -bool PIBinaryLog::checkFileHeader() { - uchar read_sig[PIBINARYLOG_SIGNATURE_SIZE]; - for (int i=0; i PIBINARYLOG_VERSION) - piCoutObj << "BinLogFile has too newest version"; - return false; -} - - -PIBinaryLog::BinLogRecord PIBinaryLog::readRecord() { - // piCoutObj << "readRecord"; - PIByteArray ba; - BinLogRecord br; - lastrecord.id = 0; - lastrecord.data.clear(); - lastrecord.timestamp = PISystemTime(); - ba.resize(sizeof(BinLogRecord) - sizeof(PIByteArray)); - if(file.read(ba.data(), ba.size_s()) > 0) { - ba >> br.id >> br.size >> br.timestamp; - // piCoutObj << "read" << br.id << br.size << br.timestamp; - } else { - br.id = -1; - return br; - } - if (br.id > 0 && br.size > 0) { - ba.resize(br.size); - if(file.read(ba.data(), ba.size_s()) > 0) br.data = ba; - else br.id = 0; - } else br.id = 0; - lastrecord = br; - if (br.id == 0) fileError(); - return br; -} - - -PIString PIBinaryLog::constructFullPath() const { - PIString ret(fullPathPrefix() + "://"); - ret << logDir() << ":" << filePrefix() << ":" << defaultID(); - return ret; -} - - -void PIBinaryLog::configureFromFullPath(const PIString & full_path) { - PIStringList pl = full_path.split(":"); - for (int i = 0; i < pl.size_s(); ++i) { - PIString p(pl[i]); - switch (i) { - case 0: setLogDir(p); break; - case 1: setFilePrefix(p); break; - case 2: setDefaultID(p.toInt()); break; - } - } -} - diff --git a/pibinarylog.h b/pibinarylog.h deleted file mode 100644 index 9958fb41..00000000 --- a/pibinarylog.h +++ /dev/null @@ -1,175 +0,0 @@ -/*! \file pibinarylog.h - * \brief Binary log -*/ -/* - PIP - Platform Independent Primitives - Class for write binary data to logfile, and read or playback this data - Copyright (C) 2014 Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIBINARYLOG_H -#define PIBINARYLOG_H - -#include "pifile.h" - -#define PIBINARYLOG_VERSION 0x31 -#define PIBINARYLOG_SIGNATURE_SIZE 6 - - -class PIBinaryLog: public PIIODevice -{ - PIIODEVICE(PIBinaryLog) -public: - PIBinaryLog(); - ~PIBinaryLog() {closeDevice();} - - //! \brief Play modes for \a PIBinaryLog - enum PlayMode { - PlayRealTime /*! Play in system real time */ , - PlayVariableSpeed /*! Play in software time with speed, set by \a setSpeed. Set by default */ - }; - - - //! Current \a PlayMode - PlayMode playMode() const {return (PlayMode)(property("playMode").toInt());} - - //! Current directory where billogs wiil be saved - PIString logDir() const {return property("logDir").toString();} - - //! Returns current file prefix - PIString filePrefix() const {return property("filePrefix").toString();} - - //! Current LogDir, returns directory where billogs wiil be saved - int defaultID() const {return property("defaultID").toInt();} - - //! Returns current play speed - float playSpeed() const {return property("playSpeed").toFloat();} - - //! Returns if rapid start enabled - bool rapidStart() const {return property("rapidStart").toBool();} - - - //! Set \a PlayMode - void setPlayMode(PlayMode mode) {setProperty("playMode", (int)mode);} - - //! Set path to directory where binlogs will be saved - void setLogDir(const PIString & path) {setProperty("logDir", path);} - - //! Set file prefix, used to - void setFilePrefix(const PIString & prefix) {setProperty("filePrefix", prefix);} - - //! Set defaultID, used in \a write function - void setDefaultID(int id) {setProperty("defaultID", id);} - - //! If enabled BinLog \a ThreadedRead starts without delay for first record, e.g. first record will be readed immediately - void setRapidStart(bool enabled) {setProperty("rapidStart", enabled);} - -// /** \brief Set play speed multiplyer, used only in \a PlayMode = \a PlayRealTime default value 1x. -// * If "speedX" > 0 than it use as speed increase by X times, else as speed decrease by X times. -// * While is running this function does nothing and returns false. If "speedX" is set, returns true.*/ -// bool setRealSpeedX(int speedX) {if (speedX == 0 || isRunning()) return false; real_speedX = speedX; return true;} -// //! Returns current play speed multiplyer -// float realSpeedX() const {return real_speedX;} - //! Set play speed, used only if \a playMode = \a PlayVariableSpeed, default value 1.0 - void setPlaySpeed(float speed) {setProperty("playSpeed", speed);} - - - //! Write one record to BinLog file, with ID = id, id must be greather than 0 - int writeBinLog(int id, PIByteArray data) {return writeBinLog(id, data.data(), data.size_s());} - - int writeBinLog(int id, const void * data, int size); - - //! Read one record from BinLog file, with ID = id, if id = 0 than any id will be readed - PIByteArray readBinLog(int id = 0); - - int readBinLog(int id, void * read_to, int max_size); - - //! Return true, if position at the end of BinLog file - bool isEnd() {if (!opened_) return true; return file.isEnd();} - - //! Returns if BinLog file is empty - bool isEmpty() {return (file.size() <= PIBINARYLOG_SIGNATURE_SIZE + 1);} - - int lastReadedID() const {return lastrecord.id;} - - //! Read one message from binlog file, with ID contains in "filterID" or any ID, if "filterID" is empty - int read(void *read_to, int max_size); - - //! Write one record to BinLog file, with ID = "defaultID" - int write(const void * data, int size) {return writeBinLog(defaultID(), data, size);} - - //! Array of ID, that BinLog can read from binlog file, when use \a read function, or in \a ThreadedRead - PIVector filterID; - - //! Go to begin of BinLog file - void restart(); - - PIString constructFullPath() const; - - //! \handlers - //! \{ - - //! \fn PIString createNewFile() - //! \brief Open device - - //! \} - //! \events - //! \{ - - //! \fn void fileEnd() - //! \brief Create new binlog file in \a logDir, if successful returns filename, else returns empty string. - //! Filename is like \a filePrefix + "yyyy_MM_dd__hh_mm_ss.binlog" - - //! \fn void fileError() - //! \brief Raise on file creation error - - //! \} - - EVENT_HANDLER(PIString, createNewFile); - EVENT(fileEnd) - EVENT(fileError) - -protected: - PIString fullPathPrefix() const {return "binlog";} - void configureFromFullPath(const PIString & full_path); - bool openDevice(); - bool closeDevice(); - bool threadedRead(uchar *readed, int size); - -private: - struct BinLogRecord { - int id; - int size; - PISystemTime timestamp; - PIByteArray data; - }; - - bool writeFileHeader(); - bool checkFileHeader(); - BinLogRecord readRecord(); - - PIFile file; - BinLogRecord lastrecord; - PISystemTime startlogtime; - //BinLogRecord nextrecord; - double play_time; //milliseconds - //int real_speedX; // in X - bool is_started, is_thread_ok; - uchar binlog_sig[PIBINARYLOG_SIGNATURE_SIZE]; - -}; - -#endif // PIBINARYLOG_H diff --git a/pibitarray.h b/pibitarray.h deleted file mode 100644 index 2c874f0e..00000000 --- a/pibitarray.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - PIP - Platform Independent Primitives - Bit array - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIBITARRAY_H -#define PIBITARRAY_H - -#include "picontainers.h" - -class PIP_EXPORT PIBitArray { -public: - PIBitArray(const int & size = 0) {resize(size);} - PIBitArray(uchar val) {resize(sizeof(val) * 8); data_[0] = val;} - PIBitArray(ushort val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} - PIBitArray(uint val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} - PIBitArray(ulong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} - PIBitArray(ullong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} - PIBitArray(uchar * bytes, uint size) {resize(size * 8); memcpy(data(), bytes, size);} - - uint bitSize() const {return size_;} - uint byteSize() const {return bytesInBits(size_);} - PIBitArray & resize(const uint & size) {size_ = size; data_.resize(bytesInBits(size_)); return *this;} - - PIBitArray & clearBit(const uint & index) {data_[index / 8] &= ~(1 << (index % 8)); return *this;} - PIBitArray & setBit(const uint & index) {data_[index / 8] |= (1 << (index % 8)); return *this;} - PIBitArray & writeBit(const uint & index, const bool & value) {if (value) setBit(index); else clearBit(index); return *this;} - PIBitArray & writeBit(const uint & index, const uchar & value) {return writeBit(index, value > 0);} - - PIBitArray & push_back(const bool & value) {resize(size_ + 1); writeBit(size_ - 1, value); return *this;} - PIBitArray & push_back(const uchar & value) {return push_back(value > 0);} - PIBitArray & insert(const uint & index, const bool & value) { - resize(size_ + 1); - uint fi = byteSize() - 1, si = index / 8, ti = index % 8; - uchar c = data_[si]; - for (uint i = fi; i > si; --i) { - data_[i] <<= 1; - if ((0x80 & data_[i - 1]) == 0x80) data_[i] |= 1; - else data_[i] &= 0xFE;} - data_[si] &= (0xFF >> (7 - ti)); - data_[si] |= ((c << 1) & (0xFF << (ti))); - if (value) data_[si] |= (1 << ti); - else data_[si] &= ~(1 << ti); - return *this;} - PIBitArray & insert(const uint & index, const uchar & value) {return insert(index, value > 0);} - PIBitArray & push_front(const bool & value) {return insert(0, value);} - PIBitArray & push_front(const uchar & value) {return push_front(value > 0);} - PIBitArray & pop_back() {return resize(size_ - 1);} - PIBitArray & pop_front() { - if (size_ == 0) return *this; - uint fi = byteSize() - 1; - for (uint i = 0; i < fi; ++i) { - data_[i] >>= 1; - if ((1 & data_[i + 1]) == 1) data_[i] |= 0x80; - else data_[i] &= 0x7F;} - data_[fi] >>= 1; - resize(size_ - 1); - return *this;} - PIBitArray & append(const PIBitArray & ba) {for (uint i = 0; i < ba.bitSize(); ++i) push_back(ba[i]); return *this;} - - uchar * data() {return data_.data();} - uchar toUChar() {if (size_ == 0) return 0; return data_[0];} - ushort toUShort() {ushort t = 0; memcpy(&t, data(), piMin(byteSize(), sizeof(t))); return t;} - uint toUInt() {uint t = 0; memcpy(&t, data(), piMin(byteSize(), sizeof(t))); return t;} - ulong toULong() {ulong t = 0; memcpy(&t, data(), piMin(byteSize(), sizeof(t))); return t;} - ullong toULLong() {ullong t = 0; memcpy(&t, data(), piMin(byteSize(), sizeof(t))); return t;} - - bool at(const uint & index) const {return (1 & (data_[index / 8] >> (index % 8))) == 1 ? true : false;} - bool operator [](const uint & index) const {return at(index);} - void operator +=(const PIBitArray & ba) {append(ba);} - bool operator ==(const PIBitArray & ba) const {if (bitSize() != ba.bitSize()) return false; for (uint i = 0; i < bitSize(); ++i) if (at(i) != ba[i]) return false; return true;} - bool operator !=(const PIBitArray & ba) const {return !(*this == ba);} - void operator =(const uchar & val) {resize(sizeof(val) * 8); data_[0] = val;} - void operator =(const ushort & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} - void operator =(const uint & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} - void operator =(const ulong & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} - void operator =(const ullong & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} - -private: - uint bytesInBits(const uint & bits) const {return (bits + 7) / 8;} - - PIVector data_; - uint size_; - -}; - -inline std::ostream & operator <<(std::ostream & s, const PIBitArray & ba) {for (uint i = 0; i < ba.bitSize(); ++i) {s << ba[i]; if (i % 8 == 7) s << ' ';} return s;} -inline PICout operator <<(PICout s, const PIBitArray & ba) {s.space(); s.setControl(0, true); for (uint i = 0; i < ba.bitSize(); ++i) {s << ba[i]; if (i % 8 == 7) s << ' ';} s.restoreControl(); return s;} - -#endif // PIBITARRAY_H diff --git a/pibytearray.cpp b/pibytearray.cpp deleted file mode 100644 index 679afde4..00000000 --- a/pibytearray.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* - PIP - Platform Independent Primitives - Byte array - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pibytearray.h" -#include "pistring.h" - -/*! \class PIByteArray - * \brief Byte array - * \details This class based on PIDeque and provide some handle function - * to manipulate it. - * - * \section PIByteArray_sec0 Usage - * %PIByteArray can be used to store custom data and manipulate it. There are many - * stream operators to store/restore common types to byte array. Store operators - * places data at the end of array, restore operators takes data from the beginning - * of array. - * In addition there are Base 64 convertions and checksums: - * * plain 8-bit - * * plain 32-bit - * - * One of the major usage of %PIByteArray is stream functions. You can form binary - * packet from many types (also dynamic types, e.g. PIVector) with one line: - * \snippet pibytearray.cpp 0 - * - * Or you can descibe stream operator of your own type and store/restore vectors of - * your type: - * \snippet pibytearray.cpp 1 - * - * For store/restore custom data blocks there is PIByteArray::RawData class. Stream - * operators of this class simply store/restore data block to/from byte array. - * \snippet pibytearray.cpp 2 - * - * \section PIByteArray_sec1 Attention - * Stream operator of %PIByteArray store byte array as vector, not simply append - * content of byte array. This operators useful to transmit custom data as %PIByteArray - * packed into parent byte array, e.g. to form packet from %PIByteArray. - * To append one byte array to another use funtion \a append(). - * \snippet pibytearray.cpp 3 - * - * - */ - - -#pragma pack(push, 1) - -const char PIByteArray::base64Table[64] = { -0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, -0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, -0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, -0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, -0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, -0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, -0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, -0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f}; - -const char PIByteArray::base64InvTable[256] = { -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x3F, -0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, -0x3C, 0x3D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, -0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, -0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, -0x17, 0x18, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, -0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, -0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, -0x31, 0x32, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - -#pragma pack(pop) - - -int PIHuffman::nodeCompare(const void * f, const void * s) { - return (reinterpret_cast(const_cast(s))->freq - - reinterpret_cast(const_cast(f))->freq); -} - - -PIDeque PIHuffman::compress(const PIDeque & src) { - calcFrequencies(src); - return src; -} - - -void PIHuffman::calcFrequencies(const PIDeque & src) { - nodes.resize(256); - for (int i = 0; i < 256; ++i) { - nodes[i].parent = nodes[i].right = nodes[i].left = 0; - nodes[i].freq = 0; - nodes[i].word.resize(1); - nodes[i].word[0] = static_cast(i); - } - for (int i = 0; i < src.size_s(); ++i) - nodes[src[i]].freq++; - std::qsort(nodes.data(), 256, sizeof(node), nodeCompare); - for (int i = 255; i >= 0; --i) - if (nodes[i].freq > 0 && i < 255) - {nodes.remove(i + 1, 255 - i); break;} - for (int i = 0; i < nodes.size_s(); ++i) - cout << string((char*)nodes[i].word.data(), 1) << ": " << nodes[i].freq << endl; -} - - -PIHuffman PIByteArray::huffman; - -PIByteArray & PIByteArray::convertToBase64() { - base64HelpStruct hs; - PIByteArray t; - if (size() == 0) return *this; - int sz = (size_s() / 3) * 3; - for (int i = 0; i < sz; ++i) { - hs.byte.byte0 = hs.byte.byte1 = hs.byte.byte2 = 0; - hs.byte.byte0 = at(i); - hs.byte.byte1 = at(++i); - hs.byte.byte2 = at(++i); - t.push_back(base64Table[hs.ascii.ascii0]); - t.push_back(base64Table[hs.ascii.ascii1]); - t.push_back(base64Table[hs.ascii.ascii2]); - t.push_back(base64Table[hs.ascii.ascii3]); - } - hs.byte.byte0 = hs.byte.byte1 = hs.byte.byte2 = 0; sz = size() % 3; - switch (sz) { - case 1: - hs.byte.byte0 = back(); - t.push_back(base64Table[hs.ascii.ascii0]); - t.push_back(base64Table[hs.ascii.ascii1]); - t.push_back('='); - t.push_back('='); - break; - case 2: - hs.byte.byte0 = at(size() - 2); hs.byte.byte1 = back(); - t.push_back(base64Table[hs.ascii.ascii0]); - t.push_back(base64Table[hs.ascii.ascii1]); - t.push_back(base64Table[hs.ascii.ascii2]); - t.push_back('='); - break; - default: break; - } - *this = t; - return *this; -} - - -PIByteArray & PIByteArray::convertFromBase64() { - base64HelpStruct hs; - PIByteArray t; - uint sz = size(); - if (sz == 0) return *this; - for (uint i = 0; i < sz; ++i) { - hs.byte.byte0 = hs.byte.byte1 = hs.byte.byte2 = 0; - hs.ascii.ascii0 = base64InvTable[at(i)]; - hs.ascii.ascii1 = base64InvTable[at(++i)]; - hs.ascii.ascii2 = base64InvTable[at(++i)]; - hs.ascii.ascii3 = base64InvTable[at(++i)]; - t.push_back(hs.byte.byte0); - t.push_back(hs.byte.byte1); - t.push_back(hs.byte.byte2); - } - if (back() == '=') t.pop_back(); - if (sz > 1) if (at(sz - 2) == '=') t.pop_back(); - *this = t; - return *this; -} - - -PIByteArray & PIByteArray::compressRLE(uchar threshold) { - PIByteArray t; - uchar fb, clen, mlen = 255 - threshold; - for (uint i = 0; i < size();) { - fb = at(i); - clen = 1; - while (at(++i) == fb) { - ++clen; - if (clen == mlen) - break; - } - if (clen > 1) { - t.push_back(threshold + clen); - t.push_back(fb); - continue; - } - if (fb >= threshold) { - t.push_back(threshold + 1); - t.push_back(fb); - } else - t.push_back(fb); - } - *this = t; - return *this; -} - - -PIByteArray & PIByteArray::decompressRLE(uchar threshold) { - PIByteArray t; - uchar fb, clen; - for (uint i = 0; i < size(); ++i) { - fb = at(i); - if (fb >= threshold) { - clen = fb - threshold; - fb = at(++i); - for (uint j = 0; j < clen; ++j) - t.push_back(fb); - continue; - } else - t.push_back(fb); - } - *this = t; - return *this; -} - - -uchar PIByteArray::checksumPlain8() const { - uchar c = 0; - int sz = size_s(); - for (int i = 0; i < sz; ++i) - c += at(i); - c = ~(c + 1); - return c; -} - - -uint PIByteArray::checksumPlain32() const { - uint c = 0; - int sz = size_s(); - for (int i = 0; i < sz; ++i) - c += at(i) * (i + 1); - c = ~(c + 1); - return c; -} - - -PIString PIByteArray::toString(int base) const { - PIString ret; - int sz = size_s(); - for (int i = 0; i < sz; ++i) { - if (i > 0) ret += " "; - if (base == 2) ret += "b"; - if (base == 8) ret += "0"; - if (base == 16) ret += "0x"; - ret += PIString::fromNumber(at(i), base); - } - return ret; -} - - -PIByteArray PIByteArray::fromString(PIString str) { - PIByteArray ret; - if (str.trim().isEmpty()) return ret; - str.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " "); - PIStringList bl(str.split(" ")); - bool ok(false); - piForeachC (PIString & b, bl) { - int bv = b.toInt(-1, &ok); - if (ok) ret << uchar(bv); - } - return ret; -} diff --git a/pibytearray.h b/pibytearray.h deleted file mode 100644 index 92e1acf7..00000000 --- a/pibytearray.h +++ /dev/null @@ -1,261 +0,0 @@ -/*! \file pibytearray.h - * \brief Byte array -*/ -/* - PIP - Platform Independent Primitives - Byte array - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIBYTEARRAY_H -#define PIBYTEARRAY_H - -#ifdef DOXYGEN -//! This macro allow stream template operators for write and read any type from byte array. Use it with attention! -# define PIP_BYTEARRAY_STREAM_ANY_TYPE -#endif - -#include "pibitarray.h" - -class PIString; -class PIByteArray; - -class PIHuffman { -public: - PIDeque compress(const PIDeque & src); - -private: - struct node { - int freq; - PIDeque word; - PIBitArray path; - node * parent; - node * right; - node * left; - }; - static int nodeCompare(const void * f, const void * s); - void calcFrequencies(const PIDeque & src); - PIVector nodes; -}; - -class PIP_EXPORT PIByteArray: public PIDeque -{ -public: - - //! Constructs an empty byte array - PIByteArray() {;} - - //! Constructs 0-filled byte array with size "size" - PIByteArray(const uint size) {resize(size);} - - //! Constructs byte array from data "data" and size "size" - PIByteArray(const void * data, const uint size): PIDeque((const uchar*)data, size_t(size)) {/*for (uint i = 0; i < size; ++i) push_back(((uchar * )data)[i]);*/} - - - //! Help struct to store/restore custom blocks of data to/from PIByteArray - struct RawData { - friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v); - friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v); - public: - //! Constructs data block - RawData(void * data = 0, int size = 0) {d = data; s = size;} - //! Constructs data block - RawData(const void * data, const int size) {d = const_cast(data); s = size;} - RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;} - private: - void * d; - int s; - }; - - //! Return resized byte array - PIByteArray resized(int new_size) const {PIByteArray tv(*this); tv.resize(new_size); return tv;} - - //! Convert data to Base 64 and return this byte array - PIByteArray & convertToBase64(); - - //! Convert data from Base 64 and return this byte array - PIByteArray & convertFromBase64(); - - //! Return converted to Base 64 data - PIByteArray toBase64() const {PIByteArray ba(*this); ba.convertToBase64(); return ba;} - - //! Return converted from Base 64 data - PIByteArray fromBase64() const {PIByteArray ba(*this); ba.convertFromBase64(); return ba;} - - PIByteArray & compressRLE(uchar threshold = 192); - PIByteArray & decompressRLE(uchar threshold = 192); - PIByteArray compressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.compressRLE(threshold); return ba;} - PIByteArray decompressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.decompressRLE(threshold); return ba;} - - PIByteArray & compressHuffman() {*this = huffman.compress(*this); return *this;} - - PIString toString(int base = 16) const; - - //! Add to the end data "data" with size "size" - PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;} - - //! Add to the end byte array "data" - PIByteArray & append(const PIByteArray & data_) {uint ps = size(); enlarge(data_.size_s()); memcpy(data(ps), data_.data(), data_.size()); return *this;} - /*PIByteArray & operator <<(short v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} - PIByteArray & operator <<(ushort v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} - PIByteArray & operator <<(int v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} - PIByteArray & operator <<(uint v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} - PIByteArray & operator <<(llong v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} - PIByteArray & operator <<(ullong v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}*/ - //PIByteArray & operator <<(const PIByteArray & v) {for (uint i = 0; i < v.size(); ++i) push_back(v[i]); return *this;} - - //! Returns plain 8-bit checksum - uchar checksumPlain8() const; - - //! Returns plain 32-bit checksum - uint checksumPlain32() const; - - void operator =(const PIDeque & d) {resize(d.size()); memcpy(data(), d.data(), d.size());} - - static PIByteArray fromString(PIString str); - -private: - union base64HelpStruct { - base64HelpStruct() {memset(this, 0, sizeof(base64HelpStruct));} - struct { - uchar ascii0: 6; - uchar ascii1: 6; - uchar ascii2: 6; - uchar ascii3: 6; - } ascii; - struct { - uchar byte0; - uchar byte1; - uchar byte2; - } byte; - }; - - static const char base64Table[64]; - static const char base64InvTable[256]; - static PIHuffman huffman; - -}; - -inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {if (v0.size() == v1.size()) {for (uint i = 0; i < v0.size(); ++i) if (v0[i] != v1[i]) return v0[i] < v1[i]; return false;} return v0.size() < v1.size();} -//! \relatesalso PIByteArray \brief Output to std::ostream operator -inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba) {s << "{"; for (uint i = 0; i < ba.size(); ++i) {s << ba[i]; if (i < ba.size() - 1) s << ", ";} s << "}"; return s;} - -//! \relatesalso PIByteArray \brief Output to PICout operator -inline PICout operator <<(PICout s, const PIByteArray & ba) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < ba.size(); ++i) {s << ba[i]; if (i < ba.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;} - -#define PBA_OPERATOR_TO int os = s.size_s(); s.enlarge(sizeof(v)); memcpy(s.data(os), &v, sizeof(v)); - -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, uchar v) {s.push_back(v); return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const short v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const int v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const long & v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const llong & v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const ushort v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const uint v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const ulong & v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const float v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator -inline PIByteArray & operator <<(PIByteArray & s, const double & v) {PBA_OPERATOR_TO return s;} -//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details -inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {s << v.size_s(); int os = s.size_s(); s.enlarge(v.size_s()); if (v.size_s() > 0) memcpy(s.data(os), v.data(), v.size()); return s;} -//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details -inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {int os = s.size_s(); s.enlarge(v.s); if (v.s > 0) memcpy(s.data(os), v.d, v.s); return s;} -//! \relatesalso PIByteArray \brief Store operator -template -inline PIByteArray & operator <<(PIByteArray & s, const PIPair & v) {s << v.first << v.second; return s;} -//! \relatesalso PIByteArray \brief Store operator -template -inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} -//! \relatesalso PIByteArray \brief Store operator -template -inline PIByteArray & operator <<(PIByteArray & s, const PIList & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} -//! \relatesalso PIByteArray \brief Store operator -template -inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} -#ifdef PIP_BYTEARRAY_STREAM_ANY_TYPE -template -inline PIByteArray & operator <<(PIByteArray & s, const T & v) {PBA_OPERATOR_TO return s;} -#endif - -#undef PBA_OPERATOR_TO -#define PBA_OPERATOR_FROM memcpy(&v, s.data(), sizeof(v)); s.remove(0, sizeof(v)); - -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, short & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, int & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, long & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, llong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, ushort & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, uint & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, ulong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, float & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator -inline PIByteArray & operator >>(PIByteArray & s, double & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details -inline PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); if (sz > 0) memcpy(v.data(), s.data(), v.size()); s.remove(0, v.size()); return s;} -//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details -inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {assert(s.size_s() >= v.s); if (v.s > 0) memcpy(v.d, s.data(), v.s); s.remove(0, v.s); return s;} -//! \relatesalso PIByteArray \brief Restore operator -template -inline PIByteArray & operator >>(PIByteArray & s, PIPair & v) {s >> v.first >> v.second; return s;} -//! \relatesalso PIByteArray \brief Restore operator -template -inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} -//! \relatesalso PIByteArray \brief Restore operator -template -inline PIByteArray & operator >>(PIByteArray & s, PIList & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} -//! \relatesalso PIByteArray \brief Restore operator -template -inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} -// //! \relatesalso PIByteArray \brief Restore operator -//template -//inline PIByteArray & operator >>(PIByteArray & s, PIMap & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} -#ifdef PIP_BYTEARRAY_STREAM_ANY_TYPE -template -inline PIByteArray & operator >>(PIByteArray & s, T & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} -#endif - - -#undef PBA_OPERATOR_FROM - -//! \relatesalso PIByteArray \brief Byte arrays compare operator -inline bool operator ==(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return false; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return false; return true;} -//! \relatesalso PIByteArray \brief Byte arrays compare operator -inline bool operator !=(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return true; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return true; return false;} - -#endif // PIBYTEARRAY_H diff --git a/pichar.h b/pichar.h deleted file mode 100644 index c0cd81ea..00000000 --- a/pichar.h +++ /dev/null @@ -1,221 +0,0 @@ -/*! \file pichar.h - * \brief Unicode char -*/ -/* - PIP - Platform Independent Primitives - Unicode char - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PICHAR_H -#define PICHAR_H - -#include "pibytearray.h" -/*! \brief Unicode char - * \details This class is wrapper around \c "uint". - * There are many contructors and information functions - */ -class PIP_EXPORT PIChar -{ - friend class PIString; - friend PIByteArray & operator <<(PIByteArray & s, const PIChar & v); - friend PIByteArray & operator >>(PIByteArray & s, PIChar & v); -public: - //! Contructs ascii symbol - PIChar(const char c) {ch = c; ch &= 0xFF;} - - //! Contructs 2-bytes symbol - PIChar(const short c) {ch = c; ch &= 0xFFFF;} - - //! Contructs 4-bytes symbol - PIChar(const int c) {ch = c;} - - //! Contructs ascii symbol - PIChar(const uchar c) {ch = c; ch &= 0xFF;} - - //! Contructs 2-bytes symbol - PIChar(const ushort c) {ch = c; ch &= 0xFFFF;} - - //! Default constructor. Contructs 4-bytes symbol - PIChar(const uint c = 0) {ch = c;} - - //! Contructs symbol from no more than 4 bytes of string - PIChar(const char * c) {ch = *reinterpret_cast(c);} - - //inline operator const int() {return static_cast(ch);} - //inline operator const char() {return toAscii();} - - //! Copy operator - 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;}*/ - - //! Compare operator - 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);}*/ - - //! Compare operator - 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);}*/ - - //! Compare operator - bool operator >(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) < 0;} - - //! Compare operator - bool operator <(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) > 0;} - - //! Compare operator - bool operator >=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) <= 0;} - - //! Compare operator - bool operator <=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) >= 0;} - - //! Return \b true if symbol is digit ('0' to '9') - bool isDigit() const {return isdigit(ch) != 0;} - - //! Return \b true if symbol is HEX digit ('0' to '9', 'a' to 'f', 'A' to 'F') - bool isHex() const {return isxdigit(ch) != 0;} - - //! Return \b true if symbol is drawable (without space) - bool isGraphical() const {return isgraph(ch) != 0;} - - //! Return \b true if symbol is control byte (< 32 or 127) - bool isControl() const {return iscntrl(ch) != 0;} - - //! Return \b true if symbol is in lower case - bool isLower() const {return islower(ch) != 0;} - - //! Return \b true if symbol is in upper case - bool isUpper() const {return isupper(ch) != 0;} - - //! Return \b true if symbol is printable (with space) - bool isPrint() const {return isprint(ch) != 0;} - - //! Return \b true if symbol is space or tab - bool isSpace() const {return isspace(ch) != 0;} - - //! Return \b true if symbol is alphabetical letter - bool isAlpha() const {return isalpha(ch) != 0;} - - //! Return \b true if symbol is ascii (< 128) - bool isAscii() const {return isascii(ch) != 0;} - - int toInt() const {return int(ch);} - const wchar_t * toWCharPtr() const {return reinterpret_cast(&ch);} - - //! Return as "char * " string - const char * toCharPtr() const {return reinterpret_cast(&ch);} - - wchar_t toWChar() const {return wchar_t(ch);} - char toAscii() const {return ch % 256;} - 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 - - //! Return symbol in upper case - PIChar toUpper() const {return PIChar(toupper(ch));} - - //! Return symbol in lower case - PIChar toLower() const {return PIChar(tolower(ch));} -//#endif - -private: - uint ch; - -}; - -__PICONTAINERS_SIMPLE_TYPE__(PIChar) - -//! Output operator to \c std::ostream -inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;} - -//! Output operator to \a PICout -inline PICout operator <<(PICout s, const PIChar & v) {s.space(); s.setControl(0, true); s << v.toCharPtr(); s.restoreControl(); return s;} - - -//! Write operator to \c PIByteArray -inline PIByteArray & operator <<(PIByteArray & s, const PIChar & v) {s << uint(v.ch); return s;} - -//! Read operator from \c PIByteArray -inline PIByteArray & operator >>(PIByteArray & s, PIChar & v) {uint i; s >> i; v.ch = wchar_t(i); return s;} - - -//! Compare operator -inline bool operator ==(const char v, const PIChar & c) {return (PIChar(v) == c);} - -//! Compare operator -inline bool operator >(const char v, const PIChar & c) {return (PIChar(v) > c);} - -//! Compare operator -inline bool operator <(const char v, const PIChar & c) {return (PIChar(v) < c);} - -//! Compare operator -inline bool operator >=(const char v, const PIChar & c) {return (PIChar(v) >= c);} - -//! Compare operator -inline bool operator <=(const char v, const PIChar & c) {return (PIChar(v) <= c);} - - -//! Compare operator -inline bool operator ==(const char * v, const PIChar & c) {return (PIChar(v) == c);} - -//! Compare operator -inline bool operator >(const char * v, const PIChar & c) {return (PIChar(v) > c);} - -//! Compare operator -inline bool operator <(const char * v, const PIChar & c) {return (PIChar(v) < c);} - -//! Compare operator -inline bool operator >=(const char * v, const PIChar & c) {return (PIChar(v) >= c);} - -//! Compare operator -inline bool operator <=(const char * v, const PIChar & c) {return (PIChar(v) <= c);} - - -//! Compare operator -inline bool operator ==(const int v, const PIChar & c) {return (PIChar(v) == c);} - -//! Compare operator -inline bool operator >(const int v, const PIChar & c) {return (PIChar(v) > c);} - -//! Compare operator -inline bool operator <(const int v, const PIChar & c) {return (PIChar(v) < c);} - -//! Compare operator -inline bool operator >=(const int v, const PIChar & c) {return (PIChar(v) >= c);} - -//! Compare operator -inline bool operator <=(const int v, const PIChar & c) {return (PIChar(v) <= c);} - -#endif // PICHAR_H diff --git a/picli.cpp b/picli.cpp deleted file mode 100644 index eeeae750..00000000 --- a/picli.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - PIP - Platform Independent Primitives - Command-Line Parser - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "picli.h" - - -/*! \class PICLI - * \brief Command-line arguments parser - * - * \section PICLI_sec0 Synopsis - * This class provide handy parsing of command-line arguments. First you should add - * arguments to PICLI with function \a addArgument(). Then you can check if there - * is some argument in application command-line with function \a hasArgument(); - * \section PICLI_sec1 Example - * \snippet picli.cpp main - */ - - -PICLI::PICLI(int argc, char * argv[]) { - needParse = true; - _prefix_short = "-"; - _prefix_full = "--"; - _count_opt = 0; - _count_mand = 0; - 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); - piForeach (Argument & 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) { - bool found = false; - piForeach (Argument & a, _args) { - if (a.short_key == cra[j]) { - a.found = true; - last = &a; - found = true; - break; - } - } - if (!found) break; - } - } else { - if (last == 0 ? true : !last->has_value) { - if (_args_mand.size_s() < _count_mand) { - _args_mand << cra; - continue; - } - if (_args_opt.size_s() < _count_opt || _count_opt < 0) { - _args_opt << cra; - continue; - } - piCoutObj << "[PICli] Arguments overflow, \"" << cra << "\" ignored"; - } - if (last == 0 ? false : last->has_value) { - last->value = cra; - last = 0; - } - } - } - } - needParse = false; -} diff --git a/picli.h b/picli.h deleted file mode 100644 index ce58d5f8..00000000 --- a/picli.h +++ /dev/null @@ -1,101 +0,0 @@ -/*! \file picli.h - * \brief Command-Line parser -*/ -/* - PIP - Platform Independent Primitives - Command-Line Parser - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PICLI_H -#define PICLI_H - -#include "piobject.h" - -class PIP_EXPORT PICLI: public PIObject -{ - PIOBJECT(PICLI) -public: - - //! Constructor - PICLI(int argc, char * argv[]); - - - //! Add argument with name "name", short key = name first letter, full key = name - void addArgument(const PIString & name, bool value = false) {_args << Argument(name, name[0], name, value); needParse = true;} - - //! Add argument with name "name", short key = "shortKey", full key = name - void addArgument(const PIString & name, const PIChar & shortKey, bool value = false) {_args << Argument(name, shortKey, name, value); needParse = true;} - - //! Add argument with name "name", short key = "shortKey", full key = name - void addArgument(const PIString & name, const char * shortKey, bool value = false) {_args << Argument(name, PIChar(shortKey), name, value); needParse = true;} - - //! Add argument with name "name", short key = "shortKey", full key = "fullKey" - void addArgument(const PIString & name, const PIChar & shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, shortKey, fullKey, value); needParse = true;} - - //! Add argument with name "name", short key = "shortKey", full key = "fullKey" - void addArgument(const PIString & name, const char * shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, PIChar(shortKey), fullKey, value); needParse = true;} - - - //! Returns unparsed command-line argument by index "index". Index 0 is program execute command. - PIString rawArgument(int index) {parse(); return _args_raw[index];} - PIString mandatoryArgument(int index) {parse(); return _args_mand[index];} - PIString optionalArgument(int index) {parse(); return _args_opt[index];} - - //! Returns unparsed command-line arguments - const PIStringList & rawArguments() {parse(); return _args_raw;} - const PIStringList & mandatoryArguments() {parse(); return _args_mand;} - const PIStringList & optionalArguments() {parse(); return _args_opt;} - - //! Returns program execute command without arguments - PIString programCommand() {parse(); return _args_raw.size() > 0 ? _args_raw.front() : PIString();} - bool hasArgument(const PIString & name) {parse(); piForeach (Argument & i, _args) if (i.name == name && i.found) return true; return false;} - PIString argumentValue(const PIString & name) {parse(); piForeach (Argument &i, _args) if (i.name == name && i.found) return i.value; return PIString();} - PIString argumentShortKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.short_key; return PIString();} - PIString argumentFullKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.full_key; return PIString();} - - const PIString & shortKeyPrefix() const {return _prefix_short;} - const PIString & fullKeyPrefix() const {return _prefix_full;} - int mandatoryArgumentsCount() const {return _count_mand;} - int optionalArgumentsCount() const {return _count_opt;} - void setShortKeyPrefix(const PIString & prefix) {_prefix_short = prefix; needParse = true;} - void setFullKeyPrefix(const PIString & prefix) {_prefix_full = prefix; needParse = true;} - void setMandatoryArgumentsCount(const int count) {_count_mand = count; needParse = true;} - void setOptionalArgumentsCount(const int count) {_count_opt = count; needParse = true;} - -private: - struct Argument { - 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 deleted file mode 100644 index cecb3d32..00000000 --- a/picodec.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - PIP - Platform Independent Primitives - Text codings coder, based on "iconv" - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "picodec.h" - - -PIStringList PICodec::availableCodecs() { - exec("/usr/bin/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("/usr/bin/iconv", ("-f=" + from), ("-t=" + to), tf.path()); - waitForFinish(); - return readOutput(); -} diff --git a/picodec.h b/picodec.h deleted file mode 100644 index 81517b48..00000000 --- a/picodec.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - PIP - Platform Independent Primitives - Text codings coder, based on "iconv" - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PICODEC_H -#define PICODEC_H - -#include "piprocess.h" - -class PIP_EXPORT PICodec: private PIProcess -{ -public: - PICodec(): PIProcess() {setGrabOutput(true); tf = PIFile::openTemporary(PIIODevice::ReadWrite); tf.open();} - PICodec(const PIString & from, const PIString & to): PIProcess() {setCodings(from, to); tf = PIFile::openTemporary(PIIODevice::ReadWrite);} - ~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/picodeinfo.cpp b/picodeinfo.cpp deleted file mode 100644 index ef2801b3..00000000 --- a/picodeinfo.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - PIP - Platform Independent Primitives - C++ code info structs - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "picodeinfo.h" - - -PIString PICodeInfo::EnumInfo::memberName(int value_) const { - piForeachC (PICodeInfo::EnumeratorInfo & e, members) - if (e.value == value_) - return e.name; - return PIString(); -} - - -int PICodeInfo::EnumInfo::memberValue(const PIString & name_) const { - piForeachC (PICodeInfo::EnumeratorInfo & e, members) - if (e.name == name_) - return e.value; - return -1; -} - - -PIMap * PICodeInfo::classesInfo; -PIMap * PICodeInfo::enumsInfo; - -bool __PICodeInfoInitializer__::_inited_ = false; diff --git a/picodeinfo.h b/picodeinfo.h deleted file mode 100644 index c303941c..00000000 --- a/picodeinfo.h +++ /dev/null @@ -1,149 +0,0 @@ -/*! \file picodeinfo.h - * \brief C++ code info structs -*/ -/* - PIP - Platform Independent Primitives - C++ code info structs - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - - -#ifndef PICODEINFO_H -#define PICODEINFO_H - -#include "pistring.h" - -namespace PICodeInfo { - -enum TypeFlag {NoFlag, Const = 0x01, Static = 0x02, Mutable = 0x04, Volatile = 0x08, Inline = 0x10, Virtual = 0x20}; - -typedef PIFlags TypeFlags; - -struct TypeInfo { - TypeInfo(const PIString & n = PIString(), const PIString & t = PIString(), PICodeInfo::TypeFlags f = 0) {name = n; type = t; flags = f;} - PIString name; - PIString type; - PICodeInfo::TypeFlags flags; -}; - -struct FunctionInfo { - PIString name; - TypeInfo return_type; - PIVector arguments; -}; - -struct ClassInfo { - PIString name; - PIStringList parents; - PIVector variables; - PIVector functions; -}; - -struct EnumeratorInfo { - EnumeratorInfo(const PIString & n = PIString(), int v = 0) {name = n; value = v;} - PIString name; - int value; -}; - -struct EnumInfo { - PIString memberName(int value) const; - int memberValue(const PIString & name) const; - PIString name; - PIVector members; -}; - - -inline PICout operator <<(PICout s, const PICodeInfo::TypeInfo & v) { - if (v.flags[Inline]) s << "inline "; - if (v.flags[Virtual]) s << "virtual "; - if (v.flags[Mutable]) s << "mutable "; - if (v.flags[Volatile]) s << "volatile "; - if (v.flags[Static]) s << "static "; - if (v.flags[Const]) s << "const "; - s << v.type; - if (!v.name.isEmpty()) - s << " " << v.name; - return s; -} - -inline PICout operator <<(PICout s, const PICodeInfo::EnumeratorInfo & v) {s << v.name << " = " << v.value; return s;} - -inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) { - s.setControl(0, true); - s << "class " << v.name; - if (!v.parents.isEmpty()) { - s << ": "; - bool first = true; - piForeachC (PIString & i, v.parents) { - if (first) first = false; - else s << ", "; - s << i; - } - } - s << " {\n"; - piForeachC (FunctionInfo & i, v.functions) { - s << Tab << i.return_type << " " << i.name << "("; - bool fa = true; - piForeachC (TypeInfo & a, i.arguments) { - if (fa) fa = false; - else s << ", "; - s << a; - } - s << ");\n"; - } - if (!v.functions.isEmpty() && !v.variables.isEmpty()) - s << "\n"; - piForeachC (TypeInfo & i, v.variables) { - s << Tab << i << ";\n"; - } - s << "}\n"; - s.restoreControl(); - return s; -} - -inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) { - s.setControl(0, true); - s << "enum " << v.name << " {\n"; - piForeachC (EnumeratorInfo & i, v.members) { - bool f = true; - if (f) f = false; - else s << ", "; - s << Tab << i << "\n"; - } - s << "}\n"; - s.restoreControl(); - return s; -} - -extern PIMap * classesInfo; -extern PIMap * enumsInfo; - -} - -class __PICodeInfoInitializer__ { -public: - __PICodeInfoInitializer__() { - if (_inited_) return; - _inited_ = true; - PICodeInfo::classesInfo = new PIMap; - PICodeInfo::enumsInfo = new PIMap; - } - static bool _inited_; -}; - -static __PICodeInfoInitializer__ __picodeinfoinitializer__; - -#endif // PICODEINFO_H diff --git a/picodeparser.cpp b/picodeparser.cpp deleted file mode 100644 index 04644f15..00000000 --- a/picodeparser.cpp +++ /dev/null @@ -1,762 +0,0 @@ -/* - PIP - Platform Independent Primitives - C++ code parser - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "picodeparser.h" - - - -PIString PICodeParser::Macro::expand(const PIStringList & arg_vals, bool * ok) const { - if (args.size() != arg_vals.size()) { - piCout << ("Error: in expansion of macro \"" + name + "(" + args.join(", ") + ")\": expect") - << args.size() << "arguments but takes" << arg_vals.size() << "!"; - if (ok != 0) *ok = false; - return PIString(); - } - PIString ret = value; - for (int i = 0; i < args.size_s(); ++i) { - const PIString & an(args[i]), av(arg_vals[i]); - int ind(-1); - while ((ind = ret.find(an, ind + 1)) >= 0) { - PIChar ppc(0), pc(0), nc(0); - if (ind > 1) ppc = ret[ind - 2]; - if (ind > 0) pc = ret[ind - 1]; - if (ind + an.size_s() < ret.size_s()) nc = ret[ind + an.size_s()]; - if (ppc != '#' && pc == '#' && !_isCChar(nc)) { // to chars - ind--; - ret.replace(ind, an.size_s() + 1, "\"" + av + "\""); - ind -= an.size_s() - av.size_s() - 1; - continue; - } - if (_isCChar(pc) || _isCChar(nc)) continue; - ret.replace(ind, an.size_s(), av); - ind -= an.size_s() - av.size_s(); - } - } - ret.replaceAll("##", ""); - if (ok != 0) *ok = true; - return ret; -} - - - -PICodeParser::PICodeParser() { - macros_iter = 32; - clear(); - includes << ""; -} - - -void PICodeParser::parseFile(const PIString & file) { - clear(); - parseFileInternal(file); - /*piCout << "\n\nDefines:"; - piForeachC (Define & m, defines) - piCout << "define" << m.first << m.second; - piCout << "\n\nMacros:"; - piForeachC (Macro & m, macros) - piCout << "Macro:" << m.name << m.args << m.value; - piCout << "\n\nClasses:"; - piForeachC (Entity * c, entities) - piCout << "class" << c->name << c->parents; - piCout << "\n\nEnums:"; - piForeachC (Enum & c, enums) - piCout << "enum" << c.name << c.members; - piCout << "\n\nTypedefs:"; - piForeachC (Typedef & c, typedefs) - piCout << "typedef" << c;*/ -} - - -void PICodeParser::parseFiles(const PIStringList & files) { - clear(); - piForeachC (PIString & f, files) - parseFileInternal(f); - /*piCout << "\n\nDefines:"; - piForeachC (Define & m, defines) - piCout << "define" << m.first << m.second; - piCout << "\n\nMacros:"; - piForeachC (Macro & m, macros) - piCout << "Macro:" << m.name << m.args << m.value; - piCout << "\n\nClasses:"; - piForeachC (Entity * c, entities) - piCout << "class" << c->name << c->parents; - piCout << "\n\nEnums:"; - piForeachC (Enum & c, enums) - piCout << "enum" << c.name << c.members; - piCout << "\n\nTypedefs:"; - piForeachC (Typedef & c, typedefs) - piCout << "typedef" << c;*/ -} - - -bool PICodeParser::isEnum(const PIString & name) { - piForeachC (Enum & e, enums) - if (e.name == name) - return true; - return false; -} - - -bool PICodeParser::parseFileInternal(const PIString & file) { - if (proc_files[file]) return true; - proc_files << file; - cur_file = file; - PIFile f(file, PIIODevice::ReadOnly); - int ii = 0; - while (!f.isOpened() && ii < (includes.size_s() - 1)) { - f.setPath(includes[++ii] + "/" + file); - //piCout << "try" << f.path(); - f.open(PIIODevice::ReadOnly); - } - if (!f.isOpened()) { - //piCout << ("Error: can`t open file \"" + file + "\"!"); - return false; - } - PIString fc = f.readAll(); - piCout << "parsing" << f.path() << "..."; - bool ret = parseFileContent(fc); - piCout << "parsing" << f.path() << "done"; - return ret; -} - - -void PICodeParser::clear() { - piForeach (Entity * i, entities) delete i; - defines.clear(); - macros.clear(); - enums.clear(); - typedefs.clear(); - entities.clear(); - proc_files.clear(); - cur_namespace.clear(); - evaluator.clearCustomVariables(); - defines << Define("PICODE", "") << custom_defines; -} - - -bool PICodeParser::parseFileContent(PIString & fc) { - bool mlc = false, cc = false; - int mls = 0, ole = -1, /*ccs = 0,*/ end = 0; - char c = 0, pc = 0; - PIString pfc, line, ccmn, tmp; - PIMap cchars; - - /// Remove comments, join multiline "*" and replace "*" to $n (cchars) - fc.replaceAll("\r\n", "\n"); - fc.replaceAll("\r", "\n"); - for (int i = 0; i < fc.size_s() - 1; ++i) { - if (i > 0) pc = c; - c = fc[i].toAscii(); - if (c == '"' && !mlc && pc != '\'') { - if (i > 0) if (fc[i - 1] == '\\') continue; - cc = !cc; - /*if (cc) ccs = i; - if (!cc) { - ccmn = "$" + PIString::fromNumber(cchars.size()); - cchars[ccmn] = fc.mid(ccs, i - ccs + 1); - fc.replace(ccs, i - ccs + 1, ccmn); - i = ccs - 1 + ccmn.size_s(); - }*/ - continue; - } - if (i > 0) - if (c == '\\' && fc[i - 1].toAscii() != '\\') { - fc.cutMid(i, 2); - --i; - continue; - } - if (cc) continue; - if (fc.mid(i, 2) == "/*") {mlc = true; mls = i; ++i; continue;} - if (fc.mid(i, 2) == "*/" && mlc) {mlc = false; fc.cutMid(mls, i - mls + 2); i = mls - 1; continue;} - if (fc.mid(i, 2) == "//" && !mlc) {ole = fc.find('\n', i); fc.cutMid(i, ole < 0 ? -1 : ole - i); --i; continue;} - } - //piCout << fc; - pfc = procMacros(fc); - - bool replaced = true; - int replaced_cnt = 0; - while (replaced) { - //piCout << "MACRO iter" << replaced_cnt; - if (replaced_cnt >= macros_iter) { - piCout << "Error: recursive macros detected!"; - break;//return false; - } - replaced_cnt++; - replaced = false; - piForeachC (Define & d, defines) { - int ind(-1); - while ((ind = pfc.find(d.first, ind + 1)) >= 0) { - PIChar pc(0), nc(0); - if (ind > 0) pc = pfc[ind - 1]; - if (ind + d.first.size_s() < pfc.size_s()) nc = pfc[ind + d.first.size_s()]; - if (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue; - pfc.replace(ind, d.first.size_s(), d.second); - ind -= d.first.size_s() - d.second.size_s(); - replaced = true; - } - } - piForeachC (Macro & m, macros) { - int ind(-1); - while ((ind = pfc.find(m.name, ind + 1)) >= 0) { - PIChar pc(0), nc(0); - if (ind > 0) pc = pfc[ind - 1]; - if (ind + m.name.size_s() < pfc.size_s()) nc = pfc[ind + m.name.size_s()]; - if (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue; - PIString ret, range; bool ok(false); - range = pfc.mid(ind + m.name.size_s()).takeRange("(", ")"); - ret = m.expand(range.split(",").trim(), &ok); - if (!ok) return false; - int rlen = pfc.find(range, ind + m.name.size_s()) + range.size_s() + 1 - ind; - pfc.replace(ind, rlen, ret); - ind -= rlen - ret.size_s(); - replaced = true; - } - } - } - - //piCout << NewLine << "file" << cur_file << pfc; - for (int i = 0; i < pfc.size_s() - 5; ++i) { - if (pfc.mid(i, 8) == "template") { - pfc.cutLeft(i + 8); - pfc.takeRange("<", ">"); - bool def = !isDeclaration(pfc, 0, &end); - pfc.cutLeft(end); - if (def) pfc.takeRange("{", "}"); - else pfc.takeSymbol(); - i = 0; - continue; - } - if (pfc.mid(i, 5) == "class" || pfc.mid(i, 6) == "struct") { - int dind = pfc.find("{", i), find = pfc.find(";", i); - if (dind < 0 && find < 0) {pfc.cutLeft(i + 6); i = 0; continue;} - if (dind < 0 || find < dind) {pfc.cutLeft(i + 6); i = 0; continue;} - ccmn = pfc.mid(i, dind - i) + "{\n" + pfc.mid(dind).takeRange('{', '}') + "\n}\n"; - pfc.remove(i, ccmn.size()); - parseClass(ccmn); - i = 0; - continue; - } - if (pfc.mid(i, 4) == "enum") { - pfc.cutLeft(i + 4); - tmp = pfc.takeCWord(); - parseEnum(cur_namespace + tmp, pfc.takeRange("{", "}")); - pfc.takeSymbol(); - i = 0; - continue; - } - if (pfc.mid(i, 7) == "typedef") { - pfc.cutLeft(i + 7); - typedefs << parseTypedef(pfc.takeLeft(pfc.find(";"))); - if (typedefs.back().first.isEmpty()) typedefs.pop_back(); - pfc.takeSymbol(); - i = 0; - continue; - } - } - - return true; -} - - -PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc) { - PIString cd = fc.trimmed().removeAll('\n').replaceAll("\t", " ").replaceAll(" ", " "), pn; - //piCout << "found class <****\n" << cd << "\n****>"; - int ind = cd.find(":"); - PIVector parents; - if (ind > 0) { - PIStringList pl = cd.takeMid(ind + 1).trim().split(","); - cd.cutRight(1); - Entity * pe = 0; - piForeachC (PIString & p, pl) { - if (p.contains(" ")) pn = p.mid(p.find(" ") + 1); - else pn = p; - pe = findEntityByName(pn); - if (pe == 0) ;//{piCout << "Error: can`t find" << pn;} - else parents << pe; - } - } - bool is_class = cd.left(5) == "class"; - cur_def_vis = (is_class ? Private : Public); - PIString cn = cd.mid(6).trim(); - if (cn.isEmpty()) return 0; - Entity * e = new Entity(); - e->name = cur_namespace + cn; - e->type = (is_class ? "class" : "struct"); - e->parents = parents; - e->file = cur_file; - entities << e; - return e; -} - - -PIString PICodeParser::parseClass(PIString & fc) { - Visibility prev_vis = cur_def_vis; - int dind = fc.find("{"), find = fc.find(";"), end = 0; - if (dind < 0 && find < 0) return PIString(); - if (dind < 0 || find < dind) return fc.left(find); - Entity * ce = parseClassDeclaration(fc.takeLeft(dind)); - fc.trim().cutLeft(1).cutRight(1).trim(); - //piCout << "found class <****\n" << fc << "\n****>"; - if (!ce) return PIString(); - int ps = -1; - bool def = false; - PIString prev_namespace = cur_namespace, stmp; - cur_namespace = ce->name + "::"; - //piCout << "parse class" << ce->name << "namespace" << cur_namespace; - //piCout << "\nparse class" << ce->name << "namespace" << cur_namespace; - while (!fc.isEmpty()) { - PIString cw = fc.takeCWord(), tmp; - //piCout << "\ntaked word" << cw; - if (cw == "public") {cur_def_vis = Public; fc.cutLeft(1); continue;} - if (cw == "protected") {cur_def_vis = Protected; fc.cutLeft(1); continue;} - if (cw == "private") {cur_def_vis = Private; fc.cutLeft(1); continue;} - if (cw == "class") {if (isDeclaration(fc, 0, &end)) {fc.cutLeft(end); fc.takeSymbol(); continue;} tmp = fc.takeLeft(fc.find("{")); stmp = fc.takeRange("{", "}"); fc.takeSymbol(); stmp = "class " + tmp + "{" + stmp + "}"; parseClass(stmp); continue;} - if (cw == "struct") {if (isDeclaration(fc, 0, &end)) {fc.cutLeft(end); fc.takeSymbol(); continue;} tmp = fc.takeLeft(fc.find("{")); stmp = fc.takeRange("{", "}"); fc.takeSymbol(); stmp = "struct " + tmp + "{" + stmp + "}"; parseClass(stmp); continue;} - if (cw == "enum") {tmp = fc.takeCWord(); parseEnum(cur_namespace + tmp, fc.takeRange("{", "}")); fc.takeSymbol(); continue;} - if (cw == "friend") {fc.cutLeft(fc.find(";") + 1); continue;} - if (cw == "typedef") {ce->typedefs << parseTypedef(fc.takeLeft(fc.find(";"))); typedefs << ce->typedefs.back(); typedefs.back().first.insert(0, cur_namespace); if (ce->typedefs.back().first.isEmpty()) ce->typedefs.pop_back(); fc.takeSymbol(); continue;} - if (cw == "template") { - fc.takeRange("<", ">"); - def = !isDeclaration(fc, 0, &end); - fc.cutLeft(end); - if (def) fc.takeRange("{", "}"); - else fc.takeSymbol(); - continue; - } - def = !isDeclaration(fc, 0, &end); - tmp = (cw + fc.takeLeft(end)).trim(); - if (!tmp.isEmpty()) - parseMember(ce, tmp); - if (def) fc.takeRange("{", "}"); - else fc.takeSymbol(); - if (ps == fc.size_s()) {/*cur_namespace = prev_namespace;*/ fc.cutLeft(1);/*return false*/;} - ps = fc.size_s(); - } - cur_def_vis = prev_vis; - cur_namespace = prev_namespace; - return ce->name; -} - - -bool PICodeParser::parseEnum(const PIString & name, PIString fc) { - //piCout << "enum" << name << fc; - Enum e(name); - PIStringList vl(fc.split(",")); - PIString vn; - int cv = -1, ind = 0; - piForeachC (PIString & v, vl) { - vn = v; ind = v.find("="); - if (ind > 0) {cv = v.right(v.size_s() - ind - 1).toInt(); vn = v.left(ind);} - if (ind < 0) ++cv; - e.members << Enumerator(vn.trim(), cv); - } - enums << e; - return true; -} - - -PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) { - //piCout << "parse typedef" << fc; - Typedef td; - fc.replaceAll("\t", " "); - - if (fc.contains("(")) { - int start = fc.find("("), end = fc.find(")"); - td.first = fc.takeMid(start + 1, end - start - 1).trim(); - if (td.first.left(1) == "*") {td.first.cutLeft(1).trim(); fc.insert(start + 1, "*");} - td.second = fc.trim(); - } else { - td.first = fc.takeMid(fc.findLast(" ")).trim(); - td.second = fc.trim(); - } - //piCout << "found typedef" << td; - return td; -} - - -bool PICodeParser::parseMember(Entity * parent, PIString & fc) { - if (fc.trim().isEmpty()) return true; - if (fc.find("operator") >= 0) return true; - tmp_temp.clear(); - //piCout << "parse member" << fc; - int ts = fc.find("<"), te = 0; - PIString ctemp, crepl; - while (ts >= 0) { - ctemp = fc.mid(ts).takeRange("<", ">"); - if (ctemp.isEmpty()) {te = ts + 1; ts = fc.find("<", te); continue;} - crepl = "$" + PIString::fromNumber(tmp_temp.size_s()).expandLeftTo(3, "0"); - fc.replace(ts, ctemp.size_s() + 2, crepl); - tmp_temp[crepl] = "<" + ctemp + ">"; - ts = fc.find("<", te); - } - fc.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " ").replaceAll(", ", ","); - PIStringList tl, al; - Member me; - //piCout << fc; - if (fc.contains("(")) { - fc.cutRight(fc.size_s() - fc.findLast(")") - 1); - te = fc.find("("); - //piCout << fc; - for (ts = te - 1; ts >= 0; --ts) - if (!_isCChar(fc[ts]) && !(fc[ts].isDigit())) break; - //piCout << "takeMid" << ts + 1 << te - ts - 1; - me.name = fc.takeMid(ts + 1, te - ts - 1); - if (me.name == parent->name) return true; - me.arguments_full = fc.takeMid(ts + 2).cutRight(1).split(","); - me.type = fc.cutRight(1).trim(); - me.visibility = cur_def_vis; - if (me.type.find("inline ") >= 0) { - me.attributes |= Inline; - me.type.removeAll("inline "); - } - if (me.type.find("static ") >= 0) { - me.attributes |= Static; - me.type.removeAll("static "); - } - if (me.type.find("virtual ") >= 0) { - me.attributes |= Virtual; - me.type.removeAll("virtual "); - } - normalizeEntityNamespace(me.type); - int i = 0; - piForeach (PIString & a, me.arguments_full) - if ((i = a.find("=")) > 0) - a.cutRight(a.size_s() - i).trim(); - me.arguments_type = me.arguments_full; - piForeach (PIString & a, me.arguments_type) { - crepl.clear(); - if (a.contains("[")) - crepl = a.takeMid(a.find("["), a.findLast("]") - a.find("[") + 1); - for (ts = a.size_s() - 1; ts >= 0; --ts) - if (!_isCChar(a[ts]) && !(a[ts].isDigit())) break; - a.cutRight(a.size_s() - ts - 1); - normalizeEntityNamespace(a); - a += crepl; - a.trim(); - } - restoreTmpTemp(&me); - //piCout << "func" << me.type << me.name << me.arguments_full << me.arguments_type; - parent->functions << me; - } else { - tl = fc.split(","); - bool vn = true; - ctemp = tl.front(); - for (ts = ctemp.size_s() - 1; ts > 0; --ts) { - if (vn) {if (!_isCChar(ctemp[ts]) && !ctemp[ts].isDigit() && ctemp[ts] != '[' && ctemp[ts] != ']') vn = false;} - else {if (_isCChar(ctemp[ts]) || ctemp[ts].isDigit()) break;} - } - me.type = ctemp.takeLeft(ts + 1); - me.visibility = cur_def_vis; - restoreTmpTemp(&me); - PIString type = " " + me.type; - if (type.find(" const ") >= 0) { - me.attributes |= Const; - type.replaceAll(" const ", " "); - } - if (type.find(" static ") >= 0) { - me.attributes |= Static; - type.replaceAll(" static ", " "); - } - if (type.find(" mutable ") >= 0) { - me.attributes |= Mutable; - type.replaceAll(" mutable ", " "); - } - if (type.find(" volatile ") >= 0) { - me.attributes |= Volatile; - type.replaceAll(" volatile ", " "); - } - type.trim(); - normalizeEntityNamespace(type); - tl[0] = ctemp.trim(); - piForeachC (PIString & v, tl) { - crepl.clear(); - me.name = v.trimmed(); - me.type = type; - if (me.name.isEmpty()) continue; - if (me.name.contains("[")) - crepl = me.name.takeMid(me.name.find("["), me.name.findLast("]") - me.name.find("[") + 1); - while (!me.name.isEmpty()) { - if (me.name.front() == "*" || me.name.front() == "&") { - me.type += me.name.takeLeft(1); - me.name.trim(); - } else break; - } - me.is_type_ptr = (me.type.right(1) == "]" || me.type.right(1) == "*"); - me.type += crepl; - //piCout << "var" << me.type << me.name << me.is_const << me.is_static; - parent->members << me; - } - } - //piCout << "parse member" << fc; - return true; -} - - -void PICodeParser::normalizeEntityNamespace(PIString & n) { - PIString suff, pref; - for (int i = n.size_s() - 1; i > 0; --i) - if (_isCChar(n[i]) || n[i].isDigit()) { - suff = n.right(n.size_s() - i - 1); - n.cutRight(suff.size_s()); - break; - } - n.push_front(" "); - if (n.find(" static ") >= 0) {n.replaceAll(" static ", ""); pref += "static ";} - if (n.find(" const ") >= 0) {n.replaceAll(" const ", ""); pref += "const ";} - if (n.find(" mutable ") >= 0) {n.replaceAll(" mutable ", ""); pref += "mutable ";} - if (n.find(" volatile ") >= 0) {n.replaceAll(" volatile ", ""); pref += "volatile ";} - n.trim(); - int f = 0; - piForeachC (Entity * e, entities) { - if (e->name == n) { - n = (pref + n + suff).trim(); - return; - } - if ((f = e->name.find(n)) >= 0) - if (e->name.mid(f - 1, 1) == ":") - if (e->name.find(cur_namespace) >= 0) { - n = pref + e->name + suff; - return; - } - } - piForeachC (Enum & e, enums) - if ((f = e.name.find(n)) >= 0) - if (e.name.mid(f - 1, 1) == ":") - if (e.name.find(cur_namespace) >= 0) { - //piCout << "change" << n << "to" << e.name + suff; - n = pref + e.name + suff; - return; - } - piForeachC (Typedef & e, typedefs) - if ((f = e.first.find(n)) >= 0) - if (e.first.mid(f - 1, 1) == ":") - if (e.first.find(cur_namespace) >= 0) { - //piCout << "change" << n << "to" << e.name + suff; - n = pref + e.first + suff; - return; - } - n = (pref + n + suff).trim(); -} - - -void PICodeParser::restoreTmpTemp(Member * e) { - int i = 0; - piForeach (PIString & a, e->arguments_full) { - while ((i = a.find("$")) >= 0) - a.replace(i, 4, tmp_temp[a.mid(i, 4)]); - } - piForeach (PIString & a, e->arguments_type) { - while ((i = a.find("$")) >= 0) - a.replace(i, 4, tmp_temp[a.mid(i, 4)]); - } - while ((i = e->type.find("$")) >= 0) - e->type.replace(i, 4, tmp_temp[e->type.mid(i, 4)]); -} - - -bool PICodeParser::macroCondition(const PIString & mif, PIString mifcond) { - //piCout << "macroCondition" << mif << mifcond; - if (mif == "ifdef") return isDefineExists(mifcond); - if (mif == "ifndef") return !isDefineExists(mifcond); - if (mif == "if" || mif == "elif") { - mifcond.removeAll(" ").removeAll("\t"); - return procMacrosCond(mifcond) > 0.; - } - return false; -} - - -double PICodeParser::procMacrosCond(PIString fc) { - bool neg = false, first = true, br = false; - double ret = 0., brv = 0.; - int oper = 0, ps = -1; - char cc, nc; - PIString ce; - fc.removeAll("defined"); - //piCout << "procMacrosCond" << fc; - while (!fc.isEmpty()) { - cc = fc[0].toAscii(); - nc = (fc.size() > 1 ? fc[1].toAscii() : 0); - if (cc == '!') {neg = true; fc.pop_front(); continue;} - if (cc == '(') {br = true; brv = procMacrosCond(fc.takeRange('(', ')'));} - if (cc == '&' && nc == '&') {fc.remove(0, 2); oper = 1; continue;} - if (cc == '|' && nc == '|') {fc.remove(0, 2); oper = 2; continue;} - if (!br) { - ce = fc.takeCWord(); - if (ce.isEmpty()) ce = fc.takeNumber(); - } - if (first) { - first = false; - ret = br ? brv : defineValue(ce); - if (neg) ret = -ret; - } else { - //piCout << "oper" << oper << "with" << ce; - if (!br) brv = defineValue(ce); - switch (oper) { - case 1: ret = ret && (neg ? -brv : brv); break; - case 2: ret = ret || (neg ? -brv : brv); break; - } - } - if (ps == fc.size_s()) fc.cutLeft(1); - ps = fc.size_s(); - br = neg = false; - } - //piCout << "return" << ret; - return ret; -} - - -bool PICodeParser::isDefineExists(const PIString & dn) { - piForeachC (Define & d, defines) { - if (d.first == dn) - return true; - } - return false; -} - - -double PICodeParser::defineValue(const PIString & dn) { - piForeachC (Define & d, defines) { - if (d.first == dn) - return d.second.isEmpty() ? 1. : d.second.toDouble(); - } - return dn.toDouble(); -} - - -PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) { - piForeach (Entity * e, entities) - if (e->name == en) - return e; - return 0; -} - - -bool PICodeParser::isDeclaration(const PIString & fc, int start, int * end) { - int dind = fc.find("{", start), find = fc.find(";", start); - //piCout << "isDeclaration" << dind << find; - if (dind < 0 && find < 0) {if (end) *end = -1; return true;} - if (dind < 0 || find < dind) {if (end) *end = find; return true;} - if (end) *end = dind; - return false; -} - - -PIString PICodeParser::procMacros(PIString fc) { - if (fc.isEmpty()) return PIString(); - int ifcnt = 0; - bool grab = false, skip = false, cond_ok = false; - PIString pfc, nfc, line, mif, mifcond; - //piCout << "procMacros\n<******" << fc << "\n******>"; - fc += "\n"; - while (!fc.isEmpty()) { - line = fc.takeLine().trimmed(); - if (line.left(1) == "#") { - mifcond = line.mid(1); - mif = mifcond.takeCWord(); - //piCout << "mif mifcond" << mif << mifcond << ifcnt; - if (skip || grab) { - if (mif.left(2) == "if") ifcnt++; - if (mif.left(5) == "endif") { - if (ifcnt > 0) ifcnt--; - else { - //piCout << "main endif" << skip << grab; - if (grab) pfc << procMacros(nfc); - skip = grab = false; - continue; - } - } - if (mif.left(4) == "elif" && ifcnt == 0) { - //piCout << "main elif" << skip << grab << cond_ok; - if (cond_ok) { - if (grab) { - pfc << procMacros(nfc); - skip = true; grab = false; - } - continue; - } - if (skip) { - //piCout << "check elif" << skip << grab << cond_ok; - if (!macroCondition(mif, mifcond.trimmed())) continue; - //piCout << "check elif ok"; - skip = false; grab = cond_ok = true; - continue; - } - continue; - } - if (mif.left(4) == "else" && ifcnt == 0) { - //piCout << "main else" << skip << grab; - if (grab) pfc << procMacros(nfc); - if (skip && !cond_ok) {skip = false; grab = true;} - else {skip = true; grab = false;} - continue; - } - if (grab) nfc << line << "\n"; - continue; - } - if (mif.left(2) == "if") { - //piCout << "main if"; - skip = grab = cond_ok = false; - if (macroCondition(mif, mifcond.trimmed())) grab = cond_ok = true; - else skip = true; - ifcnt = 0; - nfc.clear(); - } else { - if (!parseDirective(line.cutLeft(1).trim())) - ;//return false; /// WARNING - } - } else { - if (grab) nfc << line << "\n"; - else if (!skip) pfc << line << "\n"; - } - } - return pfc; -} - - -bool PICodeParser::parseDirective(PIString d) { - if (d.isEmpty()) return true; - PIString dname = d.takeCWord(); - //piCout << "parseDirective" << d; - if (dname == "include") { - d.replaceAll("<", "\"").replaceAll(">", "\""); - PIString cf = cur_file; - bool ret = parseFileInternal(d.takeRange("\"", "\"")); - cur_file = cf; - return ret; - } - if (dname == "define") { - PIString mname = d.takeCWord(); - if (d.left(1) == "(") { // macro - PIStringList args = d.takeRange("(", ")").split(",").trim(); - macros << Macro(mname, d.trim(), args); - } else { // define - defines << Define(mname, d.trim()); - evaluator.setVariable(mname, complexd_1); - } - return true; - } - if (dname == "undef") { - PIString mname = d.takeCWord(); - for (int i = 0; i < defines.size_s(); ++i) - if (defines[i].first == mname) {defines.remove(i); --i;} - return true; - } - return true; -} diff --git a/picodeparser.h b/picodeparser.h deleted file mode 100644 index 9ed6b1cd..00000000 --- a/picodeparser.h +++ /dev/null @@ -1,148 +0,0 @@ -/*! \file picodeparser.h - * \brief C++ code parser -*/ -/* - PIP - Platform Independent Primitives - C++ code parser - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - - -#ifndef PICODEPARSER_H -#define PICODEPARSER_H - -#include "pifile.h" -#include "pievaluator.h" - -inline bool _isCChar(const PIChar & c) {return (c.isAlpha() || (c.toAscii() == '_'));} -inline bool _isCChar(const PIString & c) {if (c.isEmpty()) return false; return _isCChar(c[0]);} - -class PIP_EXPORT PICodeParser { -public: - PICodeParser(); - - enum PIP_EXPORT Visibility {Global, Public, Protected, Private}; - enum PIP_EXPORT Attribute {NoAttributes = 0x0, Const = 0x01, Static = 0x02, Mutable = 0x04, Volatile = 0x08, Inline = 0x10, Virtual = 0x20}; - - typedef PIFlags Attributes; - typedef PIPair Define; - typedef PIPair Typedef; - typedef PIPair Enumerator; - - struct PIP_EXPORT Macro { - Macro(const PIString & n = PIString(), const PIString & v = PIString(), const PIStringList & a = PIStringList()) { - name = n; - value = v; - args = a; - } - PIString expand(const PIStringList & arg_vals, bool * ok = 0) const; - PIString name; - PIString value; - PIStringList args; - }; - - struct PIP_EXPORT Member { - Member() { - visibility = Global; - size = 0; - is_type_ptr = false; - attributes = NoAttributes; - } - PIString type; - PIString name; - PIStringList arguments_full; - PIStringList arguments_type; - Visibility visibility; - Attributes attributes; - bool is_type_ptr; - int size; - }; - - struct PIP_EXPORT Entity { - Entity() { - visibility = Global; - size = 0; - } - PIString type; - PIString name; - PIString file; - Visibility visibility; - int size; - PIVector parents; - //PIVector children; - PIVector functions; - PIVector members; - PIVector typedefs; - }; - - struct PIP_EXPORT Enum { - Enum(const PIString & n = PIString()) { - name = n; - } - PIString name; - PIVector members; - }; - - void parseFile(const PIString & file); - void parseFiles(const PIStringList & files); - - void includeDirectory(const PIString & dir) {includes << dir;} - void addDefine(const PIString & def_name, const PIString & def_value) {custom_defines << Define(def_name, def_value);} - bool isEnum(const PIString & name); - Entity * findEntityByName(const PIString & en); - - int macrosSubstitutionMaxIterations() const {return macros_iter;} - void setMacrosSubstitutionMaxIterations(int value) {macros_iter = value;} - - PIVector defines, custom_defines; - PIVector macros; - PIVector enums; - PIVector typedefs; - PIVector entities; - -private: - void clear(); - bool parseFileInternal(const PIString & file); - bool parseFileContent(PIString & fc); - bool parseDirective(PIString d); - Entity * parseClassDeclaration(const PIString & fc); - PIString parseClass(PIString & fc); - bool parseEnum(const PIString & name, PIString fc); - Typedef parseTypedef(PIString fc); - bool parseMember(Entity * parent, PIString & fc); - void restoreTmpTemp(Member * e); - bool macroCondition(const PIString & mif, PIString mifcond); - bool isDefineExists(const PIString & dn); - double defineValue(const PIString & dn); - PIString procMacros(PIString fc); - double procMacrosCond(PIString fc); - bool isDeclaration(const PIString & fc, int start, int * end); - void normalizeEntityNamespace(PIString & n); - - int macros_iter; - PIEvaluator evaluator; - //PIVector tree; - PISet proc_files; - PIString cur_file; - PIStringList includes; - Entity root_; - Visibility cur_def_vis; - PIString cur_namespace; - PIMap tmp_temp; - -}; - -#endif // PICODEPARSER_H diff --git a/picollection.cpp b/picollection.cpp deleted file mode 100644 index ad64b690..00000000 --- a/picollection.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "picollection.h" - - -/** \class PICollection - * \brief Interface to discover element groups - * \details - * \section PICollection_sec0 Synopsis - * This class has only static functions so no need to create instance of the - * %PICollection. This class provide macros to add some classes or existing - * objects to global collection and access to them from any place of the code. - * \snippet picollection.cpp main - * */ - - -PIStringList PICollection::groups() { - PIStringList sl; - piForeachC (Group & g, *_groups) - sl << g.name; - return sl; -} - - -PIVector PICollection::groupElements(const PIString & group) { - piForeachC (Group & g, *_groups) - if (g.name == group) - return g.elements; - return PIVector(); -} - - -void PICollection::addToGroup(const PIString & group, const PIObject * element) { - //piCout << "add to" << group << element; - PIString n = element->className(); - piForeach (Group & g, *_groups) - if (g.name == group) { - for (int i = 0; i < g.elements.size_s(); ++i) - if (PIString(g.elements[i]->className()) == n) - return; - g.elements << element; - //piCout << "new group" << group << ", ok"; - return; - } - *_groups << Group(group); - _groups->back().elements << element; - //piCout << "new group" << group << ", ok"; -} - -bool __PICollectionInitializer::_inited_(false); -PIVector * PICollection::_groups; diff --git a/picollection.h b/picollection.h deleted file mode 100644 index b9f0488e..00000000 --- a/picollection.h +++ /dev/null @@ -1,94 +0,0 @@ -/*! \file picollection.h - * \brief Custom elements collection -*/ -/* - PIP - Platform Independent Primitives - Peer - named I/O ethernet node, forming self-organized peering network - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PICOLLECTION_H -#define PICOLLECTION_H - -#include "piobject.h" - -#ifdef DOXYGEN - -/** \brief Add existing element "object" in group with name "group" - * \relatesalso PICollection - * \details If there is no group with name "group" it will be created. - * Only one element of the class "object" can be in group "group". If - * this is already exists nothing be happens. \n "object" should to - * be pointer to object based on PIObject. */ -# define ADD_TO_COLLECTION(group, object) - -/** \brief Add new element of class "class" in group with name "group" - * \relatesalso PICollection - * \details If there is no group with name "group" it will be created. - * Only one element of the class "class" can be in group "group". If - * this is already exists nothing be happens. \n "class" should to - * be name of the any class based on PIObject. */ -# define ADD_NEW_TO_COLLECTION(group, class) - -#else -# define ADD_TO_COLLECTION(group, object) static PICollection::CollectionAdder __##group##_##__LINE__##_##adder##__(#group, object); -# define ADD_NEW_TO_COLLECTION(group, class) static PICollection::CollectionAdder __##group##_##class##_##adder##__(#group, new class()); -#endif - -class PIP_EXPORT PICollection -{ - friend class __PICollectionInitializer; -public: - PICollection() {;} - - //! \brief Returns all existing groups by their names - static PIStringList groups(); - - //! \brief Returns all elements of group "group" - static PIVector groupElements(const PIString & group); - - static void addToGroup(const PIString & group, const PIObject * element); - - class CollectionAdder { - public: - CollectionAdder(const PIString & group, const PIObject * element) {PICollection::addToGroup(group, element);} - }; - -protected: - struct Group { - Group(const PIString & name_ = PIString()) {name = name_;} - //~Group() {piCout << "delete group" << name << this; piForeach (const PIObject * o, elements) delete o; elements.clear();} - PIString name; - PIVector elements; - }; - - static PIVector * _groups; - -}; - -class PIP_EXPORT __PICollectionInitializer { -public: - __PICollectionInitializer() { - if (_inited_) return; - _inited_ = true; - PICollection::_groups = new PIVector(); - } - static bool _inited_; -}; - -static __PICollectionInitializer __picollectioninitializer; - -#endif // PICOLLECTION_H diff --git a/piconfig.cpp b/piconfig.cpp deleted file mode 100644 index 15cd1d48..00000000 --- a/piconfig.cpp +++ /dev/null @@ -1,601 +0,0 @@ -/* - PIP - Platform Independent Primitives - Config parser - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "piconfig.h" - -/*! \class PIConfig - * \brief Configuration file - * \details This class provide handle access to configuration file. - * - * \section PIConfig_sec0 Synopsis - * PIConfig reads configuration file and create internal dendritic - * representation of all entries of this file. You can easily read - * some values and write new. - * \image html piconfig.png - * - * %PIConfig supports also INI-style files with sections "[section]". - * In this case line with section name interpret as prefix to the next - * lines. For example, these configs are equal: - * \code - * ser.device = /dev/ttyS0 - * ser.speed = 115200 - * debug = true - * \endcode - * \code - * [ser] - * device = /dev/ttyS0 - * speed = 115200 - * [] - * debug = true - * \endcode - * - * \section PIConfig_sec1 Concepts - * Each node of internal tree has type PIConfig::Entry. %PIConfig - * has one root element \a rootEntry(). Any entry of configuration file is a - * child of this element. - * - */ - -/*! \class PIConfig::Entry - * \brief %Entry of configuration file - * \details This class is node of internal PIConfig tree. - * %Entry provide access to elements of PIConfig. Each entry has - * children or next properties: - * * name - * * value - * * type - * * comment - * - * Each property is a PIString. These properties forms from text line with - * format: \code{.cpp} = # \endcode - * Type and comment are optional fields. Type is a single letter immediately - * after comment symbol "#". \n \n - * %Entry has many implicit convertions to common types: boolean, integers, - * float, double, PIString, PIStringList. \n \n - * Generally there is no need to create instance of %PIConfig::Entry manually, - * it returns by functions \a getValue() of \a PIConfig, \a PIConfig::Entry or - * \a PIConfig::Branch. If there is no suitable entry to return, reference to - * internal instance of %PIConfig::Entry with "default" value will be returned. - * \snippet piconfig.cpp PIConfig::Entry - * -*/ - -/*! \class PIConfig::Branch - * \brief %Branch is a list of entries of configuration file - * \details %Branch provides some features to get entries lists. - * \snippet piconfig.cpp PIConfig::Branch - * -*/ - - -PIConfig::Entry PIConfig::Branch::_empty; -PIConfig::Entry PIConfig::Entry::_empty; - - -PIConfig::Branch PIConfig::Branch::allLeaves() { - Branch b; - b.delim = delim; - piForeach (Entry * 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; - piForeach (Entry * 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; - } - piForeach (PIString & 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; - piForeach (Entry * i, *this) { - if (i->isLeaf()) { - if (i->_name.find(name) >= 0) - b << i; - } else { - piForeach (Entry * j, i->_children) - if (j->_name.find(name) >= 0) - b << j; - } - } - return b; -} - - -PIConfig::Branch PIConfig::Branch::getLeaves() { - Branch b; - b.delim = delim; - piForeach (Entry * i, *this) - if (i->isLeaf()) - b << i; - return b; -} - - -PIConfig::Branch PIConfig::Branch::getBranches() { - Branch b; - b.delim = delim; - piForeach (Entry * 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; - } - piForeachC (Entry * 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; - piForeach (PIString & 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; - piForeach (Entry * 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; - } - piForeachC (Entry * i, e->_children) - if (entryExists(i, name)) return true; - return false; -} - - -PIConfig::PIConfig(const PIString & path, PIIODevice::DeviceMode mode): PIFile(path, mode) { - delim = "."; - root.delim = delim; - empty.delim = delim; - empty._parent = 0; - if (!isOpened()) - open(path, mode); - parse(); -} - - -PIConfig::Entry & PIConfig::getValue(const PIString & vname, const PIString & def, bool * exist) { - PIStringList tree = vname.split(delim); - Entry * ce = &root; - piForeach (PIString & 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 = true; - return *ce; -} - - -PIConfig::Branch PIConfig::getValues(const PIString & vname) { - Branch b; - b.delim = delim; - piForeach (Entry * 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; - piForeach (PIString & 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; - ch.sort(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; - ch.sort(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) { - Entry & e(getValue(name)); - if (&e == &empty) { - addEntry(name, value, type, write); - return; - } - e._value = value; - e._type = type; - if (write) writeAll(); -} - - -int PIConfig::entryIndex(const PIString & name) { - PIStringList tree = name.split(delim); - Entry * ce = &root; - piForeach (PIString & i, tree) { - ce = ce->findChild(i); - if (ce == 0) - return -1; - } - Branch b = allLeaves(); - return allLeaves().indexOf(ce); -} - - -void PIConfig::setValue(uint number, const PIString & value, bool write) { - Entry & e(entryByIndex(number)); - if (&e == &empty) return; - e._value = value; - if (write) 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, bool write) { - Entry & e(entryByIndex(number)); - if (&e == &empty) return; - e._type = type; - if (write) 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::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()) other.remove(e->_line); - 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()); - } - 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.removeOne(e); - b.removeOne(e); - delete e; -} - - -PIString PIConfig::getPrefixFromLine(PIString line, bool * exists) { - line.trim(); - if (line.left(1) == "#") {if (exists) *exists = false; return PIString();} - int ci = line.find("#"); - if (ci >= 0) line.cutRight(line.size() - ci); - if (line.find("=") >= 0) {if (exists) *exists = false; return PIString();} - if (line.find("[") >= 0 && line.find("]") >= 0) { - if (exists) *exists = true; - return line.takeRange('[', ']').trim(); - } - if (exists) *exists = false; - return PIString(); -} - - -void PIConfig::writeAll() { - //cout << this << " write < " << size() << endl; - PIFile::clear(); - //*this << "1234567894132456798\n"; return; - //writeEntry(&root); - buildFullNames(&root); - Branch b = allLeaves(); - PIString prefix, tprefix; - bool isPrefix; - //for (int i = 0; i < b.size_s(); ++i) - // cout << b[i]->_name << " = " << b[i]->_value << endl; - 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).cutLeft(prefix.size()) << '\n'; - //cout << this << " " << b[j]->_all << endl; - ++j; - } else { - *this << other[i]; - tprefix = getPrefixFromLine(other[i], &isPrefix); - if (isPrefix) { - prefix = tprefix; - if (!prefix.isEmpty()) - prefix += delim; - } - if (i < other.size_s() - 1) *this << '\n'; - //cout << this << " " << other[i] << endl; - } - } else { - *this << other[i]; - tprefix = getPrefixFromLine(other[i], &isPrefix); - if (isPrefix) { - prefix = tprefix; - if (!prefix.isEmpty()) - prefix += delim; - } - if (i < other.size_s() - 1) *this << '\n'; - //cout << this << " " << other[i] << endl; - } - } - flush(); - readAll(); - //cout << this << " write > " << size() << endl; -} - - -void PIConfig::readAll() { - root.deleteBranch(); - root.clear(); - parse(); -} - - -bool PIConfig::entryExists(const Entry * e, const PIString & name) const { - if (e->_children.isEmpty()) { - if (e->_name == name) return true; - else return false; - } - piForeachC (Entry * i, e->_children) - if (entryExists(i, name)) return true; - return false; -} - - -void PIConfig::parse() { - PIString src, str, tab, comm, all, name, type, prefix, tprefix; - PIStringList tree; - Entry * entry, * te, * ce; - int ind, sind; - bool isNew, isPrefix; - if (!isOpened()) return; - seekToBegin(); - other.clear(); - lines = centry = 0; - while (!isEnd()) { - other.push_back(PIString()); - src = str = readLine(); - tprefix = getPrefixFromLine(src, &isPrefix); - if (isPrefix) { - prefix = tprefix; - if (!prefix.isEmpty()) - prefix += delim; - } - tab = str.left(str.find(str.trimmed().left(1))); - str.trim(); - //cout << endl << str << endl << endl; - all = str; - ind = str.find('='); - if ((ind > 0) && !(str[0] == '#')) { - sind = str.find('#'); - if (sind > 0) { - 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 { - type = "s"; - comm = ""; - } - //name = str.left(ind).trimmed(); - tree = (prefix + str.left(ind).trimmed()).split(delim); - name = tree.back(); - tree.pop_back(); - entry = &root; - piForeachC (PIString & 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); - buildFullNames(&root); -} diff --git a/piconfig.h b/piconfig.h deleted file mode 100644 index 951bbd6a..00000000 --- a/piconfig.h +++ /dev/null @@ -1,502 +0,0 @@ -/*! \file piconfig.h - * \brief Configuration file -*/ -/* - PIP - Platform Independent Primitives - Config parser - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PICONFIG_H -#define PICONFIG_H - -#include "pifile.h" - -#define PICONFIG_GET_VALUE \ - Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) {return getValue(vname, PIString(def), exists);} \ - Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) {return getValue(vname, def.join("%|%"), exists);} \ - Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) {return getValue(vname, PIString::fromBool(def), exists);} \ - Entry & getValue(const PIString & vname, const short def, bool * exists = 0) {return getValue(vname, itos(def), exists);} \ - Entry & getValue(const PIString & vname, const int def, bool * exists = 0) {return getValue(vname, itos(def), exists);} \ - Entry & getValue(const PIString & vname, const long def, bool * exists = 0) {return getValue(vname, ltos(def), exists);} \ - Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \ - Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \ - Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \ - Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) {return getValue(vname, ultos(def), exists);} \ - Entry & getValue(const PIString & vname, const float def, bool * exists = 0) {return getValue(vname, ftos(def), exists);} \ - Entry & getValue(const PIString & vname, const double def, bool * exists = 0) {return getValue(vname, dtos(def), exists);} \ - \ - Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) const {return getValue(vname, PIString(def), exists);} \ - Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) const {return getValue(vname, def.join("%|%"), exists);} \ - Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) const {return getValue(vname, PIString::fromBool(def), exists);} \ - Entry & getValue(const PIString & vname, const short def, bool * exists = 0) const {return getValue(vname, itos(def), exists);} \ - Entry & getValue(const PIString & vname, const int def, bool * exists = 0) const {return getValue(vname, itos(def), exists);} \ - Entry & getValue(const PIString & vname, const long def, bool * exists = 0) const {return getValue(vname, ltos(def), exists);} \ - Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \ - Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \ - Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \ - Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) const {return getValue(vname, ultos(def), exists);} \ - Entry & getValue(const PIString & vname, const float def, bool * exists = 0) const {return getValue(vname, ftos(def), exists);} \ - Entry & getValue(const PIString & vname, const double def, bool * exists = 0) const {return getValue(vname, dtos(def), exists);} - -class PIP_EXPORT PIConfig: public PIFile -{ - friend class Entry; - friend class Branch; -public: - - //! Contructs and read configuration file at path "path" in mode "mode" - PIConfig(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); - - ~PIConfig() {root.deleteBranch(); close();} - - class Entry; - - - class PIP_EXPORT Branch: public PIVector { - friend class PIConfig; - friend class Entry; - friend std::ostream & operator <<(std::ostream & s, const Branch & v); - friend PICout operator <<(PICout s, const Branch & v); - public: - Branch() {;} - - Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0); - Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {return const_cast(this)->getValue(vname, def, exists);} - PICONFIG_GET_VALUE - - Branch allLeaves(); - Branch getValues(const PIString & name); - Branch getLeaves(); - Branch getBranches(); - Branch & filter(const PIString & f); - bool isEntryExists(const PIString & name) const {piForeachC (Entry * i, *this) if (entryExists(i, name)) return true; return false;} - int indexOf(const Entry * e) {for (int i = 0; i < size_s(); ++i) if (at(i) == e) return i; return -1;} - - //void clear() {piForeach (Entry * i, *this) delete i; PIVector::clear();} - - private: - bool entryExists(const Entry * e, const PIString & name) const; - void allLeaves(Branch & b, Entry * e) {piForeach (Entry * i, e->_children) {if (i->isLeaf()) b << i; else allLeaves(b, i);}} - void coutt(std::ostream & s, const PIString & p) const {piForeachC (Entry * i, *this) i->coutt(s, p);} - void piCoutt(PICout s, const PIString & p) const {piForeachC (Entry * i, *this) i->piCoutt(s, p);} - - static Entry _empty; - PIString delim; - - }; - - - class PIP_EXPORT Entry { - friend class PIConfig; - friend class Branch; - public: - Entry() {_parent = 0;} - - //! Returns parent entry, or 0 if there is no parent (root of default value) - Entry * parent() const {return _parent;} - - //! Returns children count - int childCount() const {return _children.size_s();} - - //! Returns children as \a PIConfig::Branch - Branch & children() const {_children.delim = delim; return _children;} - - //! Returns child at index "index" - Entry * child(const int index) const {return _children[index];} - - //! Returns first child with name "name" - Entry * findChild(const PIString & name) {piForeach (Entry * i, _children) if (i->_name == name) return i; return 0;} - - //! Returns first child with name "name" - const Entry * findChild(const PIString & name) const {piForeachC (Entry * i, _children) if (i->_name == name) return i; return 0;} - - //! Returns \b true if there is no children - bool isLeaf() const {return _children.isEmpty();} - - - //! Returns name - const PIString & name() const {return _name;} - - //! Returns value - const PIString & value() const {return _value;} - - //! Returns type - const PIString & type() const {return _type;} - - //! Returns comment - const PIString & comment() const {return _comment;} - - /** \brief Returns full name, i.e. name as it looks in file - * \details In case of default entry full name always is empty - * \snippet piconfig.cpp fullName */ - const PIString & fullName() const {return _full_name;} - - //! Set name to "value" and returns this - Entry & setName(const PIString & value) {_name = value; return *this;} - - //! Set type to "value" and returns this - Entry & setType(const PIString & value) {_type = value; return *this;} - - //! Set comment to "value" and returns this - Entry & setComment(const PIString & value) {_comment = value; return *this;} - - //! Set value to "value" and returns this - Entry & setValue(const PIString & value) {_value = value; return *this;} - - //! Set value to "value" and returns this. Type is set to "l" - Entry & setValue(const PIStringList & value) {setValue(value.join("%|%")); setType("l"); return *this;} - - //! Set value to "value" and returns this. Type is set to "s" - Entry & setValue(const char * value) {setValue(PIString(value)); setType("s"); return *this;} - - //! Set value to "value" and returns this. Type is set to "b" - Entry & setValue(const bool value) {setValue(btos(value)); setType("b"); return *this;} - - //! Set value to "value" and returns this. Type is set to "s" - Entry & setValue(const char value) {setValue(PIString(1, value)); setType("s"); return *this;} - - //! Set value to "value" and returns this. Type is set to "n" - Entry & setValue(const short value) {setValue(itos(value)); setType("n"); return *this;} - - //! Set value to "value" and returns this. Type is set to "n" - Entry & setValue(const int value) {setValue(itos(value)); setType("n"); return *this;} - - //! Set value to "value" and returns this. Type is set to "n" - Entry & setValue(const long value) {setValue(ltos(value)); setType("n"); return *this;} - - //! Set value to "value" and returns this. Type is set to "n" - Entry & setValue(const uchar value) {setValue(uitos(value)); setType("n"); return *this;} - - //! Set value to "value" and returns this. Type is set to "n" - Entry & setValue(const ushort value) {setValue(uitos(value)); setType("n"); return *this;} - - //! Set value to "value" and returns this. Type is set to "n" - Entry & setValue(const uint value) {setValue(uitos(value)); setType("n"); return *this;} - - //! Set value to "value" and returns this. Type is set to "n" - Entry & setValue(const ulong value) {setValue(ultos(value)); setType("n"); return *this;} - - //! Set value to "value" and returns this. Type is set to "f" - Entry & setValue(const float value) {setValue(ftos(value)); setType("f"); return *this;} - - //! Set value to "value" and returns this. Type is set to "f" - Entry & setValue(const double value) {setValue(dtos(value)); setType("f"); return *this;} - - - /** \brief Returns entry with name "vname" and default value "def" - * \details If there is no suitable entry found, reference to default internal entry with - * value = "def" will be returned, and if "exists" not null it will be set to \b false */ - Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0); - Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {return const_cast(this)->getValue(vname, def, exists);} - PICONFIG_GET_VALUE - - //! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const short def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const int def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const long def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const float def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const double def, bool * exists = 0) - //! \brief Returns entry with name "vname" and default value "def" - - - //! Find all entries with names with substrings "vname" and returns them as \a PIConfig::Branch - Branch getValues(const PIString & vname); - - - //! If there is no children returns if name == "name". Else returns if any child has name == "name" - bool isEntryExists(const PIString & name) const {return entryExists(this, name);} - - - //! Convertion to boolean - operator bool() {return _value.toBool();} - - //! Convertion to char - operator char() {return (_value.isEmpty() ? 0 : _value[0].toAscii());} - - //! Convertion to short - operator short() {return _value.toShort();} - - //! Convertion to int - operator int() {return _value.toInt();} - - //! Convertion to long - operator long() {return _value.toLong();} - - //! Convertion to uchar - operator uchar() {return _value.toInt();} - - //! Convertion to ushort - operator ushort() {return _value.toShort();} - - //! Convertion to uint - operator uint() {return _value.toInt();} - - //! Convertion to ulong - operator ulong() {return _value.toLong();} - - //! Convertion to float - operator float() {return _value.toFloat();} - - //! Convertion to double - operator double() {return _value.toDouble();} - - //! Convertion to PIString - operator PIString() {return _value;} - - //! Convertion to PIStringList - operator PIStringList() {return _value.split("%|%");} - - private: - typedef PIConfig::Entry * EntryPtr; - static int compare(const EntryPtr * f, const EntryPtr * s) {return (*f)->_line == (*s)->_line ? 0 : (*f)->_line < (*s)->_line ? -1 : 1;} - bool entryExists(const Entry * e, const PIString & name) const; - void buildLine() {_all = _tab + _full_name + " = " + _value + " #" + _type + " " + _comment;} - void clear() {_children.clear(); _name = _value = _type = _comment = _all = PIString(); _line = 0; _parent = 0;} - 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; piForeachC (Entry * i, _children) i->coutt(s, nl);} - void piCoutt(PICout s, const PIString & p) const {PIString nl = p + " "; if (!_value.isEmpty()) s << p << _name << " = " << _value << NewLine; else cout << p << _name << endl; piForeachC (Entry * i, _children) i->piCoutt(s, nl);} - void deleteBranch() {piForeach (Entry * i, _children) {i->deleteBranch(); delete i;}} - - static Entry _empty; - Entry * _parent; - mutable Branch _children; - PIString _tab; - PIString _name; - PIString _value; - PIString _type; - PIString _comment; - PIString _all; - PIString _full_name; - PIString delim; - int _line; - }; - - - //! Returns top-level entry with name "vname", if doesn`t exists return entry with value "def" and set *exist to false - Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0); - Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {return const_cast(this)->getValue(vname, def, exists);} - - PICONFIG_GET_VALUE - - //! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const short def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const int def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const long def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const float def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - //! \fn Entry & getValue(const PIString & vname, const double def, bool * exists = 0) - //! \brief Returns top-level entry with name "vname" and default value "def" - - - //! Returns top-level entries with names with substrings "vname" - Branch getValues(const PIString & vname); - - - //! Set top-level entry with name "name" value to "value", type to "type" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); - - //! Set top-level entry with name "name" value to "value", type to "l" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const PIStringList & value, bool write = true) {setValue(name, value.join("%|%"), "l", write);} - - //! Set top-level entry with name "name" value to "value", type to "s" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const char * value, bool write = true) {setValue(name, PIString(value), "s", write);} - - //! Set top-level entry with name "name" value to "value", type to "b" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const bool value, bool write = true) {setValue(name, btos(value), "b", write);} - - //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const short value, bool write = true) {setValue(name, itos(value), "n", write);} - - //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const int value, bool write = true) {setValue(name, itos(value), "n", write);} - - //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const long value, bool write = true) {setValue(name, ltos(value), "n", write);} - - //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const uchar value, bool write = true) {setValue(name, uitos(value), "n", write);} - - //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const ushort value, bool write = true) {setValue(name, uitos(value), "n", write);} - - //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const uint value, bool write = true) {setValue(name, uitos(value), "n", write);} - - //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const ulong value, bool write = true) {setValue(name, ultos(value), "n", write);} - - //! Set top-level entry with name "name" value to "value", type to "f" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const float value, bool write = true) {setValue(name, ftos(value), "f", write);} - - //! Set top-level entry with name "name" value to "value", type to "f" and if "write" immediate write to file. Add new entry if there is no suitable exists - void setValue(const PIString & name, const double value, bool write = true) {setValue(name, dtos(value), "f", write);} - - //! Returns root entry - Entry & rootEntry() {return root;} - - //! Returns top-level entries count - int entriesCount() const {return childCount(&root);} - - //! Returns if top-level entry with name "name" exists - bool isEntryExists(const PIString & name) const {return entryExists(&root, name);} - - //! Returns all top-level entries - Branch allTree() {Branch b; piForeach (Entry * i, root._children) b << i; b.delim = delim; return b;} - - //! Returns all entries without children - Branch allLeaves() {Branch b; allLeaves(b, &root); b.sort(Entry::compare); b.delim = delim; return b;} - - int entryIndex(const PIString & name); - - PIString getName(uint number) {return entryByIndex(number)._name;} - PIString getValue(uint number) {return entryByIndex(number)._value;} - PIChar getType(uint number) {return entryByIndex(number)._type[0];} - 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); - 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); - - //! Remove all tree and file content - void clear() {PIFile::clear(); parse();} - - //! Parse file and build internal tree - void readAll(); - - //! Write all internal tree to file - void writeAll(); - - //! Returns current tree delimiter, default "." - const PIString & delimiter() const {return delim;} - - //! Set current tree delimiter - void setDelimiter(const PIString & d) {delim = d; setEntryDelim(&root, d); readAll();} - -private: - int childCount(const Entry * e) const {int c = 0; piForeachC (Entry * 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) {piForeach (Entry * 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) {piForeach (Entry * i, e->_children) {if ((!i->_value.isEmpty() && !i->isLeaf()) || i->isLeaf()) b << i; allLeaves(b, i);}} - void setEntryDelim(Entry * e, const PIString & d) {piForeach (Entry * i, e->_children) setEntryDelim(i, d); e->delim = d;} - 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 deleteEntry(Entry * e) {piForeach (Entry * i, e->_children) deleteEntry(i); delete e;} - PIString getPrefixFromLine(PIString line, bool * exists); - void parse(); - - 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;} -inline PICout operator <<(PICout s, const PIConfig::Branch & v) {s.setControl(0, true); v.piCoutt(s, ""); s.restoreControl(); return s;} -inline PICout operator <<(PICout s, const PIConfig::Entry & v) {s << v.value(); return s;} - - -/** \relatesalso PIConfig \relatesalso PIIODevice - * \brief Service function. useful for configuring devices - * \details Function takes entry name "name", default value "def" and two - * \a PIConfig::Entry sections: "em" and their parent "ep". If there is no - * parent ep = 0. If "ep" is not null and entry "name" exists in "ep" function - * returns this value. Else returns value of entry "name" in section "em" or - * "def" if entry doesn`t exists. \n This function useful to read settings - * from configuration file in implementation \a PIIODevice::configureDevice() function */ -template -T readDeviceSetting(const PIString & name, const T & def, const PIConfig::Entry * em, const PIConfig::Entry * ep) { - if (ep != 0) { - T ret; - bool ex; - ret = ep->getValue(name, def, &ex); - if (!ex) ret = em->getValue(name, def); - return ret; - } - return em->getValue(name, def); - -} - -#endif // PICONFIG_H diff --git a/piconnection.cpp b/piconnection.cpp deleted file mode 100644 index fcc3d2f3..00000000 --- a/piconnection.cpp +++ /dev/null @@ -1,764 +0,0 @@ -/* - PIP - Platform Independent Primitives - Complex I/O point - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "piconnection.h" -#include "piconfig.h" - -/** \class PIConnection - * \brief Complex Input/Output point - * - * \section PIConnection_synopsis Synopsis - * %PIConnection provides abstract layer over physical devices, - * filtering and connecting data streams. Each %PIConnection - * works through Device Pool, so several %PIConnections can - * read from single physical device. General scheme: - * \image html piconnection.png - * - * \section PIConnection_pool Device pool concept - * Device pool is static object, single for each application, which - * contains unique devices. Each %PIConnection works with real devices - * through Device pool. Each device has assosiated thread for read - * and it can be started or stopped with %PIConnection functions - * \a startThreadedRead() and \a stopThreadedRead(). - * - * \section PIConnection_config Configuration - * You can create %PIConnection from config file section or configure - * it later with function \a configureFromConfig(). Devices describes - * with its full pathes, for details see \ref PIIODevice_sec7. Example: - * \image html piconnection_conf.png - * -*/ - - -PIVector PIConnection::_connections; - - -PIConnection::PIConnection(): PIObject() { - _connections << this; -} - - -PIConnection::PIConnection(const PIString & config, const PIString & name_): PIObject(name_) { - _connections << this; - configureFromConfig(config, name_); -} - - -PIConnection::~PIConnection() { - __device_pool__->unboundConnection(this); - removeAllFilters(); - _connections.removeAll(this); -} - - -bool PIConnection::configureFromConfig(const PIString & conf_path, const PIString & name_) { - PIConfig conf(conf_path, PIIODevice::ReadOnly); - if (!conf.isOpened()) return false; - __device_pool__->unboundConnection(this); - removeAllChannels(); - removeAllFilters(); - removeAllDevices(); - setName(name_); - PIConfig::Entry ce(conf.getValue(name_)); - PIConfig::Branch db(ce.getValue("device").children()), fb(ce.getValue("filter").children()), cb(ce.getValue("channel").children()); - PIStringList dev_list(ce.getValue("device").value()); - piForeachC (PIConfig::Entry * e, db) - dev_list << e->value(); - dev_list.removeStrings(""); - piForeachC (PIString & s, dev_list) { - PIString fn(s); - PIIODevice::DeviceMode dm = PIIODevice::ReadWrite; - if (fn.find("(") > 0 && fn.find(")") > 0) { - PIString dms(fn.right(fn.length() - fn.find("(")).takeRange("(", ")").trim().toLowerCase().removeAll(" ")); - //piCout << dms; - if (dms == "r" || dms == "ro" || dms == "read" || dms == "readonly") - dm = PIIODevice::ReadOnly; - if (dms == "w" || dms == "wo" || dms == "write" || dms == "writeonly") - dm = PIIODevice::WriteOnly; - fn.cutRight(fn.length() - fn.find("(") + 1).trim(); - } - //piCout << fn; - PIIODevice * dev = addDevice(fn, dm); - if (dev) dev->setName(name_ + ".device." + s); - } - piForeachC (PIConfig::Entry * e, fb) { - PIPacketExtractor::SplitMode sm = PIPacketExtractor::None; - PIString sms(e->getValue("splitMode").value()); - int smi = sms.toInt(); - if (smi >= 1 && smi <= 5) sm = (PIPacketExtractor::SplitMode)smi; - else { - sms = sms.trim().toLowerCase(); - if (sms.find("header") >= 0 && sms.find("footer") >= 0) - sm = PIPacketExtractor::HeaderAndFooter; - else { - if (sms.find("header") >= 0) - sm = PIPacketExtractor::Header; - else { - if (sms.find("footer") >= 0) - sm = PIPacketExtractor::Footer; - else { - if (sms.find("time") >= 0) - sm = PIPacketExtractor::Timeout; - else { - if (sms.find("size") >= 0) - sm = PIPacketExtractor::Size; - } - } - } - } - } - PIStringList devs(e->value()); - PIConfig::Branch db(e->getValue("device").children()); - piForeachC (PIConfig::Entry * e2, db) - devs << e2->value(); - devs.removeStrings(""); - if (devs.isEmpty()) continue; - PIPacketExtractor * pe = addFilter(e->name(), devs.front(), sm); - if (pe == 0) continue; - for (int i = 1; i < devs.size_s(); ++i) - addFilter(e->name(), devs[i], sm); - pe->setPayloadSize(e->getValue("payloadSize", pe->payloadSize())); - pe->setPacketSize(e->getValue("packetSize", pe->packetSize())); - pe->setTimeout(e->getValue("timeout", pe->timeout())); - pe->setHeader(PIByteArray::fromString(e->getValue("header", "").value())); - pe->setFooter(PIByteArray::fromString(e->getValue("footer", "").value())); - } - piForeachC (PIConfig::Entry * e, cb) { - PIString f(e->getValue("from").value()), t(e->getValue("to").value()); - addChannel(f, t); - } - return true; -} - - -PIString PIConnection::makeConfig() const { - PIString ret; - ret << "[" << name() << "]\n"; - PIVector devs(boundedDevices()); - int dn(0); - piForeachC (PIIODevice * d, devs) { - ret << "device." << dn << " = " << d->constructFullPath(); ++dn; - if (d->mode() == PIIODevice::ReadOnly) ret << " (ro)"; - if (d->mode() == PIIODevice::WriteOnly) ret << " (wo)"; - ret << "\n"; - } - piForeachC (PEPair & f, extractors) { - if (f.second == 0) continue; - if (f.second->extractor == 0) continue; - PIString prefix = "filter." + f.first; - for (int i = 0; i < f.second->devices.size_s(); ++i) - ret << prefix << ".device." << i << " = " << f.second->devices[i]->constructFullPath() << "\n"; - ret << prefix << ".splitMode = "; - switch (f.second->extractor->splitMode()) { - case PIPacketExtractor::None: ret << "none"; break; - case PIPacketExtractor::Header: ret << "header"; break; - case PIPacketExtractor::Footer: ret << "footer"; break; - case PIPacketExtractor::HeaderAndFooter: ret << "header & footer"; break; - case PIPacketExtractor::Size: ret << "size"; break; - case PIPacketExtractor::Timeout: ret << "timeout"; break; - } - ret << "\n"; - ret << prefix << ".payloadSize = " << f.second->extractor->payloadSize() << "\n"; - ret << prefix << ".packetSize = " << f.second->extractor->packetSize() << "\n"; - ret << prefix << ".timeout = " << f.second->extractor->timeout() << "\n"; - ret << prefix << ".header = " << f.second->extractor->header().toString() << "\n"; - ret << prefix << ".footer = " << f.second->extractor->footer().toString() << "\n"; - } - dn = 0; - piForeachC (CPair & c, channels_) { - piForeachC (PIIODevice * d, c.second) { - PIString prefix = "channel." + PIString::fromNumber(dn); ++dn; - ret << prefix << ".from = " << devPath(c.first) << "\n"; - ret << prefix << ".to = " << devPath(d) << "\n"; - } - } - ret << "[]\n"; - return ret; -} - - -PIIODevice * PIConnection::addDevice(const PIString & full_path, PIIODevice::DeviceMode mode, bool start) { - PIIODevice * dev = __device_pool__->addDevice(this, full_path, mode, start); - if (dev) { - dev->setName(name() + ".device." + full_path); - device_modes[dev] = mode; - } - return dev; -} - - -bool PIConnection::removeDevice(const PIString & full_path) { - PIIODevice * dev = __device_pool__->device(full_path); - if (dev == 0) return false; - device_modes.remove(dev); - piForeachC (PEPair & i, extractors) { - if (i.second == 0) continue; - i.second->devices.removeAll(dev); - } - bounded_extractors.remove(dev); - channels_.remove(dev); - for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) - it.value().removeAll(dev); - return __device_pool__->removeDevice(this, full_path); -} - - -void PIConnection::removeAllDevices() { - PIVector bdevs(__device_pool__->boundedDevices(this)); - piForeach (PIIODevice * d, bdevs) { - channels_.remove(d); - for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) - it.value().removeAll(d); - } - __device_pool__->unboundConnection(this); - device_modes.clear(); - bounded_extractors.clear(); - piForeachC (PEPair & i, extractors) { - if (i.second == 0) continue; - i.second->devices.clear(); - } -} - - -PIIODevice * PIConnection::device(const PIString & full_path) const { - DevicePool::DeviceData * dd = __device_pool__->devices.value(full_path); - if (dd == 0) return 0; - if (dd->dev == 0) return 0; - if (!dd->listeners.contains(const_cast(this))) return 0; - return dd->dev; -} - - -PIVector PIConnection::boundedDevices() const { - return __device_pool__->boundedDevices(this); -} - - -PIPacketExtractor * PIConnection::addFilter(const PIString & name_, const PIString & full_path, PIPacketExtractor::SplitMode mode) { - Extractor * e = extractors.value(name_); - PIIODevice * dev = __device_pool__->device(full_path); - if (dev == 0) { - piCoutObj << "\"addPacketExtractor\" error: no such device \"" << full_path << "\"!"; - return 0; - } - if (e == 0) { - e = new Extractor(); - extractors[name_] = e; - } - if (e->extractor == 0) { - e->extractor = new PIPacketExtractor(0, mode); - e->extractor->setName(name_); - e->extractor->setThreadedReadData(new PIPair(this, name_)); - e->extractor->setHeaderCheckSlot(filterValidateHeaderS); - e->extractor->setFooterCheckSlot(filterValidateFooterS); - e->extractor->setPayloadCheckSlot(filterValidatePayloadS); - CONNECT2(void, uchar * , int, e->extractor, packetReceived, this, packetExtractorReceived) - } - if (!e->devices.contains(dev)) { - bounded_extractors[dev] << e->extractor; - e->devices << dev; - } - return e->extractor; -} - - -PIPacketExtractor * PIConnection::addFilter(const PIString & name_, const PIIODevice * dev, PIPacketExtractor::SplitMode mode) { - if (dev == 0) return 0; - PIString fp; - if (dev->isPropertyExists("__fullPath__")) fp = dev->property("__fullPath__").toString(); - fp = dev->constructFullPath(); - return addFilter(name_, fp, mode); -} - - -bool PIConnection::removeFilter(const PIString & name_, const PIString & full_path) { - Extractor * p = extractors.value(name_); - if (p == 0) return false; - bool ret = false; - for (int i = 0; i < p->devices.size_s(); ++i) { - if (p->devices[i]->property("__fullPath__").toString() == full_path) { - bounded_extractors[p->devices[i]].removeAll(p->extractor); - p->devices.remove(i); - --i; - ret = true; - } - } - if (p->devices.isEmpty()) { - unboundExtractor(p->extractor); - delete p; - } - return ret; -} - - -bool PIConnection::removeFilter(const PIString & name, const PIIODevice * dev) { - if (dev == 0) return false; - return removeFilter(name, dev->property("__fullPath__").toString()); -} - - -bool PIConnection::removeFilter(const PIString & name_) { - Extractor * p = extractors.value(name_); - if (p == 0) return false; - unboundExtractor(p->extractor); - delete p; - return true; -} - - -void PIConnection::removeAllFilters() { - piForeachC (PEPair & i, extractors) { - if (i.second == 0) continue; - channels_.remove(i.second->extractor); - for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) - it.value().removeAll(i.second->extractor); - delete i.second; - } - extractors.clear(); - bounded_extractors.clear(); -} - - -PIVector PIConnection::filters() const { - PIVector ret; - piForeachC (PEPair & i, extractors) - if (i.second != 0) - if (i.second->extractor != 0) ret << i.second->extractor; - return ret; -} - - -PIStringList PIConnection::filterNames() const { - PIStringList ret; - piForeachC (PEPair & i, extractors) - if (i.second != 0) - if (i.second->extractor != 0) ret << i.first; - return ret; -} - - -PIPacketExtractor * PIConnection::filter(const PIString & name) const { - piForeachC (PEPair & i, extractors) - if (i.second != 0) - if (i.second->extractor != 0 && i.first == name) - return i.second->extractor; - return 0; -} - - -PIVector PIConnection::filterBoundedDevices(const PIString & name_) const { - PIVector ret; - Extractor * p = extractors.value(name_); - if (p == 0) return ret; - return p->devices; -} - - -bool PIConnection::addChannel(const PIString & name0, const PIString & name1) { - //piCout << "addChannel" << name0 << name1; - if (name0.isEmpty() || name1.isEmpty()) return false; - PIIODevice * dev0 = device(name0), * dev1 = device(name1); - PIPacketExtractor * pe0(0), * pe1(0); - if (extractors.value(name0) != 0) pe0 = extractors.value(name0)->extractor; - if (extractors.value(name1) != 0) pe1 = extractors.value(name1)->extractor; - if (pe0 != 0) dev0 = pe0; - if (pe1 != 0) dev1 = pe1; - if (dev0 == 0 || dev1 == 0) { - if (dev0 == 0) piCoutObj << "\"addChannel\" error: no such device \"" << name0 << "\"!"; - if (dev1 == 0) piCoutObj << "\"addChannel\" error: no such device \"" << name1 << "\"!"; - return false; - } - if (!channels_[dev0].contains(dev1)) - channels_[dev0] << dev1; - return true; -} - - -bool PIConnection::removeChannel(const PIString & name0, const PIString & name1) { - PIIODevice * dev0 = device(name0), * dev1 = device(name1); - PIPacketExtractor * pe0(0), * pe1(0); - if (extractors.value(name0) != 0) pe0 = extractors.value(name0)->extractor; - if (extractors.value(name1) != 0) pe1 = extractors.value(name1)->extractor; - if (pe0 != 0) dev0 = pe0; - if (pe1 != 0) dev1 = pe1; - if (dev0 == 0 || dev1 == 0) return false; - channels_[dev0].removeAll(dev1); - return true; -} - - -bool PIConnection::removeChannel(const PIString & name0) { - PIIODevice * dev0 = device(name0); - PIPacketExtractor * pe0(0); - if (extractors.value(name0) != 0) pe0 = extractors.value(name0)->extractor; - if (pe0 != 0) dev0 = pe0; - if (dev0 == 0) return false; - channels_.remove(dev0); - for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) - it.value().removeAll(dev0); - return true; -} - - -void PIConnection::removeAllChannels() { - channels_.clear(); -} - - -PIString PIConnection::devPath(const PIIODevice * d) const { - if (d == 0) return PIString(); - if (strcmp(d->className(), "PIPacketExtractor") == 0) return d->name(); - return d->constructFullPath(); -} - - -PIString PIConnection::devFPath(const PIIODevice * d) const { - if (d == 0) return PIString(); - if (d->isPropertyExists("__fullPath__")) return d->property("__fullPath__").toString(); - return d->name(); -} - - -PIVector > PIConnection::channels() const { - PIVector > ret; - piForeachC (CPair & i, channels_) { - PIString fp0(devFPath(i.first)); - piForeachC (PIIODevice * d, i.second) - ret << PIPair(fp0, devFPath(d)); - } - return ret; -} - - -void PIConnection::startThreadedRead(const PIString & full_path) { - DevicePool::DeviceData * dd = __device_pool__->devices.value(full_path, 0); - if (dd == 0) return; - if (dd->dev == 0) return; - if (dd->started || dd->dev->mode() == PIIODevice::WriteOnly) return; - dd->rthread->start(); - dd->started = true; -} - - -void PIConnection::startAllThreadedReads() { - piForeachC (DevicePool::DDPair & d, __device_pool__->devices) - startThreadedRead(d.first); -} - - -void PIConnection::stopThreadedRead(const PIString & full_path) { - DevicePool::DeviceData * dd = __device_pool__->devices.value(full_path, 0); - if (dd == 0) return; - if (dd->dev == 0) return; - if (!dd->started || dd->dev->mode() == PIIODevice::WriteOnly) return; - dd->rthread->stop(); - dd->started = false; -} - - -void PIConnection::stopAllThreadedReads() { - piForeachC (DevicePool::DDPair & d, __device_pool__->devices) - stopThreadedRead(d.first); -} - - -int PIConnection::write(const PIString & full_path, const PIByteArray & data) { - PIIODevice * dev = __device_pool__->device(full_path); - if (dev == 0) { - piCoutObj << "Null Device!"; - return -1; - } - if (!dev->canWrite()) { - piCoutObj << "Device \"" << full_path << "\" can`t write!"; - return -1; - } - return dev->write(data); -} - - -PIVector< PIConnection * > PIConnection::allConnections() { - return _connections; -} - - -PIVector< PIIODevice * > PIConnection::allDevices() { - return __device_pool__->boundedDevices(); -} - - - -PIIODevice * PIConnection::DevicePool::addDevice(PIConnection * parent, const PIString & fp, PIIODevice::DeviceMode mode, bool start) { - DeviceData * dd = devices[fp]; - int pmode(0); - bool need_start = false; - if (dd == 0) { - dd = new DeviceData(); - devices[fp] = dd; - } - if (dd->dev == 0) { - //piCout << "new device" << fp; - dd->dev = PIIODevice::createFromFullPath(fp); - if (dd->dev == 0) { - piCoutObj << "Error: can`t create device \"" << fp << "\"!"; //:" << errorString(); - return 0; - } - dd->dev->setProperty("__fullPath__", fp); - } else - pmode = dd->dev->mode(); - if (!dd->listeners.contains(parent)) - dd->listeners << parent; - if (pmode == mode || pmode == PIIODevice::ReadWrite) - return dd->dev; - if ((mode & PIIODevice::ReadOnly) > 0) { - if (dd->rthread != 0) { - delete dd->rthread; - dd->rthread = 0; - dd->started = false; - } - dd->rthread = new PIThread(dd, threadReadDP); - need_start = true; - pmode |= PIIODevice::ReadOnly; - } - if ((mode & PIIODevice::WriteOnly) > 0) - pmode |= PIIODevice::WriteOnly; - dd->dev->close(); - dd->dev->open((PIIODevice::DeviceMode)pmode); - if (need_start && start) { - dd->rthread->start(); - dd->started = true; - } - return dd->dev; -} - - -bool PIConnection::DevicePool::removeDevice(PIConnection * parent, const PIString & fp) { - DeviceData * dd = devices.value(fp); - if (dd == 0) - return false; - if (dd->dev == 0) - return false; - bool ok = dd->listeners.contains(parent); - dd->listeners.removeAll(parent); - if (dd->listeners.isEmpty()) { - delete dd; - devices.remove(fp); - } - return ok; -} - - -void PIConnection::DevicePool::unboundConnection(PIConnection * parent) { - PIStringList rem; - piForeachC (DDPair & i, devices) { - if (i.second == 0) { - rem << i.first; - continue; - } - i.second->listeners.removeAll(parent); - if (i.second->listeners.isEmpty()) - rem << i.first; - } - piForeachC (PIString & i, rem) { - DeviceData * dd = devices.value(i); - if (dd == 0) - continue; - delete dd; - devices.remove(i); - } -} - - -PIIODevice * PIConnection::DevicePool::device(const PIString & fp) const { - DeviceData * dd = devices.value(fp); - if (dd == 0) return 0; - return dd->dev; -} - - -PIVector PIConnection::DevicePool::boundedConnections() const { - PIVector ret; - piForeachC (DDPair & i, devices) { - if (i.second == 0) - continue; - ret << i.second->listeners; - } - for (int i = 0; i < ret.size_s(); ++i) - for (int j = i + 1; j < ret.size_s(); ++j) - if (ret[i] == ret[j]) { - ret.remove(j); - --j; - } - return ret; -} - - -PIVector< PIIODevice * > PIConnection::DevicePool::boundedDevices() const { - PIVector ret; - piForeachC (DDPair & i, devices) { - if (i.second == 0) continue; - if (i.second->dev == 0) continue; - ret << i.second->dev; - } - return ret; -} - - -PIVector PIConnection::DevicePool::boundedDevices(const PIConnection * parent) const { - PIVector ret; - piForeachC (DDPair & i, devices) { - if (i.second == 0) continue; - if (i.second->dev == 0) continue; - if (i.second->listeners.contains(const_cast(parent))) - ret << i.second->dev; - } - return ret; -} - - -PIConnection::DevicePool::DeviceData::~DeviceData() { - if (rthread != 0) { - rthread->stop(); - delete rthread; - rthread = 0; - } - if (dev != 0) { - delete dev; - dev = 0; - } -} - - -void PIConnection::DevicePool::threadReadDP(void * ddp) { - DeviceData * dd((DeviceData * )ddp); - if (dd->dev == 0) {piMSleep(100); return;} - PIByteArray ba; - ba = dd->dev->read(dd->dev->threadedReadBufferSize()); - if (ba.isEmpty()) {piMSleep(10); return;} - //piCout << "Readed from" << dd->dev->path() << Hex << ba; - __device_pool__->deviceReaded(dd, ba); -} - - -void PIConnection::DevicePool::deviceReaded(PIConnection::DevicePool::DeviceData * dd, const PIByteArray & data) { - PIString from = dd->dev->property("__fullPath__").toString(); - piForeach (PIConnection * ld, dd->listeners) - ld->rawReceived(dd->dev, from, data); -} - - -bool PIConnection::filterValidateHeaderS(void * c, uchar * src, uchar * rec, int size) { - PIPair * p((PIPair * )c); - return p->first->filterValidateHeader(p->second, src, rec, size); -} - - -bool PIConnection::filterValidateFooterS(void * c, uchar * src, uchar * rec, int size) { - PIPair * p((PIPair * )c); - return p->first->filterValidateFooter(p->second, src, rec, size); -} - - -bool PIConnection::filterValidatePayloadS(void * c, uchar * rec, int size) { - PIPair * p((PIPair * )c); - return p->first->filterValidatePayload(p->second, rec, size); -} - - -void PIConnection::rawReceived(PIIODevice * dev, const PIString & from, const PIByteArray & data) { - dataReceived(from, data); - dataReceivedEvent(from, data); - PIVector be(bounded_extractors.value(dev)); - //piCout << be; - piForeach (PIPacketExtractor * i, be) - i->threadedRead(const_cast(data.data()), data.size_s()); - PIVector chd(channels_.value(dev)); - piForeach (PIIODevice * d, chd) - d->write(data); -} - - -bool PIConnection::filterValidateHeader(const PIString & filter_name, uchar * src, uchar * rec, int size) { - for (int i = 0; i < size; ++i) - if (src[i] != rec[i]) - return false; - return true; -} - - -bool PIConnection::filterValidateFooter(const PIString & filter_name, uchar * src, uchar * rec, int size) { - for (int i = 0; i < size; ++i) - if (src[i] != rec[i]) - return false; - return true; -} - - -bool PIConnection::filterValidatePayload(const PIString & filter_name, uchar * rec, int size) { - return true; -} - - -PIConnection::Extractor::~Extractor() { - if (extractor != 0) { - if (extractor->threadedReadData() != 0) - delete (PIPair * )(extractor->threadedReadData()); - delete extractor; - extractor = 0; - } -} - - -void PIConnection::unboundExtractor(PIPacketExtractor * pe) { - if (pe == 0) return; - channels_.remove(pe); - for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) - it.value().removeAll(pe); - PIVector k = bounded_extractors.keys(); - piForeach (PIIODevice * i, k) { - PIVector & be(bounded_extractors[i]); - be.removeAll(pe); - if (be.isEmpty()) - bounded_extractors.remove(i); - } - extractors.remove(pe->name()); -} - - -void PIConnection::packetExtractorReceived(uchar * data, int size) { - PIString from(emitter() == 0 ? "" : emitter()->name()); - packetReceived(from, PIByteArray(data, size)); - packetReceivedEvent(from, PIByteArray(data, size)); - PIIODevice * cd = (PIIODevice * )emitter(); - if (cd == 0) return; - PIVector chd(channels_.value(cd)); - piForeach (PIIODevice * d, chd) - d->write(data, size); -} - - - -PIConnection::DevicePool * __device_pool__; - -bool __DevicePoolContainer__::inited_(false); - -__DevicePoolContainer__::__DevicePoolContainer__() { - if (inited_) return; - inited_ = true; - __device_pool__ = new PIConnection::DevicePool(); -} diff --git a/piconnection.h b/piconnection.h deleted file mode 100644 index c00f85da..00000000 --- a/piconnection.h +++ /dev/null @@ -1,291 +0,0 @@ -/*! \file piconnection.h - * \brief Complex I/O point -*/ -/* - PIP - Platform Independent Primitives - Complex I/O point - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PICONNECTION_H -#define PICONNECTION_H - -#include "pipacketextractor.h" - - -class PIP_EXPORT PIConnection: public PIObject -{ - PIOBJECT(PIConnection) -public: - - //! Constructs an empty connection - PIConnection(); - - //! Constructs connection and configure it from config file "config" from section "name" - PIConnection(const PIString & config, const PIString & name); - - ~PIConnection(); - - - /*! \brief Configure connection from config file "config" from section "name". Returns if configuration was successful - * \details \b Warning: all devices, filters and channels removed before configure! */ - bool configureFromConfig(const PIString & config, const PIString & name); - - //! Returns config file section of current connection configuration - PIString makeConfig() const; - - - /*! \brief Add device with full path "full_path", open mode "mode" to Device pool and connection - * \details Returns pointer to device or null if device can not be created. If "start" is true, - * read thread is started immediately. Else, you can start read thread with functions \a startThreadedRead() - * or \a startAllThreadedReads(). By default, read thread doesn`t start */ - PIIODevice * addDevice(const PIString & full_path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = false); - - /*! \brief Remove device with full path "full_path" from connection - * \details Returns if device was removed. If there is no connection bounded to this device, - * it will be removed from Device pool */ - bool removeDevice(const PIString & full_path); - - /*! \brief Remove all device from connection - * \details If there is no connection bounded to there devices, they removed from Device pool */ - void removeAllDevices(); - - //! Returns device with full path "full_path" or null if there is no such device - PIIODevice * device(const PIString & full_path) const; - - //! Returns all devices bounded to this connection - PIVector boundedDevices() const; - - - /*! \brief Add filter with name "name" to device with full path "full_path" - * \details If there is no filter with name "name", connection create new with split mode "mode" and bound - * to it device "full_path". If filter with name "name" already exists, device "full_path" add to this filter. - * \b Attention! "mode" is altual olny if new filter was created! - * This function returns PIPacketExtractor * assosiated with this filter */ - PIPacketExtractor * addFilter(const PIString & name, const PIString & full_path, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None); - - //! Add filter with name "name" to device "dev" - PIPacketExtractor * addFilter(const PIString & name, const PIIODevice * dev, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None); - - /*! \brief Remove from filter with name "name" device with full path "full_path" - * \details If there is no devices bounded to this filter, it will be removed. Returns - * if device was removed */ - bool removeFilter(const PIString & name, const PIString & full_path); - - //! Remove from filter with name "name" device "dev" - bool removeFilter(const PIString & name, const PIIODevice * dev); - - //! Remove filter with name "name". Returns if filter was removed - bool removeFilter(const PIString & name); - - //! Remove all filters from connection - void removeAllFilters(); - - - //! Returns all filters of connection - PIVector filters() const; - - //! Returns all filter names of connection - PIStringList filterNames() const; - - //! Returns PIPacketExtractor * assosiated with filter "name" or null if there is no such filter - PIPacketExtractor * filter(const PIString & name) const; - - //! Returns all devices bounded to filter "name" - PIVector filterBoundedDevices(const PIString & name) const; - - - /*! \brief Add to connection channel from "name_from" to "name_to" - * \details "name_from" and "name_to" can be full pathes of devices or filter names. - * Returns \b false if there if no such device or filter, else create channel and returns \b true */ - bool addChannel(const PIString & name_from, const PIString & name_to); - - //! Add to connection channel from "name_from" to "dev_to" - bool addChannel(const PIString & name_from, const PIIODevice * dev_to) {return addChannel(name_from, devFPath(dev_to));} - - //! Add to connection channel from "dev_from" to "name_to" - bool addChannel(const PIIODevice * dev_from, const PIString & name_to) {return addChannel(devFPath(dev_from), name_to);} - - //! Add to connection channel from "dev_from" to "dev_to" - bool addChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) {return addChannel(devFPath(dev_from), devFPath(dev_to));} - - /*! \brief Remove from connection channel from "name_from" to "name_to" - * \details "name_from" and "name_to" can be full pathes of devices or filter names. - * Returns \b false if there if no such device or filter, else remove channel and returns \b true */ - bool removeChannel(const PIString & name_from, const PIString & name_to); - - //! Remove from connection channel from "name_from" to "dev_to" - bool removeChannel(const PIString & name_from, const PIIODevice * dev_to) {return removeChannel(name_from, devFPath(dev_to));} - - //! Remove from connection channel from "dev_from" to "name_to" - bool removeChannel(const PIIODevice * dev_from, const PIString & name_to) {return removeChannel(devFPath(dev_from), name_to);} - - //! Remove from connection channel from "dev_from" to "dev_to" - bool removeChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) {return removeChannel(devFPath(dev_from), devFPath(dev_to));} - - /*! \brief Remove from connection all channels from "name_from" - * \details "name_from" can be full path of device or filter name. - * Returns \b false if there if no such device or filter, else remove channels and returns \b true */ - bool removeChannel(const PIString & name_from); - - //! Remove from connection all channels from "dev_from" - bool removeChannel(const PIIODevice * dev_from) {return removeChannel(devFPath(dev_from));} - - //! Remove from connection all channels - void removeAllChannels(); - - //! Returns all channels of this connection as full pathes or filter names pair array (from, to) - PIVector > channels() const; - - - //! Start read thread of device with full path "full_path" - void startThreadedRead(const PIString & full_path); - - //! Start read thread of device "dev" - void startThreadedRead(const PIIODevice * dev) {startThreadedRead(devFPath(dev));} - - //! Start read threads of all Device pool device - void startAllThreadedReads(); - - //! Stop read thread of device with full path "full_path" - void stopThreadedRead(const PIString & full_path); - - //! Stop read thread of device "dev" - void stopThreadedRead(const PIIODevice * dev) {stopThreadedRead(devFPath(dev));} - - //! Stop read threads of all Device pool device - void stopAllThreadedReads(); - - - //! Returns if there is no devices in this connection - bool isEmpty() const {return device_modes.isEmpty();} - - - //! Write data "data" to device with full path "full_path" and returns result of \a write() function of device - int write(const PIString & full_path, const PIByteArray & data); - - - //! Returns all connections in application - static PIVector allConnections(); - - //! Returns all devices in Device pool - static PIVector allDevices(); - - class DevicePool: public PIObject { - PIOBJECT(DevicePool) - friend class PIConnection; - public: - DevicePool(): PIObject("PIConnection::DevicePool") {} - - PIIODevice * addDevice(PIConnection * parent, const PIString & fp, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = true); - bool removeDevice(PIConnection * parent, const PIString & fp); - void unboundConnection(PIConnection * parent); - PIIODevice * device(const PIString & fp) const; - PIVector boundedConnections() const; - PIVector boundedDevices() const; - PIVector boundedDevices(const PIConnection * parent) const; - - protected: - struct DeviceData { - DeviceData(): dev(0), rthread(0), started(false) {} - ~DeviceData(); - PIIODevice * dev; - PIThread * rthread; - bool started; - PIVector listeners; - }; - - static void threadReadDP(void * ddp); - void deviceReaded(DeviceData * dd, const PIByteArray & data); - - typedef PIMap::value_type DDPair; - PIMap devices; - }; - - EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data) - EVENT2(packetReceivedEvent, const PIString &, from, const PIByteArray &, data) - -//! \events -//! \{ - - //! \fn void dataReceivedEvent(const PIString & from, const PIByteArray & data) - //! \brief Raise on data received from device with full path "from" - - //! \fn void packetReceivedEvent(const PIString & from, const PIByteArray & data) - //! \brief Raise on packet received from filter with name "from" - -//! \} - -protected: - - //! Executes on data received from device with full path "from" - virtual void dataReceived(const PIString & from, const PIByteArray & data) {} - - //! Executes on packet received from filter with name "from" - virtual void packetReceived(const PIString & from, const PIByteArray & data) {} - - //! Validate header "rec" with source header "src" and size "size", executes from filter "filter_name" - virtual bool filterValidateHeader(const PIString & filter_name, uchar * src, uchar * rec, int size); - - //! Validate footer "rec" with source footer "src" and size "size", executes from filter "filter_name" - virtual bool filterValidateFooter(const PIString & filter_name, uchar * src, uchar * rec, int size); - - //! Validate payload "rec" with size "size", executes from filter "filter_name" - virtual bool filterValidatePayload(const PIString & filter_name, uchar * rec, int size); - -private: - static bool filterValidateHeaderS(void * c, uchar * src, uchar * rec, int size); - static bool filterValidateFooterS(void * c, uchar * src, uchar * rec, int size); - static bool filterValidatePayloadS(void * c, uchar * rec, int size); - void rawReceived(PIIODevice * dev, const PIString & from, const PIByteArray & data); - void unboundExtractor(PIPacketExtractor * pe); - EVENT_HANDLER2(void, packetExtractorReceived, uchar * , data, int, size); - - PIString devPath(const PIIODevice * d) const; - PIString devFPath(const PIIODevice * d) const; - - struct Extractor { - Extractor(): extractor(0) {} - ~Extractor(); - PIPacketExtractor * extractor; - PIVector devices; - }; - - typedef PIMap::value_type PEPair; - typedef PIMap >::value_type BEPair; - typedef PIMap >::value_type CPair; - PIMap extractors; - PIMap device_modes; - PIMap > bounded_extractors; - PIMap > channels_; - - static PIVector _connections; - -}; - - -extern PIConnection::DevicePool * __device_pool__; - -class __DevicePoolContainer__ { -public: - __DevicePoolContainer__(); - static bool inited_; -}; - -static __DevicePoolContainer__ __device_pool_container__; - - -#endif // PICONNECTION_H diff --git a/piconsole.cpp b/piconsole.cpp deleted file mode 100644 index b5526dae..00000000 --- a/piconsole.cpp +++ /dev/null @@ -1,1011 +0,0 @@ -/* - PIP - Platform Independent Primitives - Console output/input - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "piconsole.h" -#include "pipeer.h" - - -/** \class PIConsole - * \brief Console output class - * \details - * \section PIConsole_sec0 Synopsis - * This class provides output to console with automatic alignment and update. - * It supports tabs, keyboard listening, formats and colors. - * - * \section PIConsole_sec1 Layout - * %PIConsole works with variable pointers. You should add your variables with - * functions \a addVariable() which receives label name, pointer to variable - * and optional column and format. Columns count is dynamically increased if - * new column used. E.g. if you add variable to empty tab to column 3, columns - * count will be increased to 3, but two firsts columns will be empty. Each column - * filled from top to bottom, but you can add just string with function - * \a addString() or add empty line with function \a addEmptyLine(). Layout scheme: - * \image html piconsole_layout.png - * - * \section PIConsole_sec2 Keyboard usage - * %PIConsole should to be single in application. %PIConsole aggregate PIKbdListener - * which grab keyboard and automatic switch tabs by theirs bind keys. If there is no - * tab binded to pressed key external function "slot" will be called - * - **/ - - -extern PIMutex __PICout_mutex__; - - -PIConsole::PIConsole(bool startNow, KBFunc slot): PIThread() { - setPriority(piLow); - needLockRun(true); - ret_func = slot; - num_format = systime_format = 0; - vid = 0; - cur_tab = width = height = pwidth = pheight = max_y = 0; - def_align = Nothing; -#ifdef WINDOWS - ulcoord.X = 0; - hOut = GetStdHandle(STD_OUTPUT_HANDLE); - GetConsoleScreenBufferInfo(hOut, &sbi); - dattr = sbi.wAttributes; - width = sbi.srWindow.Right - sbi.srWindow.Left; - height = sbi.srWindow.Bottom - sbi.srWindow.Top; - ulcoord.Y = sbi.srWindow.Top; - GetConsoleMode(hOut, &smode); - GetConsoleCursorInfo(hOut, &curinfo); -#endif - tabs.reserve(16); - addTab("main"); - listener = new PIKbdListener(key_event, this); - peer = 0; - server_mode = false; - state = Disconnected; - peer_timer.addDelimiter(20); - CONNECT2(void, void * , int, &peer_timer, timeout, this, peerTimer); - if (startNow) start(); -} - - -PIConsole::~PIConsole() { - stopPeer(); - if (isRunning()) - stop(); - clearTabs(false); - delete listener; -#ifdef WINDOWS - SetConsoleMode(hOut, smode); - SetConsoleTextAttribute(hOut, dattr); -#endif -} - - -int PIConsole::addTab(const PIString & name, char bind_key) { - if (isRunning()) lock(); - tabs.push_back(Tab(name, bind_key)); - cur_tab = tabs.size() - 1; - if (isRunning()) unlock(); - return tabs.size(); -} - - -void PIConsole::removeTab(uint index) { - if (index >= tabs.size()) return; - if (isRunning()) lock(); - tabs.remove(index); - if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; - if (isRunning()) unlock(); -} - - -void PIConsole::removeTab(const PIString & name) { - uint index = tabs.size() + 1; - for (uint i = 0; i < tabs.size(); ++i) { - if (tabs[i].name == name) { - index = i; - break; - } - } - removeTab(index); -} - - -bool PIConsole::setTab(uint index) { - if (index >= tabs.size()) - return false; - if (!isRunning()) { - cur_tab = index; - return true; - } - lock(); - __PICout_mutex__.lock(); - cur_tab = index; - clearScreen(); - fillLabels(); - __PICout_mutex__.unlock(); - unlock(); - return true; -} - - -bool PIConsole::setTab(const PIString & name) { - uint index = tabs.size() + 1; - for (uint i = 0; i < tabs.size(); ++i) { - if (tabs[i].name == name) { - index = i; - break; - } - } - return setTab(index); -} - - -bool PIConsole::setTabBindKey(uint index, char bind_key) { - if (index >= tabs.size()) - return false; - tabs[index].key = bind_key; - return true; -} - - -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) { - index = i; - break; - } - } - return setTabBindKey(index, bind_key); -} - - -void PIConsole::key_event(char key, void * t) { - PIConsole * p = (PIConsole * )t; - int ct = p->cur_tab; - if (key == char(PIKbdListener::LeftArrow)) { - do { - ct--; - if (ct < 0) return; - } while (p->tabs[ct].key == 0); - p->setTab(ct); - return; - } - if (key == char(PIKbdListener::RightArrow)) { - do { - ct++; - if (ct >= p->tabs.size_s()) return; - } while (p->tabs[ct].key == 0); - p->setTab(ct); - return; - } - for (uint i = 0; i < p->tabsCount(); ++i) { - if (p->tabs[i].key == key) { - p->setTab(i); - return; - } - } - if (p->ret_func != 0) p->ret_func(key, t); - p->keyPressed(key, t); -} - - -void PIConsole::stop(bool clear) { - PIThread::stop(true); - if (clear) clearScreen(); - moveTo(0, max_y + 4); - showCursor(); - couts(fstr(Normal)); -#ifdef WINDOWS - SetConsoleMode(hOut, smode); - SetConsoleTextAttribute(hOut, dattr); -#endif - fflush(0); -} - - -PIString PIConsole::fstr(PIFlags f) { - num_format = systime_format = 0; - if (f[PIConsole::Dec]) num_format = 0; - if (f[PIConsole::Hex]) num_format = 1; - if (f[PIConsole::Oct]) num_format = 2; - if (f[PIConsole::Bin]) num_format = 4; - if (f[PIConsole::Scientific]) num_format = 3; - if (f[PIConsole::SystemTimeSplit]) systime_format = 0; - if (f[PIConsole::SystemTimeSeconds]) systime_format = 1; - -#ifdef WINDOWS - WORD attr = 0; - - if (f[PIConsole::Inverse]) { - if (f[PIConsole::Red]) attr |= BACKGROUND_RED; - if (f[PIConsole::Green]) attr |= BACKGROUND_GREEN; - if (f[PIConsole::Blue]) attr |= BACKGROUND_BLUE; - if (f[PIConsole::Yellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN); - 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); - 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); - if ((attr & BACKGROUND_RED) + (attr & BACKGROUND_GREEN) + (attr & BACKGROUND_BLUE) == 0) - attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - } else { - if (f[PIConsole::Red]) attr |= FOREGROUND_RED; - if (f[PIConsole::Green]) attr |= FOREGROUND_GREEN; - if (f[PIConsole::Blue]) attr |= FOREGROUND_BLUE; - if (f[PIConsole::Yellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN); - 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 ((attr & FOREGROUND_RED) + (attr & FOREGROUND_GREEN) + (attr & FOREGROUND_BLUE) == 0) - attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - } - if (f[PIConsole::Bold]) attr |= FOREGROUND_INTENSITY; - if (f[PIConsole::Underline]) attr |= COMMON_LVB_UNDERSCORE; - - SetConsoleTextAttribute(hOut, attr); - return PIString(); -#else - PIString ts("\e[0"); - - if (f[PIConsole::Bold]) ts += ";1"; - if (f[PIConsole::Faint]) ts += ";2"; - if (f[PIConsole::Italic]) ts += ";3"; - if (f[PIConsole::Underline]) ts += ";4"; - if (f[PIConsole::Blink]) ts += ";5"; - if (f[PIConsole::Inverse]) ts += ";7"; - - if (f[PIConsole::Black]) ts += ";30"; - if (f[PIConsole::Red]) ts += ";31"; - if (f[PIConsole::Green]) ts += ";32"; - if (f[PIConsole::Yellow]) ts += ";33"; - if (f[PIConsole::Blue]) ts += ";34"; - 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 -} - - -inline int PIConsole::couts(const PIString & v) {return printf("%s", v.data());} -inline int PIConsole::couts(const char * v) {return printf("%s", v);} -inline int PIConsole::couts(const bool v) {return (v ? printf("true") : printf("false"));} -inline int PIConsole::couts(const char v) {return printf("%c", v);} -inline int PIConsole::couts(const short v) { - switch (num_format) {case (1): return printf("0x%.4hX", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 2)); break; default: return printf("%hd", v); break;} -} -inline int PIConsole::couts(const int v) { - switch (num_format) {case (1): return printf("0x%.8X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 4)); break; default: return printf("%d", v); break;} -} -inline int PIConsole::couts(const long v) { - switch (num_format) {case (1): return printf("0x%.16lX", v); break; case (2): return printf("%lo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%ld", v); break;} -} -inline int PIConsole::couts(const llong v) { - switch (num_format) {case (1): return printf("0x%.16llX", v); break; case (2): return printf("%llo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%lld", v); break;} -} -inline int PIConsole::couts(const uchar v) { - switch (num_format) {case (1): return printf("0x%.2X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 1)); break; default: return printf("%u", v); break;} -} -inline int PIConsole::couts(const ushort v) { - switch (num_format) {case (1): return printf("0x%.4hX", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 2)); break; default: return printf("%hu", v); break;} -} -inline int PIConsole::couts(const uint v) { - switch (num_format) {case (1): return printf("0x%.8X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 4)); break; default: return printf("%u", v); break;} -} -inline int PIConsole::couts(const ulong v) { - switch (num_format) {case (1): return printf("0x%.16lX", v); break; case (2): return printf("%lo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%lu", v); break;} -} -inline int PIConsole::couts(const ullong v) { - switch (num_format) {case (1): return printf("0x%.16llX", v); break; case (2): return printf("%llo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%llu", v); break;} -} -inline int PIConsole::couts(const float v) { - switch (num_format) {case (3): return printf("%e", v); break; default: return printf("%.5g", v); break;} -} -inline int PIConsole::couts(const double v) { - switch (num_format) {case (3): return printf("%le", v); break; default: return printf("%.5lg", v); break;} -} -inline int PIConsole::couts(const PISystemTime & v) { - switch (systime_format) {case (1): return printf("%.6lg", v.toSeconds()); break; - default: return couts(v.seconds) + printf(" s, ") + couts(v.nanoseconds) + printf(" ns"); break;} -} - - -void PIConsole::begin() { -#ifdef WINDOWS - SetConsoleMode(hOut, ENABLE_WRAP_AT_EOL_OUTPUT); -#endif - max_y = 0; - __PICout_mutex__.lock(); - clearScreen(); - hideCursor(); - fillLabels(); - __PICout_mutex__.unlock(); -} - - -void PIConsole::run() { - uint cx, clen = 0; - int j; -#ifdef WINDOWS - GetConsoleScreenBufferInfo(hOut, &sbi); - width = sbi.srWindow.Right - sbi.srWindow.Left; - height = sbi.srWindow.Bottom - sbi.srWindow.Top; -#else - winsize ws; - ioctl(0, TIOCGWINSZ, &ws); - width = ws.ws_col; - height = ws.ws_row; -#endif - //fflush(0); return; - __PICout_mutex__.lock(); - if (pwidth != width || pheight != height) { - clearScreen(); - fillLabels(); - } - pwidth = width; - pheight = height; - col_cnt = columns().size(); - col_wid = (col_cnt > 0) ? width / col_cnt : width; - for (uint i = 0; i < col_cnt; ++i) { - PIVector & cvars(tabs[cur_tab].columns[i].variables); - cx = col_wid * i; - toUpperLeft(); - if (max_y < cvars.size()) max_y = cvars.size(); - j = 0; - piForeachC (Variable & tv, cvars) { - if (j > height - 3) continue; - j++; - moveRight(cx); - if (tv.type == 15) { - newLine(); - continue; - } - moveRight(tv.offset); - const void * ptr = 0; - if (tv.remote) { - if (tv.type == 0) { - rstr.clear(); - rba = tv.rdata; - rba >> rstr; - rstr.trim(); - ptr = &rstr; - } else - ptr = tv.rdata.data(); - } else - ptr = tv.ptr; - switch (tv.type) { - case 0: clen = printValue(ptr != 0 ? *(const PIString*)ptr : PIString(), tv.format); break; - case 1: clen = printValue(ptr != 0 ? *(const bool*)ptr : false, tv.format); break; - case 2: clen = printValue(ptr != 0 ? *(const int*)ptr : 0, tv.format); break; - case 3: clen = printValue(ptr != 0 ? *(const long*)ptr : 0l, tv.format); break; - case 4: clen = printValue(ptr != 0 ? *(const char*)ptr : char(0), tv.format); break; - case 5: clen = printValue(ptr != 0 ? *(const float*)ptr : 0.f, tv.format); break; - case 6: clen = printValue(ptr != 0 ? *(const double*)ptr : 0., tv.format); break; - case 7: clen = printValue(ptr != 0 ? *(const short*)ptr : short(0), tv.format); break; - case 8: clen = printValue(ptr != 0 ? *(const uint*)ptr : 0u, tv.format); break; - case 9: clen = printValue(ptr != 0 ? *(const ulong*)ptr : 0ul, tv.format); break; - case 10: clen = printValue(ptr != 0 ? *(const ushort*)ptr : ushort(0), tv.format); break; - case 11: clen = printValue(ptr != 0 ? *(const uchar*)ptr : uchar(0), tv.format); break; - case 12: clen = printValue(ptr != 0 ? *(const llong*)ptr : 0l, tv.format); break; - case 13: clen = printValue(ptr != 0 ? *(const ullong*)ptr: 0ull, tv.format); break; - case 20: clen = printValue(ptr != 0 ? *(const PISystemTime*)ptr: PISystemTime(), tv.format); break; - case 14: clen = printValue(bitsValue(ptr, tv.bitFrom, tv.bitCount), tv.format); break; - } - if (clen + tv.offset < (uint)col_wid) { - PIString ts = PIString( -#if defined(QNX) || defined(FREE_BSD) - col_wid - clen - tv.offset - 1, ' '); -#else - col_wid - clen - tv.offset, ' '); -#endif - printf("%s", ts.data()); - } - newLine(); - } - } -#ifdef WINDOWS - moveTo(0, max_y + 1); -#else - moveTo(0, max_y + 2); -#endif - fflush(0); - __PICout_mutex__.unlock(); -} - - -void PIConsole::fillLabels() { - if (!isRunning()) return; - uint cx, cy, mx = 0, dx; -#ifdef WINDOWS - GetConsoleScreenBufferInfo(hOut, &sbi); - width = sbi.srWindow.Right - sbi.srWindow.Left; - height = sbi.srWindow.Bottom - sbi.srWindow.Top; -#else - winsize ws; - ioctl(0, TIOCGWINSZ, &ws); - width = ws.ws_col; - height = ws.ws_row; -#endif - max_y = 0; - col_cnt = columns().size(); - col_wid = (col_cnt > 0) ? width / col_cnt : width; - for (uint i = 0; i < col_cnt; ++i) { - Column & ccol(tabs[cur_tab].columns[i]); - PIVector & cvars(ccol.variables); - if (ccol.alignment != Nothing) { - mx = 0; - piForeachC (Variable & j, cvars) - if (!j.isEmpty()) - if (mx < j.name.size()) - mx = j.name.size(); - mx += 2; - } - cx = col_wid * i; - cy = 1; - toUpperLeft(); - for (uint j = 0; j < cvars.size(); ++j) { - if (int(j) > height - 3) continue; - if (max_y < j) max_y = j; - moveRight(cx); - Variable & tv(cvars[j]); - cvars[j].nx = cx; - cvars[j].ny = cy; - if (tv.name.isEmpty()) { - cvars[j].offset = 0; - clearLine(); - newLine(); - cy++; - continue; - } - clearLine(); - //piCout << tv.name << tv.type << tv.ptr; - if (tv.type == 15) { - cvars[j].offset = cvars[j].name.length(); - cvars[j].nx += cvars[j].offset; - printLine(tv.name, cx, tv.format); - newLine(); - cy++; - continue; - } - if (!tv.isEmpty()) { - switch (ccol.alignment) { - case Nothing: - cvars[j].offset = (tv.name + ": ").length(); - cvars[j].nx += cvars[j].offset; - printValue(tv.name + ": ", tv.format); - break; - case Left: - cvars[j].offset = mx; - cvars[j].nx += cvars[j].offset; - printValue(tv.name + ": ", tv.format); - break; - case Right: - cvars[j].offset = mx; - cvars[j].nx += cvars[j].offset; - dx = mx - (tv.name + ": ").length(); - moveRight(dx); - printValue(tv.name + ": ", tv.format); - moveLeft(dx); - break; - } - } - newLine(); - cy++; - } - } -#ifdef WINDOWS - moveTo(0, max_y + 1); -#else - moveTo(0, max_y + 2); -#endif - if (!tabs[cur_tab].status.isEmpty()) { - printValue(tabs[cur_tab].status); - newLine(); - } - status(); - //fflush(0); -} - - -void PIConsole::status() { - Tab * ctab; - //clearLine(); - for (uint i = 0; i < tabsCount(); ++i) { - ctab = &tabs[i]; - if (ctab->key == 0) continue; - printValue(ctab->key, PIConsole::White | PIConsole::Bold); - if (i == cur_tab) - printValue(ctab->name + " ", PIConsole::BackYellow | PIConsole::Black); - else - printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse); - printValue(" "); - } - newLine(); -} - - -int PIConsole::bitsValue(const void * src, int offset, int count) const { - int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8; - 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 = reinterpret_cast(src)[stbyte]; - } - } - return ret; -} - - -const char * PIConsole::toBin(const void * d, int s) { - binstr.clear(); - uchar cc, b; - for (int i = 0; i < s; ++i) { - cc = ((const uchar *)d)[i]; - b = 1; - for (int j = 0; j < 8; ++j) { - binstr << (cc & b ? "1" : "0"); - b <<= 1; - } - if (i < s - 1) binstr << " "; - } - binstr.reverse(); - return binstr.data(); -} - - -#define ADD_VAR_BODY vid++; tv.id = vid; tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; tv.remote = false; checkColumn(col); - -void PIConsole::addString(const PIString & name, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 15; tv.size = 0; tv.ptr = 0; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const PIString * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 0; tv.size = 0; tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const bool * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 1; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const int * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 2; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const long * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 3; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const char * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 4; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const float * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 5; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const double * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 6; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const short * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 7; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const uint * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 8; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const ulong * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 9; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const ushort * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 10; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const uchar * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 11; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const llong * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 12; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const ullong * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 13; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, const PISystemTime * ptr, int col, PIFlags format) { - ADD_VAR_BODY tv.type = 20; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} -/** \brief Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - * \details This function add to column "column" next lines: - * * "protocol " - * * "Rec - receiverDeviceName": \a PIProtocol::receiverDeviceState - * * "Send - senderDeviceName": \a PIProtocol::senderDeviceState - * * "Received count": \a PIProtocol::receiveCount - * * "Invalid count": \a PIProtocol::wrongCount - * * "Missed count": \a PIProtocol::missedCount - * * "Sended count": \a PIProtocol::sendCount - * * "Immediate Frequency, Hz": \a PIProtocol::immediateFrequency - * * "Integral Frequency, Hz": \a PIProtocol::integralFrequency - * * "Receive speed": \a PIProtocol::receiveSpeed - * * "Send speed": \a PIProtocol::sendSpeed - * * "Receiver history size": \a PIProtocol::receiverHistorySize - * * "Sender history size": \a PIProtocol::senderHistorySize - * * "Disconnect Timeout, s": \a PIProtocol::disconnectTimeout - * * "Quality": \a PIProtocol::quality - * */ -void PIConsole::addVariable(const PIString & name, const PIProtocol * ptr, int col, PIFlags format) { - addString("protocol " + name, col, format | PIConsole::Bold); - addVariable("Rec - " + ptr->receiverDeviceName(), ptr->receiverDeviceState_ptr(), col, format); - addVariable("Send - " + ptr->senderDeviceName(), ptr->senderDeviceState_ptr(), col, format); - addVariable("Received count", ptr->receiveCount_ptr(), col, format); - addVariable("Invalid count", ptr->wrongCount_ptr(), col, format); - addVariable("Missed count", ptr->missedCount_ptr(), col, format); - addVariable("Sended count", ptr->sendCount_ptr(), col, format); - addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format); - addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format); - addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format); - addVariable("Send speed", ptr->sendSpeed_ptr(), col, format); - addVariable("Receiver history size", ptr->receiverHistorySize_ptr(), col, format); - addVariable("Sender history size", ptr->senderHistorySize_ptr(), col, format); - addVariable("Disconnect Timeout, s", ptr->disconnectTimeout_ptr(), col, format); - addVariable("Quality", ptr->quality_ptr(), col, format); -} -/** \brief Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - * \details This function add to column "column" next lines: - * * " diagnostics" - * * "Received count": \a PIDiagnostics::receiveCount - * * "Invalid count": \a PIDiagnostics::wrongCount - * * "Sended count": \a PIDiagnostics::sendCount - * * "Immediate Frequency, Hz": \a PIDiagnostics::immediateFrequency - * * "Integral Frequency, Hz": \a PIDiagnostics::integralFrequency - * * "Receive speed": \a PIDiagnostics::receiveSpeed - * * "Send speed": \a PIDiagnostics::sendSpeed - * * "Quality": \a PIDiagnostics::quality - * */ -void PIConsole::addVariable(const PIString & name, const PIDiagnostics * ptr, int col, PIFlags format) { - addString(name + " diagnostics", col, format | PIConsole::Bold); - addVariable("Received count", ptr->receiveCount_ptr(), col, format); - addVariable("Invalid count", ptr->wrongCount_ptr(), col, format); - addVariable("Sended count", ptr->sendCount_ptr(), col, format); - addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format); - addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format); - addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format); - addVariable("Send speed", ptr->sendSpeed_ptr(), col, format); - addVariable("Quality", ptr->quality_ptr(), col, format); -} -void PIConsole::addVariable(const PIString & name, const PISystemMonitor * ptr, int col, PIFlags format) { - addString("monitor " + name, col, format | PIConsole::Bold); - addVariable("state", &(ptr->statistic().state), col, format); - addVariable("threads", &(ptr->statistic().threads), col, format); - addVariable("priority", &(ptr->statistic().priority), col, format); - addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), col, format); - addVariable("memory shared", &(ptr->statistic().share_memsize_readable), col, format); - addVariable("cpu load", &(ptr->statistic().cpu_load_user), col, format); -} -void PIConsole::addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int col, PIFlags format) { - vid++; tv.id = vid; tv.size = sizeof(ullong); tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = format; - checkColumn(col); column(col).push_back(tv);} -void PIConsole::addEmptyLine(int col, uint count) { - tv.id = 0; tv.size = 0; tv.name = ""; tv.type = 0; tv.ptr = 0; tv.format = Normal; - for (uint i = 0; i < count; ++i) { - checkColumn(col); - column(col).push_back(tv); - } -} - - -PIString PIConsole::getString(int x, int y) { - bool run = isRunning(); - if (run) PIThread::stop(true); - listener->setActive(false); - msleep(50); -#ifdef WINDOWS - moveTo(x - 1, y - 1); -#else - moveTo(x, y); -#endif - showCursor(); - PIByteArray ba(4096); -#ifdef CC_VC - int ret = scanf_s(" %s", ba.data()); -#else - int ret = scanf(" %s", ba.data()); -#endif - listener->setActive(true); - if (run) start(); - if (ret >= 1) return PIString(ba); - else return PIString(); -} - - -PIString PIConsole::getString(const PIString & name) { - piForeachC (Column & i, tabs[cur_tab].columns) - piForeachC (Variable & j, i.variables) - if (j.name == name) - return getString(j.nx + 1, j.ny); - return PIString(); -} - - -#define PRINT_VAR_BODY couts(fstr(format)); int ret = couts(value); couts(fstr(PIConsole::Dec)); return ret; - -inline void PIConsole::printLine(const PIString & value, int dx, PIFlags format) { - int i = width - value.length() - dx; -#if defined(QNX) || defined(FREE_BSD) - --i; -#endif - PIString ts = fstr(format); - couts(ts); - if (i >= 0) ts = value + PIString(i, ' '); - else ts = value.left(value.size() + i); - couts(ts); - couts(fstr(Dec)); -} -inline int PIConsole::printValue(const PIString & value, PIFlags format) { - couts(fstr(format)); - int ret = couts(value); - fstr(PIConsole::Dec); - return ret; -} -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} -inline int PIConsole::printValue(const PISystemTime & value, PIFlags format) {PRINT_VAR_BODY} - - - -void PIConsole::startServer(const PIString & name) { - stopPeer(); - server_mode = true; - peer = new PIPeer("_rcs_:" + name); - CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived); - CONNECT1(void, const PIString & , peer, peerDisconnectedEvent, this, peerDisconnectedEvent); - peer_timer.start(50.); - serverSendInfo(); -} - - -void PIConsole::stopPeer() { - remote_clients.clear(); - peer_timer.stop(); - if (peer != 0) delete peer; - peer = 0; - state = Disconnected; -} - - -PIStringList PIConsole::clients() const { - PIStringList sl; - if (peer == 0) return sl; - piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) { - if (i.name.left(6) != "_rcc_:") continue; - sl << i.name.right(i.name.length() - 6); - } - return sl; -} - - -void PIConsole::listenServers() { - stopPeer(); - server_mode = false; - server_name.clear(); - srand(PISystemTime::current().nanoseconds); - peer = new PIPeer("_rcc_:" + PIDateTime::current().toString("hhmmssddMMyy_") + PIString::fromNumber(rand())); - CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived); - peer_timer.start(100.); -} - - -PIStringList PIConsole::availableServers() const { - PIStringList sl; - if (peer == 0) return sl; - piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) { - if (i.name.left(6) != "_rcs_:") continue; - sl << i.name.right(i.name.length() - 6); - } - return sl; -} - - -void PIConsole::connectToServer(const PIString & name) { - if (peer == 0) listenServers(); - server_name = name; -} - - -void PIConsole::disconnect() { - stopPeer(); -} - - -void PIConsole::serverSendInfo() { - if (peer == 0) return; - PIByteArray ba; - ba << int(0xAA); - peer->sendToAll(ba); -} - - -void PIConsole::serverSendData() { - if (peer == 0) return; - PIByteArray ba; - PIVector content; - piForeach (Tab & t, tabs) - piForeach (Column & c, t.columns) - piForeach (Variable & v, c.variables) - if (!v.isEmpty() && v.id > 0) { - VariableContent vc; - vc.id = v.id; - v.writeData(vc.rdata); - content << vc; - } - piForeach (RemoteClient & rc, remote_clients) { - ba.clear(); - switch (rc.state) { - case FetchingData: - ba << int(0xCC) << tabs; - //piCout << "server send const data" << rc.name << ba.size_s(); - break; - case Committing: - ba << int(0xDD); - break; - case Connected: - ba << int(0xEE) << content; - //piCout << "send data" << ba.size(); - break; - default: break; - } - if (!ba.isEmpty()) - peer->send(rc.name, ba); - } -} - - -PIConsole::RemoteClient & PIConsole::remoteClient(const PIString & fname) { - piForeach (RemoteClient & i, remote_clients) - if (i.name == fname) - return i; - remote_clients << RemoteClient(fname); - return remote_clients.back(); -} - - -void PIConsole::peerReceived(const PIString & from, const PIByteArray & data) { - int type; - PIByteArray ba(data); - ba >> type; - //piCout << "rec packet from" << from << "type" << PICoutManipulators::Hex << type; - if (server_mode) { - if (from.left(5) != "_rcc_") return; - //PIString rcn = from.right(from.length() - 6); - RemoteClient & rc(remoteClient(from)); - switch (type) { - case 0xBB: // fetch const data request - //piCout << "fetch data request from" << from << rc.state; - if (rc.state != Connected) - rc.state = FetchingData; - break; - case 0xCC: // const data commit - //piCout << "commit from" << from; - if (rc.state != Connected) - rc.state = Connected; - break; - default: break; - } - } else { - PIVector content; - PIMap vids; - if (from.left(5) != "_rcs_") return; - PIString rcn = from.right(from.length() - 6); - switch (type) { - case 0xAA: // new server - //piCout << "new server" << rcn; - break; - case 0xCC: // const data - //piCout << "received const data"; - state = Committing; - ba >> tabs; - cur_tab = tabs.isEmpty() ? -1 : 0; - piForeach (Tab & t, tabs) - piForeach (Column & c, t.columns) - piForeach (Variable & v, c.variables) - v.remote = true; - break; - case 0xDD: // const data commit - //piCout << "received commit"; - state = Connected; - break; - case 0xEE: // dynamic data - //piCout << "received data" << ba.size_s(); - piForeach (Tab & t, tabs) - piForeach (Column & c, t.columns) - piForeach (Variable & v, c.variables) - if (!v.isEmpty() && v.id > 0) - vids[v.id] = &v; - ba >> content; - piForeach (VariableContent & vc, content) { - if (vc.id <= 0) continue; - Variable * v = vids.at(vc.id); - if (v == 0) continue; - //piCout << "read" << v->name << vc.rdata.size_s(); - v->rdata = vc.rdata; - } - break; - default: break; - } - } -} - - -void PIConsole::peerTimer(void * data, int delim) { - if (peer == 0) return; - //piCout << "timer" << delim; - if (server_mode) { - if (delim == 20) - serverSendInfo(); - else - serverSendData(); - } else { - if (delim != 1 || server_name.isEmpty()) return; - const PIPeer::PeerInfo * p = peer->getPeerByName("_rcs_:" + server_name); - if (p == 0) return; - PIByteArray ba; - switch (state) { - case Disconnected: - peer_timer.reset(); - ba << int(0xBB); - //piCout << "send to" << server_name << "fetch request disc"; - peer->send(p, ba); - state = FetchingData; - break; - case FetchingData: - if (peer_timer.elapsed_s() < 3.) - return; - peer_timer.reset(); - ba << int(0xBB); - //piCout << "send to" << server_name << "fetch request fd"; - peer->send(p, ba); - break; - case Committing: - peer_timer.reset(); - ba << int(0xCC); - //piCout << "send to" << server_name << "committing"; - state = Connected; - peer->send(p, ba); - break; - default: break; - }; - } -} - - -void PIConsole::peerDisconnectedEvent(const PIString & name) { - for (int i = 0; i < remote_clients.size_s(); ++i) - if (remote_clients[i].name == name) { - remote_clients.remove(i); - --i; - } -} diff --git a/piconsole.h b/piconsole.h deleted file mode 100644 index 429fdd53..00000000 --- a/piconsole.h +++ /dev/null @@ -1,489 +0,0 @@ -/*! \file piconsole.h - * \brief Console output class -*/ -/* - PIP - Platform Independent Primitives - Console output/input - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PICONSOLE_H -#define PICONSOLE_H - -#include "pikbdlistener.h" -#include "piprotocol.h" -#include "pidiagnostics.h" -#include "pisystemmonitor.h" -#ifndef WINDOWS -# include -# include -#else -# define COMMON_LVB_UNDERSCORE 0x8000 -#endif - -class PIPeer; - -class PIP_EXPORT PIConsole: public PIThread -{ - PIOBJECT(PIConsole) -public: - - //! Constructs %PIConsole with key handler "slot" and if "startNow" start it - PIConsole(bool startNow = true, KBFunc slot = 0); - - ~PIConsole(); - - - //! Variables output format - enum Format { - Normal /** Default console format */ = 0x01, - Bold /** Bold text */ = 0x02, - Faint = 0x04, - Italic = 0x08, - Underline /** Underlined text */ = 0x10, - Blink /** Blinked text */ = 0x20, - Inverse /** Swap text and background colors */ = 0x40, - Black /** Black text */ = 0x100, - Red /** Red text */ = 0x200, - Green /** Green text */ = 0x400, - Yellow /** Yellow text */ = 0x800, - Blue /** Blue text */ = 0x1000, - Magenta /** Magenta text */ = 0x2000, - Cyan /** Cyan text */ = 0x4000, - White /** White text */ = 0x8000, - BackBlack /** Black background */ = 0x10000, - BackRed /** Red background */ = 0x20000, - BackGreen /** Green background */ = 0x40000, - BackYellow /** Yellow background */ = 0x80000, - BackBlue /** Blue background */ = 0x100000, - BackMagenta /** Magenta background */ = 0x200000, - BackCyan /** Cyan background */ = 0x400000, - BackWhite /** White background */ = 0x800000, - Dec /** Decimal base for integers */ = 0x1000000, - Hex /** Hexadecimal base for integers */ = 0x2000000, - Oct /** Octal base for integers */ = 0x4000000, - Bin /** Binary base for integers */ = 0x8000000, - Scientific /** Scientific representation of floats */ = 0x10000000, - SystemTimeSplit /** PISystemTime split representation (* s, * ns) */ = 0x20000000, - SystemTimeSeconds /** PISystemTime seconds representation (*.* s) */ = 0x40000000 - }; - - //! Column labels alignment - enum Alignment { - Nothing /** No alignment */ , - Left /** Labels align left and variables align left */ , - Right /** Labels align right and variables align left */ - }; - - //! Add to current tab to column "column" string "name" with format "format" - void addString(const PIString & name, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const PIString * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const char * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const bool * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const short * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const int * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const long * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const llong * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const uchar * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const ushort * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const uint * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const ulong * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const ullong * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const float * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const double * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" - void addVariable(const PIString & name, const PISystemTime * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - void addVariable(const PIString & name, const PIProtocol * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, const PIDiagnostics * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, const PISystemMonitor * ptr, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" bits field with label "name", pointer "ptr" and format "format" - void addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitsCount, int column = 1, PIFlags format = PIConsole::Normal); - - //! Add to current tab to column "column" "count" empty lines - 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();} - - - //! Returns tabs count - uint tabsCount() const {return tabs.size();} - - //! Returns current tab name - PIString currentTab() const {return tabs[cur_tab].name;} - - //! Add new tab with name "name", bind key "bind_key" and returns this tab index - int addTab(const PIString & name, char bind_key = 0); - - //! Remove tab with index "index" - void removeTab(uint index); - - //! Remove tab with name "name" - void removeTab(const PIString & name); - - //! Set current tab to tab with index "index", returns if tab exists - bool setTab(uint index); - - //! Set current tab to tab with name "name", returns if tab exists - bool setTab(const PIString & name); - - //! Set tab with index "index" bind key to "bind_key", returns if tab exists - bool setTabBindKey(uint index, char bind_key); - - //! Set tab with name "name" bind key to "bind_key", returns if tab exists - bool setTabBindKey(const PIString & name, char bind_key); - - //! Remove all tabs and if "clearScreen" clear the screen - void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();} - - - //! Set custom status text of current tab to "str" - void addCustomStatus(const PIString & str) {tabs[cur_tab].status = str;} - - //! Clear custom status text of current tab - void clearCustomStatus() {tabs[cur_tab].status.clear();} - - //! Returns default alignment - Alignment defaultAlignment() const {return def_align;} - - //! Set default alignment to "align" - void setDefaultAlignment(Alignment align) {def_align = align;} - - //! Set column "col" alignment to "align" - void setColumnAlignment(int col, Alignment align) {if (col < 0 || col >= columns().size_s()) return; column(col).alignment = align;} - - //! Set all columns of all tabs alignment to "align" - void setColumnAlignmentToAll(Alignment align) {piForeach (Tab & i, tabs) piForeach (Column & j, i.columns) j.alignment = align; fillLabels();} - PIString fstr(PIFlags f); - - - //! Directly call function from \a PIKbdListener - void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);} - - //! Directly call function from \a PIKbdListener - void disableExitCapture() {listener->disableExitCapture();} - - //! Directly call function from \a PIKbdListener - bool exitCaptured() const {return listener->exitCaptured();} - - //! Directly call function from \a PIKbdListener - char exitKey() const {return listener->exitKey();} - - // Server functions - void startServer(const PIString & name); - void stopPeer(); - bool isServerStarted() const {return peer != 0;} - PIStringList clients() const; - - // Client functions - void listenServers(); - PIStringList availableServers() const; - PIString selectedServer() const {return server_name;} - void connectToServer(const PIString & name); - void disconnect(); - bool isConnected() const {return state == Connected;} - -#ifdef WINDOWS - void toUpperLeft() {SetConsoleCursorPosition(hOut, ulcoord);} - void moveRight(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(n));} - void moveLeft(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(-n));} - void moveTo(int x = 0, int y = 0) {ccoord.X = x; ccoord.Y = ulcoord.Y + y; SetConsoleCursorPosition(hOut, ccoord);} - void clearScreen() {toUpperLeft(); FillConsoleOutputAttribute(hOut, dattr, width * (height + 1), ulcoord, &written); - FillConsoleOutputCharacter(hOut, ' ', width * (height + 1), ulcoord, &written);} - void clearScreenLower() {getWinCurCoord(); FillConsoleOutputAttribute(hOut, dattr, width * height - width * ccoord.Y + ccoord.X, ccoord, &written); - FillConsoleOutputCharacter(hOut, ' ', width * height - width * ccoord.Y + ccoord.X, ccoord, &written);} - void clearLine() {getWinCurCoord(); FillConsoleOutputAttribute(hOut, dattr, width - ccoord.X, ccoord, &written); - FillConsoleOutputCharacter(hOut, ' ', width - ccoord.X, ccoord, &written);} - void newLine() {getWinCurCoord(); ccoord.X = 0; ccoord.Y++; SetConsoleCursorPosition(hOut, ccoord);} - void hideCursor() {curinfo.bVisible = false; SetConsoleCursorInfo(hOut, &curinfo);} - void showCursor() {curinfo.bVisible = true; SetConsoleCursorInfo(hOut, &curinfo);} -#else - void toUpperLeft() {printf("\e[H");} - void moveRight(int n = 1) {if (n > 0) printf("\e[%dC", n);} - void moveLeft(int n = 1) {if (n > 0) printf("\e[%dD", n);} - void moveTo(int x = 0, int y = 0) {printf("\e[%d;%dH", y, x);} - void clearScreen() {printf("\e[H\e[J");} - void clearScreenLower() {printf("\e[J");} - void clearLine() {printf("\e[K");} - void newLine() {printf("\eE");} - void hideCursor() {printf("\e[?25l");} - void showCursor() {printf("\e[?25h");} -#endif - - EVENT_HANDLER0(void, clearVariables) {clearVariables(true);} - EVENT_HANDLER1(void, clearVariables, bool, clearScreen) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} columns().clear();} - - EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT} - EVENT_HANDLER0(void, start) {start(false);} - EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();} - EVENT_HANDLER0(void, stop) {stop(false);} - EVENT_HANDLER1(void, stop, bool, clear); - - EVENT2(keyPressed, char, key, void * , data) - -//! \handlers -//! \{ - - //! \fn void waitForFinish() - //! \brief block until finished (exit key will be pressed) - - //! \fn void clearVariables(bool clearScreen = true) - //! \brief Remove all columns at current tab and if "clearScreen" clear the screen - - //! \fn void start(bool wait = false) - //! \brief Start console output and if "wait" block until finished (exit key will be pressed) - - //! \fn void stop(bool clear = false) - //! \brief Stop console output and if "clear" clear the screen - -//! \} -//! \events -//! \{ - - //! \fn void keyPressed(char key, void * data) - //! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object - -//! \} - -private: -#ifdef WINDOWS - void getWinCurCoord() {GetConsoleScreenBufferInfo(hOut, &csbi); ccoord = csbi.dwCursorPosition;} - COORD & getWinCoord(int dx = 0, int dy = 0) {getWinCurCoord(); ccoord.X += dx; ccoord.Y += dy; return ccoord;} -#endif - - void begin(); - void run(); - void fillLabels(); - void status(); - void checkColumn(uint col) {while (columns().size() < col) columns().push_back(Column(def_align));} - int bitsValue(const void * src, int offset, int count) const; - const char * toBin(const void * d, int s); - 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); - inline int printValue(const PISystemTime & value, PIFlags format = PIConsole::Normal); - static void key_event(char key, void * t); - - struct Variable { - Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = Normal; remote = false; ptr = 0; id = 1;} - bool isEmpty() const {return (remote ? false : ptr == 0);} - const void * data() {return (remote ? rdata.data() : ptr);} - void writeData(PIByteArray & ba) { - if (remote) ba << rdata; - else { - if (type == 0) ba << (*(PIString * )ptr); - else ba << PIByteArray::RawData(ptr, size); - } - } - PIString name; - PIFlags format; - int nx; - int ny; - int type; - int offset; - int bitFrom; - int bitCount; - int size; - int id; - bool remote; - const void * ptr; - PIByteArray rdata; - void operator =(const Variable & src) {remote = src.remote; name = src.name; format = src.format; type = src.type; offset = src.offset; size = src.size; - bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny; rdata = src.rdata; id = src.id;} - }; - - struct VariableContent { - int id; - PIByteArray rdata; - }; - - struct Column { - Column(Alignment align = PIConsole::Right) {variables.reserve(16); alignment = align;} - PIVector variables; - Alignment alignment; - uint size() const {return variables.size();} - Variable & operator [](int index) {return variables[index];} - const Variable & operator [](int index) const {return variables[index];} - void push_back(const Variable & v) {variables.push_back(v);} - void operator =(const Column & src) {variables = src.variables; alignment = src.alignment;} - }; - - struct Tab { - Tab(PIString n = "", char k = 0) {columns.reserve(16); name = n; key = k;} - PIVector columns; - PIString name; - PIString status; - char key; - }; - - enum ConnectedState {Disconnected, FetchingData, Committing, Connected}; - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::VariableContent & v); - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Variable & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Variable & v); - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Column & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v); - - friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Tab & v); - friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v); - - PIVector & columns() {return tabs[cur_tab].columns;} - Column & column(int index) {return tabs[cur_tab].columns[index - 1];} - inline int couts(const PIString & v); - inline int couts(const char * v); - inline int couts(const bool v); - inline int couts(const char v); - inline int couts(const short v); - inline int couts(const int v); - inline int couts(const long v); - inline int couts(const llong v); - inline int couts(const uchar v); - inline int couts(const ushort v); - inline int couts(const uint v); - inline int couts(const ulong v); - inline int couts(const ullong v); - inline int couts(const float v); - inline int couts(const double v); - inline int couts(const PISystemTime & v); - - struct RemoteClient; - - void serverSendInfo(); - void serverSendData(); - RemoteClient & remoteClient(const PIString & fname); - EVENT_HANDLER2(void, peerReceived, const PIString &, from, const PIByteArray &, data); - EVENT_HANDLER2(void, peerTimer, void * , data, int, delim); - EVENT_HANDLER1(void, peerDisconnectedEvent, const PIString &, name); - -#ifdef WINDOWS - void * hOut; - CONSOLE_SCREEN_BUFFER_INFO sbi, csbi; - CONSOLE_CURSOR_INFO curinfo; - COORD ccoord, ulcoord; - WORD dattr; - DWORD smode, written; -#else - struct termios sterm, vterm; -#endif - PIVector tabs; - PIString binstr, rstr; - PIByteArray rba; - Variable tv; - PIKbdListener * listener; - Alignment def_align; - KBFunc ret_func; - int width, height, pwidth, pheight, ret, col_wid, num_format, systime_format; - uint max_y; - int vid; - uint cur_tab, col_cnt; - - PIPeer * peer; - PITimer peer_timer; - PIString server_name; - bool server_mode; - ConnectedState state; - - /*struct RemoteData { - RemoteData() {msg_count = msg_rec = msg_send = 0;} - void clear() {msg_count = msg_rec = msg_send = 0; data.clear();} - bool isEmpty() const {return msg_count == 0;} - bool isReadyRec() const {return msg_count == msg_rec;} - bool isReadySend() const {return msg_count == msg_send;} - void setData(const PIByteArray & ba) {data = ba; msg_rec = msg_send = 0; msg_count = (data.size_s() - 1) / 4096 + 1;} - PIByteArray data; - int msg_count; - int msg_rec; - int msg_send; - };*/ - - struct RemoteClient { - RemoteClient(const PIString & n = "") {name = n; state = Disconnected;} - PIString name; - ConnectedState state; - }; - - PIVector remote_clients; - -}; - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v) {ba << v.id << v.rdata; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::VariableContent & v) {ba >> v.id; ba >> v.rdata; return ba;} - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Variable & v) {ba << v.name << v.id << (int)v.format << v.type << v.size << v.bitFrom << v.bitCount; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Variable & v) {ba >> v.name >> v.id >> (int & )v.format >> v.type >> v.size >> v.bitFrom >> v.bitCount; return ba;} - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Column & v) {ba << (int)v.alignment << v.variables; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v) {ba >> (int & )v.alignment >> v.variables; return ba;} - -inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Tab & v) {ba << v.name << v.status << (uchar)v.key << v.columns; return ba;} -inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v) {ba >> v.name >> v.status >> (uchar&)v.key >> v.columns; return ba;} - -#endif // PICONSOLE_H diff --git a/picontainers.cpp b/picontainers.cpp deleted file mode 100644 index bf438569..00000000 --- a/picontainers.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - PIP - Platform Independent Primitives - Generic containers - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -// * This class based on std::vector, expanding his functionality - -#include "pivector.h" - -/** \class PIVector - * \brief Dynamic array of any type - * \details This class used to store dynamic array of any - * type of data. In memory data stored linear. You can insert - * item in any place of remove some items from any place. - * For quick add elements this is stream operator <<. - - * \fn PIVector::PIVector(); - * Contructs an empty vector - - * \fn PIVector::PIVector(ullong size, const Type & value = Type()); - * \brief Contructs vector with size "size" filled elements "value" - * \details Example: \snippet picontainers.cpp PIVector::PIVector - - * \fn const Type & PIVector::at(ullong index) const; - * \brief Read-only access to element by index "index" - * \details Example: \snippet picontainers.cpp PIVector::at_c - * \sa \a operator[] - - * \fn Type & PIVector::at(ullong index); - * \brief Full access to element by index "index" - * \details Example: \snippet picontainers.cpp PIVector::at - * \sa \a operator[] - - * \fn const Type * PIVector::data(ullong index = 0) const; - * \brief Read-only pointer to element by index "index" - * \details Example: \snippet picontainers.cpp PIVector::data_c - - * \fn Type * PIVector::data(ullong index = 0); - * \brief Pointer to element by index "index" - * \details Example: \snippet picontainers.cpp PIVector::data - - * \fn ullong PIVector::size() const; - * \brief Elements count - - * \fn int PIVector::size_s() const; - * \brief Elements count - - * \fn bool PIVector::isEmpty() const; - * \brief Return \c "true" if vector is empty, i.e. size = 0 - - * \fn bool PIVector::has(const Type & t) const; - - * \fn bool PIVector::contains(const Type & v) const; - * \brief Return \c "true" if vector has at least one element equal "t" - - * \fn int PIVector::etries(const Type & t) const; - * \brief Return how many times element "t" appears in vector - - * \fn static int PIVector::compare_func(const Type * t0, const Type * t1); - * \brief Standard compare function for type "Type". Return 0 if t0 = t1, -1 if t0 < t1 and 1 if t0 > t1. - - * \fn void PIVector::resize(ullong size, const Type & new_type = Type()); - * \brief Resize vector to size "size" - * \details Elements removed from end of vector if new size < old size, or added new elements = "new_type" if new size > old size.\n - * Example: \snippet picontainers.cpp PIVector::resize - * \sa \a size(), \a clear() - - * \fn PIVector & PIVector::enlarge(ullong size); - * \brief Increase vector size with "size" elements - - * \fn void PIVector::clear(); - * \brief Clear vector. Equivalent to call "resize(0)" - - * \fn PIVector & PIVector::sort(CompareFunc compare = compare_func); - * \brief Sort vector using quick sort algorithm and standard compare function - * \details Example: \snippet picontainers.cpp PIVector::sort_0 - * With custom compare function: \snippet picontainers.cpp PIVector::sort_1 - - * \fn PIVector & PIVector::fill(const Type & t); - * \brief Fill vector with elements "t" leave size is unchanged and return reference to vector - * \details Example: \snippet picontainers.cpp PIVector::fill - - * \fn Type & PIVector::back(); - * \brief Last element of the vector - - * \fn const Type & PIVector::back() const; - * \brief Last element of the vector - - * \fn Type & PIVector::front(); - * \brief First element of the vector - - * \fn const Type & PIVector::front() const; - * \brief First element of the vector - - * \fn PIVector & PIVector::push_back(const Type & t); - * \brief Add new element "t" at the end of vector and return reference to vector - - * \fn PIVector & PIVector::push_front(const Type & t); - * \brief Add new element "t" at the beginning of vector and return reference to vector - - * \fn PIVector & PIVector::pop_back(); - * \brief Remove one element from the end of vector and return reference to vector - - * \fn PIVector & PIVector::pop_front(); - * \brief Remove one element from the beginning of vector and return reference to vector - - * \fn Type PIVector::take_back(); - * \brief Remove one element from the end of vector and return it - - * \fn Type PIVector::take_front(); - * \brief Remove one element from the beginning of vector and return it - - * \fn PIVector & PIVector::remove(uint index); - * \brief Remove one element by index "index" and return reference to vector - * \details Example: \snippet picontainers.cpp PIVector::remove_0 - * \sa \a removeOne(), \a removeAll() - - * \fn PIVector & PIVector::remove(uint index, uint count); - * \brief Remove "count" elements by first index "index" and return reference to vector - * \details Example: \snippet picontainers.cpp PIVector::remove_1 - * \sa \a removeOne(), \a removeAll() - - * \fn PIVector & PIVector::removeOne(const Type & v); - * \brief Remove no more than one element equal "v" and return reference to vector - * \details Example: \snippet picontainers.cpp PIVector::removeOne - * \sa \a remove(), \a removeAll() - - * \fn PIVector & PIVector::removeAll(const Type & v); - * \brief Remove all elements equal "v" and return reference to vector - * \details Example: \snippet picontainers.cpp PIVector::removeAll - * \sa \a remove(), \a removeOne() - - * \fn PIVector & PIVector::insert(uint pos, const Type & t); - * \brief Insert element "t" after index "pos" and return reference to vector - * \details Example: \snippet picontainers.cpp PIVector::insert_0 - - * \fn PIVector & PIVector::insert(uint pos, const PIVector & t); - * \brief Insert other vector "t" after index "pos" and return reference to vector - * \details Example: \snippet picontainers.cpp PIVector::insert_1 - - * \fn Type & PIVector::operator [](uint index); - * \brief Full access to element by index "index" - * \details Example: \snippet picontainers.cpp PIVector::() - * \sa \a at() - - * \fn const Type & PIVector::operator [](uint index) const; - * \brief Read-only access to element by index "index" - * \details Example: \snippet picontainers.cpp PIVector::()_c - * \sa \a at() - - * \fn PIVector & PIVector::operator <<(const Type & t); - * \brief Add new element "t" at the end of vector and return reference to vector - - * \fn PIVector & PIVector::operator <<(const PIVector & t); - * \brief Add vector "t" at the end of vector and return reference to vector - - * \fn bool PIVector::operator ==(const PIVector & t); - * \brief Compare with vector "t" - - * \fn bool PIVector::operator !=(const PIVector & t); - * \brief Compare with vector "t" - - * */ diff --git a/picontainers.h b/picontainers.h deleted file mode 100644 index 2ecb6e8c..00000000 --- a/picontainers.h +++ /dev/null @@ -1,324 +0,0 @@ -/*! \file picontainers.h - * \brief Generic containers - * - * This file declare all containers and useful macros - * to use them -*/ -/* - PIP - Platform Independent Primitives - Generic containers - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PICONTAINERS_H -#define PICONTAINERS_H - -#include "piincludes.h" - -template -class PIP_EXPORT PIPair { -public: - PIPair() {first = Type0(); second = Type1();} - 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 -inline bool operator ==(const PIPair & value0, const PIPair & value1) {return (value0.first == value1.first) && (value0.second == value1.second);} -template -inline bool operator !=(const PIPair & value0, const PIPair & value1) {return (value0.first != value1.first) || (value0.second != value1.second);} -template -inline std::ostream & operator <<(std::ostream & s, const PIPair & v) {s << "(" << v.first << ", " << v.second << ")"; return s;} -template -inline PICout operator <<(PICout s, const PIPair & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;} - -#include "pivector.h" -#include "pistack.h" -#include "piqueue.h" -#include "pideque.h" -#include "pimap.h" - -#ifdef DOXYGEN -/*! \def piForeach(i,c) - * \brief Macro for iterate any container - * \details Use this macros instead of standard "for" - * to get read/write access to each element of container. - * Pass direction is direct \n - * Example: \snippet picontainers.cpp foreach - */ -/*! \def piForeachC(i,c) - * \brief Macro for iterate any container only for read - * \details Use this macros instead of standard "for" - * to get read access to each element of container. - * Pass direction is direct \n - * Example: \snippet picontainers.cpp foreachC - */ -/*! \def piForeachR(i,c) - * \brief Macro for iterate any container with reverse direction - * \details Use this macros instead of standard "for" - * to get read/write access to each element of container. - * Pass direction is reverse \n - * Example: \snippet picontainers.cpp foreachR - */ -/*! \def piForeachCR(i,c) - * \brief Macro for iterate any container only for read with reverse direction - * \details Use this macros instead of standard "for" - * to get read access to each element of container. - * Pass direction is reverse \n - * Example: \snippet picontainers.cpp foreachCR - */ -#endif - -#ifdef CC_GCC - -template -class _PIForeach { -public: - _PIForeach(Type & t): _t(t) {_it = _t.begin(); _break = false;} - typename Type::value_type _var; - typename Type::iterator _it; - Type & _t; - bool _break; - inline bool isEnd() {return _it == _t.end();} - inline void operator ++() {_it++; _break = false;} -}; - -template -class _PIForeachR { -public: - _PIForeachR(Type & t): _t(t) {_rit = _t.rbegin(); _break = false;} - typename Type::value_type _var; - typename Type::reverse_iterator _rit; - Type & _t; - bool _break; - inline bool isEnd() {return _rit == _t.rend();} - inline void operator ++() {_rit++; _break = false;} -}; - -template -class _PIForeachC { -public: - _PIForeachC(const Type & t): _t(t) {_it = _t.begin(); _break = false;} - typename Type::value_type _var; - typename Type::const_iterator _it; - const Type & _t; - bool _break; - inline bool isEnd() {return _it == _t.end();} - inline void operator ++() {_it++; _break = false;} -}; - -template -class _PIForeachCR { -public: - _PIForeachCR(const Type & t): _t(t) {_rit = _t.rbegin(); _break = false;} - typename Type::value_type _var; - typename Type::const_reverse_iterator _rit; - const Type & _t; - bool _break; - inline bool isEnd() {return _rit == _t.rend();} - inline void operator ++() {_rit++; _break = false;} -}; - -#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(_PIForeachR _for(c); !_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(_PIForeachR _for(c); !_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(_PIForeachCR _for(c); !_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(_PIForeachCR _for(c); !_for.isEnd(); ++_for) \ - for(const typeof(_for._var) & i(*_for._rit); !_for._break; _for._break = true) - -#define piForeachRA piForeachAR -#define piForeachAC piForeachCA -#define piForeachCRA piForeachCAR -#define piForeachARC piForeachCAR -#define piForeachACR piForeachCAR -#define piForeachRCA piForeachCAR -#define piForeachRAC piForeachCAR - -#else - -struct _PIForeachBase {mutable bool _break;}; - -template -class _PIForeach: public _PIForeachBase { -public: - _PIForeach(Type & t, bool i = false): _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin(); _break = false;} - mutable typename Type::value_type _var; - mutable typename Type::iterator _it; - mutable typename Type::reverse_iterator _rit; - Type & _t; - bool _inv; - bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();} - void operator ++() {if (_inv) _rit++; else _it++; _break = false;} -}; - -template -class _PIForeachC: public _PIForeachBase { -public: - _PIForeachC(const Type & t, bool i = false): _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin(); _break = false;} - mutable typename Type::value_type _var; - mutable typename Type::const_iterator _it; - mutable typename Type::const_reverse_iterator _rit; - const Type & _t; - bool _inv; - bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();} - void operator ++() {if (_inv) _rit++; else _it++; _break = false;} -}; - -template inline _PIForeach _PIForeachNew(T & t, bool i = false) {return _PIForeach(t, i);} -template inline _PIForeach * _PIForeachCast(_PIForeachBase & c, T & ) {return static_cast<_PIForeach * >(&c);} - -template inline _PIForeachC _PIForeachNewC(const T & t, bool i = false) {return _PIForeachC(t, i);} -template inline _PIForeachC * _PIForeachCastC(_PIForeachBase & c, const T & ) {return static_cast<_PIForeachC * >(&c);} - -#define piForeach(i,c) for(_PIForeachBase & _for = _PIForeachNew(c); !_PIForeachCast(_for, c)->isEnd(); ++(*_PIForeachCast(_for, c))) \ - for(i = *(_PIForeachCast(_for, c)->_it); !_for._break; _for._break = true) -#define piForeachR(i,c) for(_PIForeachBase & _for = _PIForeachNew(c, true); !_PIForeachCast(_for, c)->isEnd(); ++(*_PIForeachCast(_for, c))) \ - for(i = *(_PIForeachCast(_for, c)->_rit); !_for._break; _for._break = true) -#define piForeachC(i,c) for(_PIForeachBase & _for = _PIForeachNewC(c); !_PIForeachCastC(_for, c)->isEnd(); ++(*_PIForeachCastC(_for, c))) \ - for(const i = *(_PIForeachCastC(_for, c)->_it); !_for._break; _for._break = true) -#define piForeachCR(i,c) for(_PIForeachBase & _for = _PIForeachNewC(c, false); !_PIForeachCastC(_for, c)->isEnd(); ++(*_PIForeachCastC(_for, c))) \ - for(const i = *(_PIForeachCastC(_for, c)->_rit); !_for._break; _for._break = true) - -#endif - -#define piForeachRC piForeachCR - -#define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c) - - -template > -class PIP_EXPORT PIList: public list { - typedef PIList _CList; - typedef list _stlc; -public: - PIList() {piMonitor.containers++;} - PIList(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);} - PIList(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);} - PIList(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);} - PIList(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);} - PIList(uint size, const Type & value = Type()) {piMonitor.containers++; _stlc::resize(size, value);} - ~PIList() {piMonitor.containers--;} - Type & operator [](uint index) {return (*this)[index];} - Type & operator [](uint index) const {return (*this)[index];} - const Type * data(uint index = 0) const {return &(*this)[index];} - Type * data(uint index = 0) {return &(*this)[index];} - int size_s() const {return static_cast(_stlc::size());} - bool isEmpty() const {return _stlc::empty();} - bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;} - int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;} - _CList & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;} - _CList & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;} - _CList & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;} - _CList & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;} - _CList & operator <<(const Type & t) {_stlc::push_back(t); return *this;} - PIVector toVector() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} -}; - -/*! \brief Set of any type - * \details This class used to store collection of unique elements - * of any type. You can only add values to set with \a operator<< or - * with function \a insert(). You can discover if value already in - * set with \a operator[] or with function \a find(). These function - * has logarithmic complexity. - */ -template, typename Allocator = std::allocator > -class PIP_EXPORT PISet: public set { - typedef PISet _CSet; - typedef set _stlc; -public: - - //! Contructs an empty set - PISet() {piMonitor.containers++;} - - //! Contructs set with one element "value" - PISet(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);} - - //! Contructs set with elements "v0" and "v1" - PISet(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::insert(v0); _stlc::insert(v1);} - - //! Contructs set with elements "v0", "v1" and "v2" - PISet(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::insert(v0); _stlc::insert(v1); _stlc::insert(v2);} - - //! Contructs set with elements "v0", "v1", "v2" and "v3" - PISet(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::insert(v0); _stlc::insert(v1); _stlc::insert(v2); _stlc::insert(v3);} - - ~PISet() {piMonitor.containers--;} - - //! Returns elements count - int size_s() const {return static_cast(_stlc::size());} - - //! Returns if set is empty - bool isEmpty() const {return _stlc::empty();} - -#ifdef DOXYGEN - - //! Clear th set - void clear(); - - //! Insert element "t" if it doesn`t exists in this set - void insert(const Type & t); - -#endif - - _CSet & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;} - _CSet & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;} - _CSet & operator <<(const Type & t) {_stlc::insert(t); return *this;} - - //! Returns if element "t" exists in this set - bool operator [](const Type & t) {return _stlc::find(t) != _stlc::end();} - - //! Returns content of set as PIVector - PIVector toVector() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} -}; - - -#ifndef PIP_CONTAINERS_STL - -# define __PICONTAINERS_SIMPLE_TYPE__(T) \ -__PIDEQUE_SIMPLE_TYPE__(T)\ -__PIVECTOR_SIMPLE_TYPE__(T) - -__PICONTAINERS_SIMPLE_TYPE__(bool) -__PICONTAINERS_SIMPLE_TYPE__(char) -__PICONTAINERS_SIMPLE_TYPE__(uchar) -__PICONTAINERS_SIMPLE_TYPE__(short) -__PICONTAINERS_SIMPLE_TYPE__(ushort) -__PICONTAINERS_SIMPLE_TYPE__(int) -__PICONTAINERS_SIMPLE_TYPE__(uint) -__PICONTAINERS_SIMPLE_TYPE__(long) -__PICONTAINERS_SIMPLE_TYPE__(ulong) -__PICONTAINERS_SIMPLE_TYPE__(llong) -__PICONTAINERS_SIMPLE_TYPE__(ullong) -__PICONTAINERS_SIMPLE_TYPE__(float) -__PICONTAINERS_SIMPLE_TYPE__(double) -__PICONTAINERS_SIMPLE_TYPE__(ldouble) - -#endif - - -#endif // PICONTAINERS_H diff --git a/picrc.h b/picrc.h deleted file mode 100644 index 7677fbf6..00000000 --- a/picrc.h +++ /dev/null @@ -1,234 +0,0 @@ -/*! \file picrc.h - * \brief CRC checksum calculator -*/ -/* - PIP - Platform Independent Primitives - Abstract input/output device - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PICRC_H -#define PICRC_H - -#include "pistring.h" - -template -class PIP_EXPORT uint_cl { -public: - uint_cl() {for (int i = 0; i < L / 8; ++i) data_[i] = 0;} - uint_cl(const uint_cl & v) {for (int i = 0; i < L / 8; ++i) data_[i] = v.data_[i];} - uint_cl(uchar v) {for (int i = 0; i < L / 8; ++i) data_[i] = (i == 0 ? v : 0);} - uint_cl(char v) {for (int i = 0; i < L / 8; ++i) data_[i] = (i == 0 ? v : 0);} - uint_cl(ushort v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} - uint_cl(short v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} - uint_cl(uint v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} - uint_cl(int v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} - uint_cl(ulong v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} - uint_cl(long v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} - uint_cl(ullong v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} - uint_cl(llong v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} - - operator bool() {for (int i = 0; i < L / 8; ++i) if (data_[i] > 0) return true; return false;} - operator char() {return (char)data_[0];} - operator short() {short t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} - operator int() {int t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} - operator long() {long t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} - operator llong() {llong t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} - operator uchar() {return data_[0];} - operator ushort() {ushort t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} - operator uint() {uint t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} - operator ulong() {ulong t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} - operator ullong() {ullong t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} - - uint_cl operator +(const uint_cl & v) { - uint_cl t; - uint cv; - bool ov = false; - for (int i = 0; i < L / 8; ++i) { - cv = v.data_[i] + data_[i]; - if (ov) ++cv; - ov = cv > 255; - t.data_[i] = ov ? cv - 256 : cv; - } - return t; - } - - uint_cl operator &(const uint_cl & v) const {uint_cl t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] & data_[i]; return t;} - uint_cl operator &(const uchar & v) const {return *this & uint_cl(v);} - uint_cl operator &(const ushort & v) const {return *this & uint_cl(v);} - uint_cl operator &(const uint & v) const {return *this & uint_cl(v);} - uint_cl operator &(const ulong & v) const {return *this & uint_cl(v);} - uint_cl operator &(const ullong & v) const {return *this & uint_cl(v);} - uint_cl operator &(const char & v) const {return *this & uint_cl(v);} - uint_cl operator &(const short & v) const {return *this & uint_cl(v);} - uint_cl operator &(const int & v) const {return *this & uint_cl(v);} - uint_cl operator &(const long & v) const {return *this & uint_cl(v);} - uint_cl operator &(const llong & v) const {return *this & uint_cl(v);} - - uint_cl operator |(const uint_cl & v) const {uint_cl t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] | data_[i]; return t;} - uint_cl operator |(const uchar & v) const {return *this | uint_cl(v);} - uint_cl operator |(const ushort & v) const {return *this | uint_cl(v);} - uint_cl operator |(const uint & v) const {return *this | uint_cl(v);} - uint_cl operator |(const ulong & v) const {return *this | uint_cl(v);} - uint_cl operator |(const ullong & v) const {return *this | uint_cl(v);} - uint_cl operator |(const char & v) const {return *this | uint_cl(v);} - uint_cl operator |(const short & v) const {return *this | uint_cl(v);} - uint_cl operator |(const int & v) const {return *this | uint_cl(v);} - uint_cl operator |(const long & v) const {return *this | uint_cl(v);} - uint_cl operator |(const llong & v) const {return *this | uint_cl(v);} - - uint_cl operator ^(const uint_cl & v) const {uint_cl t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] ^ data_[i]; return t;} - uint_cl operator ^(const uchar & v) const {return *this ^ uint_cl(v);} - uint_cl operator ^(const ushort & v) const {return *this ^ uint_cl(v);} - uint_cl operator ^(const uint & v) const {return *this ^ uint_cl(v);} - uint_cl operator ^(const ulong & v) const {return *this ^ uint_cl(v);} - uint_cl operator ^(const ullong & v) const {return *this ^ uint_cl(v);} - uint_cl operator ^(const char & v) const {return *this ^ uint_cl(v);} - uint_cl operator ^(const short & v) const {return *this ^ uint_cl(v);} - uint_cl operator ^(const int & v) const {return *this ^ uint_cl(v);} - uint_cl operator ^(const long & v) const {return *this ^ uint_cl(v);} - uint_cl operator ^(const llong & v) const {return *this ^ uint_cl(v);} - - bool operator <(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] > data_[i]) return true; if (v.data_[i] < data_[i]) return false;} return false;} - bool operator <=(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] > data_[i]) return true; if (v.data_[i] < data_[i]) return false;} return true;} - bool operator >(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] < data_[i]) return true; if (v.data_[i] > data_[i]) return false;} return false;} - bool operator >=(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] < data_[i]) return true; if (v.data_[i] > data_[i]) return false;} return true;} - bool operator ==(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) if (v.data_[i] != data_[i]) return false; return true;} - bool operator !=(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) if (v.data_[i] != data_[i]) return true; return false;} - - uint_cl operator >>(const int & c) const { - uint_cl t; - int l = L - c; - bool bit; - if (l <= 0) return t; - for (int i = 0; i < l; ++i) { - bit = 1 & (data_[(i + c) / 8] >> ((i + c) % 8)); - if (bit) t.data_[i / 8] |= (1 << (i % 8)); - else t.data_[i / 8] &= ~(1 << (i % 8)); - } - return t; - } - uint_cl operator >>(const uint & c) const {return (*this << (int)c);} - uint_cl operator <<(const int & c) const { - uint_cl t; - int l = L - c; - bool bit; - if (l <= 0) return t; - for (int i = c; i < L; ++i) { - bit = 1 & (data_[(i - c) / 8] >> ((i - c) % 8)); - if (bit) t.data_[i / 8] |= (1 << (i % 8)); - else t.data_[i / 8] &= ~(1 << (i % 8)); - } - return t; - } - uint_cl operator <<(const uint & c) const {return (*this >> (int)c);} - - uint_cl & inverse() const {for (int i = 0; i < L / 8; ++i) data_[i] = ~data_[i]; return *this;} - uint_cl inversed() const {uint_cl t(*this); for (int i = 0; i < L / 8; ++i) t.data_[i] = ~t.data_[i]; return t;} - uint_cl reversed() const { - uint_cl t; - bool bit; - for (int i = 0; i < L; ++i) { - bit = 1 & (data_[(L - i - 1) / 8] >> ((L - i - 1) % 8)); - if (bit) t.data_[i / 8] |= (1 << (i % 8)); - else t.data_[i / 8] &= ~(1 << (i % 8)); - } - return t; - } - - const uchar * data() const {return data_;} - uchar * data() {return data_;} - uint length() const {return L / 8;} - -private: - uchar data_[L / 8]; - -}; - -template -inline std::ostream & operator <<(std::ostream & s, const uint_cl & v) {std::ios::fmtflags f = s.flags(); s << std::hex; for (uint i = 0; i < v.length(); ++i) {s << int(v.data()[i]); if (v.data()[i] < 0x10) s << '0'; s << ' ';} s.flags(f); return s;} - - -template -class PIP_EXPORT PICRC { -public: - PICRC(const uint_cl & poly) {poly_ = poly; reverse_poly = true; init_ = uint_cl(0).inversed(); out_ = uint_cl(0).inversed(); reverse_before_xor = reverse_data = false; initTable();} - PICRC(const uint_cl & poly, bool reverse_poly_, const uint_cl & initial, const uint_cl & out_xor) {poly_ = poly; reverse_poly = reverse_poly_; init_ = initial; out_ = out_xor; reverse_before_xor = reverse_data = false; initTable();} - - void setInitial(const uint_cl & v) {init_ = v;} - void setOutXor(const uint_cl & v) {out_ = v;} - void setReversePolynome(bool yes) {reverse_poly = yes; initTable();} - void setReverseOutBeforeXOR(bool yes) {reverse_before_xor = yes;} - void setReverseDataBytes(bool yes) {reverse_data = yes;} - - void initTable() { - uint_cl tmp, pol = reverse_poly ? poly_.reversed() : poly_; - //cout << std::hex << "poly " << (uint)uint_cl(poly_) << " -> " << (uint)uint_cl(pol) << endl; - for (int i = 0; i < 256; ++i) { - tmp = uchar(i); - for (int j = 0; j < 8; ++j) - tmp = ((tmp & 1) ? ((tmp >> 1) ^ pol) : (tmp >> 1)); - table[i] = tmp; - } - - } - - uint_cl calculate(const void * data, int size) { - uint_cl crc = init_; - uchar * data_ = (uchar * )data, cb; - //cout << "process " << size << endl; - uchar nTemp; - for (int i = 0; i < size; ++i) { - cb = data_[i]; - if (reverse_data) cb = reverseByte(cb); - nTemp = cb ^ uchar(crc); - crc = crc >> 8; - crc = crc ^ table[nTemp]; - } - if (reverse_before_xor) crc = crc.reversed(); - return crc ^ out_; - - } - uint_cl calculate(const PIByteArray & d) {return calculate(d.data(), d.size());} - uint_cl calculate(const char * str) {string s(str); return calculate((void * )s.data(), s.size());} - -private: - uchar reverseByte(uchar b) { - uchar ret = 0; - bool bit; - for (int i = 0; i < 8; ++i) { - bit = 1 & (b >> (7 - i)); - if (bit) ret |= (1 << i); - } - return ret; - } - - uint_cl table[256]; - uint_cl poly_, init_, out_; - bool reverse_poly, reverse_before_xor, reverse_data; - -}; - -typedef PICRC<32> CRC_32; -typedef PICRC<24> CRC_24; -typedef PICRC<16> CRC_16; -typedef PICRC<8> CRC_8; - -inline CRC_32 standardCRC_32() {return CRC_32(0x04C11DB7, true, 0xFFFFFFFF, 0xFFFFFFFF);} -inline CRC_16 standardCRC_16() {return CRC_16(0x8005, true, 0x0, 0x0);} -inline CRC_8 standardCRC_8() {return CRC_8(0xD5, true, 0x0, 0x0);} - -#endif // CRC_H diff --git a/pideque.h b/pideque.h deleted file mode 100644 index 074a48a3..00000000 --- a/pideque.h +++ /dev/null @@ -1,477 +0,0 @@ -/*! \file pideque.h - * \brief Dynamic array of any type - * - * This file declares PIDeque -*/ -/* - PIP - Platform Independent Primitives - Dynamic array of any type - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIDEQUE_H -#define PIDEQUE_H - -#include "piincludes.h" - - -#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN) - - -template -class PIDeque { -public: - PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { - //printf("new vector 1 %p (%s) ... !{\n", this, typeid(T).name()); - //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); - } - PIDeque(const PIDeque & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { - //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name()); - alloc(other.pid_size, true); - newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size); - //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); - } - PIDeque(const T * data, size_t size): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { - //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name()); - alloc(size, true); - newT(pid_data + pid_start, data, pid_size); - //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); - } - PIDeque(size_t pid_size, const T & f = T()): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { - //printf("new vector 3 %p (%s) ... !{\n", this, typeid(T).name()); - resize(pid_size, f); - //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); - } - ~PIDeque() { - //printf("delete deque %p (%s) (s=%d, rs=%d, st=%d, d=%p) ... ~{\n", this, typeid(T).name(), int(pid_size), int(pid_rsize), int(pid_start), pid_data); - deleteT(pid_data + pid_start, pid_size); - dealloc(); - //deleteRaw(pid_tdata); - _reset(); - //printf("}~\n"); - } - - PIDeque & operator =(const PIDeque & other) { - if (this == &other) return *this; - deleteT(pid_data + pid_start, pid_size); - alloc(other.pid_size, true); - newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size); - return *this; - } - - typedef T value_type; - - class iterator { - friend class PIDeque; - private: - iterator(PIDeque * v, size_t p): parent(v), pos(p) {} - PIDeque * parent; - size_t pos; - public: - iterator(): parent(0) {} - T & operator *() {return (*parent)[pos];} - const T & operator *() const {return (*parent)[pos];} - void operator ++() {++pos;} - void operator ++(int) {++pos;} - void operator --() {--pos;} - void operator --(int) {--pos;} - bool operator ==(const iterator & it) const {return (pos == it.pos);} - bool operator !=(const iterator & it) const {return (pos != it.pos);} - }; - - class const_iterator { - friend class PIDeque; - private: - const_iterator(const PIDeque * v, size_t p): parent(v), pos(p) {} - const PIDeque * parent; - size_t pos; - public: - const_iterator(): parent(0) {} - //T & operator *() {return (*parent)[pos];} - const T & operator *() const {return (*parent)[pos];} - void operator ++() {++pos;} - void operator ++(int) {++pos;} - void operator --() {--pos;} - void operator --(int) {--pos;} - bool operator ==(const const_iterator & it) const {return (pos == it.pos);} - bool operator !=(const const_iterator & it) const {return (pos != it.pos);} - }; - - class reverse_iterator { - friend class PIDeque; - private: - reverse_iterator(PIDeque * v, size_t p): parent(v), pos(p) {} - PIDeque * parent; - size_t pos; - public: - reverse_iterator(): parent(0) {} - T & operator *() {return (*parent)[pos];} - const T & operator *() const {return (*parent)[pos];} - void operator ++() {--pos;} - void operator ++(int) {--pos;} - void operator --() {++pos;} - void operator --(int) {++pos;} - bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);} - bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);} - }; - - class const_reverse_iterator { - friend class PIDeque; - private: - const_reverse_iterator(const PIDeque * v, size_t p): parent(v), pos(p) {} - const PIDeque * parent; - size_t pos; - public: - const_reverse_iterator(): parent(0) {} - //T & operator *() {return (*parent)[pos];} - const T & operator *() const {return (*parent)[pos];} - void operator ++() {--pos;} - void operator ++(int) {--pos;} - void operator --() {++pos;} - void operator --(int) {++pos;} - bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);} - bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} - }; - - iterator begin() {return iterator(this, 0);} - iterator end() {return iterator(this, pid_size);} - const_iterator begin() const {return const_iterator(this, 0);} - const_iterator end() const {return const_iterator(this, pid_size);} - reverse_iterator rbegin() {return reverse_iterator(this, pid_size - 1);} - reverse_iterator rend() {return reverse_iterator(this, -1);} - const_reverse_iterator rbegin() const {return const_reverse_iterator(this, pid_size - 1);} - const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} - - size_t size() const {return pid_size;} - ssize_t size_s() const {return pid_size;} - size_t length() const {return pid_size;} - size_t capacity() const {return pid_rsize;} - bool isEmpty() const {return (pid_size == 0);} - - T & operator [](size_t index) {return pid_data[pid_start + index];} - T & at(size_t index) {return pid_data[pid_start + index];} - const T & operator [](size_t index) const {return pid_data[pid_start + index];} - const T & at(size_t index) const {return pid_data[pid_start + index];} - T & back() {return pid_data[pid_start + pid_size - 1];} - const T & back() const {return pid_data[pid_start + pid_size - 1];} - T & front() {return pid_data[pid_start];} - const T & front() const {return pid_data[pid_start];} - bool operator ==(const PIDeque & t) const {if (pid_size != t.pid_size) return false; for (size_t i = 0; i < pid_size; ++i) if (t[i] != pid_data[pid_start + i]) return false; return true;} - bool operator !=(const PIDeque & t) const {if (pid_size != t.pid_size) return true; for (size_t i = 0; i < pid_size; ++i) if (t[i] != pid_data[pid_start + i]) return true; return false;} - bool contains(const T & v) const {for (size_t i = pid_start; i < pid_start + pid_size; ++i) if (v == pid_data[i]) return true; return false;} - int etries(const T & v) const {int ec = 0; for (size_t i = pid_start; i < pid_start + pid_size; ++i) if (v == pid_data[i]) ++ec; return ec;} - - T * data(size_t index = 0) {return &(pid_data[pid_start + index]);} - const T * data(size_t index = 0) const {return &(pid_data[pid_start + index]);} - PIDeque & clear() {resize(0); return *this;} - PIDeque & fill(const T & f = T()) { - //if (sizeof(T) == 1) memset(pid_data, f, pid_size); - deleteT(pid_data + pid_start, pid_size); - //zeroRaw(pid_data, pid_size); - for (size_t i = pid_start; i < pid_start + pid_size; ++i) - elementNew(pid_data + i, f); - return *this; - } - PIDeque & assign(const T & f = T()) {return fill(f);} - PIDeque & assign(size_t new_size, const T & f) {resize(new_size); return fill(f);} - PIDeque & resize(size_t new_size, const T & f = T()) { - if (new_size < pid_size) { - deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size); - pid_size = new_size; - } - if (new_size > pid_size) { - size_t os = pid_size; - alloc(new_size, true); - //if (sizeof(T) == 1) memset(&(pid_data[os]), f, ds); - //zeroRaw(&(pid_data[os]), new_size - os); - for (size_t i = os + pid_start; i < new_size + pid_start; ++i) elementNew(pid_data + i, f); - } - return *this; - } - PIDeque & reserve(size_t new_size) {if (new_size <= pid_rsize) return *this; size_t os = pid_size; alloc(new_size, true); pid_size = os; return *this;} - - PIDeque & insert(size_t index, const T & v = T()) { - bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); - //piCout << "insert" << dir << index << pid_size << pid_rsize << pid_start << "!<"; - if (dir) { - alloc(pid_size + 1, true); - if (index < pid_size - 1) { - size_t os = pid_size - index - 1; - memmove(&(pid_data[index + pid_start + 1]), &(pid_data[index + pid_start]), os * sizeof(T)); - } - } else { - pid_start--; - alloc(pid_size + 1, false); - //piCout << "insert front" << pid_size << pid_rsize << pid_start << "!<"; - if (index > 0) - memmove(&(pid_data[pid_start]), &(pid_data[pid_start + 1]), index * sizeof(T)); - } - //piCout << "insert" << pid_start << index << (pid_start + ssize_t(index)) << pid_size << ">!"; - elementNew(pid_data + pid_start + index, v); - return *this; - } - PIDeque & insert(size_t index, const PIDeque & other) { - if (other.isEmpty()) return *this; - bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); - //piCout << "insert" << dir << index << pid_size << pid_rsize << pid_start << "!<"; - if (dir) { - ssize_t os = pid_size - index; - alloc(pid_size + other.pid_size, true); - if (os > 0) - memmove(&(pid_data[index + pid_start + other.pid_size]), &(pid_data[index + pid_start]), os * sizeof(T)); - } else { - pid_start -= other.pid_size; - alloc(pid_size + other.pid_size, false); - //piCout << "insert front" << pid_size << pid_rsize << pid_start << "!<"; - if (index > 0) - memmove(&(pid_data[pid_start]), &(pid_data[pid_start + other.pid_size]), index * sizeof(T)); - } - //piCout << "insert" << pid_start << index << (pid_start + ssize_t(index)) << pid_size << ">!"; - newT(pid_data + pid_start + index, other.pid_data + other.pid_start, other.pid_size); - return *this; - } - - PIDeque & remove(size_t index, size_t count = 1) { - if (count == 0) return *this; - if (index + count >= pid_size) { - resize(index); - return *this; - } - size_t os = pid_size - index - count; - deleteT(&(pid_data[index + pid_start]), count); - if (os <= index) { - //if (true) { - if (os > 0) memmove(&(pid_data[index + pid_start]), &(pid_data[index + pid_start + count]), os * sizeof(T)); - } else { - if (index > 0) memmove(&(pid_data[pid_start + count]), &(pid_data[pid_start]), index * sizeof(T)); - pid_start += count; - } - pid_size -= count; - return *this; - } - - void swap(PIDeque & other) { - piSwap(pid_data, other.pid_data); - piSwap(pid_size, other.pid_size); - piSwap(pid_rsize, other.pid_rsize); - piSwap(pid_start, other.pid_start); - } - - typedef int (*CompareFunc)(const T * , const T * ); - static int compare_func(const T * t0, const T * t1) {return (*t0) < (*t1) ? -1 : ((*t0) == (*t1) ? 0 : 1);} - PIDeque & sort(CompareFunc compare = compare_func) {qsort(pid_data + pid_start, pid_size, sizeof(T), (int(*)(const void * , const void * ))compare); return *this;} - - PIDeque & enlarge(llong pid_size) {llong ns = size_s() + pid_size; if (ns <= 0) clear(); else resize(size_t(ns)); return *this;} - - PIDeque & removeOne(const T & v) {for (size_t i = 0; i < pid_size; ++i) if (pid_data[i + pid_start] == v) {remove(i); return *this;} return *this;} - PIDeque & removeAll(const T & v) {for (llong i = 0; i < pid_size; ++i) if (pid_data[i + pid_start] == v) {remove(i); --i;} return *this;} - - PIDeque & push_back(const T & v) {alloc(pid_size + 1, true); elementNew(pid_data + pid_start + pid_size - 1, v); return *this;} - PIDeque & append(const T & v) {return push_back(v);} - PIDeque & operator <<(const T & v) {return push_back(v);} - PIDeque & operator <<(const PIDeque & t) { - size_t ps = pid_size; - alloc(pid_size + t.pid_size, true); - newT(pid_data + ps + pid_start, t.pid_data + t.pid_start, t.pid_size); - return *this; - } - - PIDeque & push_front(const T & v) {insert(0, v); return *this;} - PIDeque & prepend(const T & v) {return push_front(v);} - - PIDeque & pop_back() {if (pid_size == 0) return *this; resize(pid_size - 1); return *this;} - PIDeque & pop_front() {if (pid_size == 0) return *this; remove(0); return *this;} - - T take_back() {T t(back()); pop_back(); return t;} - T take_front() {T t(front()); pop_front(); return t;} - -private: - void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;} - /*void * qmemmove(void * dst, void * src, size_t size) { - if (piAbs(ssize_t(dst) - ssize_t(src)) >= size) - memcpy(dst, src, size); - else { - char * tb = new char[size]; - memcpy(tb, src, size); - memcpy(dst, tb, size); - delete tb; - } - return dst; - }*/ - inline size_t asize(ssize_t s) { - if (s <= 0) return 0; - if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s)) - return pid_rsize + pid_rsize; - size_t t = 0, s_ = size_t(s) - 1; - while (s_ >> t) ++t; - return (1 << t); - } - inline void newT(T * dst, const T * src, size_t s) { - for (size_t i = 0; i < s; ++i) - elementNew(dst + i, src[i]); - } - inline T * newRaw(size_t s) { - //cout << std::dec << " ![("< (new 0x" << (llong)ret << ") ok]!" << endl; - return (T*)ret; - } - /*void reallocRawTemp(size_t s) { - if (pid_tdata == 0) pid_tdata = (T*)(malloc(s * sizeof(T))); - else pid_tdata = (T*)(realloc(pid_tdata, s * sizeof(T))); - }*/ - inline void deleteT(T * d, size_t sz) { - //cout << " ~[("< ok]~" << endl; - } - inline void deleteRaw(T *& d) { - //cout << " ~[("< ok]~" << endl; - } - void zeroRaw(T * d, size_t s) { - //cout << " ~[("< ok]~" << endl; - } - inline void elementNew(T * to, const T & from) {new(to)T(from);} - inline void elementDelete(T & from) {from.~T();} - void dealloc() {deleteRaw(pid_data);} - inline void checkMove(bool direction) { - if (pid_size >= 4 && pid_size < pid_rsize / 4) { - /*if (direction) { - if (pid_start >= 4 && pid_start > pid_size + pid_size && pid_start > pid_rsize / 2) { - piCout << (int)this << "checkMove" << direction << pid_start << (int)pid_data << pid_rsize << pid_size; - piCout << (int)this << "move from" << pid_start << "to" << pid_size << "," << (int)pid_data << pid_rsize << pid_size; - memmove(pid_data + pid_size, pid_data + pid_start, pid_size * sizeof(T)); - pid_start = pid_size; - } - } else { - if (ssize_t(pid_start) < ssize_t(pid_rsize) - pid_size - pid_size && ssize_t(pid_start) < ssize_t(pid_rsize / 2) - pid_size) { - piCout << (int)this << "checkMove" << direction << pid_start << (int)pid_data << pid_rsize << pid_size; - piCout << (int)this << "move from" << pid_start << "to" << (ssize_t(pid_rsize) - pid_size) << "," << (int)pid_data << pid_rsize << pid_size; - memmove(pid_data + ssize_t(pid_rsize) - pid_size - pid_size, pid_data + pid_start, pid_size * sizeof(T)); - pid_start = ssize_t(pid_rsize) - pid_size - pid_size; - } - }*/ - if (pid_start < pid_size + pid_size || pid_start > pid_rsize - pid_size - pid_size) { - size_t ns = (pid_rsize - pid_size) / 2; - if (pid_start != ns) { - memmove(pid_data + ns, pid_data + pid_start, pid_size * sizeof(T)); - pid_start = ns; - } - } - } - } - inline void alloc(size_t new_size, bool direction) { // direction == true -> alloc forward - if (direction) { - if (pid_start + new_size <= pid_rsize) { - pid_size = new_size; - checkMove(direction); - return; - } - pid_size = new_size; - size_t as = asize(pid_start + new_size); - if (as != pid_rsize) { - pid_data = (T*)(realloc(pid_data, as*sizeof(T))); - pid_rsize = as; - } - } else { - size_t as = asize(piMax(new_size, pid_rsize) - pid_start); - //piCout << "alloc" << new_size << pid_size << pid_rsize << as << pid_start; - if (pid_start >= 0 && as <= pid_rsize) { - pid_size = new_size; - checkMove(direction); - return; - } - size_t os = pid_size; - pid_size = new_size; - if (as > pid_rsize) { - //piCout << "alloc new size" << as; - //cout << std::hex << " ![("< 0 && pid_data != 0) { - memcpy(td + pid_start + ns, pid_data + ost, os * sizeof(T)); - deleteRaw(pid_data); - } - pid_data = td; - pid_rsize = as; - } - } - //checkMove(direction); - //piCout << "alloc new start" << pid_start; - } - - T * pid_data; - size_t pid_size, pid_rsize; - size_t pid_start; -}; - -#define __PIDEQUE_SIMPLE_TYPE__(T) \ - template<> inline void PIDeque::newT(T * dst, const T * src, size_t s) {memcpy(dst, src, s * sizeof(T));} \ - template<> inline void PIDeque::deleteT(T * d, size_t sz) {;} \ - template<> inline void PIDeque::elementNew(T * to, const T & from) {(*to) = from;} \ - template<> inline void PIDeque::elementDelete(T & from) {;} - -#else - - -template > -class PIP_EXPORT PIDeque: public deque { - typedef PIDeque _CDeque; - typedef deque _stlc; -public: - PIDeque() {piMonitor.containers++;} - PIDeque(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);} - PIDeque(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);} - PIDeque(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);} - PIDeque(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);} - ~PIDeque() {piMonitor.containers--;} - int size_s() const {return static_cast(_stlc::size());} - bool isEmpty() const {return _stlc::empty();} - bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;} - int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;} - _CDeque & operator <<(const Type & t) {_CDeque::push_back(t); return *this;} - PIDeque toVector() {PIDeque v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} -}; - - -#define __PIDEQUE_SIMPLE_FUNCTIONS__(T) - - -#endif - - -template -inline std::ostream & operator <<(std::ostream & s, const PIDeque & v) {s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;} - -template -inline PICout operator <<(PICout s, const PIDeque & v) {s.space(); s.setControl(0, true); s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;} - - -#endif // PIDEQUE_H diff --git a/pidevicepool.cpp b/pidevicepool.cpp deleted file mode 100644 index 27ff3792..00000000 --- a/pidevicepool.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - PIP - Platform Independent Primitives - Single collection of devices - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pidevicepool.h" - - -/*! \class PIDevicePool - * \brief Single collection of devices - * - * \section PIDevicePool_sec0 Synopsis - * - * \section PIDevicePool_ex0 Example - * \snippet pidevicepool.cpp 0 - */ - - -PIDevicePool::PIDevicePool(): PIObject() { -} - - -PIDevicePool::~PIDevicePool() { - /*stop(); - if (opened_) { - closeDevice(); - if (!opened_) - closed(); - }*/ -} diff --git a/pidevicepool.h b/pidevicepool.h deleted file mode 100644 index 6a1538bb..00000000 --- a/pidevicepool.h +++ /dev/null @@ -1,65 +0,0 @@ -/*! \file pidevicepool.h - * \brief Single collection of devices -*/ -/* - PIP - Platform Independent Primitives - Single collection of devices - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIDEVICEPOOL_H -#define PIDEVICEPOOL_H - -#include "piiodevice.h" - -class PIP_EXPORT PIDevicePool: public PIObject -{ - PIOBJECT(PIDevicePool) -public: - - PIDevicePool(); - ~PIDevicePool(); - - -//! \handlers -//! \{ - - //! \fn bool initialize() - //! \brief Initialize device - -//! \} -//! \vhandlers -//! \{ - - //! \fn void flush() - //! \brief Immediate write all buffers - -//! \} -//! \events -//! \{ - - //! \fn void threadedWriteEvent(ullong id, int written_size) - //! \brief Raise if write thread succesfull write some data of task with ID "id" - -//! \} - -protected: - -private: - -}; - -#endif // PIDEVICEPOOL_H diff --git a/pidiagnostics.cpp b/pidiagnostics.cpp deleted file mode 100644 index d199912f..00000000 --- a/pidiagnostics.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - PIP - Platform Independent Primitives - Speed and quality in/out diagnostics - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pidiagnostics.h" - - -/** \class PIDiagnostics - * \brief Connection quality diagnostics - * \details - * \section PIDiagnostics_sec0 Synopsis - * This class provide abstract connection quality diagnostics and - * counting. You should create instance of %PIDiagnostics and on - * packet receive call function \a received(), on packet send call - * function \a sended(). %PIDiagnostics calculates correct, wrong - * and sended counters, packets per second, bytes per seconds, - * immediate and integral receive frequencies and receive/send speeds - * in human readable representation. There statistics are calculates - * one time per period, by default 1 second. To calculate them you - * should start %PIDiagnostics with function \a start() or pass \b true - * to constructor. - * */ - - -PIDiagnostics::PIDiagnostics(bool start_): PITimer() { - PITimer::reset(); - reset(); - if (start_) start(); -} - - -void PIDiagnostics::reset() { - lock(); - qual = PIDiagnostics::Unknown; - speedIn = speedOut = PIString::readableSize(0) + "/s"; - ifreq = immediate_freq = integral_freq = 0.f; - packets[0] = packets[1] = 0; - cur_pckt = rec_once = 0; - wrong_count = receive_count = send_count = 0; - packets_in_sec = packets_out_sec = bytes_in_sec = bytes_out_sec = 0; - unlock(); -} - - -void PIDiagnostics::received(int size, bool correct) { - lock(); - packets[correct ? 1 : 0]++; - rec_once = 1; - if (correct) { - float el = elapsed_s(); - PITimer::reset(); - if (el > 0.f) immediate_freq = ifreq = 1.f / el; - else immediate_freq = ifreq = 0.f; - receive_count++; - packets_in_sec++; - bytes_in_sec += size; - } else { - immediate_freq = ifreq = 0.f; - wrong_count++; - } - unlock(); -} - - -void PIDiagnostics::sended(int size) { - lock(); - send_count++; - packets_out_sec++; - bytes_out_sec += size; - unlock(); -} - - -void PIDiagnostics::tick(void * data, int delimiter) { - lock(); - PIDiagnostics::Quality diag; - float fdel = 1. / (interval() / 1000.); - immediate_freq = ifreq; - ifreq = 0.f; - speedIn = PIString::readableSize(bytes_in_sec * fdel) + "/s"; - speedOut = PIString::readableSize(bytes_out_sec * fdel) + "/s"; - bytes_in_sec = bytes_out_sec = packets_in_sec = packets_out_sec = 0; - int arc = packets[0] + packets[1]; - float good_percents = 0.f; - if (arc > 0) good_percents = (float)packets[1] / arc * 100.f; - integral_freq = packets[1] * fdel; - if (rec_once == 0) { - diag = PIDiagnostics::Unknown; - } else { - if (good_percents == 0.f) diag = PIDiagnostics::Failure; - else if (good_percents <= 20.f) diag = PIDiagnostics::Bad; - else if (good_percents > 20.f && good_percents <= 80.f) diag = PIDiagnostics::Average; - else diag = PIDiagnostics::Good; - if (diag != qual) { - qualityChanged(diag, qual); - qual = diag; - } - } - packets[0] = packets[1] = 0; - unlock(); -} diff --git a/pidiagnostics.h b/pidiagnostics.h deleted file mode 100644 index cecd9abf..00000000 --- a/pidiagnostics.h +++ /dev/null @@ -1,170 +0,0 @@ -/*! \file pidiagnostics.h - * \brief Connection quality diagnostics -*/ -/* - PIP - Platform Independent Primitives - Speed and quality in/out diagnostics - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIDIAGNOSTICS_H -#define PIDIAGNOSTICS_H - -#include "pitimer.h" - - -class PIP_EXPORT PIDiagnostics: private PITimer -{ - PIOBJECT(PIDiagnostics) -public: - - //! Constructs an empty diagnostics and if "strat_" start it - PIDiagnostics(bool start_ = true); - - virtual ~PIDiagnostics() {;} - - //! Connection quality - enum Quality { - Unknown /** Unknown, no one packet received yet */ = 1, - Failure /** No connection, no one correct packet received for last period */ = 2, - Bad /** Bad connection, correct packets received <= 20% */ = 3, - Average /** Average connection, correct packets received > 20% and <= 80% */ = 4, - Good /** Good connection, correct packets received > 80% */ = 5 - }; - - - //! Returns immediate receive frequency, packets/s - float immediateFrequency() const {return immediate_freq;} - - //! Returns integral receive frequency for period, packets/s - float integralFrequency() const {return integral_freq;} - - //! Returns correct received packets per second - ullong receiveCountPerSec() const {return packets_in_sec;} - - //! Returns sended packets per second - ullong sendCountPerSec() const {return packets_out_sec;} - - //! Returns correct received bytes per second - ullong receiveBytesPerSec() const {return bytes_in_sec;} - - //! Returns sended bytes per second - ullong sendBytesPerSec() const {return bytes_out_sec;} - - //! Returns overall correct received packets count - ullong receiveCount() const {return receive_count;} - - //! Returns overall wrong received packets count - ullong wrongCount() const {return wrong_count;} - - //! Returns overall sended packets count - ullong sendCount() const {return send_count;} - - //! Returns connection quality - PIDiagnostics::Quality quality() const {return qual;} - - //! Returns receive speed in format "n {B|kB|MB|GB|TB}/s" - PIString receiveSpeed() const {return speedIn;} - - //! Returns send speed in format "n {B|kB|MB|GB|TB}/s" - PIString sendSpeed() const {return speedOut;} - - - //! Returns immediate receive frequency pointer, packets/s. Useful for output to PIConsole - const float * immediateFrequency_ptr() const {return &immediate_freq;} - - //! Returns integral receive frequency pointer for period, packets/s. Useful for output to PIConsole - const float * integralFrequency_ptr() const {return &integral_freq;} - - //! Returns correct received packets per second pointer. Useful for output to PIConsole - const ullong * receiveCountPerSec_ptr() const {return &packets_in_sec;} - - //! Returns sended packets per second pointer. Useful for output to PIConsole - const ullong * sendCountPerSec_ptr() const {return &packets_out_sec;} - - //! Returns correct received bytes per second pointer. Useful for output to PIConsole - const ullong * receiveBytesPerSec_ptr() const {return &bytes_in_sec;} - - //! Returns sended bytes per second pointer. Useful for output to PIConsole - const ullong * sendBytesPerSec_ptr() const {return &bytes_out_sec;} - - //! Returns overall correct received packets count pointer. Useful for output to PIConsole - const ullong * receiveCount_ptr() const {return &receive_count;} - - //! Returns overall wrong received packets count pointer. Useful for output to PIConsole - const ullong * wrongCount_ptr() const {return &wrong_count;} - - //! Returns overall sended packets count pointer. Useful for output to PIConsole - const ullong * sendCount_ptr() const {return &send_count;} - - //! Returns connection quality pointer. Useful for output to PIConsole - const int * quality_ptr() const {return (int * )&qual;} - - //! Returns receive speed pointer in format "n {B|kB|MB|GB|TB}/s". Useful for output to PIConsole - const PIString * receiveSpeed_ptr() const {return &speedIn;} - - //! Returns send speed pointer in format "n {B|kB|MB|GB|TB}/s". Useful for output to PIConsole - const PIString * sendSpeed_ptr() const {return &speedOut;} - - EVENT_HANDLER0(void, start) {start(1000.);} - EVENT_HANDLER1(void, start, double, msecs) {if (msecs > 0.) PITimer::start(msecs);} - EVENT_HANDLER0(void, reset); - - EVENT_HANDLER1(void, received, int, size) {received(size, true);} - EVENT_HANDLER2(void, received, int, size, bool, correct); - EVENT_HANDLER1(void, sended, int, size); - - EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality) - -//! \handlers -//! \{ - - //! \fn void start(double msecs = 1000.) - //! \brief Start diagnostics evaluations with period "msecs" milliseconds - - //! \fn void reset() - //! \brief Reset diagnostics counters - - //! \fn void received(int size, bool correct = true) - //! \brief Notify diagnostics about "correct" corected received packet - - //! \fn void sended(int size) - //! \brief Notify diagnostics about sended packet - -//! \} -//! \events -//! \{ - - //! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) - //! \brief Raise on change receive quality from "old_quality" to "new_quality" - -//! \} - -private: - void tick(void * data, int delimiter); - void changeDisconnectTimeout(); - - PIDiagnostics::Quality qual; - PIString speedIn, speedOut; - float ifreq, immediate_freq, integral_freq; - int packets[2]; - char cur_pckt, rec_once; - ullong wrong_count, receive_count, send_count; - ullong packets_in_sec, packets_out_sec, bytes_in_sec, bytes_out_sec; - -}; - -#endif // PIDIAGNOSTICS_H diff --git a/pidir.cpp b/pidir.cpp deleted file mode 100644 index 0fb1cc36..00000000 --- a/pidir.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* - PIP - Platform Independent Primitives - Directory - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pidir.h" - -#if !defined(ANDROID) -#ifdef WINDOWS - const PIChar PIDir::separator = '\\'; -#else - const PIChar PIDir::separator = '/'; -#endif - - -PIDir::PIDir(const PIString & dir) { - path_ = dir; -} - - -PIDir::PIDir(const PIFile & file) { - path_ = file.path(); - if (isExists()) return; - int pos = path_.findLast(separator); - path_.cutRight(path_.size_s() - pos); -} - - -bool PIDir::operator ==(const PIDir & d) const { - return d.absolutePath() == absolutePath(); -} - - -bool PIDir::isAbsolute() const { - if (path_.size() == 0) return false; -#ifdef WINDOWS - if (path_.size() < 3) return false; - return (path_[1] == ":"); -#else - return (path_[0] == separator); -#endif -} - - -PIString PIDir::absolutePath() const { - if (isAbsolute()) return path_; - PIDir d(path_); - d.setDir(PIDir::current().path_ + separator + path_); - return d.path_; -} - - -PIDir & PIDir::cleanPath() { - PIString p(path_); - if (p.size() == 0) { - path_ = "."; - return *this; - } - path_.replaceAll(PIString(separator) + PIString(separator), PIString(separator)); - bool is_abs = isAbsolute(); - PIStringList l = PIString(p).split(separator); -#ifdef WINDOWS - PIString letter; - if (is_abs) letter = l.take_front(); -#endif - l.removeAll("."); - l.removeAll(""); - 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); /// TODO think about windows - if (!is_abs) path_.prepend("."); -#ifdef WINDOWS - else path_.prepend(letter); -#endif - if (path_.size() == 0) path_ = "."; - return *this; -} - - -PIDir & PIDir::setDir(const PIString & path) { - path_ = path; - cleanPath(); - return *this; -} - - -PIDir & PIDir::cd(const PIString & path) { - if (path_.size() == 0) return *this; - if (path_[path_.size() - 1] != separator) path_ += separator; - path_ += path; - return cleanPath(); -} - - -bool PIDir::make(bool withParents) { - PIDir d = cleanedPath(); - PIString tp; - bool is_abs = isAbsolute(); - if (withParents) { - PIStringList l = d.path_.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 (!is_abs) 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; - if (makeDir(tp)) continue; - else return false; - } - break; - }; - } - } else - if (makeDir(d.path_)) return true; - return false; -} - - -PIVector PIDir::entries() { - PIVector l; - PIString p(cleanedPath().path_); -#ifdef WINDOWS - WIN32_FIND_DATA fd; memset(&fd, 0, sizeof(fd)); - p += "\\*"; - void * hf = FindFirstFile((LPCTSTR)(p.data()), &fd); - if (!hf) return l; - LARGE_INTEGER filesize; - do { - int m = 0; - filesize.LowPart = filesize.HighPart = 0; - if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) m |= S_IFHDN; - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) m |= S_IFBLK; - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) m |= S_IFDIR; - else { - m |= S_IFREG; - filesize.LowPart = fd.nFileSizeLow; - filesize.HighPart = fd.nFileSizeHigh; - } - l << DirEntry(fd.cFileName, m, filesize.QuadPart); - memset(&fd, 0, sizeof(fd)); - } while (FindNextFile(hf, &fd) != 0); - FindClose(hf); -#else - dirent ** list; -# ifndef QNX - int cnt = scandir(p.data(), &list, 0, versionsort); -# else - int cnt = scandir(const_cast(p.data()), 0, 0, versionsort); -# endif - struct stat fs; - for (int i = 0; i < cnt; ++i) { - stat((p + separator + PIString(list[i]->d_name)).data(), &fs); - l << DirEntry(list[i]->d_name, fs.st_mode, fs.st_size); - if (list[i]->d_name[0] == '.') l.back().mode |= S_IFHDN; - delete list[i]; - } - delete list; -#endif - return l; -} - - - -bool PIDir::isExists(const PIString & path) { -#ifdef WINDOWS - return (GetFileAttributes((LPCTSTR)(path.data())) & FILE_ATTRIBUTE_DIRECTORY); -#else - DIR * dir_ = opendir(path.data()); - if (dir_ == 0) return false; - closedir(dir_); -#endif - return true; -} - - -PIDir PIDir::current() { - char rc[1024]; -#ifdef WINDOWS - memset(rc, 0, 1024); - if (GetCurrentDirectory(1024, (LPTSTR)rc) == 0) return PIString(); -#else - if (getcwd(rc, 1024) == 0) return PIString(); -#endif - return PIDir(rc); -} - - -PIDir PIDir::home() { - char * rc = 0; -#ifdef WINDOWS - rc = new char[1024]; - memset(rc, 0, 1024); - if (ExpandEnvironmentStrings((LPCTSTR)"%HOMEPATH%", (LPTSTR)rc, 1024) == 0) { - delete[] rc; - return PIDir(); - } - PIString s(rc); - delete[] rc; - return PIDir(s); -#else - rc = getenv("HOME"); - if (rc == 0) return PIDir(); - return PIDir(rc); -#endif -} - - -PIDir PIDir::temporary() { - char * rc = 0; -#ifdef WINDOWS - rc = new char[1024]; - memset(rc, 0, 1024); - int ret = GetTempPath(1024, (LPTSTR)rc); - if (ret == 0) { - delete[] rc; - return PIDir(); - } - PIString s(rc); - delete[] rc; - return PIDir(s); -#else - rc = tmpnam(0); - if (rc == 0) return PIDir(); - PIString s(rc); - return PIDir(s.left(s.findLast(PIDir::separator))); -#endif -} - - -bool PIDir::make(const PIString & path, bool withParents) { - PIDir d(path); - if (d.isExists()) return true; - return d.make(withParents); -} - - -bool PIDir::setCurrent(const PIString & path) { -#ifdef WINDOWS - if (SetCurrentDirectory((LPCTSTR)(path.data())) != 0) return true; -#else - if (chdir(path.data()) == 0) return true; -#endif - printf("[PIDir] setCurrent(\"%s\") error: %s\n", path.data(), errorString().c_str()); - return false; -} - - -bool PIDir::makeDir(const PIString & path) { -#ifdef WINDOWS - if (CreateDirectory((LPCTSTR)(path.data()), NULL) != 0) return true; -#else - if (mkdir(path.data(), 16877) == 0) return true; -#endif - printf("[PIDir] makeDir(\"%s\") error: %s\n", path.data(), errorString().c_str()); - return false; -} - - -bool PIDir::removeDir(const PIString & path) { -#ifdef WINDOWS - if (RemoveDirectory((LPCTSTR)(path.data())) != 0) return true; -#else - if (rmdir(path.data()) == 0) return true; -#endif - printf("[PIDir] removeDir(\"%s\") error: %s\n", path.data(), errorString().c_str()); - return false; -} - - -bool PIDir::renameDir(const PIString & path, const PIString & new_name) { - if (::rename(path.data(), new_name.data()) == 0) return true; - printf("[PIDir] renameDir(\"%s\", \"%s\") error: %s\n", path.data(), new_name.data(), errorString().c_str()); - return false; -} - - -#endif diff --git a/pidir.h b/pidir.h deleted file mode 100644 index 8a227968..00000000 --- a/pidir.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - PIP - Platform Independent Primitives - Directory - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIDIR_H -#define PIDIR_H - -#include "pifile.h" -#if !defined(ANDROID) -#ifdef WINDOWS -# undef S_IFDIR -# undef S_IFREG -# undef S_IFLNK -# undef S_IFBLK -# undef S_IFCHR -# undef S_IFSOCK -# define S_IFDIR 0x01 -# define S_IFREG 0x02 -# define S_IFLNK 0x04 -# define S_IFBLK 0x08 -# define S_IFCHR 0x10 -# define S_IFSOCK 0x20 -#else -# ifdef ANDROID -# include -# else -# include -# endif -# include -#endif -#define S_IFHDN 0x40 - -class PIP_EXPORT PIDir -{ -public: - PIDir(const PIString & dir = PIString()); - PIDir(const PIFile & file); - - struct DirEntry { - DirEntry(const PIString & name_ = PIString(), int mode_ = 0, int size_ = 0) { - 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 isSymbolicLink() const {return (mode & S_IFLNK);} - bool isBlockDevice() const {return (mode & S_IFBLK);} - bool isCharacterDevice() const {return (mode & S_IFCHR);} - bool isSocket() const {return (mode & S_IFSOCK);} - bool isHidden() const {return (mode & S_IFHDN);} - }; - - bool isExists() const {return PIDir::isExists(path_);} - bool isAbsolute() const; - bool isRelative() const {return !isAbsolute();} - - const PIString & path() const {return path_;} - PIString absolutePath() const; - PIDir & cleanPath(); - PIDir cleanedPath() const {PIDir d(path_); d.cleanPath(); return d;} - PIDir & setDir(const PIString & path); - bool setCurrent() {return PIDir::setCurrent(path_);} - - PIVector entries(); - - bool make(bool withParents = true); - bool remove() {return PIDir::remove(path_);} - bool rename(const PIString & new_name) {if (!PIDir::rename(path_, new_name)) return false; path_ = new_name; return true;} - PIDir & cd(const PIString & path); - PIDir & up() {return cd("..");} - - bool operator ==(const PIDir & d) const; - bool operator !=(const PIDir & d) const {return !((*this) == d);} - - - static const PIChar separator; - - static PIDir current(); - static PIDir home(); - static PIDir temporary(); - static bool isExists(const PIString & path); - static bool make(const PIString & path, bool withParents = true); - static bool remove(const PIString & path) {return removeDir(path);} - static bool rename(const PIString & path, const PIString & new_name) {return PIDir::renameDir(path, new_name);} - static bool setCurrent(const PIString & path); - static bool setCurrent(const PIDir & dir) {return setCurrent(dir.path_);} - -private: - static bool makeDir(const PIString & path); - static bool removeDir(const PIString & path); - static bool renameDir(const PIString & path, const PIString & new_name); - - PIString path_; - -}; - - -inline bool operator <(const PIDir::DirEntry & v0, const PIDir::DirEntry & v1) {return (v0.name < v1.name);} -inline bool operator >(const PIDir::DirEntry & v0, const PIDir::DirEntry & v1) {return (v0.name > v1.name);} -inline bool operator ==(const PIDir::DirEntry & v0, const PIDir::DirEntry & v1) {return (v0.name == v1.name);} -inline bool operator !=(const PIDir::DirEntry & v0, const PIDir::DirEntry & v1) {return (v0.name != v1.name);} - -inline PICout operator <<(PICout s, const PIDir & v) {s.setControl(0, true); s << "PIDir(\"" << v.path() << "\")"; s.restoreControl(); return s;} -inline PICout operator <<(PICout s, const PIDir::DirEntry & v) {s.setControl(0, true); s << "DirEntry(\"" << v.name << "\", " << v.size << " b, " << PIString::fromNumber(v.mode, 16) << ")"; s.restoreControl(); return s;} - - -#endif -#endif // PIDIR_H diff --git a/piethernet.cpp b/piethernet.cpp deleted file mode 100644 index 35b2d2c9..00000000 --- a/piethernet.cpp +++ /dev/null @@ -1,877 +0,0 @@ -/* - PIP - Platform Independent Primitives - Ethernet, UDP/TCP Broadcast/Multicast - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "piethernet.h" -#include "piconfig.h" -#ifdef QNX -# include -# include -# include -#endif - - -/** \class PIEthernet - * \brief Ethernet device - * \details - * \section PIEthernet_sec0 Synopsis - * %PIEthernet designed to work with IPv4 network by two protocols: - * UDP and TCP. This class allow you send and receive packets to/from - * another computer through network. - * - * \section PIEthernet_sec1 IPv4 - * - * - * \section PIEthernet_sec2 UDP - * User Datagram Protocol - * - * \section PIEthernet_sec3 TCP - * Transmission Control Protocol - * - * */ - -REGISTER_DEVICE(PIEthernet); - - -PIEthernet::PIEthernet(): PIIODevice("", ReadWrite) { - piMonitor.ethernets++; - ip_ = ip_s = ""; - port_ = port_s = 0; - sock = sock_s = -1; - connected_ = connecting_ = listen_threaded = server_bounded = false; - server_thread_.setData(this); - setThreadedReadBufferSize(65536); - setPriority(piHigh); - setType(UDP); - setParameters(PIEthernet::ReuseAddress); - //if (type_ != UDP) init(); -} - - -PIEthernet::PIEthernet(PIEthernet::Type type_, const PIString & ip_port, const PIFlags params_): PIIODevice(ip_port, ReadWrite) { - piMonitor.ethernets++; - parseAddress(ip_port, &ip_, &port_); - ip_s = ""; - port_s = 0; - sock = sock_s = -1; - connected_ = connecting_ = listen_threaded = server_bounded = false; - server_thread_.setData(this); - setThreadedReadBufferSize(65536); - setPriority(piHigh); - setType(type_); - setParameters(params_); - if (type_ != UDP) init(); -} - - -PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) { - piMonitor.ethernets++; - parseAddress(ip_port, &ip_s, &port_s); - sock = sock_; - sock_s = -1; - init_ = opened_ = connected_ = true; - connecting_ = listen_threaded = server_bounded = false; - server_thread_.setData(this); - setParameters(PIEthernet::ReuseAddress); - setThreadedReadBufferSize(65536); - setPriority(piHigh); - setType(TCP_Client, false); - setPath(ip_port); -} - - -PIEthernet::~PIEthernet() { - piMonitor.ethernets--; - stop(); - closeDevice(); - //if (buffer_ != 0) delete buffer_; - //buffer_ = 0; -} - - -bool PIEthernet::init() { - //cout << "init " << type_ << endl; - closeSocket(sock); - closeSocket(sock_s); - int st = 0, pr = 0; -#ifdef WINDOWS - int flags = WSA_FLAG_OVERLAPPED; -#else - int so = 1; -#endif - if (type() == UDP) { - st = SOCK_DGRAM; - pr = IPPROTO_UDP; - } else { - st = SOCK_STREAM; - pr = IPPROTO_TCP; - } -#ifdef WINDOWS - if (type() == UDP) flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF; - sock = WSASocket(AF_INET, st, pr, NULL, 0, flags); - sock_s = WSASocket(AF_INET, st, pr, NULL, 0, WSA_FLAG_OVERLAPPED); -#else - sock = socket(AF_INET, st, pr); - sock_s = socket(AF_INET, st, pr); -#endif - if (sock == -1 || sock_s == -1) { - piCoutObj << "Can`t create socket, " << ethErrorString(); - return false; - } - PIFlags params = parameters(); -#ifndef WINDOWS - timeval to; - to.tv_sec = 10; - to.tv_usec = 0; - setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)); - setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &to, sizeof(to)); - if (params[PIEthernet::ReuseAddress]) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &so, sizeof(so)); - if (params[PIEthernet::Broadcast]) setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &so, sizeof(so)); -#else - BOOL bv = TRUE; - if (params[PIEthernet::ReuseAddress]) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char * )&bv, sizeof(bv)); -#endif - //cout << "inited " << sock << ": bc = " << params << endl; - //fcntl(sock, F_SETFL, 0/*O_NONBLOCK*/); - return true; -} - - -void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) { - if (ip != 0) *ip = ipp.left(ipp.find(":")); - if (port != 0) *port = ipp.right(ipp.length() - ipp.find(":") - 1).toInt(); -} - - -bool PIEthernet::openDevice() { - if (connected_) return true; - init(); - if (sock == -1 || path().isEmpty()) return false; - parseAddress(path(), &ip_, &port_); - if (type() != UDP || mode() == PIIODevice::WriteOnly) - return true; - //piCout << "bind to" << (params[PIEthernet::Broadcast] ? "bc" : ip_) << ":" << port_ << " ..."; - memset(&addr_, 0, sizeof(addr_)); - addr_.sin_family = AF_INET; - addr_.sin_port = htons(port_); - PIFlags params = parameters(); - if (params[PIEthernet::Broadcast]) addr_.sin_addr.s_addr = INADDR_ANY; - else addr_.sin_addr.s_addr = inet_addr(ip_.data()); -#ifdef QNX - addr_.sin_len = sizeof(addr_); -#endif - int tries = 0; - while ((bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) && (tries < 10)) { - init(); - tries++; - } - if (tries == 10) { - piCoutObj << "Can`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString(); - return false; - } - opened_ = true; - while (!mcast_queue.isEmpty()) - joinMulticastGroup(mcast_queue.dequeue()); - //cout << "!" << endl; - return true; -} - - -bool PIEthernet::closeDevice() { - //cout << "close\n"; - if (server_thread_.isRunning()) { - server_thread_.stop(); - if (!server_thread_.waitForFinish(100)) - server_thread_.terminate(); - } - closeSocket(sock); - closeSocket(sock_s); - piForeach (PIEthernet * i, clients_) - delete i; - clients_.clear(); - if (connected_) disconnected(false); - connected_ = false; - return true; -} - - -void PIEthernet::closeSocket(int & sd) { - if (sd != -1) { -#ifdef WINDOWS - shutdown(sd, SD_BOTH); - closesocket(sd); -#else - shutdown(sd, SHUT_RDWR); - ::close(sd); -#endif - } - sd = -1; -} - - -void PIEthernet::setParameter(PIEthernet::Parameters parameter, bool on) { - PIFlags cp = (PIFlags)(property("parameters").toInt()); - cp.setFlag(parameter, on); - setParameters(cp); -} - - -bool PIEthernet::joinMulticastGroup(const PIString & group) { - if (sock == -1) init(); - if (sock == -1) return false; - if (type() != UDP) { - piCoutObj << "Only UDP sockets can join multicast groups"; - return false; - } - if (!opened_) { - if (mcast_queue.contains(group)) - return false; - mcast_queue.enqueue(group); - if (!mcast_groups.contains(group)) mcast_groups << group; - return true; - } - PIFlags params = parameters(); -#ifdef WINDOWS - parseAddress(path(), &ip_, &port_); - memset(&addr_, 0, sizeof(addr_)); - addr_.sin_family = AF_INET; - addr_.sin_addr.s_addr = inet_addr(group.data()); - //int so = 1; - //setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char * )&so, sizeof(so)); - SOCKET ret = WSAJoinLeaf(sock, (sockaddr *)&addr_, sizeof(addr_), NULL, NULL, NULL, NULL, JL_BOTH); - if (ret == INVALID_SOCKET) { - piCoutObj << "Can`t join multicast group " << group << ", " << ethErrorString(); - return false; - } - if (ret != sock) { - leafs.insert(group, ret); - if (!mcast_groups.contains(group)) mcast_groups << group; - } -#else -# ifndef QNX - if (!params[Broadcast]) - piCoutObj << "Warning: \"Broadcast\" parameter not set, \"joinMulticastGroup(\"" << group << "\")\" may be useless!"; - parseAddress(path(), &ip_, &port_); - struct ip_mreqn mreq; - memset(&mreq, 0, sizeof(mreq)); - mreq.imr_ifindex = 0; - if (params[PIEthernet::Broadcast]) mreq.imr_address.s_addr = INADDR_ANY; - else mreq.imr_address.s_addr = inet_addr(ip_.data()); - PIEthernet::InterfaceList il = interfaces(); - const PIEthernet::Interface * ci = il.getByAddress(ip_); - if (ci != 0) mreq.imr_ifindex = ci->index; - //piCout << "join group" << group << "ip" << ip_ << "with index" << mreq.imr_ifindex; - mreq.imr_multiaddr.s_addr = inet_addr(group.data()); - int so = 1; - //setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &so, sizeof(so)); - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &so, sizeof(so)); - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq)); - if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) != 0) { - piCoutObj << "Can`t join multicast group " << group << ", " << ethErrorString(); - return false; - } - if (!mcast_groups.contains(group)) mcast_groups << group; -# endif -#endif - return true; -} - - -bool PIEthernet::leaveMulticastGroup(const PIString & group) { - if (sock == -1) init(); - if (sock == -1) return false; - if (type() != UDP) { - piCoutObj << "Only UDP sockets can leave multicast groups"; - return false; - } - PIFlags params = parameters(); -#ifdef WINDOWS - SOCKET s = leafs[group]; - if (s != SOCKET()) { - leafs.erase(group); - closesocket(s); - mcast_groups.removeAll(group); - } -#else -# ifndef QNX - parseAddress(path(), &ip_, &port_); - struct ip_mreqn mreq; - memset(&mreq, 0, sizeof(mreq)); - if (params[PIEthernet::Broadcast]) mreq.imr_address.s_addr = INADDR_ANY; - else mreq.imr_address.s_addr = inet_addr(ip_.data()); - mreq.imr_multiaddr.s_addr = inet_addr(group.data()); - mreq.imr_ifindex = 0; - if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) { - piCoutObj << "Can`t leave multicast group " << group << ", " << ethErrorString(); - return false; - } - mcast_groups.removeAll(group); -#endif -#endif - return true; -} - - -bool PIEthernet::connect() { - connecting_ = true; - return true; - /*if (sock == -1) return false; - memset(&addr_, 0, sizeof(addr_)); - parseAddress(path_, &ip_, &port_); - addr_.sin_port = htons(port_); - addr_.sin_addr.s_addr = inet_addr(ip_.data()); - addr_.sin_family = AF_INET; -#ifdef QNX - addr_.sin_len = sizeof(addr_); -#endif - //piCoutObj << "connect to " << ip << ":" << port_; - connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0); - if (!connected_) - piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString(); - opened_ = connected_; - if (connected_) connected(); - return connected_;*/ -} - - -bool PIEthernet::listen(bool threaded) { - if (sock == -1) init(); - if (sock == -1) return false; - if (threaded) { - if (server_thread_.isRunning()) { - if (!server_bounded) return true; - server_thread_.stop(); - if (!server_thread_.waitForFinish(100)) - server_thread_.terminate(); - } - listen_threaded = true; - server_bounded = false; - server_thread_.start(server_func); - return true; - } - listen_threaded = server_bounded = false; - parseAddress(path(), &ip_, &port_); - memset(&addr_, 0, sizeof(addr_)); - addr_.sin_port = htons(port_); - addr_.sin_addr.s_addr = inet_addr(ip_.data()); - addr_.sin_family = AF_INET; -#ifdef QNX - addr_.sin_len = sizeof(addr_); -#endif - opened_ = false; - int tries = 0; - while ((bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) && (tries < 10)) { - init(); - tries++; - } - if (tries == 10) { - piCoutObj << "Can`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString(); - return false; - } - if (::listen(sock, 64) == -1) { - piCoutObj << "Can`t listen on "<< ip_ << ":" << port_ << ", " << ethErrorString(); - return false; - } - opened_ = server_bounded = true; - //piCoutObj << "listen on " << ip_ << ":" << port_; - server_thread_.start(server_func); - return true; -} - - -int PIEthernet::read(void * read_to, int max_size) { - //cout << "read " << sock << endl; - if (sock == -1) init(); - if (sock == -1 || read_to == 0) return -1; - int rs = 0, s = 0, lerr = 0; - sockaddr_in client_addr; - socklen_t slen = sizeof(client_addr); - //piCoutObj << "read from " << ip_ << ":" << port_ << endl; - switch (type()) { - case TCP_SingleTCP: - ::listen(sock, 64); - s = accept(sock, (sockaddr * )&client_addr, &slen); - if (s == -1) { - //piCoutObj << "Can`t accept new connection, " << ethErrorString(); - msleep(1); - return -1; - } - rs = recv(s, (char * )read_to, max_size, 0); - closeSocket(s); - return rs; - case TCP_Client: - if (connecting_) { - memset(&addr_, 0, sizeof(addr_)); - parseAddress(path(), &ip_, &port_); - addr_.sin_port = htons(port_); - addr_.sin_addr.s_addr = inet_addr(ip_.data()); - addr_.sin_family = AF_INET; -#ifdef QNX - addr_.sin_len = sizeof(addr_); -#endif - //piCoutObj << "connect to " << ip_ << ":" << port_ << "..."; - connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0); - //piCoutObj << "connect to " << ip_ << ":" << port_ << connected_; - if (!connected_) - piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString(); - opened_ = connected_; - if (connected_) { - connecting_ = false; - connected(); - } else - piMSleep(10); - //piCout << "connected to" << path(); - } - if (!connected_) return -1; - errorClear(); -#ifdef WINDOWS - rs = recv(sock, (char * )read_to, max_size, 0); -#else - rs = recv(sock, read_to, max_size, MSG_DONTWAIT); -#endif - //piCoutObj << "readed" << rs; - if (rs <= 0) { -#ifdef WINDOWS - lerr = WSAGetLastError(); - if (lerr == WSAEWOULDBLOCK) { - piMSleep(10); - return -1; - } -#else - lerr = errno; - //piCoutObj << errorString(); - if (lerr == EAGAIN || lerr == EWOULDBLOCK) { - piMSleep(10); - return -1; - } -#endif - if (connected_) { - init(); - disconnected(rs < 0); - } - connected_ = false; - //piCoutObj << "eth" << ip_ << "disconnected"; - } - if (rs > 0) received(read_to, rs); - return rs; - case UDP: -#ifdef WINDOWS - rs = recv(sock, (char * )read_to, max_size, 0); -#else - rs = recv(sock, read_to, max_size, 0); -#endif - //piCout << "eth" << path() << "read return" << rs << errno; - if (rs > 0) received(read_to, rs); - return rs; - //return ::read(sock, read_to, max_size); - default: break; - //return ::read(sock, (char * )read_to, max_size); - } - return -1; -} - - -int PIEthernet::write(const void * data, int max_size) { - if (sock == -1) init(); - if (sock == -1 || !isWriteable()) { - //piCoutObj << "Can`t send to uninitialized socket"; - return -1; - } - //piCoutObj << "sending to " << ip_s << ":" << port_s << " " << max_size << " bytes"; - int ret = 0; - switch (type()) { - case TCP_SingleTCP: - memset(&addr_, 0, sizeof(addr_)); - addr_.sin_port = htons(port_s); - addr_.sin_addr.s_addr = inet_addr(ip_s.data()); - addr_.sin_family = AF_INET; -#ifdef QNX - addr_.sin_len = sizeof(addr_); -#endif - //piCoutObj << "connect SingleTCP" << ip_s << ":" << port_s << "..."; - if (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) != 0) { - //piCoutObj << "Can`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString(); - msleep(1); - return -1; - } - //piCoutObj << "ok, write SingleTCP" << int(data) << max_size << "bytes ..."; - ret = ::send(sock, (const char *)data, max_size, 0); - //piCoutObj << "ok, ret" << ret; - closeSocket(sock); - init(); - return ret; - case UDP: - saddr_.sin_port = htons(port_s); - /*if (params[PIEthernet::Broadcast]) saddr_.sin_addr.s_addr = INADDR_BROADCAST; - else*/ saddr_.sin_addr.s_addr = inet_addr(ip_s.data()); - saddr_.sin_family = AF_INET; - //piCout << "[PIEth] write to" << ip_s << ":" << port_s << max_size << "bytes ..."; -#ifdef WINDOWS - return sendto(sock_s, (const char * )data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_)); -#else - return sendto(sock_s, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_)); -#endif - //piCout << "[PIEth] write to" << ip_s << ":" << port_s << "ok"; - case TCP_Client: - if (connecting_) { - memset(&addr_, 0, sizeof(addr_)); - parseAddress(path(), &ip_, &port_); - addr_.sin_port = htons(port_); - addr_.sin_addr.s_addr = inet_addr(ip_.data()); - addr_.sin_family = AF_INET; -#ifdef QNX - addr_.sin_len = sizeof(addr_); -#endif - //piCoutObj << "connect to " << ip << ":" << port_; - connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0); - if (!connected_) - piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString(); - opened_ = connected_; - if (connected_) { - connecting_ = false; - connected(); - } - } - if (!connected_) return -1; - ret = ::send(sock, (const char *)data, max_size, 0); - if (ret < 0) { - connected_ = false; { - init(); - disconnected(true); - } - } - return ret; - default: break; - //return ::read(sock, read_to, max_size); - } - return -1; -} - -void PIEthernet::server_func(void * eth) { - PIEthernet * ce = (PIEthernet * )eth; - if (ce->listen_threaded) { - if (!ce->server_bounded) { - if (!ce->listen(false)) { - ce->listen_threaded = true; - piMSleep(100); - return; - } - } - } - sockaddr_in client_addr; - socklen_t slen = sizeof(client_addr); - int s = accept(ce->sock, (sockaddr * )&client_addr, &slen); - if (s == -1) { - if (ce->debug()) piCout << "[PIEthernet] Can`t accept new connection, " << ethErrorString(); - piMSleep(10); - return; - } - PIString ip(inet_ntoa(client_addr.sin_addr)); - ip += ":" + PIString::fromNumber(htons(client_addr.sin_port)); - ce->clients_ << new PIEthernet(s, ip); - ce->newConnection(ce->clients_.back()); - //cout << "connected " << ip << endl; - //char d[256]; - //cout << " recv " << recv(s, d, 256, 0) << endl; - //cout << recv(ce->clients_.back()->sock, d, 256, 0) << endl; - -} - - -bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) { - PIConfig::Entry * em = (PIConfig::Entry * )e_main; - PIConfig::Entry * ep = (PIConfig::Entry * )e_parent; - setReadIP(readDeviceSetting("ip", readIP(), em, ep)); - setReadPort(readDeviceSetting("port", readPort(), em, ep)); - setParameter(PIEthernet::Broadcast, readDeviceSetting("broadcast", isParameterSet(PIEthernet::Broadcast), em, ep)); - setParameter(PIEthernet::ReuseAddress, readDeviceSetting("reuseAddress", isParameterSet(PIEthernet::ReuseAddress), em, ep)); - return true; -} - - -PIString PIEthernet::constructFullPath() const { - PIString ret(fullPathPrefix() + "://"); - ret << (type() == PIEthernet::UDP ? "UDP" : "TCP") << ":" << readIP() << ":" << readPort(); - if (type() == PIEthernet::UDP) { - piForeachC (PIString & m, multicastGroups()) - ret << ":mcast:" << m; - } - return ret; -} - - -void PIEthernet::configureFromFullPath(const PIString & full_path) { - PIStringList pl = full_path.split(":"); - bool mcast = false; - for (int i = 0; i < pl.size_s(); ++i) { - PIString p(pl[i]); - switch (i) { - case 0: - p = p.toLowerCase(); - if (p == "udp") setType(UDP); - if (p == "tcp") setType(TCP_Client); - break; - case 1: setReadIP(p); setSendIP(p); break; - case 2: setReadPort(p.toInt()); setSendPort(p.toInt()); break; - } - if (i <= 2) continue; - if (i % 2 == 1) {if (p.toLowerCase() == "mcast") mcast = true;} - else {if (mcast) {joinMulticastGroup(p); mcast = false;}} - } -} - - -PIEthernet::InterfaceList PIEthernet::interfaces() { - PIEthernet::InterfaceList il; - Interface ci; -#ifdef WINDOWS - PIP_ADAPTER_INFO pAdapterInfo, pAdapter = 0; - int ret = 0; - ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO); - pAdapterInfo = (IP_ADAPTER_INFO * ) HeapAlloc(GetProcessHeap(), 0, (sizeof (IP_ADAPTER_INFO))); - if (pAdapterInfo == 0) { - piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo"; - return il; - } - if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { - HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); - pAdapterInfo = (IP_ADAPTER_INFO *) HeapAlloc(GetProcessHeap(), 0, (ulOutBufLen)); - if (pAdapterInfo == 0) { - piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo"; - return il; - } - } - if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { - pAdapter = pAdapterInfo; - while (pAdapter) { - ci.name = PIString(pAdapter->AdapterName); - ci.index = pAdapter->Index; - ci.address = PIString(pAdapter->IpAddressList.IpAddress.String); - if (ci.address == "0.0.0.0") { - pAdapter = pAdapter->Next; - continue; - } - ci.mac = macFromBytes(PIByteArray(pAdapter->Address, pAdapter->AddressLength)); - ci.netmask = PIString(pAdapter->IpAddressList.IpMask.String); - ci.flags = PIEthernet::ifActive | PIEthernet::ifRunning; - //if (ret->ifa_flags & IFF_BROADCAST) ci.flags |= PIEthernet::ifBroadcast; - //if (ret->ifa_flags & IFF_MULTICAST) ci.flags |= PIEthernet::ifMulticast; - if (pAdapter->Type == MIB_IF_TYPE_PPP) ci.flags |= PIEthernet::ifPTP; - if (pAdapter->Type == MIB_IF_TYPE_LOOPBACK) ci.flags |= PIEthernet::ifLoopback; - ci.broadcast.clear(); - ci.ptp.clear(); - /*if (ci.flags[PIEthernet::ifBroadcast]) - ci.broadcast = getSockAddr(ret->ifa_broadaddr); - if (ci.flags[PIEthernet::ifPTP]) - ci.ptp = getSockAddr(ret->ifa_dstaddr);*/ - il << ci; - pAdapter = pAdapter->Next; - } - } else - piCout << "[PIEthernet] GetAdaptersInfo failed with error: " << ret; - if (pAdapterInfo) - HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); -#else -/*# ifdef QNX - PIStringList il, sl; - PIProcess proc; - proc.setGrabOutput(true); - proc.exec(ifconfigPath.c_str(), "-l"); - if (!proc.waitForFinish(1000)) return sl; - PIString out(proc.readOutput()); - il = out.split(" "); - il.removeAll(""); - piForeachC (PIString & i, il) { - proc.exec(ifconfigPath.c_str(), i); - if (!proc.waitForFinish(1000)) return il; - sl << i.trimmed(); - out = proc.readOutput(); - int al = out.length(); - al = (al - out.replaceAll("alias", "").length()) / 5; - for (int j = 0; j < al; ++j) - sl << i.trimmed() + ":" + PIString::fromNumber(j); - } - return sl; -# else - PIStringList sl; - PIProcess proc; - proc.setGrabOutput(true); - proc.exec(ifconfigPath.c_str(), "-s"); - if (!proc.waitForFinish(1000)) return sl; - PIString out(proc.readOutput()); - out.cutLeft(out.find('\n') + 1); - while (!out.isEmpty()) { - sl << out.left(out.find(' ')); - out.cutLeft(out.find('\n') + 1); - } - return sl; -# endif*/ -# ifdef ANDROID - struct ifconf ifc; - int s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - ifc.ifc_len = 256; - ifc.ifc_buf = new char[ifc.ifc_len]; - if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { - piCout << "[PIEthernet] Can`t get interfaces:" << errorString(); - delete ifc.ifc_buf; - return il; - } - int icnt = ifc.ifc_len / sizeof(ifreq); - PIStringList inl; - struct ifreq ir; - for (int i = 0; i < icnt; ++i) { - PIString in(ifc.ifc_req[i].ifr_name); - if (in.isEmpty()) continue; - ci.name = in; - strcpy(ir.ifr_name, in.data()); - if (ioctl(s, SIOCGIFHWADDR, &ir) == 0) - ci.mac = macFromBytes(PIByteArray(ir.ifr_hwaddr.sa_data, 6)); - if (ioctl(s, SIOCGIFADDR, &ir) >= 0) - ci.address = getSockAddr(&ir.ifr_addr); - if (ioctl(s, SIOCGIFNETMASK, &ir) >= 0) - ci.netmask = getSockAddr(&ir.ifr_addr); - il << ci; - } - delete ifc.ifc_buf; -# else - struct ifaddrs * ret; - int s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - if (getifaddrs(&ret) == 0) { - while (ret != 0) { - if (ret->ifa_addr->sa_family != AF_INET) { - ret = ret->ifa_next; - continue; - } - ci.name = PIString(ret->ifa_name); - ci.address = getSockAddr(ret->ifa_addr); - ci.netmask = getSockAddr(ret->ifa_netmask); - ci.mac.clear(); -# ifdef QNX - int fd = ::open((PIString("/dev/io-net/") + ci.name).data(), O_RDONLY); - if (fd != 0) { - nic_config_t nic; - devctl(fd, DCMD_IO_NET_GET_CONFIG, &nic, sizeof(nic), 0); - ::close(fd); - ci.mac = macFromBytes(PIByteArray(nic.permanent_address, 6)); - } -# else -# ifdef MAC_OS - PIString req = PIString(PIInit::instance()->ifconfigPath) + " " + ci.name + " | grep ether"; - FILE * fp = popen(req.data(), "r"); - if (fp != 0) { - char in[256]; - if (fgets(in, 256, fp) != 0) { - req = PIString(in).trim(); - ci.mac = req.cutLeft(req.find(" ") + 1).trim().toUpperCase(); - } - pclose(fp); - } -# else - if (s != -1) { - struct ifreq ir; - strcpy(ir.ifr_name, ret->ifa_name); - if (ioctl(s, SIOCGIFHWADDR, &ir) == 0) - ci.mac = macFromBytes(PIByteArray(ir.ifr_hwaddr.sa_data, 6)); - } -# endif -# endif - ci.flags = 0; - if (ret->ifa_flags & IFF_UP) ci.flags |= PIEthernet::ifActive; - if (ret->ifa_flags & IFF_RUNNING) ci.flags |= PIEthernet::ifRunning; - if (ret->ifa_flags & IFF_BROADCAST) ci.flags |= PIEthernet::ifBroadcast; - if (ret->ifa_flags & IFF_MULTICAST) ci.flags |= PIEthernet::ifMulticast; - if (ret->ifa_flags & IFF_LOOPBACK) ci.flags |= PIEthernet::ifLoopback; - if (ret->ifa_flags & IFF_POINTOPOINT) ci.flags |= PIEthernet::ifPTP; - ci.broadcast.clear(); - ci.ptp.clear(); - if (ci.flags[PIEthernet::ifBroadcast]) - ci.broadcast = getSockAddr(ret->ifa_broadaddr); - if (ci.flags[PIEthernet::ifPTP]) - ci.ptp = getSockAddr(ret->ifa_dstaddr); - ci.index = if_nametoindex(ret->ifa_name); - il << ci; - ret = ret->ifa_next; - } - freeifaddrs(ret); - } else - piCout << "[PIEthernet] Can`t get interfaces:" << errorString(); - if (s != -1) ::close(s); -# endif -#endif - return il; -} - - -PIString PIEthernet::interfaceAddress(const PIString & interface_) { -#ifdef WINDOWS - piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" or \"PIEthernet::interfaces\" instead"; - return PIString(); -#else - struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - strcpy(ifr.ifr_name, interface_.data()); - int s = socket(AF_INET, SOCK_DGRAM, 0); - ioctl(s, SIOCGIFADDR, &ifr); - ::close(s); - struct sockaddr_in * sa = (struct sockaddr_in * )&ifr.ifr_addr; - return PIString(inet_ntoa(sa->sin_addr)); -#endif - -} - - -PIStringList PIEthernet::allAddresses() { -/*#ifdef WINDOWS - PIStringList al; - PIString ca; - PIP_ADAPTER_INFO pAdapterInfo, pAdapter = 0; - int ret = 0; - ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO); - pAdapterInfo = (IP_ADAPTER_INFO * ) HeapAlloc(GetProcessHeap(), 0, (sizeof (IP_ADAPTER_INFO))); - if (pAdapterInfo == 0) { - piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo"; - return PIStringList(); - } - if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { - HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); - pAdapterInfo = (IP_ADAPTER_INFO *) HeapAlloc(GetProcessHeap(), 0, (ulOutBufLen)); - if (pAdapterInfo == 0) { - piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo"; - return PIStringList(); - } - } - if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { - pAdapter = pAdapterInfo; - while (pAdapter) { - ca = PIString(pAdapter->IpAddressList.IpAddress.String); - if (ca != "0.0.0.0") al << ca; - pAdapter = pAdapter->Next; - } - } else - piCout << "[PIEthernet] GetAdaptersInfo failed with error: " << ret; - if (pAdapterInfo) - HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); - return al; -#else*/ - PIEthernet::InterfaceList il = interfaces(); - PIStringList al; - piForeachC (PIEthernet::Interface & i, il) - al << i.address; - return al.removeStrings("0.0.0.0"); -//#endif -} diff --git a/piethernet.h b/piethernet.h deleted file mode 100644 index 705f4de1..00000000 --- a/piethernet.h +++ /dev/null @@ -1,364 +0,0 @@ -/*! \file piethernet.h - * \brief Ethernet device -*/ -/* - PIP - Platform Independent Primitives - Ethernet, UDP/TCP Broadcast/Multicast - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIETHERNET_H -#define PIETHERNET_H - -#include "pitimer.h" -#include "piiodevice.h" -#include "piprocess.h" - -class PIP_EXPORT PIEthernet: public PIIODevice -{ - PIIODEVICE(PIEthernet) - friend class PIPeer; -public: - - //! Contructs UDP %PIEthernet with empty read address - PIEthernet(); - - //! \brief Type of %PIEthernet - enum PIP_EXPORT Type { - UDP /** UDP - User Datagram Protocol */ , - TCP_Client /** TCP client - allow connection to TCP server */ , - TCP_Server /** TCP server - receive connections from TCP clients */ , - TCP_SingleTCP - }; - - //! \brief Parameters of %PIEthernet - enum PIP_EXPORT Parameters { - ReuseAddress /** Rebind address if there is already binded */ = 0x1, - Broadcast /** Broadcast send */ = 0x2 - }; - - //! Contructs %PIEthernet with type "type", read address "ip_port" and parameters "params" - PIEthernet(Type type, const PIString & ip_port = PIString(), const PIFlags params = 0); - - virtual ~PIEthernet(); - - - //! Set read address - void setReadAddress(const PIString & ip, int port) {setPath(ip + ":" + PIString::fromNumber(port));} - - //! Set read address in format "i.i.i.i:p" - void setReadAddress(const PIString & ip_port) {setPath(ip_port);} - - //! Set read IP - void setReadIP(const PIString & ip) {parseAddress(path(), &ip_, &port_); setPath(ip + ":" + PIString::fromNumber(port_));} - - //! Set read port - void setReadPort(int port) {parseAddress(path(), &ip_, &port_); setPath(ip_ + ":" + PIString::fromNumber(port));} - - - //! Set send address - void setSendAddress(const PIString & ip, int port) {ip_s = ip; port_s = port;} - - //! Set send address in format "i.i.i.i:p" - void setSendAddress(const PIString & ip_port) {parseAddress(ip_port, &ip_s, &port_s);} - - //! Set send IP - void setSendIP(const PIString & ip) {ip_s = ip;} - - //! Set send port - void setSendPort(int port) {port_s = port;} - - - //! Returns read address in format "i.i.i.i:p" - PIString readAddress() const {return path();} - - //! Returns read IP - PIString readIP() const {parseAddress(path(), &ip_, &port_); return ip_;} - - //! Returns read port - int readPort() const {parseAddress(path(), &ip_, &port_); return port_;} - - - //! Returns send address in format "i.i.i.i:p" - PIString sendAddress() const {return ip_s + ":" + PIString::fromNumber(port_s);} - - //! Returns send IP - PIString sendIP() const {return ip_s;} - - //! Returns send port - int sendPort() const {return port_s;} - - - //! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them - void setParameters(PIFlags parameters_) {setProperty("parameters", (int)parameters_);} - - //! Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this - void setParameter(PIEthernet::Parameters parameter, bool on = true); - - //! Returns if parameter "parameter" is set - bool isParameterSet(PIEthernet::Parameters parameter) const {return ((PIFlags)(property("parameters").toInt()))[parameter];} - - //! Returns parameters - PIFlags parameters() const {return (PIFlags)(property("parameters").toInt());} - - //PIByteArray macAddress() {if (!init_) init(); struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); memcpy(ifr.ifr_name, "eth0", 5); ioctl(sock, SIOCSIFHWADDR, &ifr); return PIByteArray(&ifr.ifr_hwaddr.sa_data, 6);} - - //! Returns %PIEthernet type - Type type() const {return (Type)(property("type").toInt());} - - - //! Join to multicast group with address "group". Use only for UDP - bool joinMulticastGroup(const PIString & group); - - //! Leave multicast group with address "group". Use only for UDP - bool leaveMulticastGroup(const PIString & group); - - //! Returns joined multicast groups. Use only for UDP - const PIStringList & multicastGroups() const {return mcast_groups;} - - - //! Connect to TCP server with address \a readAddress(). Use only for TCP_Client - bool connect(); - - //! Connect to TCP server with address "ip":"port". Use only for TCP_Client - bool connect(const PIString & ip, int port) {setPath(ip + ":" + PIString::fromNumber(port)); return connect();} - - //! Connect to TCP server with address "ip_port". Use only for TCP_Client - bool connect(const PIString & ip_port) {setPath(ip_port); return connect();} - - //! Returns if %PIEthernet connected to TCP server. Use only for TCP_Client - bool isConnected() const {return connected_;} - - - //! Start listen for incoming TCP connections on address \a readAddress(). Use only for TCP_Server - bool listen(bool threaded = false); - - //! Start listen for incoming TCP connections on address "ip":"port". Use only for TCP_Server - bool listen(const PIString & ip, int port, bool threaded = false) {setReadAddress(ip, port); return listen(threaded);} - - //! Start listen for incoming TCP connections on address "ip_port". Use only for TCP_Server - bool listen(const PIString & ip_port, bool threaded = false) {setReadAddress(ip_port); return listen(threaded);} - - PIEthernet * client(int index) {return clients_[index];} - int clientsCount() const {return clients_.size_s();} - PIVector clients() const {return clients_;} - - - //! Send data "data" with size "size" to address "ip":"port" - bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {ip_s = ip; port_s = port; if (threaded) {writeThreaded(data, size); return true;} return send(data, size);} - - //! Send data "data" with size "size" to address "ip_port" - bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {parseAddress(ip_port, &ip_s, &port_s); if (threaded) {writeThreaded(data, size); return true;} return send(data, size);} - - //! Send data "data" with size "size" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client - bool send(const void * data, int size, bool threaded = false) {if (threaded) {writeThreaded(data, size); return true;} return (write(data, size) == size);} - - //! Send data "data" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client - bool send(const PIByteArray & data, bool threaded = false) {if (threaded) {writeThreaded(data); return true;} return (write(data) == data.size_s());} - - - //! Wait for some data and read it to "read_to" - int read(void * read_to, int max_size); - - //! Send data "read_to" with size "max_size" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client - int write(const void * data, int max_size); - - //! Send data "data" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client - int write(const PIByteArray & data) {return write(data.data(), data.size_s());} - - PIString constructFullPath() const; - - EVENT1(newConnection, PIEthernet * , client) - EVENT0(connected) - EVENT1(disconnected, bool, withError) - - - //! Flags of network interface - enum PIP_EXPORT InterfaceFlag { - ifActive /** Is active */ = 0x1, - ifRunning /** Is running */ = 0x2, - ifBroadcast /** Support broadcast */ = 0x4, - ifMulticast /** Support multicast */ = 0x8, - ifLoopback /** Is loopback */ = 0x10, - ifPTP /** Is point-to-point */ = 0x20 - }; - - //! %PIFlags of network interface flags - typedef PIFlags InterfaceFlags; - - - //! Network interface descriptor - struct PIP_EXPORT Interface { - - //! System index - int index; - - //! System name - PIString name; - - //! MAC address in format "hh:hh:hh:hh:hh:hh" or empty if there is no MAC address - PIString mac; - - //! IP address in format "i.i.i.i" or empty if there is no IP address - PIString address; - - //! Netmask of IP address in format "i.i.i.i" or empty if there is no netmask - PIString netmask; - - //! Broadcast address in format "i.i.i.i" or empty if there is no broadcast address - PIString broadcast; - - //! Point-to-point address or empty if there is no point-to-point address - PIString ptp; - - //! Flags of interface - InterfaceFlags flags; - - //! Returns if interface is active - bool isActive() const {return flags[PIEthernet::ifActive];} - - //! Returns if interface is running - bool isRunning() const {return flags[PIEthernet::ifRunning];} - - //! Returns if interface support broadcast - bool isBroadcast() const {return flags[PIEthernet::ifBroadcast];} - - //! Returns if interface support multicast - bool isMulticast() const {return flags[PIEthernet::ifMulticast];} - - //! Returns if interface is loopback - bool isLoopback() const {return flags[PIEthernet::ifLoopback];} - - //! Returns if interface is point-to-point - bool isPTP() const {return flags[PIEthernet::ifPTP];} - }; - - - //! Array of \a Interface with some features - class PIP_EXPORT InterfaceList: public PIVector { - public: - InterfaceList(): PIVector() {} - - //! Get interface with system index "index" or 0 if there is no one - const Interface * getByIndex(int index) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].index == index) return &((*this)[i]); return 0;} - - //! Get interface with system name "name" or 0 if there is no one - const Interface * getByName(const PIString & name) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].name == name) return &((*this)[i]); return 0;} - - //! Get interface with IP address "address" or 0 if there is no one - const Interface * getByAddress(const PIString & address) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].address == address) return &((*this)[i]); return 0;} - - //! Get loopback interface or 0 if there is no one - const Interface * getLoopback() const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].isLoopback()) return &((*this)[i]); return 0;} - }; - - - //! Returns all system network interfaces - static InterfaceList interfaces(); - - static PIString interfaceAddress(const PIString & interface_); - - //! Returns all system network IP addresses - static PIStringList allAddresses(); - - static void parseAddress(const PIString & ipp, PIString * ip, int * port); - static PIString macFromBytes(const PIByteArray & mac) {PIString r; for (int i = 0; i < mac.size_s(); ++i) {r += PIString::fromNumber(mac[i], 16).expandLeftTo(2, '0'); if (i < mac.size_s() - 1) r += ":";} return r;} - static PIByteArray macToBytes(const PIString & mac) {PIByteArray r; PIStringList sl = mac.split(":"); piForeachC (PIString & i, sl) r << uchar(i.toInt(16)); return r;} - static PIString applyMask(const PIString & ip, const PIString & mask) {struct in_addr ia; ia.s_addr = inet_addr(ip.data()) & inet_addr(mask.data()); return PIString(inet_ntoa(ia));} - static PIString getBroadcast(const PIString & ip, const PIString & mask) {struct in_addr ia; ia.s_addr = inet_addr(ip.data()) | ~inet_addr(mask.data()); return PIString(inet_ntoa(ia));} - -//! \events -//! \{ - - //! \fn void newConnection(PIEthernet * client) - //! \brief Raise on new TCP connection received - - //! \fn void connected() - //! \brief Raise if succesfull TCP connection - - //! \fn void disconnected(bool withError) - //! \brief Raise if TCP connection was closed - -//! \} -//! \ioparams -//! \{ -#ifdef DOXYGEN - //! \brief read ip, default "" - string ip; - - //! \brief read port, default 0 - int port; - - //! \brief Broadcast parameter, default false - bool broadcast; - - //! \brief ReuseAddress parameter, default false - bool reuseAddress; -#endif -//! \} - -protected: - PIEthernet(int sock, PIString ip_port); - - PIString fullPathPrefix() const {return "eth";} - void configureFromFullPath(const PIString & full_path); - bool configureDevice(const void * e_main, const void * e_parent = 0); - - //! Executes when any read function was successful. Default implementation does nothing - virtual void received(const void * data, int size) {;} - - bool init(); - bool openDevice(); - bool closeDevice(); - void closeSocket(int & sd); -#ifndef WINDOWS - static PIString getSockAddr(sockaddr * s) {return s == 0 ? PIString() : PIString(inet_ntoa(((sockaddr_in*)s)->sin_addr));} -#endif - - - int sock, sock_s, wrote; - mutable int port_, port_s, port_c; - bool connected_, connecting_, listen_threaded, server_bounded; - sockaddr_in addr_, saddr_; - mutable PIString ip_, ip_s, ip_c; - PIThread server_thread_; - PIVector clients_; - PIQueue mcast_queue; - PIStringList mcast_groups; -#ifdef WINDOWS - PIMap leafs; -#endif - -private: - static void server_func(void * eth); - void setType(Type t, bool reopen = true) {setProperty("type", (int)t); if (reopen && isOpened()) {closeDevice(); init(); openDevice();}} - - static std::string ethErrorString() { -#ifdef WINDOWS - char * msg; - int err = WSAGetLastError(); - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL); - return "code " + itos(err) + " - " + string(msg); -#else - return errorString(); -#endif - } - -}; - -inline bool operator <(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {return (v0.name < v1.name);} - -#endif // PIETHERNET_H diff --git a/pievaluator.cpp b/pievaluator.cpp deleted file mode 100644 index 98821562..00000000 --- a/pievaluator.cpp +++ /dev/null @@ -1,1252 +0,0 @@ -/* - PIP - Platform Independent Primitives - Evaluator designed for stream computing - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pievaluator.h" - - -/*! \class PIEvaluator - * \brief This class provide mathematical evaluations of custom expression - * - * \section PIEvaluator_sec0 Synopsis - * %PIEvaluator developed for stream evaluations of once set expression. - * It`s create internal list of instructions on function \a check() and - * executes very fast on function \a evaluate(). Once given expression - * can be evaluated any times with different variable values. Evaluator - * supports many common mathematic functions described below. Also it`s - * automatic puts unnecessarily signs and bracets. Processed expression - * can be obtains with function \a expression(). If there is an error - * in expression you can get it with function \a error(). Last evaluated - * result you can get with function \a lastResult(). - * \section PIEvaluator_sec1 Using - * First you should set your variables with function \a setVariable(). - * Next give your expression with function \a check() and check for error - * with functions \a isCorrect() and \a error(). If expression is correct - * you can get processed expression with function \a expression() and - * evaluate it with function \a evaluate(). You can change variable values - * without rechecking expression. - * - * \section PIEvaluator_sec2 Functions - * %PIEvaluator supports arithmetical operations with complex numbers, this - * is their list in priority order: - * * ^ (power) - * * * (multiply) - * * / (divide) - * * % (residue) - * * + (add) - * * - (subtract) - * - * In addition there are compare and logical operations: - * * == (equal) - * * != (not equal) - * * > (greater) - * * < (smaller) - * * >= (greater or equal) - * * <= (smaller or equal) - * * && (and) - * * || (or) - * - * Compare and logical functions works with real operators part and returns 0 or 1. - * - * Mathematical functions: - * * sin(x) - sine - * * cos(x) - cosine - * * tg(x) - tangent - * * ctg(x) - cotangent - * * arcsin(x) - arcsine - * * arccos(x) - arccosine - * * arctg(x) -arccotangent - * * arcctg(x) - arctangent - * * sh(x) - hyperbolical sine - * * ch(x) - hyperbolical cosine - * * th(x) - hyperbolical tangent - * * cth(x) - hyperbolical cotangent - * * sqr(x) - square - * * sqrt(x) - square root - * * abs(x) - absolute value - * * sign(x) - sign of real part (-1 or 1) - * * exp(x) - exponent - * * pow(x, p) - x in power p - * * ln(x) - natural logarithm - * * lg(x) - decimal logarithm - * * log(x, b) - logarithm of x with base b - * * im(x) - imaginary part of complex number - * * re(x) - real part of complex number - * * arg(x) - argument of complex number - * * len(x) - length of complex number - * * conj(x) - length of complex number - * * rad(x) - convert degrees to radians - * * deg(x) - convert radians to degrees - * * j0(x) - Bessel function first kind order 0 - * * j1(x) - Bessel function first kind order 1 - * * jn(x, n) - Bessel function first kind order n - * * y0(x) - Bessel function second kind order 0 - * * y1(x) - Bessel function second kind order 1 - * * yn(x, n) - Bessel function second kind order n - * * random(s, f) - regular random number in range [s, f] - * * min(x0, x1, ...) - minimum of x0, x1, ... - * * max(x0, x1, ...) - maximum of x0, x1, ... - * * clamp(x, a, b) - trim x on range [a, b] - * * step(x, s) - 0 if x < s, else 1 - * * mix(x, a, b) - interpolate between a and b linear for x (a * (1 - x) + b * x) - * - * There are some built-in constans: - * * i (imaginary 1) - * * e - * * pi - * - * All trigonometric functions takes angle in radians. - * - * \section PIEvaluator_sec3 Example - * \snippet pievaluator.cpp main - */ - - -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); - addFunction("j0", 1); - addFunction("j1", 1); - addFunction("jn", 2); - addFunction("y0", 1); - addFunction("y1", 1); - addFunction("yn", 2); - addFunction("min", -2); // (x0,x1,...) - addFunction("max", -2); // (x0,x1,...) - addFunction("clamp", 3); // (x,a,b) = x < a ? a : (x > b ? b : x) - addFunction("step", 2); // (x,s) = x >= s ? 1. : 0. (1 if 'x' >= 's', else 0) - addFunction("mix", 3); // (x,a,b) = a*(1.-x) + b*x (interpolate between 'a' and 'b' linear for 'x') - addFunction("defined", 1); - clearCustomVariables(); - //addVariable("n", 0.); - //addVariable("x1", 123); -} - - -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_i); - 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; - if (name == "j0") return PIEvaluatorTypes::bfJ0; - if (name == "j1") return PIEvaluatorTypes::bfJ1; - if (name == "jn") return PIEvaluatorTypes::bfJN; - if (name == "y0") return PIEvaluatorTypes::bfY0; - if (name == "y1") return PIEvaluatorTypes::bfY1; - if (name == "yn") return PIEvaluatorTypes::bfYN; - if (name == "min") return PIEvaluatorTypes::bfMin; - if (name == "max") return PIEvaluatorTypes::bfMax; - if (name == "clamp") return PIEvaluatorTypes::bfClamp; - if (name == "step") return PIEvaluatorTypes::bfStep; - if (name == "mix") return PIEvaluatorTypes::bfMix; - if (name == "defined") return PIEvaluatorTypes::bfDefined; - return PIEvaluatorTypes::bfUnknown; -} - -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_s())); - } - 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]; - PIEvaluatorTypes::Function cf; - int fac, gac; - switch (ci.operation) { - case PIEvaluatorTypes::oNone: break; - case PIEvaluatorTypes::oFunction: - cf = content.function(ci.function); - fac = cf.arguments; - gac = ci.operators.size_s(); - 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; - gac--; - } - } - if (fac > 0) { - if (gac != fac) { - lastError = "Invalid arguments count for function \"" + cf.identifier + - "\", expected " + PIString::fromNumber(fac) + " but " + - PIString::fromNumber(gac) + " given"; - return false; - } - if (error) { - lastError = "Invalid at least one of function \"" + cf.identifier + "\" argument"; - return false; - } - } - if (fac < 0) { - if (gac < -fac) { - lastError = "Invalid arguments count for function \"" + cf.identifier + - "\", expected at least " + PIString::fromNumber(-fac) + " but " + - PIString::fromNumber(gac) + " given"; - return false; - } - if (error) { - lastError = "Invalid at least one of function \"" + cf.identifier + "\" argument"; - 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, ttmp; - //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: - tmpvars[oi].value = value(ci.operators[0]).real() >= 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::bfJ0: - tmpvars[oi].value = piJ0(value(ci.operators[0]).real()); - break; - case PIEvaluatorTypes::bfJ1: - tmpvars[oi].value = piJ1(value(ci.operators[0]).real()); - break; - case PIEvaluatorTypes::bfJN: - tmpvars[oi].value = piJn(piRoundd(value(ci.operators[1]).real()), value(ci.operators[0]).real()); - break; - case PIEvaluatorTypes::bfY0: - tmpvars[oi].value = piY0(value(ci.operators[0]).real()); - break; - case PIEvaluatorTypes::bfY1: - tmpvars[oi].value = piY1(value(ci.operators[0]).real()); - break; - case PIEvaluatorTypes::bfYN: - tmpvars[oi].value = piYn(piRoundd(value(ci.operators[1]).real()), value(ci.operators[0]).real()); - break; - case PIEvaluatorTypes::bfMin: - tmp = value(ci.operators[0]); - for (int i = 1; i < ci.operators.size_s(); ++i) { - stmp = value(ci.operators[i]); - tmp = complexd(piMind(tmp.real(), stmp.real()), piMind(tmp.imag(), stmp.imag())); - } - tmpvars[oi].value = tmp; - break; - case PIEvaluatorTypes::bfMax: - tmp = value(ci.operators[0]); - for (int i = 1; i < ci.operators.size_s(); ++i) { - stmp = value(ci.operators[i]); - tmp = complexd(piMaxd(tmp.real(), stmp.real()), piMaxd(tmp.imag(), stmp.imag())); - } - tmpvars[oi].value = tmp; - break; - case PIEvaluatorTypes::bfClamp: - tmp = value(ci.operators[0]); - stmp = value(ci.operators[1]); - ttmp = value(ci.operators[2]); - tmpvars[oi].value = complexd(piClampd(tmp.real(), stmp.real(), ttmp.real()), piClampd(tmp.imag(), stmp.imag(), ttmp.imag())); - break; - case PIEvaluatorTypes::bfStep: - tmpvars[oi].value = complexd(value(ci.operators[0]).real() >= value(ci.operators[1]).real() ? complexld_1 : complexld_0); - break; - case PIEvaluatorTypes::bfMix: - tmp = value(ci.operators[0]); - stmp = value(ci.operators[1]); - ttmp = value(ci.operators[2]); - tmpvars[oi].value = stmp.real() * (1. - tmp.real()) + ttmp.real() * tmp.real(); - break; - case PIEvaluatorTypes::bfDefined: - tmpvars[oi].value = value(ci.operators[0]).real() > 0. ? complexd_1 : complexd_0; - break; - case PIEvaluatorTypes::bfRandom: - tmp = static_cast(rand()) / RAND_MAX; - stmp = value(ci.operators[1]) - value(ci.operators[0]); - 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; - } - } - if (!instructions.isEmpty()) - out = value(instructions.back().out); - return true; -} - - -bool PIEvaluator::check(const PIString & string) { - currentString = preprocess(string); - correct = check(); - if (!correct) { - instructions.clear(); - 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 deleted file mode 100644 index f2a9bf90..00000000 --- a/pievaluator.h +++ /dev/null @@ -1,227 +0,0 @@ -/*! \file pievaluator.h - * \brief Mathematic expressions calculator -*/ -/* - PIP - Platform Independent Primitives - Evaluator designed for stream computing - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIEVALUATOR_H -#define PIEVALUATOR_H - -#include "pistring.h" -#include "pimath.h" - -typedef complexd (*FuncFunc)(void * , int, complexd * ); - -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, bfJ0, bfJ1, bfJN, - bfY0, bfY1, bfYN, bfMin, bfMax, - bfClamp, bfStep, bfMix, bfDefined, - bfCustom = 0xFFFF - }; - - 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; handler = 0;} - Function(const PIString & name, int args, BaseFunctions ftype) {identifier = name; arguments = args; type = ftype; handler = 0;} - Function(const PIString & name, int args, FuncFunc h) {identifier = name; arguments = args; type = bfCustom; handler = h;} - PIString identifier; - BaseFunctions type; - FuncFunc handler; - int arguments; - }; - struct Variable { - Variable() {value = 0.;} - Variable(const PIString & var_name, complexd val) {name = var_name; value = val;} - PIString name; - complexd value; - }; -}; -/* - ≠ : - ≥ } - ≤ { - ⋀ & - ⋁ | -*/ - -class PIP_EXPORT PIEvaluatorContent -{ - friend class PIEvaluator; -public: - PIEvaluatorContent(); - ~PIEvaluatorContent() {;} - - void addFunction(const PIString & name, int args = 1) {functions.push_back(PIEvaluatorTypes::Function(name, args, getBaseFunction(name)));} - void addVariable(const PIString & name, const complexd & val = 0.) {variables.push_back(PIEvaluatorTypes::Variable(name, val)); sortVariables();} - void addCustomFunction(const PIString & name, int args_count, FuncFunc func) {functions << PIEvaluatorTypes::Function(name, args_count, func);} - int functionsCount() const {return functions.size();} - int variablesCount() const {return variables.size();} - int customVariablesCount() const {return variables.size() - cv_count;} - int findFunction(const PIString & name) const {for (uint i = 0; i < functions.size(); i++) if (functions[i].identifier == name) return i; return -1;} - 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;} - PIEvaluatorTypes::Function function(int index) {if (index < 0 || index >= functions.size_s()) return PIEvaluatorTypes::Function(); return functions[index];} - PIEvaluatorTypes::Variable variable(int index) {if (index < 0 || index >= variables.size_s()) return PIEvaluatorTypes::Variable(); return variables[index];} - PIEvaluatorTypes::Function function(const PIString & name) {return function(findFunction(name));} - PIEvaluatorTypes::Variable variable(const PIString & name) {return variable(findVariable(name));} - 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); - bool setVariableValue(const PIString & var_name, const complexd & new_value) {return setVariableValue(findVariable(var_name), new_value);} - bool setVariableName(const PIString & var_name, const PIString & new_name) {return setVariableName(findVariable(var_name), new_name);} - void removeVariable(int index) {variables.remove(index);} - 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 PIP_EXPORT PIEvaluator -{ -public: - - //! Constructs an empty evaluator - PIEvaluator() {correct = false; data_ = 0;} - - ~PIEvaluator() {;} - - - //! Returns custom data - void * data() {return data_;} - - //! Set custom data to "_data" - void setData(void * _data) {data_ = _data;} - - - //! Check mathematical expression and parse it to list of instructions - bool check(const PIString & string); - - //! Returns true if expression was checked succesfully - bool isCorrect() const {return correct;} - - //! Set variable value with name "name" to value "value". Add variable if it doesn`t exists - 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);} - - //! Set variable value with index "index" to value "value". Don`t add variable if it doesn`t exists - void setVariable(int index, complexd value = 0.) {if (index >= 0 && index < content.variablesCount()) content.setVariableValue(index, value);} - - void setCustomVariableValue(int index, complexd value = 0.) {content.variables[index + content.cv_count].value = value;} -/* - //! Add function "name" with arguments count "args_count" and handler "func". Three arguments will be passed to handler: \a data(), "args_count" and array of input values. - void addFunction(const PIString & name, int args_count, FuncFunc func) {content.addCustomFunction(name, args_count, func);} -*/ - //! Evaluate last successfully checked with function \a check() expression and returns result - complexd evaluate(); - - //! Remove variable with name "name" - void removeVariable(const PIString & name) {content.removeVariable(name);} - - //! Remove all manually added variables - void clearCustomVariables() {content.clearCustomVariables();} - - //! Returns index of variable with name "name" - int variableIndex(const PIString & name) const {return content.findVariable(name);} - - //! Returns all unknown variables founded in last expression passed to \a check() function - const PIStringList & unknownVariables() const {return unknownVars;} - - //! Returns processed last expression passed to \a check() function - const PIString & expression() const {return currentString;} - - //! Returns last error description occured in \a check() function - const PIString & error() const {return lastError;} - - //! Returns last result of \a evaluate() - const complexd & lastResult() const {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); - 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); - 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; - bool correct; - void * data_; -}; - -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 deleted file mode 100644 index 92e71325..00000000 --- a/pifile.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - PIP - Platform Independent Primitives - File - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pifile.h" - - -/*! \class PIFile - * \brief Local file - * - * \section PIFile_sec0 Synopsis - * This class provide access to local file. You can manipulate - * binary content or use this class as text stream. To binary - * access there are function \a read(), \a write(), and many - * \a writeBinary() functions. For write variables to file in - * their text representation threr are many "<<" operators. - * - * \section PIFile_sec1 Position - * Each opened file has a read/write position - logical position - * in the file content you read from or you write to. You can - * find out current position with function \a pos(). Function - * \a seek(llong position) move position to position "position", - * \a seekToBegin() move position to the begin of file, - * \a seekToEnd() move position to the end of file. - * - */ - -REGISTER_DEVICE(PIFile); - - -bool PIFile::openDevice() { - close(); - if (path().isEmpty()) return false; - //piCout << "fopen " << path_.data() << ": " << strType(mode_).data() << fd; - fd = fopen(path().data(), strType(mode_).data()); - opened_ = (fd != 0); -#ifndef WINDOWS - if (opened_) fcntl(fileno(fd), F_SETFL, O_NONBLOCK); -#endif - seekToBegin(); - //piCout << "open file" << fd << opened_; - return opened_; -} - - -bool PIFile::closeDevice() { - //piCout << "close file" << fd << opened_; - if (!opened_ || fd == 0) return true; - bool cs = (fclose(fd) == 0); - if (cs) fd = 0; - //piCout << "closed file" << fd << opened_; - return cs; -} - - -PIString PIFile::readLine() { - PIString str; - if (!opened_) return str; - int cc, cp = 0; - while (!isEnd() && cp < 4095) { - cc = fgetc(fd); - if (char(cc) == '\n' || cc == EOF) break; - str.push_back(char(cc)); - } - //cout << "readline: " << str << endl; - return str; -} - - -llong PIFile::readAll(void * data) { - llong cp = pos(), s = size(), i = -1; - seekToBegin(); - if (s < 0) { - while (!isEnd()) - read(&(((char*)data)[++i]), 1); - } else - read((char * )data, s); - seek(cp); - return s; -} - - -PIByteArray PIFile::readAll(bool forceRead) { - PIByteArray a; - llong cp = pos(); - if (forceRead) { - seekToBegin(); - while (!isEnd()) - a.push_back(readChar()); - seek(cp); - return a; - } - llong s = size(); - if (s < 0) return a; - a.resize(s); - s = readAll(a.data()); - seek(cp); - if (s >= 0) a.resize(s); - return a; -} - - -llong PIFile::size() { - if (!opened_) return -1; - llong s, cp = pos(); - seekToEnd(); - s = pos(); - seek(cp); - return s; -} - - -void PIFile::resize(llong new_size, uchar fill_) { - llong ds = new_size - size(); - if (ds == 0) return; - if (ds > 0) { - uchar * buff = new uchar[ds]; - memset(buff, fill_, ds); - write(buff, ds); - delete[] buff; - return; - } - piCoutObj << "Downsize is not support yet :-("; -} - - - -bool PIFile::isExists(const PIString & path) { - FILE * f = fopen(PIString(path).data(), "r"); - bool ok = (f != 0); - if (ok) fclose(f); - return ok; -} - - -PIString PIFile::constructFullPath() const { - return fullPathPrefix() + "://" + path(); -} - - -void PIFile::configureFromFullPath(const PIString & full_path) { - setPath(full_path); -} diff --git a/pifile.h b/pifile.h deleted file mode 100644 index dd72cc39..00000000 --- a/pifile.h +++ /dev/null @@ -1,240 +0,0 @@ -/*! \file pifile.h - * \brief Local file -*/ -/* - PIP - Platform Independent Primitives - File - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIFILE_H -#define PIFILE_H - -#include "piiodevice.h" -#include - -class PIP_EXPORT PIFile: public PIIODevice -{ - PIIODEVICE(PIFile) -public: - - //! Constructs a file with path "path" nad open mode "type" - PIFile(const PIString & path = PIString(), DeviceMode mode = ReadWrite): PIIODevice(path, mode) {setPrecision(5); if (!path.isEmpty()) openDevice();} - - ~PIFile() {close();} - - //PIFile & operator =(const PIFile & f) {path_ = f.path_; type_ = f.type_; return *this;} - - - //! Immediate write all buffered data to disk - void flush() {if (opened_) fflush(fd);} - - //! Move read/write position to "position" - void seek(llong position) {if (!opened_) return; fseek(fd, position, SEEK_SET); clearerr(fd);} - - //! Move read/write position to the begin of the file - void seekToBegin() {if (!opened_) return; fseek(fd, 0, SEEK_SET); clearerr(fd);} - - //! Move read/write position to the end of the file - void seekToEnd() {if (!opened_) return; fseek(fd, 0, SEEK_END); clearerr(fd);} - - //! Move read/write position to text line number "line" - void seekToLine(llong line) {if (!opened_) return; seekToBegin(); piForTimes (line) readLine(); clearerr(fd);} // line 0 - begin of file - //void fill(char c) {stream.fill(c);} - - //! Read one char and return it - char readChar() {return (char)fgetc(fd);} - - //! Read one text line and return it - PIString readLine(); - - //! Read all file content to "data" and return readed bytes count. Position leaved unchanged - llong readAll(void * data); - - //! Read all file content to byte array and return it. Position leaved unchanged - PIByteArray readAll(bool forceRead = false); - - - //! Set file path to "path" and reopen file if need - void setPath(const PIString & path) {PIIODevice::setPath(path); if (opened_) openDevice();} - - //! Returns file size - llong size(); - - //! Returns read/write position - llong pos() {if (!opened_) return -1; return ftell(fd);} - - //! Returns if position is at the end of file - bool isEnd() {if (!opened_) return true; return (feof(fd) || ferror(fd));} - - //! Returns if file is empty - bool isEmpty() {return (size() <= 0);} - - - //! Returns float numbers write precision - int precision() const {return prec_;} - - //! Set float numbers write precision to "prec_" digits - void setPrecision(int prec) {prec_ = prec; if (prec_ >= 0) prec_str = "." + itos(prec_); else prec_str = "";} - - - //! Read from file to "read_to" no more than "max_size" and return readed bytes count - int read(void * read_to, int max_size) {if (!canRead() || fd == 0) return -1; return fread(read_to, 1, max_size, fd);} - - //! Write to file "data" with size "max_size" and return written bytes count - int write(const void * data, int max_size) {if (!canWrite() || fd == 0) return -1; return fwrite(data, 1, max_size, fd);} - - PIFile & writeToBinLog(ushort id, const void * data, int size) {if (!isWriteable() || fd == 0) return *this; writeBinary(id).writeBinary((ushort)size); write(data, size); flush(); return *this;} - - - //! Write to file binary content of "v" - PIFile & writeBinary(const char v) {write(&v, sizeof(v)); return *this;} - //! Write to file binary content of "v" - PIFile & writeBinary(const short v) {write(&v, sizeof(v)); return *this;} - //! Write to file binary content of "v" - PIFile & writeBinary(const int v) {write(&v, sizeof(v)); return *this;} - //! Write to file binary content of "v" - PIFile & writeBinary(const long v) {write(&v, sizeof(v)); return *this;} - //! Write to file binary content of "v" - PIFile & writeBinary(const llong v) {write(&v, sizeof(v)); return *this;} - //! Write to file binary content of "v" - PIFile & writeBinary(const uchar v) {write(&v, sizeof(v)); return *this;} - //! Write to file binary content of "v" - PIFile & writeBinary(const ushort v) {write(&v, sizeof(v)); return *this;} - //! Write to file binary content of "v" - PIFile & writeBinary(const uint v) {write(&v, sizeof(v)); return *this;} - //! Write to file binary content of "v" - PIFile & writeBinary(const ulong v) {write(&v, sizeof(v)); return *this;} - //! Write to file binary content of "v" - PIFile & writeBinary(const ullong v) {write(&v, sizeof(v)); return *this;} - //! Write to file binary content of "v" - PIFile & writeBinary(const float v) {write(&v, sizeof(v)); return *this;} - //! Write to file binary content of "v" - PIFile & writeBinary(const double v) {write(&v, sizeof(v)); return *this;} - - PIFile & operator =(const PIFile & f) {PIIODevice::setPath(f.path()); mode_ = f.mode_; return *this;} - - //! Write to file text representation of "v" - PIFile & operator <<(const char v) {if (canWrite() && fd != 0) write(&v, 1); return *this;} - //PIFile & operator <<(const string & v) {write(v.c_str(), v.size()); return *this;} - //! Write to file string "v" - PIFile & operator <<(const PIString & v) {if (canWrite() && fd != 0) write(v.data(), v.lengthAscii()); return *this;} - //! Write to file text representation of "v" - PIFile & operator <<(const PIByteArray & v) {if (canWrite() && fd != 0) write(v.data(), v.size()); return *this;} - //! Write to file text representation of "v" - PIFile & operator <<(short v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%hd", v); return *this;} - //! Write to file text representation of "v" - PIFile & operator <<(int v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%d", v); return *this;} - //! Write to file text representation of "v" - PIFile & operator <<(long v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%ld", v); return *this;} - //! Write to file text representation of "v" - PIFile & operator <<(llong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%lld", v); return *this;} - //! Write to file text representation of "v" - PIFile & operator <<(uchar v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%u", int(v)); return *this;} - //! Write to file text representation of "v" - PIFile & operator <<(ushort v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%hu", v); return *this;} - //! Write to file text representation of "v" - PIFile & operator <<(uint v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%u", v); return *this;} - //! Write to file text representation of "v" - PIFile & operator <<(ulong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%lu", v); return *this;} - //! Write to file text representation of "v" - PIFile & operator <<(ullong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%llu", v); return *this;} - //! Write to file text representation of "v" with precision \a precision() - PIFile & operator <<(float v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "f").c_str(), v); return *this;} - //! Write to file text representation of "v" with precision \a precision() - PIFile & operator <<(double v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "lf").c_str(), v); return *this;} - - - //! Read from file text representation of "v" - PIFile & operator >>(char & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hhn", &v); return *this;} - //! Read from file text representation of "v" - PIFile & operator >>(short & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hn", &v); return *this;} - //! Read from file text representation of "v" - PIFile & operator >>(int & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%n", &v); return *this;} - //! Read from file text representation of "v" - PIFile & operator >>(long & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%ln", &v); return *this;} - //! Read from file text representation of "v" - PIFile & operator >>(llong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lln", &v); return *this;} - //! Read from file text representation of "v" - PIFile & operator >>(uchar & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hhn", &v); return *this;} - //! Read from file text representation of "v" - PIFile & operator >>(ushort & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hn", &v); return *this;} - //! Read from file text representation of "v" - PIFile & operator >>(uint & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%n", &v); return *this;} - //! Read from file text representation of "v" - PIFile & operator >>(ulong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%ln", &v); return *this;} - //! Read from file text representation of "v" - PIFile & operator >>(ullong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lln", &v); return *this;} - //! Read from file text representation of "v" - PIFile & operator >>(float & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%f", &v); return *this;} - //! Read from file text representation of "v" - PIFile & operator >>(double & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lf", &v); return *this;} - - PIString constructFullPath() const; - - EVENT_HANDLER(void, clear) {close(); fd = fopen(path().data(), "w"); if (fd != 0) fclose(fd); fd = 0; opened_ = false; open();} - EVENT_HANDLER0(void, remove) {close(); std::remove(path().data());} - EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);} - EVENT_HANDLER2(void, resize, llong, new_size, uchar, fill); - - - //! Returns not opened temporary file with open mode "mode" - static PIFile openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite) {return PIFile(PIString(tmpnam(0)), mode);} - - //! Returns if file with path "path" does exists - static bool isExists(const PIString & path); - - //! Remove file with path "path" and returns if remove was successful - static bool remove(const PIString & path) {return std::remove(path.data()) == 0;} - -//! \handlers -//! \{ - - //! \fn void clear() - //! \brief Raise on new TCP connection received - - //! \fn void resize(llong new_size) - //! \brief Resize file to "new_size" with "fill" filling - - //! \fn void resize(llong new_size, uchar fill) - //! \brief Resize file to "new_size" with "fill" filling - - //! \fn void remove() - //! \brief Remove file - -//! \} -//! \ioparams -//! \{ -#ifdef DOXYGEN -#endif -//! \} - -protected: - PIString fullPathPrefix() const {return "file";} - void configureFromFullPath(const PIString & full_path); - bool openDevice(); - bool closeDevice(); - -private: - PIString strType(const PIIODevice::DeviceMode type) {switch (type) {case PIIODevice::ReadOnly: return "rb"; case WriteOnly: return "ab"; case ReadWrite: return "a+b";} return "rb";} - - FILE * fd; - int ret, prec_; - string prec_str; - -}; - -#endif // PIFILE_H diff --git a/pigeometry.h b/pigeometry.h deleted file mode 100644 index dd8c25f6..00000000 --- a/pigeometry.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - PIP - Platform Independent Primitives - Geometry - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIGEOMETRY_H -#define PIGEOMETRY_H - -#include "pimath.h" - -template -class PIP_EXPORT PIPoint { -public: - Type x; - Type y; - - PIPoint() {x = y = 0;}; - PIPoint(Type x_, Type y_) {set(x_, y_);} - - PIPoint & set(Type x_, Type y_) {x = x_; y = y_; return *this;} - PIPoint & move(Type x_, Type y_) {x += x_; y += y_; return *this;} - PIPoint & move(const PIPoint & p) {x += p.x; y += p.y; return *this;} - double angleRad() const {return atan2(y, x);} - int angleDeg() const {return round(atan2(y, x) * 180. / M_PI);} - PIPoint toPolar(bool isDeg = false) const {return PIPoint(sqrt(x*x + y*y), isDeg ? angleDeg() : angleRad());} - static PIPoint fromPolar(const PIPoint & p) {return PIPoint(p.y * cos(p.x), p.y * sin(p.x));} - - PIPoint operator +(const PIPoint & p) {return PIPoint(x + p.x, y + p.y);} - PIPoint operator +(const Type & p) {return PIPoint(x + p, y + p);} - PIPoint operator -(const PIPoint & p) {return PIPoint(x - p.x, y - p.y);} - PIPoint operator -(const Type & p) {return PIPoint(x - p, y - p);} - PIPoint operator -() {return PIPoint(-x, -y);} - PIPoint operator *(const Type & d) {return PIPoint(x * d, y * d);} - PIPoint operator /(const Type & d) {return PIPoint(x / d, y / d);} - bool operator ==(const PIPoint & p) const {return (x == p.x && y == p.y);} - bool operator !=(const PIPoint & p) const {return (x != p.x || y != p.y);} - -}; - -template -std::ostream & operator <<(std::ostream & s, const PIPoint & v) {s << '{' << v.x << ", " << v.y << '}'; return s;} - -template -class PIP_EXPORT PIRect { -public: - Type x0; - Type y0; - Type x1; - Type y1; - - PIRect() {x0 = y0 = x1 = y1 = 0;}; - PIRect(Type x, Type y, Type w, Type h) {set(x, y, w, h);} - PIRect(const PIPoint & tl, const PIPoint & br) {set(tl.x, tl.y, br.x, br.y);} - PIRect(const PIPoint & p0, const PIPoint & p1, const PIPoint & p2) {set(piMin(p0.x, p1.x, p2.x), piMin(p0.y, p1.y, p2.y), - piMax(p0.x, p1.x, p2.x), piMax(p0.y, p1.y, p2.y));} - - PIRect & set(Type x, Type y, Type w, Type h) {x0 = x; y0 = y; x1 = x + w; y1 = y + h; return *this;} - bool pointIn(Type x, Type y) const {return (x <= x1 && x >= x0 && y <= y1 && y >= y0);} - bool pointIn(const PIPoint & p) const {return pointIn(p.x, p.y);} - bool isEmpty() const {return (x1 - x0 == 0 && y1 - y0 == 0);} - PIRect & translate(Type x, Type y) {x0 += x; x1 += x; y0 += y; y1 += y; return *this;} - PIRect & translate(const PIPoint & p) {x0 += p.x; x1 += p.x; y0 += p.y; y1 += p.y; return *this;} - PIRect translated(Type x, Type y) {PIRect r(*this); r.translate(x, y); return r;} - PIRect translated(const PIPoint & p) {PIRect r(*this); r.translate(p); return r;} - PIRect & scale(Type x, Type y) {setWidth(width() * x); setHeight(height() * y); return *this;} - PIRect & scale(const PIPoint & p) {setWidth(width() * p.x); setHeight(height() * p.y); return *this;} - PIRect scaled(Type x, Type y) {PIRect r(*this); r.scale(x, y); return r;} - PIRect scaled(const PIPoint & p) {PIRect r(*this); r.scale(p); return r;} - PIRect & normalize() {if (x0 > x1) piSwap(x0, x1); if (y0 > y1) piSwap(y0, y1); return *this;} - PIRect normalized() {PIRect r(*this); r.normalize(); return r;} - PIRect & unite(const PIRect & r) {x0 = piMin(x0, r.x0); y0 = piMin(y0, r.y0); x1 = piMax(x1, r.x1); y1 = piMax(y1, r.y1); return *this;} - PIRect united(const PIRect & rect) {PIRect r(*this); r.unite(rect); return r;} - PIRect & intersect(const PIRect & r) {x0 = piMax(x0, r.x0); y0 = piMax(y0, r.y0); x1 = piMin(x1, r.x1); y1 = piMin(y1, r.y1); if (x0 > x1 || y0 > y1) x0 = x1 = y0 = y1 = Type(0); return *this;} - PIRect intersected(const PIRect & rect) {PIRect r(*this); r.intersect(rect); return r;} - Type top() const {return y0;} - Type left() const {return x0;} - Type right() const {return x1;} - Type bottom() const {return y1;} - Type width() const {return x1 - x0;} - Type height() const {return y1 - y0;} - PIPoint topLeft() {return PIPoint(x0, y0);} - PIPoint topRigth() {return PIPoint(x1, y0);} - PIPoint bottomLeft() {return PIPoint(x0, y1);} - PIPoint bottomRight() {return PIPoint(x1, y1);} - void setTop(Type v) {y0 = v;} - void setLeft(Type v) {x0 = v;} - void setRigth(Type v) {x1 = v;} - void setBottom(Type v) {y1 = v;} - void setWidth(Type v) {x1 = x0 + v;} - void setHeight(Type v) {y1 = y0 + v;} - - PIRect operator -() {return PIRect(-x0, -y0, -width(), -height());} - void operator +=(Type x) {translate(x, x);} - void operator +=(const PIPoint & p) {translate(p);} - void operator -=(Type x) {translate(-x, -x);} - void operator -=(const PIPoint & p) {translate(-p);} - void operator *=(Type p) {x0 *= p; x1 *= p; y0 *= p; y1 *= p;} - void operator /=(Type p) {x0 /= p; x1 /= p; y0 /= p; y1 /= p;} - void operator |=(const PIRect & r) {unite(r);} - void operator &=(const PIRect & r) {intersect(r);} - PIRect operator +(const PIPoint & p) {return PIRect(*this).translated(p);} - PIRect operator -(const PIPoint & p) {return PIRect(*this).translated(-p);} - PIRect operator |(const PIRect & r) {return PIRect(*this).united(r);} - PIRect operator &(const PIRect & r) {return PIRect(*this).intersected(r);} - bool operator ==(const PIRect & r) const {return (x0 == r.x0 && y0 == r.y0 && x1 == r.x1 && y1 == r.y10);} - bool operator !=(const PIRect & r) const {return (x0 != r.x0 || y0 != r.y0 || x1 != r.x1 || y1 != r.y10);} - -}; - -template -std::ostream & operator <<(std::ostream & s, const PIRect & v) {s << '{' << v.x0 << ", " << v.y0 << "; " << v.x1 - v.x0 << ", " << v.y1 - v.y0 << '}'; return s;} - -typedef PIPoint PIPointi; -typedef PIPoint PIPointu; -typedef PIPoint PIPointf; -typedef PIPoint PIPointd; - -typedef PIRect PIRecti; -typedef PIRect PIRectu; -typedef PIRect PIRectf; -typedef PIRect PIRectd; - -#endif // PIGEOMETRY_H diff --git a/piincludes.cpp b/piincludes.cpp deleted file mode 100644 index f1c534db..00000000 --- a/piincludes.cpp +++ /dev/null @@ -1,592 +0,0 @@ -/* - PIP - Platform Independent Primitives - Global includes - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "piincludes.h" -#include "piconsole.h" - -bool isPIInit = false; -bool piDebug = true; -string ifconfigPath; - -PIInit piInit; -lconv * currentLocale = -#ifdef ANDROID - 0; -#else - std::localeconv(); -#endif -#ifdef HAS_LOCALE -static locale_t currentLocale_t = 0; -#endif - -#ifdef MAC_OS -clock_serv_t __pi_mac_clock; -#endif - -PIMutex __PICout_mutex__; -PIString __PICout_string__; - - -#ifdef WINDOWS -FILETIME __pi_ftjan1970; -long long __pi_perf_freq = -1; -PINtSetTimerResolution setTimerResolutionAddr = 0; -#endif - - -PIInit::PIInit() { - if (isPIInit) return; - isPIInit = true; -#ifndef WINDOWS - sigset_t ss; - sigemptyset(&ss); - sigaddset(&ss, SIGALRM); - sigprocmask(SIG_BLOCK, &ss, 0); - pthread_sigmask(SIG_BLOCK, &ss, 0); - ifconfigPath = "/bin/ifconfig"; - if (!fileExists(ifconfigPath)) { - ifconfigPath = "/sbin/ifconfig"; - if (!fileExists(ifconfigPath)) { - ifconfigPath = "/usr/bin/ifconfig"; - if (!fileExists(ifconfigPath)) { - ifconfigPath = "/usr/sbin/ifconfig"; - if (!fileExists(ifconfigPath)) { - ifconfigPath = ""; - } - } - } - } -#else - // WinSock inint - WSADATA wsaData; - WSAStartup(MAKEWORD(2, 2), &wsaData); - - // Timers init - SYSTEMTIME jan1970 = {1970, 1, 4, 1, 0, 14, 15, 0}; - SystemTimeToFileTime(&jan1970, &__pi_ftjan1970); - LARGE_INTEGER pf; - pf.QuadPart = -1; - if (QueryPerformanceFrequency(&pf) != 0) __pi_perf_freq = pf.QuadPart; - if (__pi_perf_freq == 0) __pi_perf_freq = -1; - - // Sleep precision init - ntlib = LoadLibrary("ntdll.dll"); - if (ntlib) setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(ntlib, "NtSetTimerResolution"); - /*if (setTimerResolution) setTimerResolutionAddr(1, TRUE, &prev_res);*/ -#endif - //piDebug = true; -#ifdef HAS_LOCALE - //cout << "has locale" << endl; - if (currentLocale_t != 0) { - freelocale(currentLocale_t); - currentLocale_t = 0; - } - currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0); -#else - setlocale(LC_ALL, ""); - setlocale(LC_NUMERIC, "C"); -#endif -#ifdef MAC_OS - host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock); -#endif -} - - -PIInit::~PIInit() { -#ifdef WINDOWS - WSACleanup(); - //if (setTimerResolution) setTimerResolutionAddr(prev_res, TRUE, &prev_res); - if (ntlib) FreeLibrary(ntlib); -#endif -#ifdef MAC_OS - mach_port_deallocate(mach_task_self(), __pi_mac_clock); -#endif - //if (currentLocale_t != 0) freelocale(currentLocale_t); -} - - -#ifdef WINDOWS -void * PICout::hOut = 0; -WORD PICout::dattr = 0; -DWORD PICout::smode = 0; -#endif - - -bool PICout::buffer_ = false; - - -PICout::PICout(PIFlags controls): fo_(true), cc_(false), fc_(false), cnb_(10), co_(controls) { -#ifdef WINDOWS - if (hOut == 0) { - hOut = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_SCREEN_BUFFER_INFO sbi; - GetConsoleScreenBufferInfo(hOut, &sbi); - dattr = sbi.wAttributes; - } - attr_ = dattr; -#endif - __PICout_mutex__.lock(); -} - - -PICout::~PICout() { - if (fc_) applyFormat(PICoutManipulators::Default); - if (cc_) return; - newLine(); - __PICout_mutex__.unlock(); -} - - -PICout PICout::operator <<(const PICoutAction v) { -#ifdef WINDOWS - CONSOLE_SCREEN_BUFFER_INFO sbi; - COORD coord; - CONSOLE_CURSOR_INFO curinfo; -#endif - switch (v) { - case PICoutManipulators::Flush: - if (!PICout::buffer_) - std::cout << std::flush; - break; - case PICoutManipulators::Backspace: - if (!PICout::buffer_) { -#ifdef WINDOWS - GetConsoleScreenBufferInfo(hOut, &sbi); - coord = sbi.dwCursorPosition; - coord.X = piMax(0, int(coord.X) - 1); - SetConsoleCursorPosition(hOut, coord); - printf(" "); - SetConsoleCursorPosition(hOut, coord); -#else - printf("\e[1D \e[1D"); -#endif - } - break; - case PICoutManipulators::ShowCursor: - if (!PICout::buffer_) { -#ifdef WINDOWS - GetConsoleCursorInfo(hOut, &curinfo); - curinfo.bVisible = true; - SetConsoleCursorInfo(hOut, &curinfo); -#else - printf("\e[?25h"); -#endif - } - break; - case PICoutManipulators::HideCursor: - if (!PICout::buffer_) { -#ifdef WINDOWS - GetConsoleCursorInfo(hOut, &curinfo); - curinfo.bVisible = false; - SetConsoleCursorInfo(hOut, &curinfo); -#else - printf("\e[?25l"); -#endif - } - break; - case PICoutManipulators::ClearScreen: - if (!PICout::buffer_) { -#ifdef WINDOWS - /// TODO !!! - /*GetConsoleCursorInfo(hOut, &curinfo); - curinfo.bVisible = false; - SetConsoleCursorInfo(hOut, &curinfo); - - SetConsoleCursorPosition(hOut, ulcoord); - FillConsoleOutputAttribute(hOut, dattr, width * (height + 1), ulcoord, &written); - FillConsoleOutputCharacter(hOut, ' ', width * (height + 1), ulcoord, &written);*/ -#else - printf("\e[H\e[J"); -#endif - } - break; - case PICoutManipulators::SaveContol: saveControl(); break; - case PICoutManipulators::RestoreControl: restoreControl(); break; - default: break; - }; - return *this; -} - - -#define PICOUTTOTARGET(v) {if (PICout::buffer_) __PICout_string__ << (v); else std::cout << (v);} -#define PINUMERICCOUT if (cnb_ == 10) PICOUTTOTARGET(v) else PICOUTTOTARGET(PIString::fromNumber(v, cnb_)) - - -PICout PICout::operator <<(const char * v) {space(); quote(); PICOUTTOTARGET(v) quote(); return *this;} - -PICout PICout::operator <<(const string & v) {space(); quote(); PICOUTTOTARGET(v) quote(); return *this;} - -PICout PICout::operator <<(const bool v) {space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;} - -PICout PICout::operator <<(const char v) {space(); PICOUTTOTARGET(v) return *this;} - -PICout PICout::operator <<(const uchar v) {space(); if (cnb_ == 10) PICOUTTOTARGET(ushort(v)) else PICOUTTOTARGET(PIString::fromNumber(v, cnb_)) return *this;} - -PICout PICout::operator <<(const short int v) {space(); PINUMERICCOUT return *this;} - -PICout PICout::operator <<(const ushort v) {space(); PINUMERICCOUT return *this;} - -PICout PICout::operator <<(const int v) {space(); PINUMERICCOUT return *this;} - -PICout PICout::operator <<(const uint v) {space(); PINUMERICCOUT return *this;} - -PICout PICout::operator <<(const long v) {space(); PINUMERICCOUT return *this;} - -PICout PICout::operator <<(const ulong v) {space(); PINUMERICCOUT return *this;} - -PICout PICout::operator <<(const llong v) {space(); PINUMERICCOUT return *this;} - -PICout PICout::operator <<(const ullong v) {space(); PINUMERICCOUT return *this;} - -PICout PICout::operator <<(const float v) {space(); PICOUTTOTARGET(v) return *this;} - -PICout PICout::operator <<(const double v) {space(); PICOUTTOTARGET(v) return *this;} - -PICout PICout::operator <<(const void * v) {space(); PICOUTTOTARGET("0x") PICOUTTOTARGET(PIString::fromNumber(ullong(v), 16)) return *this;} - -PICout PICout::operator <<(const PIObject * v) { - space(); - if (v == 0) PICOUTTOTARGET("PIObject*(0x0)") - else { - PICOUTTOTARGET(v->className()) - PICOUTTOTARGET("*(0x") - PICOUTTOTARGET(PIString::fromNumber(ullong(v), 16)) - PICOUTTOTARGET(", \"") - PICOUTTOTARGET(v->name()) - PICOUTTOTARGET("\")") - } - return *this; -} - -PICout PICout::operator <<(const PICoutSpecialChar v) { - switch (v) { - case Null: - if (PICout::buffer_) __PICout_string__ << PIChar(0); - else std::cout << char(0); - break; - case NewLine: - if (PICout::buffer_) __PICout_string__ << "\n"; - else std::cout << '\n'; - fo_ = true; - break; - case Tab: - if (PICout::buffer_) __PICout_string__ << "\t"; - else std::cout << '\t'; - break; - case Esc: -#ifdef CC_VC - if (PICout::buffer_) __PICout_string__ << PIChar(27); - else std::cout << char(27); -#else - if (PICout::buffer_) __PICout_string__ << "\e"; - else std::cout << '\e'; -#endif - break; - case Quote: - if (PICout::buffer_) __PICout_string__ << "\""; - else std::cout << '"'; - break; - }; - return *this; -} - -#undef PICOUTTOTARGET -#undef PINUMERICCOUT - -PICout & PICout::space() { - if (!fo_ && co_[AddSpaces]) { - if (PICout::buffer_) __PICout_string__ << " "; - else std::cout << ' '; - } - fo_ = false; - return *this; -} - -PICout & PICout::quote() { - if (co_[AddQuotes]) { - if (PICout::buffer_) __PICout_string__ << "\""; - else std::cout << '"'; - } - fo_ = false; - return *this; -} - -PICout & PICout::newLine() { - if (co_[AddNewLine]) { - if (PICout::buffer_) __PICout_string__ << "\n"; - else std::cout << std::endl; - } - fo_ = false; - return *this; -} - - -void PICout::applyFormat(PICoutFormat f) { - if (PICout::buffer_) return; - fc_ = true; -#ifdef WINDOWS - static int mask_fore = ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - static int mask_back = ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); - switch (f) { - case Bin: case Oct: case Dec: case Hex: break; - case PICoutManipulators::Bold: attr_ |= FOREGROUND_INTENSITY; break; - case PICoutManipulators::Underline: attr_ |= COMMON_LVB_UNDERSCORE; break; - case PICoutManipulators::Black: attr_ = (attr_ & mask_fore); break; - case PICoutManipulators::Red: attr_ = (attr_ & mask_fore) | FOREGROUND_RED; break; - case PICoutManipulators::Green: attr_ = (attr_ & mask_fore) | FOREGROUND_GREEN; break; - case PICoutManipulators::Blue: attr_ = (attr_ & mask_fore) | FOREGROUND_BLUE; break; - case PICoutManipulators::Yellow: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_GREEN; break; - case PICoutManipulators::Magenta: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_BLUE; break; - case PICoutManipulators::Cyan: attr_ = (attr_ & mask_fore) | FOREGROUND_GREEN | FOREGROUND_BLUE; break; - case PICoutManipulators::White: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; - case PICoutManipulators::BackBlack: attr_ = (attr_ & mask_back); break; - case PICoutManipulators::BackRed: attr_ = (attr_ & mask_back) | BACKGROUND_RED; break; - case PICoutManipulators::BackGreen: attr_ = (attr_ & mask_back) | BACKGROUND_GREEN; break; - case PICoutManipulators::BackBlue: attr_ = (attr_ & mask_back) | BACKGROUND_BLUE; break; - case PICoutManipulators::BackYellow: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_GREEN; break; - case PICoutManipulators::BackMagenta: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_BLUE; break; - case PICoutManipulators::BackCyan: attr_ = (attr_ & mask_back) | BACKGROUND_GREEN | BACKGROUND_BLUE; break; - case PICoutManipulators::BackWhite: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; break; - case PICoutManipulators::Default: attr_ = dattr; break; - default: break; - } - SetConsoleTextAttribute(hOut, attr_); -#else - switch (f) { - case Bin: case Oct: case Dec: case Hex: break; - case PICoutManipulators::Bold: printf("\e[1m"); break; - case PICoutManipulators::Faint: printf("\e[2m"); break; - case PICoutManipulators::Italic: printf("\e[3m"); break; - case PICoutManipulators::Underline: printf("\e[4m"); break; - case PICoutManipulators::Blink: printf("\e[5m"); break; - case PICoutManipulators::Black: printf("\e[30m"); break; - case PICoutManipulators::Red: printf("\e[31m"); break; - case PICoutManipulators::Green: printf("\e[32m"); break; - case PICoutManipulators::Blue: printf("\e[34m"); break; - case PICoutManipulators::Yellow: printf("\e[33m"); break; - case PICoutManipulators::Magenta: printf("\e[35m"); break; - case PICoutManipulators::Cyan: printf("\e[36m"); break; - case PICoutManipulators::White: printf("\e[37m"); break; - case PICoutManipulators::BackBlack: printf("\e[40m"); break; - case PICoutManipulators::BackRed: printf("\e[41m"); break; - case PICoutManipulators::BackGreen: printf("\e[42m"); break; - case PICoutManipulators::BackBlue: printf("\e[44m"); break; - case PICoutManipulators::BackYellow: printf("\e[43m"); break; - case PICoutManipulators::BackMagenta: printf("\e[45m"); break; - case PICoutManipulators::BackCyan: printf("\e[46m"); break; - case PICoutManipulators::BackWhite: printf("\e[47m"); break; - case PICoutManipulators::Default: printf("\e[0m"); break; - default: break; - } -#endif -} - - -bool PICout::setBufferActive(bool on, bool clear) { - PIMutexLocker ml(__PICout_mutex__); - bool ret = PICout::buffer_; - if (clear) __PICout_string__.clear(); - PICout::buffer_ = on; - return ret; -} - - -bool PICout::isBufferActive() { - return PICout::buffer_; -} - - -PIString PICout::buffer(bool clear) { - PIMutexLocker ml(__PICout_mutex__); - PIString ret = __PICout_string__; - if (clear) __PICout_string__.clear(); - return ret; -} - - -void PICout::clearBuffer() { - PIMutexLocker ml(__PICout_mutex__); - __PICout_string__.clear(); -} - - -/*! \class PICout - * \brief Class for formatted output similar std::cout - * - * \section PICout_sec0 Synopsis - * This class provide many stream operators for output with some features. - * Output to PICout is thread-sequential, i.e. doesn`t mixed from parallel - * threads. - * - * \section PICout_sec1 Features - * - insertion spaces between entries - * - insertion new line at the end of output - * - strings are quoted - * - custom output operator can be easily written - * - * \section PICout_ex0 Usage - * \snippet picout.cpp 0 - * - * \section PICout_ex1 Writing your own output operator - * \snippet picout.cpp own - */ - - -/*! \mainpage What is PIP - * PIP - Platform-Independent Primitives - is crossplatform library for C++ developers. - * It is wrap around STL and pure C++. This library can help developers write non-GUI - * projects much more quickly, efficiently and customizable than on pure C++. - * Library contains many classes, some of them are pure abstract, some classes - * can be used as they are, some classes should be inherited to new classes. - * PIP provide classes: - * * direct output to console (\a PICout) - * * containers (\a PIVector, \a PIList, \a PIMap, \a PIStack) - * * byte array (\a PIByteArray) - * * string (\a PIString, \a PIStringList) - * * base object (events and handlers) (\a PIObject) - * * thread (\a PIThread) - * * timer (\a PITimer) - * * console (information output) (\a PIConsole) - * * stand-alone - * * server - * * client - * * i/o devices - * * base class (\a PIIODevice) - * * file (\a PIFile) - * * serial port (\a PISerial) - * * ethernet (\a PIEthernet) - * * USB (\a PIUSB) - * * packets extractor (\a PIPacketExtractor) - * * binary log (\a PIBinaryLog) - * * connection quality diagnotic (\a PIDiagnostics) - * * command-line arguments parser (\a PICLI) - * * math evaluator (\a PIEvaluator) - * * peering net node (\a PIPeer) - * * process (\a PIProcess) - * * state machine (\a PIStateMachine) - * \n \n Basic using of PIP described at page \ref using_basic */ - - -/*! \page using_basic Getting started - * Many novice programmers are solved many common task with system integrity: output to console, - * keyboard buttons press detecting, working with serial ports, ethernet or files, and many other. - * These tasks can solve this library, and code, based only on PIP will be compile and work - * similar on many systems: Windows, any Linux, Red Hat, FreeBSD, MacOS X and QNX. - * Typical application on PIP looks like this: \n -\code{.cpp} -#include - - -// declare key press handler -void key_event(char key, void * ); - - -PIConsole console(false, key_event); // don`t start now, key handler is "key_event" - - -// some vars -int i = 2, j = 3; - - -// implicit key press handler -void key_event(char key, void * ) { - switch (key) { - case '-': - i--; - break; - case '+': - i++; - break; - case '(': - j--; - break; - case ')': - j++; - break; - }; -}; - - -class MainClass: public PITimer { - PIOBJECT(MainClass) -public: - MainClass() {} -protected: - void tick(void * data, int delimiter) { - piCout << "timer tick"; - // timer tick - } -}; - - -MainClass main_class; - - -int main(int argc, char * argv[]) { - // enabling auto-detection of exit button press, by default 'Q' (shift+q) - console.enableExitCapture(); - - // if we want to parse command-line arguments - PICLI cli(argc, argv); - cli.addArgument("console"); // "-c" or "--console" - cli.addArgument("debug"); // "-d" or "--debug" - - // enabling or disabling global debug flag - piDebug = cli.hasArgument("debug"); - - // configure console - console.addTab("first tab", '1'); - console.addString("PIP console", 1, PIConsole::Bold); - console.addVariable("int var (i)", &i, 1); - console.addVariable("int green var (j)", &j, 1, PIConsole::Green); - console.addString("'-' - i--", 2); - console.addString("'+' - i++", 2); - console.addString("'(' - j--", 2); - console.addString("')' - j++", 2); - console.addTab("second tab", '2'); - console.addString("col 1", 1); - console.addString("col 2", 2); - console.addString("col 3", 3); - console.setTab("first tab"); - - // start output to console if "console" argument exists - if (cli.hasArgument("console")) - console.start(); - - // start main class, e.g. 40 Hz - main_class.start(25.); - - // wait for 'Q' press, independently if console is started or not - console.waitForFinish(); - - return 0; -}; -\endcode - * This code demonstrates simple interactive configurable program, which can be started with console - * display or not, and with debug or not. \b MainClass is central class that also can be inherited from - * \a PIThread and reimplement \a run() function. - * \n Many PIP classes has events and event handlers, which can be connected one to another. - * Details you can see at \a PIObject reference page (\ref PIObject_sec0). - * \n To configure your program from file use \a PIConfig. - * \n If you want more information see \ref using_advanced */ - - -/*! \page using_advanced Advanced using - * Sorry, creativity crisis xD - */ diff --git a/piincludes.h b/piincludes.h deleted file mode 100644 index 58005cd7..00000000 --- a/piincludes.h +++ /dev/null @@ -1,978 +0,0 @@ -/*! \file piincludes.h - * \brief Global includes of PIP - * - * This file include all needed system headers, STL - * and declare many useful macros and functions -*/ -/* - PIP - Platform Independent Primitives - Global includes - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIINCLUDES_H -#define PIINCLUDES_H - -//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision) -#define PIP_VERSION 0x000400 - -//! Major value of PIP version -#define PIP_VERSION_MAJOR (PIP_VERSION & 0xFF0000) >> 16 - -//! Minor value of PIP version -#define PIP_VERSION_MINOR (PIP_VERSION & 0xFF00) >> 8 - -//! Revision value of PIP version -#define PIP_VERSION_REVISION PIP_VERSION & 0xFF - -//! Suffix of PIP version -#define PIP_VERSION_SUFFIX "_r5" - -#ifdef DOXYGEN - -//! Macro is defined when compile-time debug is enabled -# define PIP_DEBUG - -//! Macro is defined when host is any Windows -# define WINDOWS - -//! Macro is defined when host is QNX -# define QNX - -//! Macro is defined when host is FreeBSD -# define FREE_BSD - -//! Macro is defined when host is Mac OS -# define MAC_OS - -//! Macro is defined when host is Android -# define ANDROID - -//! Macro is defined when host is any Linux -# define LINUX - -//! Macro is defined when compiler is GCC or MinGW -# define CC_GCC - -//! Macro is defined when PIP is decided that host is support language -# define HAS_LOCALE - -//! Macro is defined when compiler is Visual Studio -# define CC_VC - -//! Macro is defined when compiler is unknown -# define CC_OTHER - -//! Macro is defined when PIP use "rt" library for timers implementation -# define PIP_TIMER_RT - -//! Define this macro to use STL implementation of containers, else PIP implementation will be used -# define PIP_CONTAINERS_STL - -#endif - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# define WINDOWS -# define ARCH_BITS_32 -#endif -#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) -# define WINDOWS -# define ARCH_BITS_64 -#endif -#if defined(__QNX__) || defined(__QNXNTO__) -# define QNX -#endif -#ifdef __FreeBSD__ -# define FREE_BSD -#endif -#if defined(__APPLE__) || defined(__MACH__) -# define MAC_OS -#endif -#if defined(__ANDROID__) || defined(_ANDROID_) || defined(ANDROID) -# ifndef ANDROID -# define ANDROID -# endif -#endif -#ifndef WINDOWS -# ifndef QNX -# ifndef FREE_BSD -# ifndef MAC_OS -# ifndef ANDROID -# define LINUX -# endif -# endif -# endif -# endif -#endif - -#ifndef WINDOWS -# if defined(__LP64__) || defined(_LP64_) || defined(LP64) -# define ARCH_BITS_64 -# else -# define ARCH_BITS_32 -# endif -#endif - -#ifdef __GNUC__ -# define CC_GCC -# define CC_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__) -# if CC_GCC_VERSION > 0x025F // > 2.95 -# ifdef LINUX -# define HAS_LOCALE -# endif -# pragma GCC diagnostic ignored "-Wformat" -# pragma GCC diagnostic ignored "-Wformat-extra-args" -# pragma GCC diagnostic ignored "-Wstrict-aliasing" -# endif -# ifdef ANDROID -# pragma GCC diagnostic ignored "-Wunused-parameter" -# pragma GCC diagnostic ignored "-Wextra" -# pragma GCC diagnostic ignored "-Wliteral-suffix" -# endif -# define DEPRECATED __attribute__((deprecated)) -#elif defined(_MSC_VER) -# define CC_VC -# pragma warning(disable: 4018) -# pragma warning(disable: 4061) -# pragma warning(disable: 4100) -# pragma warning(disable: 4239) -# pragma warning(disable: 4242) -# pragma warning(disable: 4244) -# pragma warning(disable: 4251) -# pragma warning(disable: 4365) -# pragma warning(disable: 4512) -# pragma warning(disable: 4668) -# pragma warning(disable: 4710) -# pragma warning(disable: 4800) -# pragma warning(disable: 4820) -# pragma warning(disable: 4986) -# pragma warning(disable: 4996) -# define DEPRECATED -# ifdef ARCH_BITS_32 - typedef long ssize_t; -# else - typedef long long ssize_t; -# endif -#else -# define CC_OTHER -# define DEPRECATED -#endif - -#ifdef WINDOWS -# ifdef CC_GCC -# define typeof __typeof -# endif -#else -# define typeof __typeof__ -#endif - -#include "pip_export.h" -#if defined(DOXYGEN) || defined(CC_GCC) || defined(PICODE) -# undef PIP_EXPORT -# define PIP_EXPORT -#endif -#include -#ifdef CC_GCC -# include -#endif -#include -#include -#ifndef QNX -# include -# include -# include -#else -# include -# include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef WINDOWS -# include -# include -# include -# ifdef CC_VC -# define SHUT_RDWR 2 -# pragma comment(lib, "Ws2_32.lib") -# pragma comment(lib, "Iphlpapi.lib") -# else -# define SHUT_RDWR SD_BOTH -# endif -# include -# include -# include - typedef int socklen_t; - typedef void(*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG); - extern FILETIME __pi_ftjan1970; - extern long long __pi_perf_freq; - extern PINtSetTimerResolution setTimerResolutionAddr; - inline long long __PIQueryPerformanceCounter() {LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart;} - inline void __PISetTimerResolution() {if (setTimerResolutionAddr == NULL) return; ULONG ret; setTimerResolutionAddr(1, TRUE, &ret);} -#else -# include -# include -# include -# include -# include -# include -# include -# ifndef ANDROID -# include -# endif -#endif -#ifdef ANDROID -//# include "ifaddrs_3rd.h" -# define tcdrain(fd) ioctl(fd, TCSBRK, 1) - inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;} - inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;} -#endif -#ifdef MAC_OS -# include -# include -# include -# include -# define environ (*_NSGetEnviron()) - typedef long time_t; - extern clock_serv_t __pi_mac_clock; -#endif -#ifdef LINUX -# define environ __environ -#endif -#if !defined(WINDOWS) && !defined(MAC_OS) -# define PIP_TIMER_RT -#endif -#ifdef FREE_BSD - extern char ** environ; -#endif -#if defined(DOXYGEN) || defined(PICODE) -# undef PIP_EXPORT -# define PIP_EXPORT -# undef DEPRECATED -# define DEPRECATED -#endif - -#include "pimonitor.h" - -extern PIMonitor piMonitor; - -//! Macro used for infinite loop -#define FOREVER for (;;) - -//! Macro used for infinite wait -#define FOREVER_WAIT FOREVER msleep(1); - -//! Macro used for infinite wait -#define WAIT_FOREVER FOREVER msleep(1); - -typedef long long llong; -typedef unsigned char uchar; -typedef unsigned short int ushort; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned long long ullong; -typedef long double ldouble; - -using std::cout; -using std::cin; -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::map; -using std::multimap; -using std::string; -#ifndef QNX - using std::wstring; -#else - typedef std::basic_string wstring; -#endif - -/*! \brief Templated function for swap two values - * \details Example:\n \snippet piincludes.cpp swap */ -template inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;} - -/*! \brief Templated function for swap two values without "=" - * \details Example:\n \snippet piincludes.cpp swapBinary */ -template inline void piSwapBinary(T & f, T & s) { - static size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T); - size_t i = 0; - for (i = 0; i < j; ++i) { - ((size_t*)(&f))[i] ^= ((size_t*)(&s))[i]; - ((size_t*)(&s))[i] ^= ((size_t*)(&f))[i]; - ((size_t*)(&f))[i] ^= ((size_t*)(&s))[i]; - } - for (i = bs; i < bf; ++i) { - ((uchar*)(&f))[i] ^= ((uchar*)(&s))[i]; - ((uchar*)(&s))[i] ^= ((uchar*)(&f))[i]; - ((uchar*)(&f))[i] ^= ((uchar*)(&s))[i]; - } -} - -/*! \brief Templated function return round of float falue - * \details Round is the nearest integer value \n - * There are some macros: - * - \c piRoundf for "float" - * - \c piRoundd for "double" - * - * Example: - * \snippet piincludes.cpp round */ -template inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));} - -/*! \brief Templated function return floor of float falue - * \details Floor is the largest integer that is not greater than value \n - * There are some macros: - * - \c piFloorf for "float" - * - \c piFloord for "double" - * - * Example: - * \snippet piincludes.cpp floor */ -template inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);} - -/*! \brief Templated function return ceil of float falue - * \details Ceil is the smallest integer that is not less than value \n - * There are some macros: - * - \c piCeilf for "float" - * - \c piCeild for "double" - * - * Example: - * \snippet piincludes.cpp ceil */ -template inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;} - -/*! \brief Templated function return absolute of numeric falue - * \details Absolute is the positive or equal 0 value \n - * There are some macros: - * - \c piAbss for "short" - * - \c piAbsi for "int" - * - \c piAbsl for "long" - * - \c piAbsll for "llong" - * - \c piAbsf for "float" - * - \c piAbsd for "double" - * - * Example: - * \snippet piincludes.cpp abs */ -template inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);} - -/*! \brief Templated function return minimum of two values - * \details There are some macros: - * - \c piMins for "short" - * - \c piMini for "int" - * - \c piMinl for "long" - * - \c piMinll for "llong" - * - \c piMinf for "float" - * - \c piMind for "double" - * - * Example: - * \snippet piincludes.cpp min2 */ -template inline T piMin(const T & f, const T & s) {return ((f > s) ? s : f);} - -/*! \brief Templated function return minimum of tree values - * \details There are some macros: - * - \c piMins for "short" - * - \c piMini for "int" - * - \c piMinl for "long" - * - \c piMinll for "llong" - * - \c piMinf for "float" - * - \c piMind for "double" - * - * Example: - * \snippet piincludes.cpp min3 */ -template inline T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));} - -/*! \brief Templated function return maximum of two values - * \details There are some macros: - * - \c piMaxs for "short" - * - \c piMaxi for "int" - * - \c piMaxl for "long" - * - \c piMaxll for "llong" - * - \c piMaxf for "float" - * - \c piMaxd for "double" - * - * Example: - * \snippet piincludes.cpp max2 */ -template inline T piMax(const T & f, const T & s) {return ((f < s) ? s : f);} - -/*! \brief Templated function return maximum of tree values - * \details There are some macros: - * - \c piMaxs for "short" - * - \c piMaxi for "int" - * - \c piMaxl for "long" - * - \c piMaxll for "llong" - * - \c piMaxf for "float" - * - \c piMaxd for "double" - * - * Example: - * \snippet piincludes.cpp max3 */ -template inline T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));} - -/*! \brief Templated function return clamped value - * \details Clamped is the not greater than "max" and not lesser than "min" value \n - * There are some macros: - * - \c piClamps for "short" - * - \c piClampi for "int" - * - \c piClampl for "long" - * - \c piClampll for "llong" - * - \c piClampf for "float" - * - \c piClampd for "double" - * - * Example: - * \snippet piincludes.cpp clamp */ -template inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));} - -/// Function inverse byte order in memory block -inline void piLetobe(void * data, int size) { - for (int i = 0; i < size / 2; i++) - piSwap(((uchar*)data)[size - i - 1], ((uchar*)data)[i]); -} - -/// \brief Templated function that inverse byte order of value "v" -template inline void piLetobe(T * v) {piLetobe(v, sizeof(T));} - -/*! \brief Templated function that returns "v" with inversed byte order - * \details This function used to convert values between little and big endian \n - * There are some macros: - * - \c piLetobes for "ushort" - * - \c piLetobei for "uint" - * - \c piLetobel for "ulong" - * - \c piLetobell for "ullong" - * - * Example: - * \snippet piincludes.cpp letobe */ -template inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;} - -// specialization -template<> inline ushort piLetobe(const ushort & v) {return (v << 8) | (v >> 8);} -template<> inline uint piLetobe(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} - -DEPRECATED inline ushort letobe_s(const ushort & v) {return (v << 8) | (v >> 8);} -DEPRECATED inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} - -#ifdef DOXYGEN - -/// \deprecated \brief Use \a piLetobe() instead of this function -ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);} - -/// \deprecated \brief Use \a piLetobe() instead of this function -uint letobe_i(uint v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} - -#endif - -#define piRoundf piRound -#define piRoundd piRound -#define piFloorf piFloor -#define piFloord piFloor -#define piCeilf piCeil -#define piCeild piCeil -#define piAbss piAbs -#define piAbsi piAbs -#define piAbsl piAbs -#define piAbsll piAbs -#define piAbsf piAbs -#define piAbsd piAbs -#define piMins piMin -#define piMini piMin -#define piMinl piMin -#define piMinll piMin -#define piMinf piMin -#define piMind piMin -#define piMaxs piMax -#define piMaxi piMax -#define piMaxl piMax -#define piMaxll piMax -#define piMaxf piMax -#define piMaxd piMax -#define piClamps piClamp -#define piClampi piClamp -#define piClampl piClamp -#define piClampll piClamp -#define piClampf piClamp -#define piClampd piClamp -#define piLetobes piLetobe -#define piLetobei piLetobe -#define piLetobel piLetobe -#define piLetobell piLetobe - -extern bool isPIInit; - -//! global variable enabling output to piCout -extern PIP_EXPORT bool piDebug; - -extern string ifconfigPath; - -class PIInit { -public: - PIInit(); - ~PIInit(); -private: - bool fileExists(const string & p) {FILE * f = fopen(p.c_str(), "r"); if (f == 0) return false; fclose(f); return true;} -#ifdef WINDOWS - HMODULE ntlib; - ULONG prev_res; -#endif -}; - -extern PIInit piInit; -extern lconv * currentLocale; - -#ifdef WINDOWS -inline int random() {return rand();} -# ifdef CC_VC -inline double round(const double & v) {return floor(v + 0.5);} -# endif -#endif -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) { - char ch[256]; -#ifndef CC_VC - sprintf(ch, "%d", num); -#else - sprintf_s(ch, 256, "%d", num); -#endif - return string(ch);} -inline string ltos(const long num) { - char ch[256]; -#ifndef CC_VC - sprintf(ch, "%ld", num); -#else - sprintf_s(ch, 256, "%ld", num); -#endif - return string(ch);} -inline string uitos(const uint num) { - char ch[256]; -#ifndef CC_VC - sprintf(ch, "%u", num); -#else - sprintf_s(ch, 256, "%u", num); -#endif - return string(ch);} -inline string ultos(const ulong num) { - char ch[256]; -#ifndef CC_VC - sprintf(ch, "%lu", num); -#else - sprintf_s(ch, 256, "%lu", num); -#endif - return string(ch);} -inline string ftos(const float num) { - char ch[256]; -#ifndef CC_VC - sprintf(ch, "%g", num); -#else - sprintf_s(ch, 256, "%g", num); -#endif - return string(ch);} -inline string dtos(const double num) { - char ch[256]; -#ifndef CC_VC - sprintf(ch, "%g", num); -#else - sprintf_s(ch, 256, "%g", num); -#endif - return string(ch);} - -/*! \fn errorString() - * \brief Return readable error description in format "code - " */ -#ifdef WINDOWS -inline void errorClear() {SetLastError(0);} -inline string errorString() { - char * msg; - int err = GetLastError(); - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL); - return "code " + itos(err) + " - " + string(msg); -} -#else -inline void errorClear() {errno = 0;} -inline string errorString() {int e = errno; return "code " + itos(e) + " - " + string(strerror(e));} -#endif - -/// Return readable version of PIP -inline string PIPVersion() {return itos(PIP_VERSION_MAJOR) + "." + itos(PIP_VERSION_MINOR) + "." + itos(PIP_VERSION_REVISION) + PIP_VERSION_SUFFIX;} - -/*! \brief This class used as container for bit flags - * \details PIFlags is wrapper around \c "int". There are many - * bit-wise operators, native conversion to int and function - * to test flag. \n Example: - * \snippet piincludes.cpp flags - */ -template -class PIP_EXPORT PIFlags { -public: - //! Constructor with flags = 0 - PIFlags(): flags(0) {;} - //! Constructor with flags = Enum "e" - PIFlags(Enum e): flags(e) {;} - //! Constructor with flags = PIFlags "f" - PIFlags(const PIFlags & f): flags(f.flags) {;} - //! Constructor with flags = int "i" - PIFlags(const int i): flags(i) {;} - //! Set flags "f" to value "on" - PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;} - //! Set flag "e" to value "on" - PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;} - //! Set flag "i" to value "on" - PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;} - //! copy operator - void operator =(const PIFlags & f) {flags = f.flags;} - //! copy operator - void operator =(const Enum & e) {flags = e;} - //! copy operator - void operator =(const int & i) {flags = i;} - //! compare operator - void operator ==(const PIFlags & f) {flags == f.flags;} - //! compare operator - void operator ==(const Enum & e) {flags == e;} - //! compare operator - void operator ==(const int i) {flags == i;} - //! compare operator - void operator !=(const PIFlags & f) {flags != f.flags;} - //! compare operator - void operator !=(const Enum & e) {flags != e;} - //! compare operator - void operator !=(const int i) {flags != i;} - //! compare operator - void operator >(const PIFlags & f) {flags > f.flags;} - //! compare operator - void operator >(const Enum & e) {flags > e;} - //! compare operator - void operator >(const int i) {flags > i;} - //! compare operator - void operator <(const PIFlags & f) {flags < f.flags;} - //! compare operator - void operator <(const Enum & e) {flags < e;} - //! compare operator - void operator <(const int i) {flags < i;} - //! compare operator - void operator >=(const PIFlags & f) {flags >= f.flags;} - //! compare operator - void operator >=(const Enum & e) {flags >= e;} - //! compare operator - void operator >=(const int i) {flags >= i;} - //! compare operator - void operator <=(const PIFlags & f) {flags <= f.flags;} - //! compare operator - void operator <=(const Enum & e) {flags <= e;} - //! compare operator - void operator <=(const int i) {flags <= i;} - //! Bit-wise AND operator - void operator &=(const PIFlags & f) {flags &= f.flags;} - //! Bit-wise AND operator - void operator &=(const Enum & e) {flags &= e;} - //! Bit-wise AND operator - void operator &=(const int i) {flags &= i;} - //! Bit-wise OR operator - void operator |=(const PIFlags & f) {flags |= f.flags;} - //! Bit-wise OR operator - void operator |=(const Enum & e) {flags |= e;} - //! Bit-wise OR operator - void operator |=(const int i) {flags |= i;} - //! Bit-wise XOR operator - void operator ^=(const PIFlags & f) {flags ^= f.flags;} - //! Bit-wise XOR operator - void operator ^=(const Enum & e) {flags ^= e;} - //! Bit-wise XOR operator - void operator ^=(const int i) {flags ^= i;} - //! Bit-wise AND operator - PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;} - //! Bit-wise AND operator - PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;} - //! Bit-wise AND operator - PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;} - //! Bit-wise OR operator - PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;} - //! Bit-wise OR operator - PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;} - //! Bit-wise OR operator - PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;} - //! Bit-wise XOR operator - PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;} - //! Bit-wise XOR operator - PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;} - //! Bit-wise XOR operator - PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;} - //! Test flag operator - bool operator [](Enum e) const {return (flags & e) == e;} - //! Implicity conversion to \c int - operator int() const {return flags;} -private: - int flags; -}; - -#ifdef DOXYGEN - -//! \brief Macro used for conditional (piDebug) output to PICout -# define piCout - -//! \relatesalso PIObject \brief Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject -# define piCoutObj - -#else -# define piCout if (piDebug) PICout() -# define piCoutObj if (piDebug && debug()) PICout() << "" << (PIString("[") + className() + " \"" + name() + "\"]") -#endif - -class PIObject; -class PIMutex; -class PIString; - -extern PIMutex __PICout_mutex__; -extern PIString __PICout_string__; - -//! \brief Namespace contains enums controlled PICout -namespace PICoutManipulators { - - //! \brief Enum contains special characters - enum PIP_EXPORT PICoutSpecialChar { - Null /*! Null-character, '\\0' */, - NewLine /*! New line character, '\\n' */, - Tab /*! Tab character, '\\t' */, - Esc /*! Escape character, '\\e' */, - Quote /*! Quote character, '"' */ - }; - - //! \brief Enum contains immediate action - enum PIP_EXPORT PICoutAction { - Flush /*! Flush the output */, - Backspace /*! Remove last symbol */, - ShowCursor /*! Show cursor */, - HideCursor /*! Hide cursor */, - ClearScreen /*! Clear the screen */, - SaveContol /*! Save control flags, equivalent to \a saveControl() */, - RestoreControl /*! Restore control flags, equivalent to \a restoreControl() */ - }; - - //! \brief Enum contains control of PICout - enum PIP_EXPORT PICoutControl { - AddNone /*! No controls */ = 0x0, - AddSpaces /*! Spaces will be appear after each output */ = 0x1, - AddNewLine /*! New line will be appear after all output */ = 0x2, - AddQuotes /*! Each string will be quoted */ = 0x4, - AddAll /*! All controls */ = 0xFFFFFFFF - }; - - //! \brief Enum contains output format - enum PIP_EXPORT PICoutFormat { - Bin /*! Binary representation of integers */ = 0x01, - Oct /*! Octal representation of integers */ = 0x02, - Dec /*! Decimal representation of integers */ = 0x04, - Hex /*! Hexadecimal representation of integers */ = 0x08, - Bold /*! Bold */ = 0x10, - Faint /*! */ = 0x20, - Italic /*! */ = 0x40, - Underline /*! Underline */ = 0x80, - Blink /*! Blink */ = 0x100, - Black /*! Black font */ = 0x400, - Red /*! Red font */ = 0x800, - Green /*! Green font */ = 0x1000, - Blue /*! Blue font */ = 0x2000, - Yellow /*! Yellow font */ = 0x4000, - Magenta /*! Magenta font */ = 0x8000, - Cyan /*! Cyan font */ = 0x10000, - White /*! White font */ = 0x20000, - BackBlack /*! Black background */ = 0x40000, - BackRed /*! Red background */ = 0x80000, - BackGreen /*! Green background */ = 0x100000, - BackBlue /*! Blue background */ = 0x200000, - BackYellow /*! Yellow background */ = 0x400000, - BackMagenta /*! Magenta background */ = 0x800000, - BackCyan /*! Cyan background */ = 0x1000000, - BackWhite /*! White background */ = 0x2000000, - Default /*! Default format */ = 0x4000000 - }; -}; - -using namespace PICoutManipulators; - -typedef PIFlags PICoutControls; - -class PIP_EXPORT PICout { -public: - //! Default constructor with default features (AddSpaces and AddNewLine) - PICout(PIFlags controls = AddSpaces | AddNewLine); - - PICout(const PICout & other): fo_(other.fo_), cc_(true), fc_(false), cnb_(other.cnb_), attr_(other.attr_), co_(other.co_) {;} - ~PICout(); - - //! Output operator for strings with "const char * " type - PICout operator <<(const char * v); - - //! Output operator for strings with "std::string" type - PICout operator <<(const string & v); - - //! Output operator for boolean values - PICout operator <<(const bool v); - - //! Output operator for "char" values - PICout operator <<(const char v); - - //! Output operator for "unsigned char" values - PICout operator <<(const uchar v); - - //! Output operator for "short" values - PICout operator <<(const short v); - - //! Output operator for "unsigned short" values - PICout operator <<(const ushort v); - - //! Output operator for "int" values - PICout operator <<(const int v); - - //! Output operator for "unsigned int" values - PICout operator <<(const uint v); - - //! Output operator for "long" values - PICout operator <<(const long v); - - //! Output operator for "unsigned long" values - PICout operator <<(const ulong v); - - //! Output operator for "long long" values - PICout operator <<(const llong v); - - //! Output operator for "unsigned long long" values - PICout operator <<(const ullong v); - - //! Output operator for "float" values - PICout operator <<(const float v); - - //! Output operator for "double" values - PICout operator <<(const double v); - - //! Output operator for pointers - PICout operator <<(const void * v); - - //! Output operator for PIObject and ancestors - PICout operator <<(const PIObject * v); - - //! Output operator for \a PICoutSpecialChar values - PICout operator <<(const PICoutSpecialChar v); - - //! Output operator for \a PIFlags values - PICout operator <<(const PIFlags v) { - if (v[Bin]) cnb_ = 2; - if (v[Oct]) cnb_ = 8; - if (v[Dec]) cnb_ = 10; - if (v[Hex]) cnb_ = 16; - if (v[Bold]) applyFormat(Bold); - if (v[Faint]) applyFormat(Faint); - if (v[Italic]) applyFormat(Italic); - if (v[Underline]) applyFormat(Underline); - if (v[Blink]) applyFormat(Blink); - if (v[Black]) applyFormat(Black); - if (v[Red]) applyFormat(Red); - if (v[Green]) applyFormat(Green); - if (v[Blue]) applyFormat(Blue); - if (v[Yellow]) applyFormat(Yellow); - if (v[Magenta]) applyFormat(Magenta); - if (v[Cyan]) applyFormat(Cyan); - if (v[White]) applyFormat(White); - if (v[BackBlack]) applyFormat(BackBlack); - if (v[BackRed]) applyFormat(BackRed); - if (v[BackGreen]) applyFormat(BackGreen); - if (v[BackBlue]) applyFormat(BackBlue); - if (v[BackYellow]) applyFormat(BackYellow); - if (v[BackMagenta]) applyFormat(BackMagenta); - if (v[BackCyan]) applyFormat(BackCyan); - if (v[BackWhite]) applyFormat(BackWhite); - if (v[Default]) applyFormat(Default); - return *this; - } - - //! Output operator for \a PICoutFormat values - PICout operator <<(const PICoutFormat v) { - switch (v) { - case Bin: cnb_ = 2; break; - case Oct: cnb_ = 8; break; - case Dec: cnb_ = 10; break; - case Hex: cnb_ = 16; break; - default: applyFormat(v); - }; - return *this; - } - - //! Do some action - PICout operator <<(const PICoutAction v); - - //! Set control flag "c" is "on" state - PICout & setControl(PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;} - - //! Set control flags "c" and if "save" exec \a saveControl() - PICout & setControl(PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c; return *this;} - - //! Save control flags to internal stack \sa \a restoreControl() - PICout & saveControl() {cos_.push(co_); return *this;} - - //! Restore control flags from internal stack \sa \a saveControl() - PICout & restoreControl() {if (!cos_.empty()) {co_ = cos_.top(); cos_.pop();} return *this;} - - /*! \brief Conditional put space character to output - * \details If it is not a first output and control \a AddSpaces is set - * space character is put \sa \a quote(), \a newLine() */ - PICout & space(); - - /*! \brief Conditional put quote character to output - * \details If control \a AddQuotes is set - * quote character is put \sa \a space(), \a newLine() */ - PICout & quote(); - - /*! \brief Conditional put new line character to output - * \details If control \a AddNewLine is set - * new line character is put \sa \a space(), \a quote() */ - PICout & newLine(); - - static bool setBufferActive(bool on, bool clear = false); - static bool isBufferActive(); - static PIString buffer(bool clear = false); - static void clearBuffer(); - -private: - void applyFormat(PICoutFormat f); - - static bool buffer_; - bool fo_, cc_, fc_; - int cnb_, attr_; - PICoutControls co_; - std::stack cos_; -#ifdef WINDOWS - static void * hOut; - static WORD dattr; - static DWORD smode; -#endif -}; - -#endif // PIINCLUDES_H diff --git a/piiodevice.cpp b/piiodevice.cpp deleted file mode 100644 index 8b01cd8b..00000000 --- a/piiodevice.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* - PIP - Platform Independent Primitives - Abstract input/output device - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "piiodevice.h" -#include "piconfig.h" - - -/*! \class PIIODevice - * \brief Base class for input/output classes - * - * \section PIIODevice_sec0 Synopsis - * This class provide open/close logic, threaded read/write and virtual input/output - * functions \a read() and \a write(). You should implement pure virtual - * function \a openDevice() in your subclass. - * - * \section PIIODevice_sec1 Open and close - * PIIODevice have boolean variable indicated open status. Returns of functions - * \a openDevice() and \a closeDevice() change this variable. - * - * \section PIIODevice_sec2 Threaded read - * PIIODevice based on PIThread, so it`s overload \a run() to exec \a read() - * in background thread. If read is successful virtual function \a threadedRead() - * is executed. Default implementation of this function execute external static - * function set by \a setThreadedReadSlot() with data set by \a setThreadedReadData(). - * Extrenal static function should have format \n - * bool func_name(void * Threaded_read_data, uchar * readed_data, int readed_size)\n - * Threaded read starts with function \a startThreadedRead(). - * - * \section PIIODevice_sec3 Threaded write - * PIIODevice aggregate another PIThread to perform a threaded write by function - * \a writeThreaded(). This function add task to internal queue and return - * queue entry ID. You should start write thread by function \a startThreadedWrite. - * On successful write event \a threadedWriteEvent is raised with two arguments - - * task ID and written bytes count. - * - * \section PIIODevice_sec4 Internal buffer - * PIIODevice have internal buffer for threaded read, and \a threadedRead() function - * receive pointer to this buffer in first argument. You can adjust size of this buffer - * by function \a setThreadedReadBufferSize() \n - * Default size of this buffer is 4096 bytes. - * - * \section PIIODevice_sec5 Reopen - * When threaded read is begin its call \a open() if device is closed. While threaded - * read running PIIODevice check if device opened every read and if not call \a open() - * every reopen timeout if reopen enabled. Reopen timeout is set by \a setReopenTimeout(), - * reopen enable is set by \a setReopenEnabled(). - * - * \section PIIODevice_sec6 Configuration - * This is virtual function \a configureDevice() which executes when \a configure() - * executes. This function takes two arguments: "e_main" and "e_parent" as void*. There - * are pointers to PIConfig::Entry entries of section "section" and their parent. If - * there is no parent "e_parent" = 0. Function \a configure() set three parameters of - * device: "reopenEnabled", "reopenTimeout" and "threadedReadBufferSize", then execute - * function \a configureDevice(). - * \n Each ancestor of %PIIODevice reimlements \a configureDevice() function to be able - * to be confured from configuration file. This parameters described at section - * "Configurable parameters" in the class reference. \n Usage example: - * \snippet piiodevice.cpp configure - * Implementation example: - * \snippet piiodevice.cpp configureDevice - * - * \section PIIODevice_sec7 Creating devices by unambiguous string - * There are some virtual functions to describe child class without its declaration. - * \n \a fullPathPrefix() should returns unique prefix of device - * \n \a constructFullPath() should returns full unambiguous string, contains prefix and all device parameters - * \n \a configureFromFullPath() provide configuring device from full unambiguous string without prefix and "://" - * \n Macro PIIODEVICE should be used instead of PIOBJECT - * \n Macro REGISTER_DEVICE should be used after definition of class, i.e. at the last line of *.cpp file - * \n \n If custom I/O device corresponds there rules, it can be returned by function \a createFromFullPath(). - * \n Each PIP I/O device has custom unambiguous string description: - * * PIFile: "file://" - * * PIBinaryLog: "binlog://[:][:]" - * * PISerial: "ser://:[:][:][:]" - * * PIEthernet: "eth://::[:)>]" - * * PIUSB: "usb://:[:][:][:]" - * \n \n Examples: - * * PIFile: "file://../text.txt" - * * PIBinaryLog: "binlog://../logs/:mylog_:1" - * * PISerial: "ser:///dev/ttyUSB0:9600:8:N:1", equivalent "ser:///dev/ttyUSB0:9600" - * * PIEthernet: "eth://TCP:127.0.0.1:16666", "eth://UDP:192.168.0.5:16666:mcast:234.0.2.1:mcast:234.0.2.2" - * * PIUSB: "usb://0bb4:0c86:1:1:2" - * \n \n - * So, custom I/O device can be created with next call: - * \code{cpp} - * // creatring devices - * PISerial * ser = (PISerial * )PIIODevice::createFromFullPath("ser://COM1:115200"); - * PIEthernet * eth = (PIEthernet * )PIIODevice::createFromFullPath("eth://UDP:127.0.0.1:4001"); - * // examine devices - * piCout << ser << ser->properties(); - * piCout << eth << eth->properties(); - * \endcode - * - * \section PIIODevice_ex0 Example - * \snippet piiodevice.cpp 0 - */ - - -PIIODevice::PIIODevice(): PIThread() { - mode_ = ReadOnly; - _init(); - setPath(PIString()); -} - - -/*! \brief Constructs a PIIODevice with path and mode - * \param path path to device - * \param type mode for open */ -PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode mode): PIThread() { - mode_ = mode; - _init(); - setPath(path); -} - - -PIIODevice::~PIIODevice() { - stop(); - if (opened_) { - closeDevice(); - if (!opened_) - closed(); - } -} - - -void PIIODevice::_init() { - opened_ = init_ = thread_started_ = false; - raise_threaded_read_ = true; - ret_func_ = 0; - ret_data_ = 0; - tri = 0; - setReopenEnabled(true); - setReopenTimeout(1000); - setThreadedReadBufferSize(4096); - CONNECT2(void, void * , int, &timer, timeout, this, check_start); - CONNECT(void, &write_thread, started, this, write_func); -} - - -void PIIODevice::check_start(void * data, int delim) { - //cout << "check " << tread_started_ << endl; - if (open()) { - thread_started_ = true; - timer.stop(); - } -} - - -void PIIODevice::write_func() { - while (!write_thread.isStopping()) { - while (!write_queue.isEmpty()) { - if (write_thread.isStopping()) return; - write_thread.lock(); - PIPair item(write_queue.dequeue()); - write_thread.unlock(); - int ret = write(item.first); - threadedWriteEvent(item.second, ret); - } - msleep(1); - } -} - - -void PIIODevice::terminate() { - thread_started_ = false; - if (!isInitialized()) return; - if (isRunning()) { - stop(); - PIThread::terminate(); - } -} - - -void PIIODevice::begin() { - //cout << " begin\n"; - thread_started_ = false; - if (!opened_) { - if (open()) { - thread_started_ = true; - //cout << " open && ok\n"; - return; - } - } else { - thread_started_ = true; - //cout << " ok\n"; - return; - } - //init(); - if (!timer.isRunning() && isReopenEnabled()) timer.start(reopenTimeout()); -} - - -void PIIODevice::run() { - if (!isReadable()) { - //cout << "not readable\n"; - PIThread::stop(); - return; - } - if (!thread_started_) { - msleep(1); - //cout << "not started\n"; - return; - } - readed_ = read(buffer_tr.data(), buffer_tr.size_s()); - if (readed_ <= 0) { - msleep(10); - //cout << readed_ << ", " << errno << ", " << errorString() << endl; - return; - } - threadedRead(buffer_tr.data(), readed_); - if (raise_threaded_read_) threadedReadEvent(buffer_tr.data(), readed_); -} - - -PIByteArray PIIODevice::readForTime(double timeout_ms) { - PIByteArray str; - if (timeout_ms <= 0.) return str; - int ret; - uchar * td = new uchar[threadedReadBufferSize()]; - timer.reset(); - while (timer.elapsed_m() < timeout_ms) { - ret = read(td, threadedReadBufferSize()); - if (ret <= 0) msleep(1); - else str.append(td, ret); - } - delete td; - return str; -} - - -ullong PIIODevice::writeThreaded(const PIByteArray & data) { - write_thread.lock(); - write_queue.enqueue(PIPair(data, tri)); - ++tri; - write_thread.unlock(); - return tri - 1; -} - - -bool PIIODevice::configure(const PIString & config_file, const PIString & section, bool parent_section) { - PIConfig conf(config_file, PIIODevice::ReadOnly); - if (!conf.isOpened()) return false; - bool ex = true; - PIConfig::Entry em; - if (section.isEmpty()) em = conf.rootEntry(); - else em = conf.getValue(section, PIString(), &ex); - if (!ex) return false; - PIConfig::Entry * ep = 0; - if (parent_section) ep = em.parent(); - if (ep != 0) { - setReopenEnabled(ep->getValue("reopenEnabled", isReopenEnabled(), &ex)); - if (!ex) setReopenEnabled(em.getValue("reopenEnabled", isReopenEnabled())); - setReopenTimeout(ep->getValue("reopenTimeout", reopenTimeout(), &ex)); - if (!ex) setReopenTimeout(em.getValue("reopenTimeout", reopenTimeout())); - setThreadedReadBufferSize(ep->getValue("threadedReadBufferSize", buffer_tr.size_s(), &ex)); - if (!ex) setThreadedReadBufferSize(em.getValue("threadedReadBufferSize", buffer_tr.size_s())); - } else { - setReopenEnabled(em.getValue("reopenEnabled", isReopenEnabled())); - setReopenTimeout(em.getValue("reopenTimeout", reopenTimeout())); - setThreadedReadBufferSize(em.getValue("threadedReadBufferSize", buffer_tr.size_s())); - } - return configureDevice(&em, ep); -} - - -PIIODevice * PIIODevice::createFromFullPath(const PIString & full_path) { - PIString prefix = full_path.left(full_path.find(":")); - if (prefix.isEmpty()) return 0; - PIVector rd(PICollection::groupElements("__PIIODevices__")); - piForeachC (PIObject * d, rd) - if (prefix == ((const PIIODevice * )d)->fullPathPrefix()) { - PIIODevice * nd = ((const PIIODevice * )d)->copy(); - if (nd) nd->configureFromFullPath(full_path.mid(prefix.length() + 3)); - return nd; - } - return 0; -} diff --git a/piiodevice.h b/piiodevice.h deleted file mode 100644 index 33d536e9..00000000 --- a/piiodevice.h +++ /dev/null @@ -1,329 +0,0 @@ -/*! \file piiodevice.h - * \brief Abstract input/output device -*/ -/* - PIP - Platform Independent Primitives - Abstract input/output device - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIIODEVICE_H -#define PIIODEVICE_H - -#include "picollection.h" -#include "pivariant.h" -#include "pitimer.h" - -// function executed from threaded read, pass ThreadedReadData, readedData, sizeOfData -typedef bool (*ReadRetFunc)(void * , uchar * , int ); - -#ifdef DOXYGEN - -//! \relatesalso PIIODevice \brief Use this macro to enable automatic creation instances of your class with \a createFromFullPath() function -# define REGISTER_DEVICE(class) - -//! \relatesalso PIIODevice \brief Use this macro instead of PIOBJECT when describe your own PIIODevice -# define PIIODEVICE(class) - -#else - -# define REGISTER_DEVICE(class) ADD_NEW_TO_COLLECTION(__PIIODevices__, class) -# define PIIODEVICE(class) PIOBJECT(class) PIIODevice * copy() const {return new class();} - -#endif - -class PIP_EXPORT PIIODevice: public PIThread -{ - PIOBJECT(PIIODevice) -public: - - //! Constructs a empty PIIODevice - PIIODevice(); - - //! \brief Open modes for PIIODevice - enum DeviceMode { - ReadOnly /*! Device can only read */ = 0x01, - WriteOnly /*! Device can only write */ = 0x02, - ReadWrite /*! Device can both read and write */ = 0x03 - }; - - PIIODevice(const PIString & path, DeviceMode mode = ReadWrite); - virtual ~PIIODevice(); - - //! Current open mode of device - DeviceMode mode() const {return mode_;} - - //! Current path of device - PIString path() const {return property("path").toString();} - - //! Set path of device - void setPath(const PIString & path) {setProperty("path", path);} - - //! Return \b true if mode is ReadOnly or ReadWrite - bool isReadable() const {return (mode_ & ReadOnly);} - - //! Return \b true if mode is WriteOnly or ReadWrite - bool isWriteable() const {return (mode_ & WriteOnly);} - - bool isInitialized() const {return init_;} - - //! Return \b true if device is successfully opened - bool isOpened() const {return opened_;} - - //! Return \b true if device is closed - bool isClosed() const {return !opened_;} - - //! Return \b true if device can read \b now - bool canRead() const {return opened_ && (mode_ & ReadOnly);} - - //! Return \b true if device can write \b now - bool canWrite() const {return opened_ && (mode_ & WriteOnly);} - - - //! Set execution of \a open enabled while threaded read on closed device - void setReopenEnabled(bool yes = true) {setProperty("reopenEnabled", yes);} - - //! Set timeout in milliseconds between \a open tryings if reopen is enabled - void setReopenTimeout(int msecs) {setProperty("reopenTimeout", msecs);} - - - //! Return reopen enable - bool isReopenEnabled() const {return property("reopenEnabled").toBool();} - - //! Return reopen timeout - int reopenTimeout() {return property("reopenTimeout").toInt();} - - - /** \brief Set "threaded read slot" - * \details Set external static function of threaded read that will be executed - * at every successful threaded read. Function should have format - * "bool func(void * data, uchar * readed, int size)" */ - void setThreadedReadSlot(ReadRetFunc func) {ret_func_ = func;} - - //! Set custom data that will be passed to "threaded read slot" - void setThreadedReadData(void * d) {ret_data_ = d;} - - /** \brief Set size of threaded read buffer - * \details Default size is 4096 bytes. If your device can read at single read - * more than 4096 bytes you should use this function to adjust buffer size */ - void setThreadedReadBufferSize(int new_size) {buffer_tr.resize(new_size);} - - //! Return size of threaded read buffer - int threadedReadBufferSize() const {return buffer_tr.size_s();} - - //! Return content of threaded read buffer - const uchar * threadedReadBuffer() const {return buffer_tr.data();} - - //! Return custom data that will be passed to "threaded read slot" - void * threadedReadData() const {return ret_data_;} - - - //! Return \b true if threaded read is started - bool isThreadedRead() const {return isRunning();} - - //! Start threaded read - void startThreadedRead() {if (!isRunning()) PIThread::start();} - - //! Start threaded read and assign "threaded read slot" to "func" - void startThreadedRead(ReadRetFunc func) {ret_func_ = func; if (!isRunning()) PIThread::start();} - - //! Stop threaded read - void stopThreadedRead() {PIThread::terminate();} - - - //! Return \b true if threaded write is started - bool isThreadedWrite() const {return write_thread.isRunning();} - - //! Start threaded write - void startThreadedWrite() {if (!write_thread.isRunning()) write_thread.startOnce();} - - //! Stop threaded write - void stopThreadedWrite() {write_thread.terminate();} - - //! Clear threaded write task queue - void clearThreadedWriteQueue() {write_thread.lock(); write_queue.clear(); write_thread.unlock();} - - - //! Start both threaded read and threaded write - void start() {startThreadedRead(); startThreadedWrite();} - - //! Stop both threaded read and threaded write and if "wait" block until both threads are stop - void stop(bool wait = false) {stopThreadedRead(); stopThreadedWrite(); if (wait) while (write_thread.isRunning() || isRunning()) msleep(1);} - - - //! Reimplement this function to read from your device - virtual int read(void * read_to, int max_size) {piCoutObj << "\"read\" is not implemented!"; return -2;} - - //! Reimplement this function to write to your device - virtual int write(const void * data, int max_size) {piCoutObj << "\"write\" is not implemented!"; return -2;} - - - //! Read from device maximum "max_size" bytes and return them as PIByteArray - PIByteArray read(int max_size) {buffer_in.resize(max_size); int ret = read(buffer_in.data(), max_size); if (ret < 0) return PIByteArray(); return buffer_in.resized(ret);} - - //! Read from device for "timeout_ms" milliseconds and return readed data as PIByteArray. Timeout should to be greater than 0 - PIByteArray readForTime(double timeout_ms); - - //! Write "data" to device - int write(const PIByteArray & data) {return write(data.data(), data.size_s());} - - - //! Add task to threaded write queue and return task ID - ullong writeThreaded(const void * data, int max_size) {return writeThreaded(PIByteArray(data, uint(max_size)));} - - //! Add task to threaded write queue and return task ID - ullong writeThreaded(const PIByteArray & data); - - - //! Configure device from section "section" of file "config_file", if "parent_section" parent section also will be read - bool configure(const PIString & config_file, const PIString & section, bool parent_section = false); - - - //! Reimplement to construct full unambiguous string, describes this device, default returns \a path() - virtual PIString constructFullPath() const {return path();} - - //! \brief Try to determine suitable device, create new one, configure it with \a configureFromFullPath() and returns it. - //! \details To function \a configureFromFullPath() "full_path" passed without \a fullPathPrefix() + "://". - //! See \ref PIIODevice_sec7 - static PIIODevice * createFromFullPath(const PIString & full_path); - - - EVENT_HANDLER(bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} - EVENT_HANDLER1(bool, open, const PIString &, _path) {setPath(_path); if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} - EVENT_HANDLER1(bool, open, const DeviceMode &, _mode) {mode_ = _mode; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} - EVENT_HANDLER2(bool, open, const PIString &, _path, const DeviceMode &, _mode) {setPath(_path); mode_ = _mode; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} - EVENT_HANDLER(bool, close) {opened_ = !closeDevice(); if (!opened_) closed(); return !opened_;} - EVENT_HANDLER(bool, initialize) {init_ = init(); return init_;} - - EVENT_VHANDLER(void, flush) {;} - - EVENT(opened) - EVENT(closed) - EVENT2(threadedReadEvent, uchar * , readed, int, size) - EVENT2(threadedWriteEvent, ullong, id, int, written_size) - -//! \handlers -//! \{ - - //! \fn bool open() - //! \brief Open device - - //! \fn bool open(const PIString & path) - //! \brief Open device with path "path" - - //! \fn bool open(const DeviceMode & mode) - //! \brief Open device with mode "mode" - - //! \fn bool open(const PIString & path, const DeviceMode & mode) - //! \brief Open device with path "path" and mode "mode" - - //! \fn bool close() - //! \brief Close device - - //! \fn bool initialize() - //! \brief Initialize device - -//! \} -//! \vhandlers -//! \{ - - //! \fn void flush() - //! \brief Immediate write all buffers - -//! \} -//! \events -//! \{ - - //! \fn void opened() - //! \brief Raise if succesfull open - - //! \fn void closed() - //! \brief Raise if succesfull close - - //! \fn void threadedReadEvent(uchar * readed, int size) - //! \brief Raise if read thread succesfull read some data - - //! \fn void threadedWriteEvent(ullong id, int written_size) - //! \brief Raise if write thread succesfull write some data of task with ID "id" - -//! \} -//! \ioparams -//! \{ -#ifdef DOXYGEN - //! \brief setReopenEnabled, default "true" - bool reopenEnabled; - - //! \brief setReopenTimeout in ms, default 1000 - int reopenTimeout; - - //! \brief setThreadedReadBufferSize in bytes, default 4096 - int threadedReadBufferSize; -#endif -//! \} - -protected: - - //! Function executed before first \a openDevice() or from constructor - virtual bool init() {return true;} - - //! Reimplement to configure device from entries "e_main" and "e_parent", cast arguments to \a PIConfig::Entry* - virtual bool configureDevice(const void * e_main, const void * e_parent = 0) {return true;} - - //! Reimplement to open device, return value will be set to "opened_" variable - virtual bool openDevice() = 0; // use path_, type_, opened_, init_ variables - - //! Reimplement to close device, inverse return value will be set to "opened_" variable - virtual bool closeDevice() {return true;} // use path_, type_, opened_, init_ variables - - //! Function executed when thread read some data, default implementation execute external slot "ret_func_" - virtual bool threadedRead(uchar * readed, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, readed, size); return true;} - - - //! Reimplement to construct full unambiguous string prefix. \ref PIIODevice_sec7 - virtual PIString fullPathPrefix() const {return PIString();} - - //! Reimplement to configure your device with parameters of full unambiguous string. Default implementation does nothing - virtual void configureFromFullPath(const PIString & full_path) {;} - - - void terminate(); - - - DeviceMode mode_; - ReadRetFunc ret_func_; - bool init_, opened_, thread_started_, raise_threaded_read_; - void * ret_data_; - -private: - EVENT_HANDLER2(void, check_start, void * , data, int, delim); - EVENT_HANDLER(void, write_func); - - virtual PIIODevice * copy() const {return 0;} - void _init(); - void begin(); - void run(); - void end() {terminate();} - - PITimer timer; - PIThread write_thread; - PIByteArray buffer_in, buffer_tr; - PIQueue > write_queue; - ullong tri; - int readed_; - -}; - -#endif // PIIODEVICE_H diff --git a/pikbdlistener.cpp b/pikbdlistener.cpp deleted file mode 100644 index dddd46c7..00000000 --- a/pikbdlistener.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - PIP - Platform Independent Primitives - Keyboard grabber for console - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pikbdlistener.h" - - -/** \class PIKbdListener - * \brief Keyboard console input listener - * \details This class provide listening of console keyboard input. - * There is two ways to receive pressed key: - * * external static functionwith format "void func(char key, void * data_)" - * * event \a keyPressed() - * - * Also there is static variable \a exiting which by default is set to - * \b false. If \a enableExitCapture() was called and listener was started - * with function \a start(), this variable will be set to \b true if exit - * key will be pressed. By default exit key is 'Q' = shift + 'q'. - * To wait for this variable changes to \b true there is WAIT_FOR_EXIT macro - * \snippet pikbdlistener.cpp main - * */ - - -bool PIKbdListener::exiting; - -PIKbdListener::PIKbdListener(KBFunc slot, void * _data): PIThread() { -#ifdef WINDOWS - 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 WINDOWS - GetConsoleMode(hIn, &tmode); - SetConsoleMode(hIn, ENABLE_PROCESSED_INPUT); -#else - struct termios term; - tcgetattr(0, &term); - term.c_lflag &= ~(ECHO | ICANON) | NOFLSH; - tterm = term; - tcsetattr(0, TCSAFLUSH, &term); -#endif -} - - -void PIKbdListener::run() { - rc = 0; - char lc = 0; -#ifdef WINDOWS - INPUT_RECORD ir; - ReadConsoleInput(hIn, &ir, 1, &ret); - if (ir.EventType == KEY_EVENT) { - KEY_EVENT_RECORD ker = ir.Event.KeyEvent; - if (ker.bKeyDown) { - bool ctrl = ((ker.dwControlKeyState & LEFT_CTRL_PRESSED) || (ker.dwControlKeyState & RIGHT_CTRL_PRESSED)); - bool shift = (ker.dwControlKeyState & SHIFT_PRESSED); - if (ker.dwControlKeyState & CAPSLOCK_ON) shift = !shift; - //cout << "key " << int(ker.wVirtualKeyCode) << endl; - switch (ker.wVirtualKeyCode) { - case 37: ret = 1; lc = (ctrl ? CtrlLeftArrow : LeftArrow); break; - case 38: ret = 1; lc = (ctrl ? CtrlUpArrow : UpArrow); break; - case 39: ret = 1; lc = (ctrl ? CtrlRightArrow : RightArrow); break; - case 40: ret = 1; lc = (ctrl ? CtrlDownArrow : DownArrow); break; - default: ret = 1; lc = (shift ? char(toupper(ker.uChar.AsciiChar)) : ker.uChar.AsciiChar); break; - } - if (lc == 0) {piMSleep(10); return;} - } else {piMSleep(10); return;} - } else {piMSleep(10); return;} - /*if (lc == 0) { - ReadConsole(hIn, &rc, 1, &ret, 0); - //cout << "read console" << endl; - lc = char(rc); - }*/ - /*if (ret < 0 || ret > 3) return; - lc = char(((uchar * )&rc)[ret - 1]); - for (int i = 0; i < ret; ++i) - cout << std::hex << int(((uchar * )&rc)[i]) << ' '; - cout << endl << std::hex << rc << endl;*/ -#else - ret = read(0, &rc, 4); - if (ret < 0 || ret > 3) {piMSleep(10); return;} - lc = char(((uchar * )&rc)[ret - 1]); - //for (int i = 0; i < ret; ++i) - // cout << std::hex << int(((uchar * )&rc)[i]) << ' '; - //cout << endl << std::hex << rc << endl; - if (((char * )&rc)[0] == '\e' && ret == 3) { - if (((char * )&rc)[1] == '[') { - switch (((char * )&rc)[2]) { - case 'A': lc = UpArrow; break; // up - case 'B': lc = DownArrow; break; // down - case 'C': lc = RightArrow; break; // right - case 'D': lc = LeftArrow; break; // left - } - } - } - if (((char * )&rc)[0] == '5' && ret == 2) { - switch (((char * )&rc)[1]) { - case 'A': lc = CtrlUpArrow; break; // up - case 'B': lc = CtrlDownArrow; break; // down - case 'C': lc = CtrlRightArrow; break; // right - case 'D': lc = CtrlLeftArrow; break; // left - } - } -#endif - if (exit_enabled && ret == 1 && lc == exit_key) { - PIKbdListener::exiting = true; - return; - } - if (ret > 0) { - keyPressed(lc, data_); - if (ret_func != 0) ret_func(lc, data_); - } -} - - -void PIKbdListener::end() { - //cout << "list end" << endl; -#ifdef WINDOWS - SetConsoleMode(hIn, smode); -#else - tcsetattr(0, TCSANOW, &sterm); -#endif -} - - -void PIKbdListener::setActive(bool yes) { - is_active = yes; - if (is_active) { -#ifdef WINDOWS - SetConsoleMode(hIn, tmode); -#else - tcsetattr(0, TCSANOW, &tterm); -#endif - } else { -#ifdef WINDOWS - SetConsoleMode(hIn, smode); -#else - tcsetattr(0, TCSANOW, &sterm); -#endif - } -} diff --git a/pikbdlistener.h b/pikbdlistener.h deleted file mode 100644 index 801b80da..00000000 --- a/pikbdlistener.h +++ /dev/null @@ -1,130 +0,0 @@ -/*! \file pikbdlistener.h - * \brief Keyboard console input listener -*/ -/* - PIP - Platform Independent Primitives - Keyboard grabber for console - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIKBDLISTENER_H -#define PIKBDLISTENER_H - -#include "pithread.h" -#ifndef WINDOWS -# include -#endif - -#define WAIT_FOR_EXIT while (!PIKbdListener::exiting) msleep(1); - -typedef void (*KBFunc)(char, void * ); - -class PIP_EXPORT PIKbdListener: public PIThread -{ - PIOBJECT(PIKbdListener) - friend class PIConsole; -public: - - //! Special keyboard keys - enum SpecialSymbol { - UpArrow /** Up arrow key */ = -1, - DownArrow /** Down arrow key */ = -2, - RightArrow /** Right arrow key */ = -3, - LeftArrow /** Left arrow key */ = -4, - CtrlUpArrow /** Ctrl + Up arrow key */ = -5, - CtrlDownArrow /** Ctrl + Down arrow key */ = -6, - CtrlRightArrow /** Ctrl + Right arrow key */ = -7, - CtrlLeftArrow /** Ctrl + Left arrow key */ = -8 - }; - - //! Constructs keyboard listener with external function "slot" and custom data "data" - PIKbdListener(KBFunc slot = 0, void * data = 0); - - ~PIKbdListener() {terminate(); end();} - - - //! Returns custom data - void * data() {return data_;} - - //! Set custom data to "_data" - void setData(void * _data) {data_ = _data;} - - //! Set external function to "slot" - void setSlot(KBFunc slot) {ret_func = slot;} - - //! Returns if exit key if awaiting - bool exitCaptured() const {return exit_enabled;} - - //! Returns exit key, default 'Q' - char exitKey() const {return exit_key;} - - - //! Returns if keyboard listening is active (not running!) - bool isActive() {return is_active;} - - EVENT_HANDLER( void, enableExitCapture) {enableExitCapture('Q');} - EVENT_HANDLER1(void, enableExitCapture, char, key) {exit_enabled = true; exit_key = key;} - EVENT_HANDLER(void, disableExitCapture) {exit_enabled = false;} - EVENT_HANDLER(void, setActive) {setActive(true);} - EVENT_HANDLER1(void, setActive, bool, yes); - - EVENT2(keyPressed, char, key, void * , data) - -//! \handlers -//! \{ - - //! \fn void enableExitCapture(char key = 'Q') - //! \brief Enable exit key "key" awaiting - - //! \fn void disableExitCapture() - //! \brief Disable exit key awaiting - - //! \fn void setActive(bool yes = true) - //! \brief Set keyboard listening is active or not - -//! \} -//! \events -//! \{ - - //! \fn void keyPressed(char key, void * data) - //! \brief Raise on key "key" pressed, "data" is custom data - -//! \} - - static bool exiting; - -private: - void begin(); - void run(); - void end(); - - KBFunc ret_func; - char exit_key; - bool exit_enabled, is_active; - void * data_; -#ifdef WINDOWS - DWORD ret, rc; - void * hIn; - DWORD smode, tmode; -#else - int rc; - int ret; - struct termios sterm, tterm; -#endif - -}; - -#endif // PIKBDLISTENER_H diff --git a/pimap.h b/pimap.h deleted file mode 100644 index 1debe2b5..00000000 --- a/pimap.h +++ /dev/null @@ -1,452 +0,0 @@ -/*! \file pimap.h - * \brief Associative array with custom types of key and value - * - * This file declares PIMap -*/ -/* - PIP - Platform Independent Primitives - Dynamic array of any type - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIMAP_H -#define PIMAP_H - -#include "pivector.h" -#include "pideque.h" - - -#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN) - -template -void piQuickSort(T * a, ssize_t N) { - if (N < 1) return; - ssize_t i = 0, j = N; - T & p(a[N >> 1]); - do { - while (a[i] < p) i++; - while (a[j] > p) j--; - if (i <= j) { - if (i != j) { - //piCout << "swap" << i << j << a[i] << a[j]; - piSwapBinary(a[i], a[j]); - } - i++; j--; - } - } while (i <= j); - if (j > 0) piQuickSort(a, j); - if (N > i) piQuickSort(a + i, N - i); -} - -template -class PIMap { -public: - PIMap() {;} - PIMap(const PIMap & other) {*this = other;} - ~PIMap() {;} - - PIMap & operator =(const PIMap & other) { - if (this == &other) return *this; - clear(); - pim_content = other.pim_content; - pim_index = other.pim_index; - return *this; - } - - typedef T mapped_type; - typedef Key key_type; - typedef PIPair value_type; - - class iterator { - friend class PIMap; - private: - iterator(const PIMap * v, ssize_t p): parent(v), pos(p) {} - const PIMap * parent; - ssize_t pos; - public: - iterator(): parent(0) {} - const Key & key() const {return const_cast * >(parent)->_key(pos);} - T & value() const {return const_cast * >(parent)->_value(pos);} - void operator ++() {++pos;} - void operator ++(int) {++pos;} - void operator --() {--pos;} - void operator --(int) {--pos;} - bool operator ==(const iterator & it) const {return (pos == it.pos);} - bool operator !=(const iterator & it) const {return (pos != it.pos);} - }; - - class reverse_iterator { - friend class PIMap; - private: - reverse_iterator(const PIMap * v, ssize_t p): parent(v), pos(p) {} - const PIMap * parent; - ssize_t pos; - public: - reverse_iterator(): parent(0) {} - const Key & key() const {return const_cast * >(parent)->_key(pos);} - T & value() const {return const_cast * >(parent)->_value(pos);} - void operator ++() {--pos;} - void operator ++(int) {--pos;} - void operator --() {++pos;} - void operator --(int) {++pos;} - bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);} - bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);} - }; - - class const_iterator { - friend class PIMap; - private: - const_iterator(const PIMap * v, ssize_t p): parent(v), pos(p) {} - const PIMap * parent; - ssize_t pos; - public: - const_iterator(): parent(0) {} - const PIMap::value_type operator *() const {return parent->_pair(pos);} - const PIMap::value_type* operator ->() const {cval = parent->_pair(pos); return &cval;} - void operator ++() {++pos;} - void operator ++(int) {++pos;} - void operator --() {--pos;} - void operator --(int) {--pos;} - bool operator ==(const const_iterator & it) const {return (pos == it.pos);} - bool operator !=(const const_iterator & it) const {return (pos != it.pos);} - mutable value_type cval; - }; - - class const_reverse_iterator { - friend class PIMap; - private: - const_reverse_iterator(const PIMap * v, ssize_t p): parent(v), pos(p) {} - const PIMap * parent; - ssize_t pos; - public: - const_reverse_iterator(): parent(0) {} - const PIMap::value_type operator *() const {return parent->_pair(pos);} - const PIMap::value_type* operator ->() const {cval = parent->_pair(pos); return &cval;} - void operator ++() {--pos;} - void operator ++(int) {--pos;} - void operator --() {++pos;} - void operator --(int) {++pos;} - bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);} - bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} - mutable value_type cval; - }; - - iterator begin() {return iterator(this, 0);} - iterator end() {return iterator(this, size());} - const_iterator begin() const {return const_iterator(this, 0);} - const_iterator end() const {return const_iterator(this, size());} - reverse_iterator rbegin() {return reverse_iterator(this, size() - 1);} - reverse_iterator rend() {return reverse_iterator(this, -1);} - const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size() - 1);} - const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} - - size_t size() const {return pim_content.size();} - int size_s() const {return pim_content.size_s();} - size_t length() const {return pim_content.size();} - bool isEmpty() const {return (pim_content.size() == 0);} - - T & operator [](const Key & key) { - bool f(false); - ssize_t i = _find(key, f); - if (f) return pim_content[pim_index[i].index]; - pim_content.push_back(T()); - pim_index.insert(i, MapIndex(key, pim_content.size() - 1)); - return pim_content.back(); - } - const T operator [](const Key & key) const {bool f(false); ssize_t i = _find(key, f); if (f) return pim_content[pim_index[i].index]; return T();} - T & at(const Key & key) {return (*this)[key];} - const T at(const Key & key) const {return (*this)[key];} - - PIMap & operator <<(const PIMap & other) { - if (other.isEmpty()) return *this; - if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;} - if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;} - pim_content << other.pim_content; - size_t si = pim_index.size(); - for (int i = 0; i < other.pim_content.size_s(); ++i) - pim_index << MapIndex(other.pim_index[i].key, other.pim_index[i].index + si); - _sort(); - return *this; - } - - bool operator ==(const PIMap & t) const {return (pim_content == t.pim_content && pim_index == t.pim_index);} - bool operator !=(const PIMap & t) const {return (pim_content != t.pim_content || pim_index != t.pim_index);} - bool contains(const Key & key) const {bool f(false); _find(key, f); return f;} - //int etries(const T & v) const {int ec = 0; for (size_t i = 0; i < pim_size; ++i) if (v == pim_data[i]) ++ec; return ec;} - - PIMap & reserve(size_t new_size) {pim_content.reserve(new_size); pim_index.reserve(new_size); return *this;} - - //PIMap & removeAll(const T & v) {for (llong i = 0; i < pim_size; ++i) if (pim_data[i] == v) {remove(i); --i;} return *this;} - PIMap & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;} - PIMap & remove(const Key & key) {return removeOne(key);} - PIMap & erase(const Key & key) {return removeOne(key);} - PIMap & clear() {pim_content.clear(); pim_index.clear(); return *this;} - - void swap(PIMap & other) { - piSwapBinary >(pim_content, other.pim_content); - piSwapBinary >(pim_index, other.pim_index); - } - - PIMap & insert(const Key & key, const T & value) { - //MapIndex * i = _find(key); - bool f(false); - ssize_t i = _find(key, f); - //piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value; - if (f) { - pim_content[pim_index[i].index] = value; - } else { - pim_content.push_back(value); - pim_index.insert(i, MapIndex(key, pim_content.size() - 1)); - //_sort(); - } - return *this; - } - //const T value(const Key & key, const T & default_ = T()) const {MapIndex * i = _find(key); if (i == 0) return default_; return pim_content[i->index];} - const T value(const Key & key, const T & default_ = T()) const {bool f(false); ssize_t i = _find(key, f); if (!f) return default_; return pim_content[pim_index[i].index];} - Key key(const T & value_, const Key & default_ = Key()) const {for (int i = 0; i < pim_index.size_s(); ++i) if (pim_content[pim_index[i].index] == value_) return pim_index[i].key; return default_;} - PIVector keys() const { - PIVector ret; - for (int i = 0; i < pim_index.size_s(); ++i) - ret << pim_index[i].key; - return ret; - } - - void dump() { - piCout << "PIMap" << size() << "entries" << NewLine << "content:"; - for (size_t i = 0; i < pim_content.size(); ++i) - piCout << Tab << i << ":" << pim_content[i]; - piCout << "index:"; - for (size_t i = 0; i < pim_index.size(); ++i) - piCout << Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index; - } - -private: - struct MapIndex { - MapIndex(Key k = Key(), size_t i = 0): key(k), index(i) {;} - Key key; - size_t index; - bool operator ==(const MapIndex & s) const {return key == s.key;} - bool operator !=(const MapIndex & s) const {return key != s.key;} - bool operator <(const MapIndex & s) const {return key < s.key;} - bool operator >(const MapIndex & s) const {return key > s.key;} - }; - - ssize_t binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const { - ssize_t mid; - while (first <= last) { - mid = (first + last) / 2; - if (key > pim_index[mid].key) first = mid + 1; - else if (key < pim_index[mid].key) last = mid - 1; - else {found = true; return mid;} - } - found = false; - return first; - } - void _sort() {piQuickSort(pim_index.data(), pim_index.size_s() - 1);} - ssize_t _find(const Key & k, bool & found) const { - /*for (size_t i = 0; i < pim_index.size(); ++i) - if (pim_index[i].key == k) { - return (MapIndex * )&(pim_index[i]); - } - return 0;*/ - //piCout << "find for" << k << pim_index.size_s(); - if (pim_index.isEmpty()) { - found = false; - return 0; - } - //piCout << k << ret << found; - return binarySearch(0, pim_index.size_s() - 1, k, found); - } - void _remove(ssize_t i) { - //if (i >= pim_index.size()) return; - size_t ci = pim_index[i].index, bi = pim_index.size() - 1; - pim_index.remove(i); - for (size_t i = 0; i < pim_index.size(); ++i) - if (pim_index[i].index == bi) { - pim_index[i].index = ci; - break; - } - piSwapBinary(pim_content[ci], pim_content.back()); - pim_content.resize(pim_index.size()); - } - const value_type _pair(ssize_t index) const { - if (index < 0 || index >= pim_index.size_s()) - return value_type(); - //piCout << "_pair" << index << pim_index[index].index; - return value_type(pim_index[index].key, pim_content[pim_index[index].index]); - } - Key & _key(ssize_t index) {return pim_index[index].key;} - T & _value(ssize_t index) {return pim_content[pim_index[index].index];} - - PIVector pim_content; - PIDeque pim_index; -}; -//template bool operator <(const typename PIMap::MapIndex & f, const typename PIMap::MapIndex & s) {return f.key < s.key;} -//template bool operator >(const typename PIMap::MapIndex & f, const typename PIMap::MapIndex & s) {return f.key > s.key;} - - -/*#define __PIMAP_SIMPLE_FUNCTIONS__(T) - template<> inline PIMap::~PIMap() {dealloc(); _reset();} \ - template<> inline PIMap & PIMap::push_back(const T & v) {alloc(pim_size + 1); pim_data[pim_size - 1] = v; return *this;} \ - template<> inline PIMap & PIMap::fill(const T & f) { \ - for (size_t i = 0; i < pim_size; ++i) \ - pim_data[i] = f; \ - return *this; \ - } \ - template<> inline PIMap & PIMap::resize(size_t new_size, const T & f) { \ - if (new_size < pim_size) \ - pim_size = new_size; \ - if (new_size > pim_size) { \ - size_t os = pim_size; \ - alloc(new_size); \ - for (size_t i = os; i < new_size; ++i) pim_data[i] = f; \ - } \ - return *this; \ - } \ - template<> inline PIMap & PIMap::insert(size_t index, const T & v) { \ - alloc(pim_size + 1); \ - if (index < pim_size - 1) { \ - size_t os = pim_size - index - 1; \ - memmove(&(pim_data[index + 1]), &(pim_data[index]), os * sizeof(T)); \ - } \ - pim_data[index] = v; \ - return *this; \ - } \ - template<> inline PIMap & PIMap::remove(size_t index, size_t count) { \ - if (index + count >= pim_size) { \ - resize(index); \ - return *this; \ - } \ - size_t os = pim_size - index - count; \ - memmove(&(pim_data[index]), &(pim_data[index + count]), os * sizeof(T)); \ - pim_size -= count; \ - return *this; \ - } - -__PIMAP_SIMPLE_FUNCTIONS__(char) -__PIMAP_SIMPLE_FUNCTIONS__(uchar) -__PIMAP_SIMPLE_FUNCTIONS__(short) -__PIMAP_SIMPLE_FUNCTIONS__(ushort) -__PIMAP_SIMPLE_FUNCTIONS__(int) -__PIMAP_SIMPLE_FUNCTIONS__(uint) -__PIMAP_SIMPLE_FUNCTIONS__(long) -__PIMAP_SIMPLE_FUNCTIONS__(ulong) -__PIMAP_SIMPLE_FUNCTIONS__(llong) -__PIMAP_SIMPLE_FUNCTIONS__(ullong) -__PIMAP_SIMPLE_FUNCTIONS__(float) -__PIMAP_SIMPLE_FUNCTIONS__(double) -__PIMAP_SIMPLE_FUNCTIONS__(ldouble)*/ - -#else - - -template -class PIP_EXPORT PIMap: public map { - typedef PIMap _CMap; - typedef map _stlc; - typedef std::pair _stlpair; -public: - PIMap() {;} - PIMap(const Key & key_, const Type & value_) {insert(key_, value_);} - bool isEmpty() const {return _stlc::empty();} - bool contains(const Key & key_) const {return _stlc::count(key_) > 0;} - int size_s() const {return static_cast(_stlc::size());} - _CMap & insert(const Key & key_, const Type & value_) {_stlc::insert(_stlpair(key_, value_)); return *this;} - _CMap & insert(PIPair entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;} - Key key(Type value_, const Key & default_ = Key()) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return default_;} - PIVector keys() const { - PIVector ret; - for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) - ret << i->first; - return ret; - } - Type & at(const Key & key_) {return _stlc::find(key_)->second;} - Type value(const Key & key_) const {typename _stlc::const_iterator it = _stlc::find(key_); if (it != _stlc::end()) return it->second; return Type();} -}; - - -template -class PIP_EXPORT PIMultiMap: public multimap { - typedef PIMultiMap _CMultiMap; - typedef multimap _stlc; - typedef std::pair _stlpair; -public: - PIMultiMap() {;} - PIMultiMap(const Key & key_, const Type & value_) {insert(key_, value_);} - _CMultiMap & insert(const Key & key_, const Type & value_) {_stlc::insert(_stlpair(key_, value_)); return *this;} - _CMultiMap & insert(PIPair entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;} - bool isEmpty() const {return _stlc::empty();} - bool contains(const Key & key_) const {return _stlc::count(key_) > 0;} - Key key(Type value_, const Key & default_ = Key()) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return default_;} - PIVector keys(Type value_) const { - PIVector ret; - for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) - if (i->second == value_) - ret << i->first; - return ret; - } - Type & value(const Key & key_) {typename _stlc::iterator i = _stlc::find(key_); if (i == _stlc::end()) return Type(); return i->second;} - Type value(const Key & key_) const {typename _stlc::const_iterator i = _stlc::find(key_); if (i == _stlc::end()) return Type(); return i->second;} - PIVector values(const Key & key_) const { - std::pair range = _stlc::equal_range(key_); - PIVector ret; - for (typename _stlc::const_iterator i = range.first; i != range.second; ++i) - ret << i->second; - return ret; - } - Type & operator [](const Key & key_) {if (!contains(key_)) return _stlc::insert(_stlpair(key_, Type()))->second; return _stlc::find(key_)->second;} - Type operator [](const Key & key_) const {return _stlc::find(key_)->second;} -}; - -#define __PIMAP_SIMPLE_FUNCTIONS__(T) - - -#endif - - -template -inline std::ostream & operator <<(std::ostream & s, const PIMap & v) { - s << "{"; - bool first = true; - for (typename PIMap::const_iterator i = v.begin(); i != v.end(); i++) { - if (!first) - s << ", "; - first = false; - s << i->first << ": " << i->second; - } - s << "}"; - return s; -} - -template -inline PICout operator <<(PICout s, const PIMap & v) { - s.space(); - s.setControl(0, true); - s << "{"; - bool first = true; - for (typename PIMap::const_iterator i = v.begin(); i != v.end(); i++) { - if (!first) - s << ", "; - first = false; - s << i->first << ": " << i->second; - } - s << "}"; - s.restoreControl(); - return s; -} - - -#endif // PIMAP_H diff --git a/pimath.cpp b/pimath.cpp deleted file mode 100644 index 6284aa40..00000000 --- a/pimath.cpp +++ /dev/null @@ -1,1627 +0,0 @@ -/* - PIP - Platform Independent Primitives - Math - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pimath.h" - - -double piJ0(const double & v) { -#ifndef PIP_MATH_J0 - double x = v; - double xsq; - double nn; - double pzero; - double qzero; - double p1; - double q1; - double result; - if (x < 0) x = -x; - if (x > 8.) { - double xsq_; - double p2; - double q2; - double p3; - double q3; - xsq_ = 64. / (x * x); - p2 = 0.0; - p2 = 2485.271928957404011288128951 + xsq_ * p2; - p2 = 153982.6532623911470917825993 + xsq_ * p2; - p2 = 2016135.283049983642487182349 + xsq_ * p2; - p2 = 8413041.456550439208464315611 + xsq_ * p2; - p2 = 12332384.76817638145232406055 + xsq_ * p2; - p2 = 5393485.083869438325262122897 + xsq_ * p2; - q2 = 1.0; - q2 = 2615.700736920839685159081813 + xsq_ * q2; - q2 = 156001.7276940030940592769933 + xsq_ * q2; - q2 = 2025066.801570134013891035236 + xsq_ * q2; - q2 = 8426449.050629797331554404810 + xsq_ * q2; - q2 = 12338310.22786324960844856182 + xsq_ * q2; - q2 = 5393485.083869438325560444960 + xsq_ * q2; - p3 = -0.0; - p3 = -4.887199395841261531199129300 +xsq_ * p3; - p3 = -226.2630641933704113967255053 +xsq_ * p3; - p3 = -2365.956170779108192723612816 +xsq_ * p3; - p3 = -8239.066313485606568803548860 +xsq_ * p3; - p3 = -10381.41698748464093880530341 +xsq_ * p3; - p3 = -3984.617357595222463506790588 +xsq_ * p3; - q3 = 1.0; - q3 = 408.7714673983499223402830260 + xsq_ * q3; - q3 = 15704.89191515395519392882766 + xsq_ * q3; - q3 = 156021.3206679291652539287109 + xsq_ * q3; - q3 = 533291.3634216897168722255057 + xsq_ * q3; - q3 = 666745.4239319826986004038103 + xsq_ * q3; - q3 = 255015.5108860942382983170882 + xsq_ * q3; - pzero = p2 / q2; - qzero = 8. * p3 / q3 / x; - nn = x- M_PI / 4.; - result = sqrt(2. / M_PI / x) * (pzero * cos(nn) - qzero * sin(nn)); - return result; - } - xsq = x * x; - p1 = 26857.86856980014981415848441; - p1 = -40504123.71833132706360663322 + xsq * p1; - p1 = 25071582855.36881945555156435 + xsq * p1; - p1 = -8085222034853.793871199468171 + xsq * p1; - p1 = 1434354939140344.111664316553 + xsq * p1; - p1 = -136762035308817138.6865416609 + xsq * p1; - p1 = 6382059341072356562.289432465 + xsq * p1; - p1 = -117915762910761053603.8440800 + xsq * p1; - p1 = 493378725179413356181.6813446 + xsq * p1; - q1 = 1.; - q1 = 1363.063652328970604442810507 + xsq * q1; - q1 = 1114636.098462985378182402543 + xsq * q1; - q1 = 669998767.2982239671814028660 + xsq * q1; - q1 = 312304311494.1213172572469442 + xsq * q1; - q1 = 112775673967979.8507056031594 + xsq * q1; - q1 = 30246356167094626.98627330784 + xsq * q1; - q1 = 5428918384092285160.200195092 + xsq * q1; - q1 = 493378725179413356211.3278438 + xsq * q1; - return p1 / q1; -#else - return j0(v); -#endif -} - - -double piJ1(const double & v) { -#ifndef PIP_MATH_J1 - double x = v; - double s; - double xsq; - double nn; - double pzero; - double qzero; - double p1; - double q1; - double result; - s = sign(x); - if (x < 0) - x = -x; - if (x > 8.) { - double xsq_; - double p2; - double q2; - double p3; - double q3; - xsq_ = 64.0 / (x * x); - p2 = -1611.616644324610116477412898; - p2 = -109824.0554345934672737413139 + xsq_ * p2; - p2 = -1523529.351181137383255105722 + xsq_ * p2; - p2 = -6603373.248364939109255245434 + xsq_ * p2; - p2 = -9942246.505077641195658377899 + xsq_ * p2; - p2 = -4435757.816794127857114720794 + xsq_ * p2; - q2 = 1.0; - q2 = -1455.009440190496182453565068 + xsq_ * q2; - q2 = -107263.8599110382011903063867 + xsq_ * q2; - q2 = -1511809.506634160881644546358 + xsq_ * q2; - q2 = -6585339.479723087072826915069 + xsq_ * q2; - q2 = -9934124.389934585658967556309 + xsq_ * q2; - q2 = -4435757.816794127856828016962 + xsq_ * q2; - p3 = 35.26513384663603218592175580; - p3 = 1706.375429020768002061283546 + xsq_ * p3; - p3 = 18494.26287322386679652009819 + xsq_ * p3; - p3 = 66178.83658127083517939992166 + xsq_ * p3; - p3 = 85145.16067533570196555001171 + xsq_ * p3; - p3 = 33220.91340985722351859704442 + xsq_ * p3; - q3 = 1.0; - q3 = 863.8367769604990967475517183 + xsq_ * q3; - q3 = 37890.22974577220264142952256 + xsq_ * q3; - q3 = 400294.4358226697511708610813 + xsq_ * q3; - q3 = 1419460.669603720892855755253 + xsq_ * q3; - q3 = 1819458.042243997298924553839 + xsq_ * q3; - q3 = 708712.8194102874357377502472 + xsq_ * q3; - pzero = p2 / q2; - qzero = 8 * p3 / q3 / x; - nn = x - 3 * M_PI / 4; - result = sqrt(2 / M_PI / x) * (pzero * cos(nn) - qzero * sin(nn)); - if (s < 0) - result = -result; - return result; - } - xsq = sqr(x); - p1 = 2701.122710892323414856790990; - p1 = -4695753.530642995859767162166 + xsq * p1; - p1 = 3413234182.301700539091292655 + xsq * p1; - p1 = -1322983480332.126453125473247 + xsq * p1; - p1 = 290879526383477.5409737601689 + xsq * p1; - p1 = -35888175699101060.50743641413 + xsq * p1; - p1 = 2316433580634002297.931815435 + xsq * p1; - p1 = -66721065689249162980.20941484 + xsq * p1; - p1 = 581199354001606143928.050809 + xsq * p1; - q1 = 1.0; - q1 = 1606.931573481487801970916749 + xsq * q1; - q1 = 1501793.594998585505921097578 + xsq * q1; - q1 = 1013863514.358673989967045588 + xsq * q1; - q1 = 524371026216.7649715406728642 + xsq * q1; - q1 = 208166122130760.7351240184229 + xsq * q1; - q1 = 60920613989175217.46105196863 + xsq * q1; - q1 = 11857707121903209998.37113348 + xsq * q1; - q1 = 1162398708003212287858.529400 + xsq * q1; - result = s * x * p1 / q1; - return result; -#else - return j1(v); -#endif -} - - -double piJn(int n, const double & v) { -#ifndef PIP_MATH_JN - double x = v; - double pkm2; - double pkm1; - double pk; - double xk; - double r; - double ans; - int k; - int sg; - double result; - if (n < 0) { - n = -n; - if (n % 2 == 0) - sg = 1; - else - sg = -1; - } else - sg = 1; - if (x < 0) { - if (n % 2 != 0) - sg = -sg; - x = -x; - } - if (n == 0) { - result = sg * piJ0(x); - return result; - } - if (n == 1) { - result = sg * piJ1(x); - return result; - } - if (n == 2) { - if (x == 0) - result = 0; - else - result = sg * (2.0 * piJ1(x) / x - piJ0(x)); - return result; - } - if (x < 1E-16) { - result = 0; - return result; - } - k = 53; - pk = 2 * (n + k); - ans = pk; - xk = x * x; - do { - pk = pk - 2.0; - ans = pk - xk / ans; - k = k - 1; - } while (k != 0); - ans = x / ans; - pk = 1.0; - pkm1 = 1.0 / ans; - k = n - 1; - r = 2 * k; - do { - pkm2 = (pkm1 * r - pk * x) / x; - pk = pkm1; - pkm1 = pkm2; - r = r - 2.0; - k = k - 1; - } while (k != 0); - if (fabs(pk) > fabs(pkm1)) - ans = piJ1(x) / pk; - else - ans = piJ0(x) / pkm1; - result = sg * ans; - return result; -#else - return jn(n, v); -#endif -} - - -double piY0(const double & v) { -#ifndef PIP_MATH_Y0 - double x = v; - double nn; - double xsq; - double pzero; - double qzero; - double p4; - double q4; - double result; - if (x > 8.) { - double xsq_; - double p2; - double q2; - double p3; - double q3; - xsq_ = 64.0 / (x * x); - p2 = 0.0; - p2 = 2485.271928957404011288128951 + xsq_ * p2; - p2 = 153982.6532623911470917825993 + xsq_ * p2; - p2 = 2016135.283049983642487182349 + xsq_ * p2; - p2 = 8413041.456550439208464315611 + xsq_ * p2; - p2 = 12332384.76817638145232406055 + xsq_ * p2; - p2 = 5393485.083869438325262122897 + xsq_ * p2; - q2 = 1.0; - q2 = 2615.700736920839685159081813 + xsq_ * q2; - q2 = 156001.7276940030940592769933 + xsq_ * q2; - q2 = 2025066.801570134013891035236 + xsq_ * q2; - q2 = 8426449.050629797331554404810 + xsq_ * q2; - q2 = 12338310.22786324960844856182 + xsq_ * q2; - q2 = 5393485.083869438325560444960 + xsq_ * q2; - p3 = -0.0; - p3 = -4.887199395841261531199129300 + xsq_ * p3; - p3 = -226.2630641933704113967255053 + xsq_ * p3; - p3 = -2365.956170779108192723612816 + xsq_ * p3; - p3 = -8239.066313485606568803548860 + xsq_ * p3; - p3 = -10381.41698748464093880530341 + xsq_ * p3; - p3 = -3984.617357595222463506790588 + xsq_ * p3; - q3 = 1.0; - q3 = 408.7714673983499223402830260 + xsq_ * q3; - q3 = 15704.89191515395519392882766 + xsq_ * q3; - q3 = 156021.3206679291652539287109 + xsq_ * q3; - q3 = 533291.3634216897168722255057 + xsq_ * q3; - q3 = 666745.4239319826986004038103 + xsq_ * q3; - q3 = 255015.5108860942382983170882 + xsq_ * q3; - pzero = p2 / q2; - qzero = 8 * p3 / q3 / x; - nn = x - M_PI / 4; - result = sqrt(2 / M_PI / x) * (pzero * sin(nn) + qzero * cos(nn)); - return result; - } - xsq = sqr(x); - p4 = -41370.35497933148554125235152; - p4 = 59152134.65686889654273830069 + xsq * p4; - p4 = -34363712229.79040378171030138 + xsq * p4; - p4 = 10255208596863.94284509167421 + xsq * p4; - p4 = -1648605817185729.473122082537 + xsq * p4; - p4 = 137562431639934407.8571335453 + xsq * p4; - p4 = -5247065581112764941.297350814 + xsq * p4; - p4 = 65874732757195549259.99402049 + xsq * p4; - p4 = -27502866786291095837.01933175 + xsq * p4; - q4 = 1.0; - q4 = 1282.452772478993804176329391 + xsq * q4; - q4 = 1001702.641288906265666651753 + xsq * q4; - q4 = 579512264.0700729537480087915 + xsq * q4; - q4 = 261306575504.1081249568482092 + xsq * q4; - q4 = 91620380340751.85262489147968 + xsq * q4; - q4 = 23928830434997818.57439356652 + xsq * q4; - q4 = 4192417043410839973.904769661 + xsq * q4; - q4 = 372645883898616588198.9980 + xsq * q4; - result = p4 / q4 + 2 / M_PI * piJ0(x) * log(x); - return result; -#else - return y0(v); -#endif -} - - -double piY1(const double & v) { -#ifndef PIP_MATH_Y1 - double x = v; - double nn; - double xsq; - double pzero; - double qzero; - double p4; - double q4; - double result; - if (x > 8.) { - double xsq_; - double p2; - double q2; - double p3; - double q3; - xsq_ = 64.0 / (x * x); - p2 = -1611.616644324610116477412898; - p2 = -109824.0554345934672737413139 + xsq_ * p2; - p2 = -1523529.351181137383255105722 + xsq_ * p2; - p2 = -6603373.248364939109255245434 + xsq_ * p2; - p2 = -9942246.505077641195658377899 + xsq_ * p2; - p2 = -4435757.816794127857114720794 + xsq_ * p2; - q2 = 1.0; - q2 = -1455.009440190496182453565068 + xsq_ * q2; - q2 = -107263.8599110382011903063867 + xsq_ * q2; - q2 = -1511809.506634160881644546358 + xsq_ * q2; - q2 = -6585339.479723087072826915069 + xsq_ * q2; - q2 = -9934124.389934585658967556309 + xsq_ * q2; - q2 = -4435757.816794127856828016962 + xsq_ * q2; - p3 = 35.26513384663603218592175580; - p3 = 1706.375429020768002061283546 + xsq_ * p3; - p3 = 18494.26287322386679652009819 + xsq_ * p3; - p3 = 66178.83658127083517939992166 + xsq_ * p3; - p3 = 85145.16067533570196555001171 + xsq_ * p3; - p3 = 33220.91340985722351859704442 + xsq_ * p3; - q3 = 1.0; - q3 = 863.8367769604990967475517183 + xsq_ * q3; - q3 = 37890.22974577220264142952256 + xsq_ * q3; - q3 = 400294.4358226697511708610813 + xsq_ * q3; - q3 = 1419460.669603720892855755253 + xsq_ * q3; - q3 = 1819458.042243997298924553839 + xsq_ * q3; - q3 = 708712.8194102874357377502472 + xsq_ * q3; - pzero = p2 / q2; - qzero = 8 * p3 / q3 / x; - nn = x - 3 * M_PI / 4; - result = sqrt(2 / M_PI / x) * (pzero * sin(nn) + qzero * cos(nn)); - return result; - } - xsq = sqr(x); - p4 = -2108847.540133123652824139923; - p4 = 3639488548.124002058278999428 + xsq * p4; - p4 = -2580681702194.450950541426399 + xsq * p4; - p4 = 956993023992168.3481121552788 + xsq * p4; - p4 = -196588746272214065.8820322248 + xsq * p4; - p4 = 21931073399177975921.11427556 + xsq * p4; - p4 = -1212297555414509577913.561535 + xsq * p4; - p4 = 26554738314348543268942.48968 + xsq * p4; - p4 = -99637534243069222259967.44354 + xsq * p4; - q4 = 1.0; - q4 = 1612.361029677000859332072312 + xsq * q4; - q4 = 1563282.754899580604737366452 + xsq * q4; - q4 = 1128686837.169442121732366891 + xsq * q4; - q4 = 646534088126.5275571961681500 + xsq * q4; - q4 = 297663212564727.6729292742282 + xsq * q4; - q4 = 108225825940881955.2553850180 + xsq * q4; - q4 = 29549879358971486742.90758119 + xsq * q4; - q4 = 5435310377188854170800.653097 + xsq * q4; - q4 = 508206736694124324531442.4152 + xsq * q4; - result = x * p4 / q4 + 2 / M_PI * (piJ1(x) * log(x) - 1 / x); - return result; -#else - return y1(v); -#endif -} - - -double piYn(int n, const double & v) { -#ifndef PIP_MATH_YN - int i; - double x = v; - double a; - double b; - double tmp; - double s; - double result; - s = 1; - if (n < 0) { - n = -n; - if (n % 2 != 0) - s = -1; - } - if (n == 0) { - result = piY0(x); - return result; - } - if (n == 1) { - result = s * piY1(x); - return result; - } - a = piY0(x); - b = piY1(x); - for (i = 1; i <= n - 1; i++) { - tmp = b; - b = 2 * i / x * b - a; - a = tmp; - } - result = s * b; - return result; -#else - return yn(n, v); -#endif -} - - -double randomn(double dv, double sv) { - static bool agen = false; - double s = 2., v0 = 0., v1 = 0.; - if (agen) { - agen = false; - v1 = v1 * sqrt(-2 * log(s) / s); - return v1 * sv + dv; - } - while (s > 1. || s == 0.) { - v0 = randomd(); - v1 = randomd(); - s = v0*v0 + v1*v1; - } - v0 = v0 * sqrt(-2 * log(s) / s); - return v0 * sv + dv; -} - - - -const char Solver::methods_desc[] = "b{Methods:}\ -\n -1 - Global settings\ -\n 01 - Eyler 1\ -\n 02 - Eyler 2\ -\n 14 - Runge-Kutta 4\ -\n 23 - Adams-Bashfort-Moulton 3\ -\n 24 - Adams-Bashfort-Moulton 4\ -\n 32 - Polynomial Approximation 2\ -\n 33 - Polynomial Approximation 3\ -\n 34 - Polynomial Approximation 4\ -\n 35 - Polynomial Approximation 5"; - -Solver::Method Solver::method_global = Solver::Eyler_2; - - -void Solver::solve(double u, double h) { - switch (method) { - case Global: - switch (method_global) { - 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; - case AdamsBashfortMoulton_4: default: solveABM4(u, h); break; - case PolynomialApproximation_2: solvePA2(u, h); break; - case PolynomialApproximation_3: solvePA3(u, h); break; - case PolynomialApproximation_4: solvePA4(u, h); break; - case PolynomialApproximation_5: solvePA5(u, h); break; - } - 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; - case AdamsBashfortMoulton_4: default: solveABM4(u, h); break; - case PolynomialApproximation_2: solvePA2(u, h); break; - case PolynomialApproximation_3: solvePA3(u, h); break; - case PolynomialApproximation_4: solvePA4(u, h); break; - case PolynomialApproximation_5: solvePA5(u, h); break; - } - step++; -} - - -void Solver::fromTF(const TransferFunction & TF) { - if (TF.vector_An.size() >= TF.vector_Bm.size()) - size = TF.vector_An.size()-1; - else { - piCout << "Solver error: {A} should be greater than {B}"; - return; - } - if (size == 0) return; - - step = 0; - times.fill(0.); - A.resize(size, size); - d.resize(size + 1); d.fill(0.); - a1.resize(size + 1); a1.fill(0.); - b1.resize(size + 1); b1.fill(0.); - X.resize(size); X.fill(0.); - F.resize(5); - for (uint i = 0; i < 5; ++i) - F[i].resize(size), F[i].fill(0.); - k1.resize(size); k1.fill(0.); - k2.resize(size); k2.fill(0.); - k3.resize(size); k3.fill(0.); - k4.resize(size); k4.fill(0.); - xx.resize(size); xx.fill(0.); - XX.resize(size); XX.fill(0.); - for (uint i = 0; i < size + 1; ++i) - a1[size - i] = TF.vector_An[i]; - for (uint i = 0; i < TF.vector_Bm.size(); ++i) - b1[size - i] = TF.vector_Bm[i]; - double a0 = a1[0]; - a1 /= a0; - b1 /= a0; - - d[0] = b1[0]; // Рассчитываем вектор d - for (uint i = 1; i < size + 1; ++i) { - sum = 0.; - for (uint m = 0; m < i; ++m) - sum += a1[i - m] * d[m]; - d[i] = b1[i] - sum; - } - - for (uint i = 0; i < size - 1; ++i) // Заполняем матрицу А - for (uint j = 0; j < size; ++j) - A[j][i] = (j == i + 1); - for (uint i = 0; i < size; ++i) - A[i][size - 1] = -a1[size - i]; - for (uint i = 0; i < size; ++i) - d[i] = d[i + 1]; -} - - -void Solver::solveEyler1(double u, double h) { - /*for (uint i = 0; i < size; ++i) { - * sum = 0.; - * for (uint j = 0; j < size; ++j) - * sum += A[j][i] * X[j]; - * xx[i] = sum + d[i] * u; - }*/ - F[0] = A * X + d * u; - X += F[0] * h; - moveF(); -} - - -void Solver::solveEyler2(double u, double h) { - F[0] = A * X + d * u; - X += (F[0] + F[1]) * h / 2.; - moveF(); -} - - -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 + 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; -} - - -void Solver::solveABM2(double u, double h) { - F[0] = A * X + d * u; - XX = X + (F[0] * 3. - F[1]) * (h / 2.); - F[1] = A * XX + d * u; - X += (F[1] + F[0]) * (h / 2.); - moveF(); -} - - -void Solver::solveABM3(double u, double h) { - F[0] = A * X + d * u; - XX = X + (F[0] * 23. - F[1] * 16. + F[2] * 5.) * (h / 12.); - F[2] = A * XX + d * u; - X += (F[2] * 5. + F[0] * 8. - F[1]) * (h / 12.); - moveF(); -} - - -void Solver::solveABM4(double u, double h) { - F[0] = A * X + d * u; - XX = X + (F[0] * 55. - F[1] * 59. + F[2] * 37. - F[3] * 9.) * (h / 24.); - F[3] = A * XX + d * u; - X += (F[3] * 9. + F[0] * 19. - F[1] * 5. + F[2]) * (h / 24.); - moveF(); -} - - -void Solver::solvePA(double u, double h, uint deg) { - F[0] = A * X + d * u; - M.resize(deg, deg); - Y.resize(deg); - pY.resize(deg); - - for (uint k = 0; k < size; ++k) { - for (uint i = 0; i < deg; ++i) { - td = 1.; - ct = times[i]; - for (uint j = 0; j < deg; ++j) { - M[j][i] = td; - td *= ct; - } - } - for (uint i = 0; i < deg; ++i) - Y[i] = F[i][k]; - /// find polynom - //if (step == 1) cout << M << endl << Y << endl; - M.invert(&ok, &Y); - //if (step == 1) cout << Y << endl; - if (!ok) { - solveEyler2(u, h); - break; - } - /// calc last piece - x0 = 0.; - td = 1.; - t = times[0]; - for (uint i = 0; i < deg; ++i) { - x0 += Y[i] * td / (i + 1.); - td *= t; - } - x0 *= t; - - x1 = 0.; - td = 1.; - t = times[1]; - for (uint i = 0; i < deg; ++i) { - x1 += Y[i] * td / (i + 1.); - td *= t; - } - x1 *= t; - lp = x0 - x1; - - if (deg > 2) { - /// calc prev piece - x0 = 0.; - td = 1.; - dh = times[1] - times[2]; - if (dh != 0. && step > 1) { - t = times[2]; - for (uint i = 0; i < deg; ++i) { - x0 += Y[i] * td / (i + 1.); - td *= t; - } - x0 *= t; - ct = x1 - x0; - /// calc correction - ct -= pY[k]; - } - /// calc final - X[k] += lp - ct; - pY[k] = lp; - } else { - X[k] += lp; - pY[k] = lp; - } - } - moveF(); -} - - - -PIFFT::PIFFT() { - prepared = false; -} - - -PIVector * PIFFT::calcFFT(const PIVector & val) { -// for (uint i=0; i *PIFFT::calcFFTinverse(const PIVector &val) -{ - result.clear(); - if (val.size_s() < 4) return &result; - fftc1dinv(val, val.size()); - return &result; -} - - -PIVector *PIFFT::calcHilbert(const PIVector &val) -{ - result.clear(); - if (val.size_s() < 4) return &result; - fftc1r(val, val.size()); - for (uint i=0; i* PIFFT::calcFFT(const PIVector & val) { - result.clear(); - if (val.size_s() < 4) return &result; - fftc1r(val, val.size()); - return &result; -} - - -PIVector PIFFT::getAmplitude() { - PIVector a; - double tmp; - for (uint i=0; i &a, uint n) { - createPlan(n); - uint i; - PIVector buf; - buf.resize(2*n); - for(i=0; iptr.p_complex[i].x; - buf[2*i+1] = a.at(i).imag();//a->ptr.p_complex[i].y; - } - ftbaseexecuteplan(&buf, 0, n, &curplan); - result.resize(n); - for(i=0; i & a, uint n) { - uint i; - if( n%2==0) { - PIVector buf; - uint n2 = n/2; - //buf.resize(n); - buf = a; - createPlan(n2); - //cout << "fftr " << n2 << endl; - ftbaseexecuteplan(&buf, 0, n2, &curplan); - result.resize(n); - uint idx; - complexd hn, hmnc, v; - for(i=0; i<=n2; i++) { - idx = 2*(i%n2); - hn = complexd(buf[idx+0], buf[idx+1]); - idx = 2*((n2-i)%n2); - hmnc = complexd(buf[idx+0], -buf[idx+1]); - v = complexd(sin(M_PI*i/n2), cos(M_PI*i/n2)); - result[i] = ((hn + hmnc) - (v * (hn - hmnc))); - result[i] *= 0.5; - } - for(i=n2+1; i cbuf; - cbuf.resize(n); - for(i=0; i &a, uint n) -{ - PIVector cbuf; - cbuf.resize(n); - uint i; - for(i=0; i(stackmemsize,1));//ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1)); - curplan.tmpbuf.resize(piMax(tmpmemsize,1));//ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1)); - curplan.precomputed.resize(piMax(precomputedsize,1));//ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize, 1)); - stackptr = 0; - ftbase_ftbaseprecomputeplanrec(plan, 0, stackptr); - if (stackptr!=0) { return;}//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!"); -} - - -/************************************************************************* -Recurrent subroutine for the FFTGeneratePlan: - -PARAMETERS: - N plan size - IsReal whether input is real or not. - subroutine MUST NOT ignore this flag because real - inputs comes with non-initialized imaginary parts, - so ignoring this flag will result in corrupted output - HalfOut whether full output or only half of it from 0 to - floor(N/2) is needed. This flag may be ignored if - doing so will simplify calculations - Plan plan array - PlanSize size of used part (in integers) - PrecomputedSize size of precomputed array allocated yet - PlanArraySize plan array size (actual) - TmpMemSize temporary memory required size - BluesteinMemSize temporary memory required size - --- ALGLIB -- - Copyright 01.05.2009 by Bochkanov Sergey -*************************************************************************/ -void PIFFT::ftbase_ftbasegenerateplanrec( - int n, - int tasktype, - ftplan* plan, - int* plansize, - int* precomputedsize, - int* planarraysize, - int* tmpmemsize, - int* stackmemsize, - ae_int_t stackptr, int debugi) -{ - int k, m, n1, n2, esize, entryoffset; - int ftbase_ftbaseplanentrysize = 8; - int ftbase_ftbasecffttask = 0; - int ftbase_fftcooleytukeyplan = 0; - int ftbase_fftbluesteinplan = 1; - int ftbase_fftcodeletplan = 2; - int ftbase_fftrealcooleytukeyplan = 5; - int ftbase_fftemptyplan = 6; - if( *plansize+ftbase_ftbaseplanentrysize>(*planarraysize)) { - curplan.plan.resize(8*(*planarraysize)); - *planarraysize = 8*(*planarraysize); - } - entryoffset = *plansize; - esize = ftbase_ftbaseplanentrysize; - *plansize = *plansize+esize; - if( n==1) { - curplan.plan[entryoffset+0] = esize; - curplan.plan[entryoffset+1] = -1; - curplan.plan[entryoffset+2] = -1; - curplan.plan[entryoffset+3] = ftbase_fftemptyplan; - curplan.plan[entryoffset+4] = -1; - curplan.plan[entryoffset+5] = -1; - curplan.plan[entryoffset+6] = -1; - curplan.plan[entryoffset+7] = -1; - return; - } - ftbasefactorize(n, &n1, &n2); - if( n1!=1) { - *tmpmemsize = piMax(*tmpmemsize, 2*n1*n2); - curplan.plan[entryoffset+0] = esize; - curplan.plan[entryoffset+1] = n1; - curplan.plan[entryoffset+2] = n2; - if( tasktype==ftbase_ftbasecffttask) - curplan.plan[entryoffset+3] = ftbase_fftcooleytukeyplan; - else - curplan.plan[entryoffset+3] = ftbase_fftrealcooleytukeyplan; - curplan.plan[entryoffset+4] = 0; - curplan.plan[entryoffset+5] = *plansize; - debugi++; - ftbase_ftbasegenerateplanrec(n1, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr,debugi); - curplan.plan[entryoffset+6] = *plansize; - ftbase_ftbasegenerateplanrec(n2, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr,debugi); - curplan.plan[entryoffset+7] = -1; - return; - } else { - if (n>=2 && n<=5) { - curplan.plan[entryoffset+0] = esize; - curplan.plan[entryoffset+1] = n1; - curplan.plan[entryoffset+2] = n2; - curplan.plan[entryoffset+3] = ftbase_fftcodeletplan; - curplan.plan[entryoffset+4] = 0; - curplan.plan[entryoffset+5] = -1; - curplan.plan[entryoffset+6] = -1; - curplan.plan[entryoffset+7] = *precomputedsize; - if( n==3) - *precomputedsize = *precomputedsize+2; - if( n==5) - *precomputedsize = *precomputedsize+5; - return; - } else { - k = 2*n2-1; - m = ftbasefindsmooth(k); - *tmpmemsize = piMax(*tmpmemsize, 2*m); - curplan.plan[entryoffset+0] = esize; - curplan.plan[entryoffset+1] = n2; - curplan.plan[entryoffset+2] = -1; - curplan.plan[entryoffset+3] = ftbase_fftbluesteinplan; - curplan.plan[entryoffset+4] = m; - curplan.plan[entryoffset+5] = *plansize; - stackptr = stackptr+2*2*m; - *stackmemsize = piMax(*stackmemsize, stackptr); - ftbase_ftbasegenerateplanrec(m, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr); - stackptr = stackptr-2*2*m; - curplan.plan[entryoffset+6] = -1; - curplan.plan[entryoffset+7] = *precomputedsize; - *precomputedsize = *precomputedsize+2*m+2*n; - return; - } - } -} - - -/************************************************************************* -Recurrent subroutine for precomputing FFT plans - --- ALGLIB -- - Copyright 01.05.2009 by Bochkanov Sergey -*************************************************************************/ -void PIFFT::ftbase_ftbaseprecomputeplanrec(ftplan* plan, - int entryoffset, - ae_int_t stackptr) -{ - int n1, n2, n, m, offs; - double v, bx, by; - int ftbase_fftcooleytukeyplan = 0; - int ftbase_fftbluesteinplan = 1; - int ftbase_fftcodeletplan = 2; - int ftbase_fhtcooleytukeyplan = 3; - int ftbase_fhtcodeletplan = 4; - int ftbase_fftrealcooleytukeyplan = 5; - if( (curplan.plan[entryoffset+3]==ftbase_fftcooleytukeyplan||curplan.plan[entryoffset+3]==ftbase_fftrealcooleytukeyplan)||curplan.plan[entryoffset+3]==ftbase_fhtcooleytukeyplan) { - ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+5], stackptr); - ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+6], stackptr); - return; - } - if( curplan.plan[entryoffset+3]==ftbase_fftcodeletplan||curplan.plan[entryoffset+3]==ftbase_fhtcodeletplan) { - n1 = curplan.plan[entryoffset+1]; - n2 = curplan.plan[entryoffset+2]; - n = n1*n2; - if( n==3) { - offs = curplan.plan[entryoffset+7]; - curplan.precomputed[offs+0] = cos(2*M_PI/3)-1; - curplan.precomputed[offs+1] = sin(2*M_PI/3); - return; - } - if( n==5) { - offs = curplan.plan[entryoffset+7]; - v = 2*M_PI/5; - curplan.precomputed[offs+0] = (cos(v)+cos(2*v))/2-1; - curplan.precomputed[offs+1] = (cos(v)-cos(2*v))/2; - curplan.precomputed[offs+2] = -sin(v); - curplan.precomputed[offs+3] = -(sin(v)+sin(2*v)); - curplan.precomputed[offs+4] = sin(v)-sin(2*v); - return; - } - } - if( curplan.plan[entryoffset+3]==ftbase_fftbluesteinplan) { - ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+5], stackptr); - n = curplan.plan[entryoffset+1]; - m = curplan.plan[entryoffset+4]; - offs = curplan.plan[entryoffset+7]; - for(int i=0; i<=2*m-1; i++) - curplan.precomputed[offs+i] = 0; - for(int i=0; i0) { - curplan.precomputed[offs+2*(m-i)+0] = bx; - curplan.precomputed[offs+2*(m-i)+1] = by; - } - } - ftbaseexecuteplanrec(&curplan.precomputed, offs, plan, curplan.plan[entryoffset+5], stackptr); - return; - } -} - - -void PIFFT::ftbasefactorize(int n, int* n1, int* n2) { - *n1 = *n2 = 0; - int ftbase_ftbasecodeletrecommended = 5; - if( (*n1)*(*n2)!=n) { - for(int j=ftbase_ftbasecodeletrecommended; j>=2; j--) { - if( n%j==0) { - *n1 = j; - *n2 = n/j; - break; - } - } - } - if( (*n1)*(*n2)!=n) { - for(int j=ftbase_ftbasecodeletrecommended+1; j<=n-1; j++) { - if( n%j==0) { - *n1 = j; - *n2 = n/j; - break; - } - } - } - if( (*n1)*(*n2)!=n) { - *n1 = 1; - *n2 = n; - } - if( (*n2)==1 && (*n1)!=1) { - *n2 = *n1; - *n1 = 1; - } -} - - -/************************************************************************* -Is number smooth? - --- ALGLIB -- - Copyright 01.05.2009 by Bochkanov Sergey -*************************************************************************/ -void PIFFT::ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int* best) { - if( seed>=n) { - *best = piMin(*best, seed); - return; - } - if( leastfactor<=2) - ftbase_ftbasefindsmoothrec(n, seed*2, 2, best); - if( leastfactor<=3) - ftbase_ftbasefindsmoothrec(n, seed*3, 3, best); - if( leastfactor<=5) - ftbase_ftbasefindsmoothrec(n, seed*5, 5, best); -} - - -int PIFFT::ftbasefindsmooth(int n) { - int best, result; - best = 2; - while(best* a, int m, int n, int astart, PIVector* buf) { - ftbase_fftirltrec(a, astart, n, buf, 0, m, m, n); - for (int i=0; i<2*m*n; i++) (*a)[astart+i] = (*buf)[i]; -} - - -void PIFFT::ftbase_fftirltrec(PIVector* a, int astart, int astride, PIVector* b, int bstart, int bstride, int m, int n) { - int idx1, idx2; - int m1, n1; - if( m==0||n==0) - return; - if( piMax(m, n)<=8) { - for(int i=0; i<=m-1; i++) { - idx1 = bstart+i; - idx2 = astart+i*astride; - for(int j=0; j<=n-1; j++) { - (*b)[idx1] = a->at(idx2); - idx1 = idx1+bstride; - idx2 = idx2+1; - } - } - return; - } - if( n>m) { - n1 = n/2; - if( n-n1>=8&&n1%8!=0) - n1 = n1+(8-n1%8); - ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m, n1); - ftbase_fftirltrec(a, astart+n1, astride, b, bstart+n1*bstride, bstride, m, n-n1); - } else { - m1 = m/2; - if( m-m1>=8&&m1%8!=0) - m1 = m1+(8-m1%8); - ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m1, n); - ftbase_fftirltrec(a, astart+m1*astride, astride, b, bstart+m1, bstride, m-m1, n); - } -} - - -void PIFFT::ftbase_internalcomplexlintranspose(PIVector* a, int m, int n, int astart, PIVector* buf) { - ftbase_ffticltrec(a, astart, n, buf, 0, m, m, n); - for (int i=0; i<2*m*n; i++) - (*a)[astart+i] = (*buf)[i]; -} - - -void PIFFT::ftbase_ffticltrec(PIVector* a, int astart, int astride, PIVector* b, int bstart, int bstride, int m, int n) { - int idx1, idx2, m2, m1, n1; - if( m==0||n==0) - return; - if( piMax(m, n)<=8) { - m2 = 2*bstride; - for(int i=0; i<=m-1; i++) { - idx1 = bstart+2*i; - idx2 = astart+2*i*astride; - for(int j=0; j<=n-1; j++) { - (*b)[idx1+0] = a->at(idx2+0); - (*b)[idx1+1] = a->at(idx2+1); - idx1 = idx1+m2; - idx2 = idx2+2; - } - } - return; - } - if( n>m) { - n1 = n/2; - if( n-n1>=8&&n1%8!=0) - n1 = n1+(8-n1%8); - ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m, n1); - ftbase_ffticltrec(a, astart+2*n1, astride, b, bstart+2*n1*bstride, bstride, m, n-n1); - } else { - m1 = m/2; - if( m-m1>=8&&m1%8!=0) - m1 = m1+(8-m1%8); - ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m1, n); - ftbase_ffticltrec(a, astart+2*m1*astride, astride, b, bstart+2*m1, bstride, m-m1, n); - } -} - - -void PIFFT::ftbaseexecuteplan(PIVector* a, int aoffset, int n, ftplan* plan) { - ae_int_t stackptr; - stackptr = 0; - ftbaseexecuteplanrec(a, aoffset, plan, 0, stackptr); -} - - -/************************************************************************* -Recurrent subroutine for the FTBaseExecutePlan - -Parameters: - A FFT'ed array - AOffset offset of the FFT'ed part (distance is measured in doubles) - --- ALGLIB -- - Copyright 01.05.2009 by Bochkanov Sergey -*************************************************************************/ -void PIFFT::ftbaseexecuteplanrec(PIVector* a, int aoffset, ftplan* plan, int entryoffset, ae_int_t stackptr) { - int n1, n2, n, m, offs, offs1, offs2, offsa, offsb, offsp; - double hk, hnk, x, y, bx, by, v0, v1, v2, v3; - double a0x, a0y, a1x, a1y, a2x, a2y, a3x, a3y; - double t1x, t1y, t2x, t2y, t3x, t3y, t4x, t4y, t5x, t5y; - double m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y, m5x, m5y; - double s1x, s1y, s2x, s2y, s3x, s3y, s4x, s4y, s5x, s5y; - double c1, c2, c3, c4, c5; - int ftbase_fftcooleytukeyplan = 0; - int ftbase_fftbluesteinplan = 1; - int ftbase_fftcodeletplan = 2; - int ftbase_fhtcooleytukeyplan = 3; - int ftbase_fhtcodeletplan = 4; - int ftbase_fftrealcooleytukeyplan = 5; - int ftbase_fftemptyplan = 6; - PIVector & tmpb(curplan.tmpbuf); - - if( curplan.plan[entryoffset+3]==ftbase_fftemptyplan) - return; - if( curplan.plan[entryoffset+3]==ftbase_fftcooleytukeyplan) { - n1 = curplan.plan[entryoffset+1]; - n2 = curplan.plan[entryoffset+2]; - ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); - for(int i=0; i<=n2-1; i++) - ftbaseexecuteplanrec(a, aoffset+i*n1*2, plan, curplan.plan[entryoffset+5], stackptr); - ftbase_ffttwcalc(a, aoffset, n1, n2); - ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); - for(int i=0; i<=n1-1; i++) - ftbaseexecuteplanrec(a, aoffset+i*n2*2, plan, curplan.plan[entryoffset+6], stackptr); - ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); - return; - } - if( curplan.plan[entryoffset+3]==ftbase_fftrealcooleytukeyplan) { - n1 = curplan.plan[entryoffset+1]; - n2 = curplan.plan[entryoffset+2]; - ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); - for(int i=0; i<=n1/2-1; i++) { - offs = aoffset+2*i*n2*2; - for(int k=0; k<=n2-1; k++) - (*a)[offs+2*k+1] = (*a)[offs+2*n2+2*k+0]; - ftbaseexecuteplanrec(a, offs, plan, curplan.plan[entryoffset+6], stackptr); - tmpb[0] = (*a)[offs+0]; - tmpb[1] = 0; - tmpb[2*n2+0] = (*a)[offs+1]; - tmpb[2*n2+1] = 0; - for(int k=1; k<=n2-1; k++) { - offs1 = 2*k; - offs2 = 2*n2+2*k; - hk = (*a)[offs+2*k+0]; - hnk = (*a)[offs+2*(n2-k)+0]; - tmpb[offs1+0] = 0.5*(hk+hnk); - tmpb[offs2+1] = -0.5*(hk-hnk); - hk = (*a)[offs+2*k+1]; - hnk = (*a)[offs+2*(n2-k)+1]; - tmpb[offs2+0] = 0.5*(hk+hnk); - tmpb[offs1+1] = 0.5*(hk-hnk); - } - for (int i=0; i<2*n2*2; i++) (*a)[offs+i] = tmpb[i]; - } - if( n1%2!=0) - ftbaseexecuteplanrec(a, aoffset+(n1-1)*n2*2, plan, curplan.plan[entryoffset+6], stackptr); - ftbase_ffttwcalc(a, aoffset, n2, n1); - ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); - for(int i=0; i<=n2-1; i++) - ftbaseexecuteplanrec(a, aoffset+i*n1*2, plan, curplan.plan[entryoffset+5], stackptr); - ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); - return; - } - if( curplan.plan[entryoffset+3]==ftbase_fhtcooleytukeyplan) { - n1 = curplan.plan[entryoffset+1]; - n2 = curplan.plan[entryoffset+2]; - n = n1*n2; - ftbase_internalreallintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); - for(int i=0; i<=n2-1; i++) - ftbaseexecuteplanrec(a, aoffset+i*n1, plan, curplan.plan[entryoffset+5], stackptr); - for(int i=0; i<=n2-1; i++) { - for(int j=0; j<=n1-1; j++) { - offsa = aoffset+i*n1; - hk = (*a)[offsa+j]; - hnk = (*a)[offsa+(n1-j)%n1]; - offs = 2*(i*n1+j); - tmpb[offs+0] = -0.5*(hnk-hk); - tmpb[offs+1] = 0.5*(hk+hnk); - } - } - ftbase_ffttwcalc(&(curplan.tmpbuf), 0, n1, n2); - for(int j=0; j<=n1-1; j++) - (*a)[aoffset+j] = tmpb[2*j+0]+tmpb[2*j+1]; - if( n2%2==0) { - offs = 2*(n2/2)*n1; - offsa = aoffset+n2/2*n1; - for(int j=0; j<=n1-1; j++) - (*a)[offsa+j] = tmpb[offs+2*j+0]+tmpb[offs+2*j+1]; - } - for(int i=1; i<=(n2+1)/2-1; i++) { - offs = 2*i*n1; - offs2 = 2*(n2-i)*n1; - offsa = aoffset+i*n1; - for(int j=0; j<=n1-1; j++) - (*a)[offsa+j] = tmpb[offs+2*j+1]+tmpb[offs2+2*j+0]; - offsa = aoffset+(n2-i)*n1; - for(int j=0; j<=n1-1; j++) - (*a)[offsa+j] = tmpb[offs+2*j+0]+tmpb[offs2+2*j+1]; - } - ftbase_internalreallintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); - for(int i=0; i<=n1-1; i++) - ftbaseexecuteplanrec(a, aoffset+i*n2, plan, curplan.plan[entryoffset+6], stackptr); - ftbase_internalreallintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); - return; - } - if( curplan.plan[entryoffset+3]==ftbase_fftcodeletplan) { - n1 = curplan.plan[entryoffset+1]; - n2 = curplan.plan[entryoffset+2]; - n = n1*n2; - if( n==2) { - a0x = (*a)[aoffset+0]; - a0y = (*a)[aoffset+1]; - a1x = (*a)[aoffset+2]; - a1y = (*a)[aoffset+3]; - v0 = a0x+a1x; - v1 = a0y+a1y; - v2 = a0x-a1x; - v3 = a0y-a1y; - (*a)[aoffset+0] = v0; - (*a)[aoffset+1] = v1; - (*a)[aoffset+2] = v2; - (*a)[aoffset+3] = v3; - return; - } - if( n==3) { - offs = curplan.plan[entryoffset+7]; - c1 = curplan.precomputed[offs+0]; - c2 = curplan.precomputed[offs+1]; - a0x = (*a)[aoffset+0]; - a0y = (*a)[aoffset+1]; - a1x = (*a)[aoffset+2]; - a1y = (*a)[aoffset+3]; - a2x = (*a)[aoffset+4]; - a2y = (*a)[aoffset+5]; - t1x = a1x+a2x; - t1y = a1y+a2y; - a0x = a0x+t1x; - a0y = a0y+t1y; - m1x = c1*t1x; - m1y = c1*t1y; - m2x = c2*(a1y-a2y); - m2y = c2*(a2x-a1x); - s1x = a0x+m1x; - s1y = a0y+m1y; - a1x = s1x+m2x; - a1y = s1y+m2y; - a2x = s1x-m2x; - a2y = s1y-m2y; - (*a)[aoffset+0] = a0x; - (*a)[aoffset+1] = a0y; - (*a)[aoffset+2] = a1x; - (*a)[aoffset+3] = a1y; - (*a)[aoffset+4] = a2x; - (*a)[aoffset+5] = a2y; - return; - } - if( n==4) { - a0x = (*a)[aoffset+0]; - a0y = (*a)[aoffset+1]; - a1x = (*a)[aoffset+2]; - a1y = (*a)[aoffset+3]; - a2x = (*a)[aoffset+4]; - a2y = (*a)[aoffset+5]; - a3x = (*a)[aoffset+6]; - a3y = (*a)[aoffset+7]; - t1x = a0x+a2x; - t1y = a0y+a2y; - t2x = a1x+a3x; - t2y = a1y+a3y; - m2x = a0x-a2x; - m2y = a0y-a2y; - m3x = a1y-a3y; - m3y = a3x-a1x; - (*a)[aoffset+0] = t1x+t2x; - (*a)[aoffset+1] = t1y+t2y; - (*a)[aoffset+4] = t1x-t2x; - (*a)[aoffset+5] = t1y-t2y; - (*a)[aoffset+2] = m2x+m3x; - (*a)[aoffset+3] = m2y+m3y; - (*a)[aoffset+6] = m2x-m3x; - (*a)[aoffset+7] = m2y-m3y; - return; - } - if( n==5) { - offs = curplan.plan[entryoffset+7]; - c1 = curplan.precomputed[offs+0]; - c2 = curplan.precomputed[offs+1]; - c3 = curplan.precomputed[offs+2]; - c4 = curplan.precomputed[offs+3]; - c5 = curplan.precomputed[offs+4]; - t1x = (*a)[aoffset+2]+(*a)[aoffset+8]; - t1y = (*a)[aoffset+3]+(*a)[aoffset+9]; - t2x = (*a)[aoffset+4]+(*a)[aoffset+6]; - t2y = (*a)[aoffset+5]+(*a)[aoffset+7]; - t3x = (*a)[aoffset+2]-(*a)[aoffset+8]; - t3y = (*a)[aoffset+3]-(*a)[aoffset+9]; - t4x = (*a)[aoffset+6]-(*a)[aoffset+4]; - t4y = (*a)[aoffset+7]-(*a)[aoffset+5]; - t5x = t1x+t2x; - t5y = t1y+t2y; - (*a)[aoffset+0] = (*a)[aoffset+0]+t5x; - (*a)[aoffset+1] = (*a)[aoffset+1]+t5y; - m1x = c1*t5x; - m1y = c1*t5y; - m2x = c2*(t1x-t2x); - m2y = c2*(t1y-t2y); - m3x = -c3*(t3y+t4y); - m3y = c3*(t3x+t4x); - m4x = -c4*t4y; - m4y = c4*t4x; - m5x = -c5*t3y; - m5y = c5*t3x; - s3x = m3x-m4x; - s3y = m3y-m4y; - s5x = m3x+m5x; - s5y = m3y+m5y; - s1x = (*a)[aoffset+0]+m1x; - s1y = (*a)[aoffset+1]+m1y; - s2x = s1x+m2x; - s2y = s1y+m2y; - s4x = s1x-m2x; - s4y = s1y-m2y; - (*a)[aoffset+2] = s2x+s3x; - (*a)[aoffset+3] = s2y+s3y; - (*a)[aoffset+4] = s4x+s5x; - (*a)[aoffset+5] = s4y+s5y; - (*a)[aoffset+6] = s4x-s5x; - (*a)[aoffset+7] = s4y-s5y; - (*a)[aoffset+8] = s2x-s3x; - (*a)[aoffset+9] = s2y-s3y; - return; - } - } - if( curplan.plan[entryoffset+3]==ftbase_fhtcodeletplan) { - n1 = curplan.plan[entryoffset+1]; - n2 = curplan.plan[entryoffset+2]; - n = n1*n2; - if( n==2) { - a0x = (*a)[aoffset+0]; - a1x = (*a)[aoffset+1]; - (*a)[aoffset+0] = a0x+a1x; - (*a)[aoffset+1] = a0x-a1x; - return; - } - if( n==3) { - offs = curplan.plan[entryoffset+7]; - c1 = curplan.precomputed[offs+0]; - c2 = curplan.precomputed[offs+1]; - a0x = (*a)[aoffset+0]; - a1x = (*a)[aoffset+1]; - a2x = (*a)[aoffset+2]; - t1x = a1x+a2x; - a0x = a0x+t1x; - m1x = c1*t1x; - m2y = c2*(a2x-a1x); - s1x = a0x+m1x; - (*a)[aoffset+0] = a0x; - (*a)[aoffset+1] = s1x-m2y; - (*a)[aoffset+2] = s1x+m2y; - return; - } - if( n==4) { - a0x = (*a)[aoffset+0]; - a1x = (*a)[aoffset+1]; - a2x = (*a)[aoffset+2]; - a3x = (*a)[aoffset+3]; - t1x = a0x+a2x; - t2x = a1x+a3x; - m2x = a0x-a2x; - m3y = a3x-a1x; - (*a)[aoffset+0] = t1x+t2x; - (*a)[aoffset+1] = m2x-m3y; - (*a)[aoffset+2] = t1x-t2x; - (*a)[aoffset+3] = m2x+m3y; - return; - } - if( n==5) { - offs = curplan.plan[entryoffset+7]; - c1 = curplan.precomputed[offs+0]; - c2 = curplan.precomputed[offs+1]; - c3 = curplan.precomputed[offs+2]; - c4 = curplan.precomputed[offs+3]; - c5 = curplan.precomputed[offs+4]; - t1x = (*a)[aoffset+1]+(*a)[aoffset+4]; - t2x = (*a)[aoffset+2]+(*a)[aoffset+3]; - t3x = (*a)[aoffset+1]-(*a)[aoffset+4]; - t4x = (*a)[aoffset+3]-(*a)[aoffset+2]; - t5x = t1x+t2x; - v0 = (*a)[aoffset+0]+t5x; - (*a)[aoffset+0] = v0; - m2x = c2*(t1x-t2x); - m3y = c3*(t3x+t4x); - s3y = m3y-c4*t4x; - s5y = m3y+c5*t3x; - s1x = v0+c1*t5x; - s2x = s1x+m2x; - s4x = s1x-m2x; - (*a)[aoffset+1] = s2x-s3y; - (*a)[aoffset+2] = s4x-s5y; - (*a)[aoffset+3] = s4x+s5y; - (*a)[aoffset+4] = s2x+s3y; - return; - } - } - if( curplan.plan[entryoffset+3]==ftbase_fftbluesteinplan) { - n = curplan.plan[entryoffset+1]; - m = curplan.plan[entryoffset+4]; - offs = curplan.plan[entryoffset+7]; - for(int i=stackptr+2*n; i<=stackptr+2*m-1; i++) - curplan.stackbuf[i] = 0; - offsp = offs+2*m; - offsa = aoffset; - offsb = stackptr; - for(int i=0; i * a, int aoffset, int n1, int n2) { - int n, idx, offs; - double x, y, twxm1, twy, twbasexm1, twbasey, twrowxm1, twrowy, tmpx, tmpy, v; - int ftbase_ftbaseupdatetw = 4; - n = n1*n2; - v = -2*M_PI/n; - twbasexm1 = -2*sqr(sin(0.5*v)); - twbasey = sin(v); - twrowxm1 = 0; - twrowy = 0; - for(int i=0, j = 0; i<=n2-1; i++) { - twxm1 = 0; - twy = 0; - for(j=0; j<=n1-1; j++) { - idx = i*n1+j; - offs = aoffset+2*idx; - x = (*a)[offs+0]; - y = (*a)[offs+1]; - tmpx = x*twxm1-y*twy; - tmpy = x*twy+y*twxm1; - (*a)[offs+0] = x+tmpx; - (*a)[offs+1] = y+tmpy; - if( j. -*/ - -#ifndef PIMATH_H -#define PIMATH_H - -#include "pibytearray.h" -#ifndef QNX -# include -# include -#else -# include -# include -# undef PIP_MATH_J0 -# undef PIP_MATH_J1 -# undef PIP_MATH_JN -# undef PIP_MATH_Y0 -# undef PIP_MATH_Y1 -# undef PIP_MATH_YN -#endif - -#ifndef M_LN2 -# define M_LN2 0.69314718055994530942 -#endif -#ifndef M_LN10 -# define M_LN10 2.30258509299404568402 -#endif -#ifndef M_SQRT2 -# define M_SQRT2 1.41421356237309514547 -#endif -#ifndef M_SQRT3 -# define M_SQRT3 1.73205080756887719318 -#endif -#ifndef M_1_SQRT2 -# define M_1_SQRT2 0.70710678118654746172 -#endif -#ifndef M_1_SQRT3 -# define M_1_SQRT3 0.57735026918962584208 -#endif -#ifndef M_PI -# define M_PI 3.14159265358979323846 -#endif -#ifndef M_2PI -# define M_2PI 6.28318530717958647692 -#endif -#ifndef M_PI_3 -# define M_PI_3 1.04719755119659774615 -#endif -#ifndef M_2PI_3 -# define M_2PI_3 2.0943951023931954923 -#endif -#ifndef M_180_PI -# define M_180_PI 57.2957795130823208768 -#endif -#ifndef M_PI_180 -# define M_PI_180 1.74532925199432957692e-2 -#endif -#ifndef M_E -# define M_E 2.7182818284590452353602874713527 -#endif -#ifndef M_LIGHT_SPEED -# define M_LIGHT_SPEED 2.99792458e+8 -#endif - -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.); - -__PICONTAINERS_SIMPLE_TYPE__(complexi) -__PICONTAINERS_SIMPLE_TYPE__(complexf) -__PICONTAINERS_SIMPLE_TYPE__(complexd) -__PICONTAINERS_SIMPLE_TYPE__(complexld) - -const double deg2rad = M_PI_180; -const double rad2deg = M_180_PI; - -inline int sign(const float & x) {return (x < 0.) ? -1 : (x > 0. ? 1 : 0);} -inline int sign(const double & x) {return (x < 0.) ? -1 : (x > 0. ? 1 : 0);} -inline complexd sign(const complexd & x) {return complexd(sign(x.real()), sign(x.imag()));} -inline int pow2(const int p) {return 1 << p;} -inline double sqr(const int v) {return v * v;} -inline double sqr(const float & v) {return v * v;} -inline double sqr(const double & v) {return v * v;} -inline double sinc(const double & v) {if (v == 0.) return 1.; double t = M_PI * v; return sin(t) / t;} -inline complexd round(const complexd & c) {return complexd(piRound(c.real()), piRound(c.imag()));} -inline complexd floor(const complexd & c) {return complexd(floor(c.real()), floor(c.imag()));} -inline complexd ceil(const complexd & c) {return complexd(ceil(c.real()), ceil(c.imag()));} -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 CC_GCC -# if CC_GCC_VERSION <= 0x025F -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;} -# endif -#endif -double piJ0(const double & v); -double piJ1(const double & v); -double piJn(int n, const double & v); -double piY0(const double & v); -double piY1(const double & v); -double piYn(int n, const double & v); -inline double toDb(double val) {return 10. * log10(val);} -inline double fromDb(double val) {return pow(10., val / 10.);} -inline double toRad(double deg) {return deg * M_PI_180;} -inline double toDeg(double rad) {return rad * M_180_PI;} - -template -inline PICout operator <<(PICout s, const complex & v) {s.space(); s.setControl(0, true); s << "(" << v.real() << "; " << v.imag() << ")"; s.restoreControl(); return s;} - -// [-1 ; 1] -inline double randomd() {return (double)random() / RAND_MAX * 2. - 1.;} -// [-1 ; 1] normal -double randomn(double dv = 0., double sv = 1.); - -inline PIVector abs(const PIVector & v) { - PIVector result; - result.resize(v.size()); - for (uint i = 0; i < v.size(); i++) - result[i] = abs(v[i]); - return result; -} -inline PIVector abs(const PIVector & v) { - PIVector result; - result.resize(v.size()); - for (uint i = 0; i < v.size(); i++) - result[i] = abs(v[i]); - return result; -} - -template -class PIMathMatrixT; - -/// Vector templated - -#define PIMV_FOR(v, s) for (uint v = s; v < Size; ++v) - -#pragma pack(push, 1) -template -class PIP_EXPORT 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); set(st, fn);} - - uint size() const {return Size;} - _CVector & fill(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;} - _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;} - _CVector & set(const _CVector & st, const _CVector & fn) {PIMV_FOR(i, 0) c[i] = fn[i] - st[i]; return *this;} - _CVector & move(const Type & v) {PIMV_FOR(i, 0) c[i] += v; return *this;} - _CVector & move(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i]; return *this;} - _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;} - Type lengthSqr() const {Type tv(0); PIMV_FOR(i, 0) tv += (c[i] * c[i]); return tv;} - Type length() const {return sqrt(lengthSqr());} - Type manhattanLength() const {Type tv(0); PIMV_FOR(i, 0) tv += fabs(c[i]); return tv;} - Type angleCos(const _CVector & v) const {Type tv = v.length() * length(); return (tv == Type(0) ? Type(0) : ((*this) ^ v) / tv);} - Type angleSin(const _CVector & v) const {Type tv = angleCos(v); return sqrt(Type(1) - tv * tv);} - Type angleRad(const _CVector & v) const {return acos(angleCos(v));} - Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));} - _CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));} - _CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; if (piAbs(tv) <= Type(1E-100)) {fill(Type(0)); return *this;} PIMV_FOR(i, 0) c[i] /= tv; return *this;} - _CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;} - bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;} - bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);} - - Type & at(uint index) {return c[index];} - Type at(uint index) const {return c[index];} - Type & operator [](uint index) {return c[index];} - Type operator [](uint index) const {return c[index];} - _CVector & operator =(const _CVector & v) {memcpy(c, v.c, sizeof(Type) * Size); return *this;} - bool operator ==(const _CVector & v) const {PIMV_FOR(i, 0) if (c[i] != v[i]) return false; return true;} - bool operator !=(const _CVector & v) const {return !(*this == c);} - void operator +=(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i];} - void operator -=(const _CVector & v) {PIMV_FOR(i, 0) c[i] -= v[i];} - void operator *=(const Type & v) {PIMV_FOR(i, 0) c[i] *= v;} - void operator *=(const _CVector & v) {PIMV_FOR(i, 0) c[i] *= v[i];} - void operator /=(const Type & v) {PIMV_FOR(i, 0) c[i] /= v;} - void operator /=(const _CVector & v) {PIMV_FOR(i, 0) c[i] /= v[i];} - _CVector operator -() const {_CVector tv; PIMV_FOR(i, 0) tv[i] = -c[i]; return tv;} - _CVector operator +(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] += v[i]; return tv;} - _CVector operator -(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] -= v[i]; return tv;} - _CVector operator *(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v; return tv;} - _CVector operator /(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v; return tv;} - _CVector operator /(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v[i]; return tv;} - _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;} - Type operator ^(const _CVector & v) const {Type tv(0); PIMV_FOR(i, 0) tv += c[i] * v[i]; return tv;} - - operator PIMathMatrixT<1, Size, Type>() {return PIMathMatrixT<1, Size, Type>(c);} - Type distToLine(const _CVector & lp0, const _CVector & lp1) { - _CVector a(lp0, lp1), b(lp0, *this), c(lp1, *this); - Type f = fabs(a[0]*b[1] - a[1]*b[0]) / a.length();//, s = b.length() + c.length() - a.length(); - return f;} - - template /// vector {Size, Type} to vector {Size1, Type1} - PIMathVectorT turnTo() const {PIMathVectorT tv; uint sz = piMin(Size, Size1); for (uint i = 0; i < sz; ++i) tv[i] = c[i]; return tv;} - -private: - void resize(uint size, const Type & new_value = Type()) {s = size; for (int i = 0; i < s; ++i) c[i] = new_value;} - - int s; - Type c[Size]; - -}; -#pragma pack(pop) - -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 PICout operator <<(PICout s, const PIMathVectorT & v) {s << '{'; PIMV_FOR(i, 0) {s << v[i]; if (i < Size - 1) s << ", ";} s << '}'; return s;} -template -inline bool operator ||(const PIMathVectorT & f, const PIMathVectorT & s) {return (f * s).isNull();} -template -inline PIMathVectorT sqrt(const PIMathVectorT & v) {PIMathVectorT ret; PIMV_FOR(i, 0) {ret[i] = sqrt(v[i]);} return ret;} -template -inline PIMathVectorT sqr(const PIMathVectorT & v) {PIMathVectorT ret; PIMV_FOR(i, 0) {ret[i] = sqr(v[i]);} return ret;} - -template -inline PIByteArray & operator <<(PIByteArray & s, const PIMathVectorT & v) {for (int i = 0; i < Size; ++i) s << v[i]; return s;} -template -inline PIByteArray & operator >>(PIByteArray & s, PIMathVectorT & v) {for (int i = 0; i < Size; ++i) s >> v[i]; return s;} - -//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;} - -typedef PIMathVectorT<2u, int> PIMathVectorT2i; -typedef PIMathVectorT<3u, int> PIMathVectorT3i; -typedef PIMathVectorT<4u, int> PIMathVectorT4i; -typedef PIMathVectorT<2u, double> PIMathVectorT2d; -typedef PIMathVectorT<3u, double> PIMathVectorT3d; -typedef PIMathVectorT<4u, double> PIMathVectorT4d; - -/// Matrix templated - -#define PIMM_FOR(c, r) for (uint c = 0; c < Cols; ++c) { for (uint r = 0; r < Rows; ++r) { -#define PIMM_FOR_WB(c, r) for (uint c = 0; c < Cols; ++c) for (uint r = 0; r < Rows; ++r) // without brakes -#define PIMM_FOR_I(c, r) for (uint r = 0; r < Rows; ++r) { for (uint c = 0; c < Cols; ++c) { -#define PIMM_FOR_I_WB(c, r) for (uint r = 0; r < Rows; ++r) for (uint c = 0; c < Cols; ++c) // without brakes -#define PIMM_FOR_C(v) for (uint v = 0; v < Cols; ++v) -#define PIMM_FOR_R(v) for (uint v = 0; v < Rows; ++v) - -#pragma pack(push, 1) -template -class PIP_EXPORT PIMathMatrixT { - typedef PIMathMatrixT _CMatrix; - typedef PIMathMatrixT _CMatrixI; - typedef PIMathVectorT _CMCol; - typedef PIMathVectorT _CMRow; -public: - PIMathMatrixT() {resize(Cols, Rows);} - PIMathMatrixT(Type fval, ...) {resize(Cols, Rows); va_list vl; va_start(vl, fval); PIMM_FOR_I_WB(c, r) m[c][r] = (r + c == 0 ? fval : va_arg(vl, Type)); va_end(vl);} - PIMathMatrixT(const PIVector & val) {resize(Cols, Rows); int i = 0; PIMM_FOR_I_WB(c, r) m[c][r] = val[i++];} - - static _CMatrix identity() {_CMatrix tm = _CMatrix(); PIMM_FOR_WB(c, r) tm.m[c][r] = (c == r ? Type(1) : Type(0)); return tm;} - static _CMatrix rotation(double angle) {return _CMatrix();} - static _CMatrix rotationX(double angle) {return _CMatrix();} - static _CMatrix rotationY(double angle) {return _CMatrix();} - static _CMatrix rotationZ(double angle) {return _CMatrix();} - - uint cols() const {return Cols;} - uint rows() const {return Rows;} - _CMCol col(uint index) {_CMCol tv; PIMM_FOR_R(i) tv[i] = m[index][i]; return tv;} - _CMRow row(uint index) {_CMRow tv; PIMM_FOR_C(i) tv[i] = m[i][index]; return tv;} - _CMatrix & setCol(uint index, const _CMCol & v) {PIMM_FOR_R(i) m[index][i] = v[i]; return *this;} - _CMatrix & setRow(uint index, const _CMRow & v) {PIMM_FOR_C(i) m[i][index] = v[i]; return *this;} - _CMatrix & swapRows(uint r0, uint r1) {Type t; PIMM_FOR_C(i) {t = m[i][r0]; m[i][r0] = m[i][r1]; m[i][r1] = t;} return *this;} - _CMatrix & swapCols(uint c0, uint c1) {Type t; PIMM_FOR_R(i) {t = m[c0][i]; m[c0][i] = m[c1][i]; m[c1][i] = t;} return *this;} - _CMatrix & fill(const Type & v) {PIMM_FOR_WB(c, r) m[c][r] = v; return *this;} - //inline _CMatrix & set(Type fval, ...) {m[0] = fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) m[i] = va_arg(vl, Type); va_end(vl); return *this;} - //inline void normalize() {Type tv = length(); if (tv == Type(1)) return; PIMV_FOR(i, 0) m[i] /= tv;} - bool isSquare() const {return cols() == rows();} - bool isIdentity() const {PIMM_FOR_WB(c, r) if ((c == r) ? m[c][r] != Type(1) : m[c][r] != Type(0)) return false; return true;} - bool isNull() const {PIMM_FOR_WB(c, r) if (m[c][r] != Type(0)) return false; return true;} - - Type & at(uint col, uint row) {return m[col][row];} - Type at(uint col, uint row) const {return m[col][row];} - Type * operator [](uint col) {return m[col];} - const Type * operator [](uint col) const {return m[col];} - void operator =(const _CMatrix & sm) {memcpy(m, sm.m, sizeof(Type) * Cols * Rows);} - bool operator ==(const _CMatrix & sm) const {PIMM_FOR_WB(c, r) if (m[c][r] != sm.m[c][r]) return false; return true;} - bool operator !=(const _CMatrix & sm) const {return !(*this == sm);} - void operator +=(const _CMatrix & sm) {PIMM_FOR_WB(c, r) m[c][r] += sm.m[c][r];} - void operator -=(const _CMatrix & sm) {PIMM_FOR_WB(c, r) m[c][r] -= sm.m[c][r];} - void operator *=(const Type & v) {PIMM_FOR_WB(c, r) m[c][r] *= v;} - void operator /=(const Type & v) {PIMM_FOR_WB(c, r) m[c][r] /= v;} - _CMatrix operator -() {_CMatrix tm; PIMM_FOR_WB(c, r) tm.m[c][r] = -m[c][r]; return tm;} - _CMatrix operator +(const _CMatrix & sm) {_CMatrix tm = _CMatrix(*this); PIMM_FOR_WB(c, r) tm.m[c][r] += sm.m[c][r]; return tm;} - _CMatrix operator -(const _CMatrix & sm) {_CMatrix tm = _CMatrix(*this); PIMM_FOR_WB(c, r) tm.m[c][r] -= sm.m[c][r]; return tm;} - _CMatrix operator *(const Type & v) {_CMatrix tm = _CMatrix(*this); PIMM_FOR_WB(c, r) tm.m[c][r] *= v; return tm;} - _CMatrix operator /(const Type & v) {_CMatrix tm = _CMatrix(*this); PIMM_FOR_WB(c, r) tm.m[c][r] /= v; return tm;} - - _CMatrix & toUpperTriangular(bool * ok = 0) { - if (Cols != Rows) { - if (ok != 0) *ok = false; - return *this; - } - _CMatrix smat(*this); - bool ndet; - uint crow; - Type mul; - for (uint i = 0; i < Cols; ++i) { - ndet = true; - for (uint j = 0; j < Rows; ++j) if (smat.m[i][j] != 0) ndet = false; - if (ndet) { - if (ok != 0) *ok = false; - return *this; - } - for (uint j = 0; j < Cols; ++j) if (smat.m[j][i] != 0) ndet = false; - if (ndet) { - if (ok != 0) *ok = false; - return *this; - } - } - for (uint i = 0; i < Cols; ++i) { - crow = i; - while (smat.m[i][i] == Type(0)) - smat.swapRows(i, ++crow); - for (uint j = i + 1; j < Rows; ++j) { - mul = smat.m[i][j] / smat.m[i][i]; - for (uint k = i; k < Cols; ++k) smat.m[k][j] -= mul * smat.m[k][i]; - } - if (i < Cols - 1) { - if (fabs(smat.m[i+1][i+1]) < Type(1E-100)) { - if (ok != 0) *ok = false; - return *this; - } - } - } - if (ok != 0) *ok = true; - memcpy(m, smat.m, sizeof(Type) * Cols * Rows); - return *this; - } - - _CMatrix & invert(bool * ok = 0) { - if (Cols != Rows) { - if (ok != 0) *ok = false; - return *this; - } - _CMatrix mtmp = _CMatrix::identity(), smat(*this); - bool ndet; - uint crow; - Type mul, iddiv; - for (uint i = 0; i < Cols; ++i) { - ndet = true; - for (uint j = 0; j < Rows; ++j) if (smat.m[i][j] != 0) ndet = false; - if (ndet) { - if (ok != 0) *ok = false; - return *this; - } - for (uint j = 0; j < Cols; ++j) if (smat.m[j][i] != 0) ndet = false; - if (ndet) { - if (ok != 0) *ok = false; - return *this; - } - } - for (uint i = 0; i < Cols; ++i) { - crow = i; - while (smat.m[i][i] == Type(0)) { - ++crow; - smat.swapRows(i, crow); - mtmp.swapRows(i, crow); - } - for (uint j = i + 1; j < Rows; ++j) { - mul = smat.m[i][j] / smat.m[i][i]; - for (uint k = i; k < Cols; ++k) smat.m[k][j] -= mul * smat.m[k][i]; - for (uint k = 0; k < Cols; ++k) mtmp.m[k][j] -= mul * mtmp.m[k][i]; - } - //cout << i << endl << smat << endl; - if (i < Cols - 1) { - if (fabs(smat.m[i+1][i+1]) < Type(1E-100)) { - if (ok != 0) *ok = false; - return *this; - } - } - iddiv = smat.m[i][i]; - for (uint j = i; j < Cols; ++j) smat.m[j][i] /= iddiv; - for (uint j = 0; j < Cols; ++j) mtmp.m[j][i] /= iddiv; - } - for (uint i = Cols - 1; i > 0; --i) { - for (uint j = 0; j < i; ++j) { - mul = smat.m[i][j]; - smat.m[i][j] -= mul; - for (uint k = 0; k < Cols; ++k) mtmp.m[k][j] -= mtmp.m[k][i] * mul; - } - } - if (ok != 0) *ok = true; - memcpy(m, mtmp.m, sizeof(Type) * Cols * Rows); - return *this; - } - _CMatrix inverted(bool * ok = 0) {_CMatrix tm(*this); tm.invert(ok); return tm;} - _CMatrixI transposed() {_CMatrixI tm; PIMM_FOR_WB(c, r) tm[r][c] = m[c][r]; return tm;} - -private: - void resize(uint cols_, uint rows_, const Type & new_value = Type()) {c_ = cols_; r_ = rows_; PIMM_FOR_WB(c, r) m[c][r] = new_value;} - int c_, r_; - Type m[Cols][Rows]; - -}; -#pragma pack(pop) - - -template<> inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::rotation(double angle) {double c = cos(angle), s = sin(angle); PIMathMatrixT<2u, 2u> tm; tm[0][0] = tm[1][1] = c; tm[0][1] = -s; tm[1][0] = s; return tm;} -template<> inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationX(double angle) {double c = cos(angle), s = sin(angle); PIMathMatrixT<3u, 3u> tm; tm[0][0] = 1.; tm[1][1] = tm[2][2] = c; tm[2][1] = -s; tm[1][2] = s; return tm;} -template<> inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationY(double angle) {double c = cos(angle), s = sin(angle); PIMathMatrixT<3u, 3u> tm; tm[1][1] = 1.; tm[0][0] = tm[2][2] = c; tm[2][0] = s; tm[0][2] = -s; return tm;} -template<> inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationZ(double angle) {double c = cos(angle), s = sin(angle); PIMathMatrixT<3u, 3u> tm; tm[2][2] = 1.; tm[0][0] = tm[1][1] = c; tm[1][0] = -s; tm[0][1] = s; return tm;} - -template -inline std::ostream & operator <<(std::ostream & s, const PIMathMatrixT & m) {s << '{'; PIMM_FOR_I(c, r) s << m[c][r]; if (c < Cols - 1 || r < Rows - 1) s << ", ";} if (r < Rows - 1) s << endl << ' ';} s << '}'; return s;} -template -inline PICout operator <<(PICout s, const PIMathMatrixT & m) {s << '{'; PIMM_FOR_I(c, r) s << m[c][r]; if (c < Cols - 1 || r < Rows - 1) s << ", ";} if (r < Rows - 1) s << NewLine << ' ';} s << '}'; return s;} - -/// Multiply matrices {CR x Rows0} on {Cols1 x CR}, result is {Cols1 x Rows0} -template -inline PIMathMatrixT operator *(const PIMathMatrixT & fm, - const PIMathMatrixT & sm) { - PIMathMatrixT tm; - Type t; - for (uint j = 0; j < Rows0; ++j) { - for (uint i = 0; i < Cols1; ++i) { - t = Type(0); - for (uint k = 0; k < CR; ++k) - t += fm[k][j] * sm[i][k]; - tm[i][j] = t; - } - } - return tm; -} - -/// Multiply matrix {Cols x Rows} on vector {Cols}, result is vector {Rows} -template -inline PIMathVectorT operator *(const PIMathMatrixT & fm, - const PIMathVectorT & sv) { - PIMathVectorT tv; - Type t; - for (uint i = 0; i < Rows; ++i) { - t = Type(0); - for (uint j = 0; j < Cols; ++j) - t += fm[j][i] * sv[j]; - tv[i] = t; - } - return tv; -} - -typedef PIMathMatrixT<2u, 2u, int> PIMathMatrixT22i; -typedef PIMathMatrixT<3u, 3u, int> PIMathMatrixT33i; -typedef PIMathMatrixT<4u, 4u, int> PIMathMatrixT44i; -typedef PIMathMatrixT<2u, 2u, double> PIMathMatrixT22d; -typedef PIMathMatrixT<3u, 3u, double> PIMathMatrixT33d; -typedef PIMathMatrixT<4u, 4u, double> PIMathMatrixT44d; - - -template -class PIMathMatrix; - -#undef PIMV_FOR -#undef PIMM_FOR -#undef PIMM_FOR_WB -#undef PIMM_FOR_I -#undef PIMM_FOR_I_WB -#undef PIMM_FOR_C -#undef PIMM_FOR_R - -/// Vector - -#define PIMV_FOR(v, s) for (uint v = s; v < size_; ++v) - -template -class PIP_EXPORT PIMathVector { - typedef PIMathVector _CVector; -public: - PIMathVector(const uint size = 3) {resize(size);} - PIMathVector(const uint size, 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);} - PIMathVector(const PIVector & val) {resize(val.size); PIMV_FOR(i, 0) c[i] = val[i];} - PIMathVector(const _CVector & st, const _CVector & fn) {resize(st.size()); PIMV_FOR(i, 0) c[i] = fn[i] - st[i];} - - uint size() const {return size_;} - _CVector & resize(uint size, const Type & new_value = Type()) {size_ = size; c.resize(size, new_value); return *this;} - _CVector resized(uint size, const Type & new_value = Type()) {_CVector tv = _CVector(*this); tv.resize(size, new_value); return tv;} - _CVector & fill(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;} - _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;} - _CVector & move(const Type & v) {PIMV_FOR(i, 0) c[i] += v; return *this;} - _CVector & move(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i]; return *this;} - _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;} - _CVector & swap(uint fe, uint se) {piSwap(c[fe], c[se]); return *this;} - Type lengthSqr() const {Type tv(0); PIMV_FOR(i, 0) tv += (c[i] * c[i]); return tv;} - Type length() const {return sqrt(lengthSqr());} - Type manhattanLength() const {Type tv(0); PIMV_FOR(i, 0) tv += fabs(c[i]); return tv;} - Type angleCos(const _CVector & v) const {Type tv = v.length() * length(); return (tv == Type(0) ? Type(0) : ((*this) ^ v) / tv);} - Type angleSin(const _CVector & v) const {Type tv = angleCos(v); return sqrt(Type(1) - tv * tv);} - Type angleRad(const _CVector & v) const {return acos(angleCos(v));} - Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));} - _CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));} - _CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; if (piAbs(tv) <= Type(1E-100)) {fill(Type(0)); return *this;} PIMV_FOR(i, 0) c[i] /= tv; return *this;} - _CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;} - bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;} - bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);} - - Type & at(uint index) {return c[index];} - Type at(uint index) const {return c[index];} - Type & operator [](uint index) {return c[index];} - Type operator [](uint index) const {return c[index];} - void operator =(const _CVector & v) {c = v.c;} - bool operator ==(const _CVector & v) const {PIMV_FOR(i, 0) if (c[i] != v[i]) return false; return true;} - bool operator !=(const _CVector & v) const {return !(*this == c);} - void operator +=(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i];} - void operator -=(const _CVector & v) {PIMV_FOR(i, 0) c[i] -= v[i];} - void operator *=(const Type & v) {PIMV_FOR(i, 0) c[i] *= v;} - void operator *=(const _CVector & v) {PIMV_FOR(i, 0) c[i] *= v[i];} - void operator /=(const Type & v) {PIMV_FOR(i, 0) c[i] /= v;} - void operator /=(const _CVector & v) {PIMV_FOR(i, 0) c[i] /= v[i];} - _CVector operator -() {_CVector tv; PIMV_FOR(i, 0) tv[i] = -c[i]; return tv;} - _CVector operator +(const _CVector & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] += v[i]; return tv;} - _CVector operator -(const _CVector & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] -= v[i]; return tv;} - _CVector operator *(const Type & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v; return tv;} - _CVector operator /(const Type & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v; return tv;} - _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;} - Type operator ^(const _CVector & v) const {Type tv(0); PIMV_FOR(i, 0) tv += c[i] * v[i]; return tv;} - - //inline operator PIMathMatrix<1, Size, Type>() {return PIMathMatrix<1, Size, Type>(c);} - Type distToLine(const _CVector & lp0, const _CVector & lp1) { - _CVector a(lp0, lp1), b(lp0, *this), c(lp1, *this); - Type f = fabs(a[0]*b[1] - a[1]*b[0]) / a.length();//, s = b.length() + c.length() - a.length(); - return f;} - - template - PIMathVector turnTo(uint size) {PIMathVector tv; uint sz = piMin(size_, size); for (uint i = 0; i < sz; ++i) tv[i] = c[i]; return tv;} - -private: - uint size_; - PIVector c; - -}; - -template -inline std::ostream & operator <<(std::ostream & s, const PIMathVector & v) {s << '{'; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << '}'; return s;} -template -inline PICout operator <<(PICout s, const PIMathVector & v) {s << '{'; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << '}'; return s;} - -typedef PIMathVector PIMathVectori; -typedef PIMathVector PIMathVectord; - -/// Matrix - -#define PIMM_FOR(c, r) for (uint c = 0; c < cols_; ++c) { for (uint r = 0; r < rows_; ++r) { -#define PIMM_FOR_WB(c, r) for (uint c = 0; c < cols_; ++c) for (uint r = 0; r < rows_; ++r) // without brakes -#define PIMM_FOR_I(c, r) for (uint r = 0; r < rows_; ++r) { for (uint c = 0; c < cols_; ++c) { -#define PIMM_FOR_I_WB(c, r) for (uint r = 0; r < rows_; ++r) for (uint c = 0; c < cols_; ++c) // without brakes -#define PIMM_FOR_C(v) for (uint v = 0; v < cols_; ++v) -#define PIMM_FOR_R(v) for (uint v = 0; v < rows_; ++v) - -template -class PIP_EXPORT PIMathMatrix { - typedef PIMathMatrix _CMatrix; - typedef PIMathVector _CMCol; - typedef PIMathVector _CMRow; -public: - PIMathMatrix(const uint cols = 3, const uint rows = 3) {resize(cols, rows);} - PIMathMatrix(const uint cols, const uint rows, Type fval, ...) {resize(cols, rows); va_list vl; va_start(vl, fval); PIMM_FOR_I_WB(c, r) m[c][r] = (r + c == 0 ? fval : va_arg(vl, Type)); va_end(vl);} - PIMathMatrix(const uint cols, const uint rows, const PIVector & val) {resize(cols, rows); int i = 0; PIMM_FOR_I_WB(c, r) m[c][r] = val[i++];} - - static _CMatrix identity(const uint cols_, const uint rows_) {_CMatrix tm(cols_, rows_); PIMM_FOR_WB(c, r) tm.m[c][r] = (c == r ? Type(1) : Type(0)); return tm;} - - uint cols() const {return cols_;} - uint rows() const {return rows_;} - _CMCol col(uint index) {_CMCol tv; PIMM_FOR_R(i) tv[i] = m[index][i]; return tv;} - _CMRow row(uint index) {_CMRow tv; PIMM_FOR_C(i) tv[i] = m[i][index]; return tv;} - _CMatrix & resize(const uint cols, const uint rows, const Type & new_value = Type()) {cols_ = cols; rows_ = rows; m.resize(cols); PIMM_FOR_C(i) m[i].resize(rows, new_value); return *this;} - _CMatrix & setCol(uint index, const _CMCol & v) {PIMM_FOR_R(i) m[index][i] = v[i]; return *this;} - _CMatrix & setRow(uint index, const _CMRow & v) {PIMM_FOR_C(i) m[i][index] = v[i]; return *this;} - _CMatrix & swapRows(uint r0, uint r1) {Type t; PIMM_FOR_C(i) {t = m[i][r0]; m[i][r0] = m[i][r1]; m[i][r1] = t;} return *this;} - _CMatrix & swapCols(uint c0, uint c1) {Type t; PIMM_FOR_R(i) {t = m[c0][i]; m[c0][i] = m[c1][i]; m[c1][i] = t;} return *this;} - _CMatrix & fill(const Type & v) {PIMM_FOR_WB(c, r) m[c][r] = v; return *this;} - //inline _CMatrix & set(Type fval, ...) {m[0] = fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) m[i] = va_arg(vl, Type); va_end(vl); return *this;} - //inline void normalize() {Type tv = length(); if (tv == Type(1)) return; PIMV_FOR(i, 0) m[i] /= tv;} - bool isSquare() const {return cols() == rows();} - bool isIdentity() const {PIMM_FOR_WB(c, r) if ((c == r) ? m[c][r] != Type(1) : m[c][r] != Type(0)) return false; return true;} - bool isNull() const {PIMM_FOR_WB(c, r) if (m[c][r] != Type(0)) return false; return true;} - - Type & at(uint col, uint row) {return m[col][row];} - Type at(uint col, uint row) const {return m[col][row];} - PIVector & operator [](uint col) {return m[col];} - PIVector operator [](uint col) const {return m[col];} - void operator =(const _CMatrix & sm) {m = sm.m;} - bool operator ==(const _CMatrix & sm) const {PIMM_FOR_WB(c, r) if (m[c][r] != sm.m[c][r]) return false; return true;} - bool operator !=(const _CMatrix & sm) const {return !(*this == sm);} - void operator +=(const _CMatrix & sm) {PIMM_FOR_WB(c, r) m[c][r] += sm.m[c][r];} - void operator -=(const _CMatrix & sm) {PIMM_FOR_WB(c, r) m[c][r] -= sm.m[c][r];} - void operator *=(const Type & v) {PIMM_FOR_WB(c, r) m[c][r] *= v;} - void operator /=(const Type & v) {PIMM_FOR_WB(c, r) m[c][r] /= v;} - _CMatrix operator -() {_CMatrix tm(*this); PIMM_FOR_WB(c, r) tm.m[c][r] = -m[c][r]; return tm;} - _CMatrix operator +(const _CMatrix & sm) {_CMatrix tm(*this); PIMM_FOR_WB(c, r) tm.m[c][r] += sm.m[c][r]; return tm;} - _CMatrix operator -(const _CMatrix & sm) {_CMatrix tm(*this); PIMM_FOR_WB(c, r) tm.m[c][r] -= sm.m[c][r]; return tm;} - _CMatrix operator *(const Type & v) {_CMatrix tm(*this); PIMM_FOR_WB(c, r) tm.m[c][r] *= v; return tm;} - _CMatrix operator /(const Type & v) {_CMatrix tm(*this); PIMM_FOR_WB(c, r) tm.m[c][r] /= v; return tm;} - - _CMatrix & toUpperTriangular(bool * ok = 0) { - if (cols_ != rows_) { - if (ok != 0) *ok = false; - return *this; - } - _CMatrix smat(*this); - bool ndet; - uint crow; - Type mul; - for (uint i = 0; i < cols_; ++i) { - ndet = true; - for (uint j = 0; j < rows_; ++j) if (smat.m[i][j] != 0) ndet = false; - if (ndet) { - if (ok != 0) *ok = false; - return *this; - } - for (uint j = 0; j < cols_; ++j) if (smat.m[j][i] != 0) ndet = false; - if (ndet) { - if (ok != 0) *ok = false; - return *this; - } - } - for (uint i = 0; i < cols_; ++i) { - crow = i; - while (smat.m[i][i] == Type(0)) - smat.swapRows(i, ++crow); - for (uint j = i + 1; j < rows_; ++j) { - mul = smat.m[i][j] / smat.m[i][i]; - for (uint k = i; k < cols_; ++k) smat.m[k][j] -= mul * smat.m[k][i]; - } - if (i < cols_ - 1) { - if (fabs(smat.m[i+1][i+1]) < Type(1E-100)) { - if (ok != 0) *ok = false; - return *this; - } - } - } - if (ok != 0) *ok = true; - m = smat.m; - return *this; - } - - _CMatrix & invert(bool * ok = 0, _CMCol * sv = 0) { - if (cols_ != rows_) { - if (ok != 0) *ok = false; - return *this; - } - _CMatrix mtmp = _CMatrix::identity(cols_, rows_), smat(*this); - bool ndet; - uint crow; - Type mul, iddiv; - for (uint i = 0; i < cols_; ++i) { - ndet = true; - for (uint j = 0; j < rows_; ++j) if (smat.m[i][j] != 0) ndet = false; - if (ndet) { - if (ok != 0) *ok = false; - return *this; - } - for (uint j = 0; j < cols_; ++j) if (smat.m[j][i] != 0) ndet = false; - if (ndet) { - if (ok != 0) *ok = false; - return *this; - } - } - for (uint i = 0; i < cols_; ++i) { - crow = i; - while (smat.m[i][i] == Type(0)) { - ++crow; - smat.swapRows(i, crow); - mtmp.swapRows(i, crow); - if (sv != 0) sv->swap(i, crow); - } - for (uint j = i + 1; j < rows_; ++j) { - mul = smat.m[i][j] / smat.m[i][i]; - for (uint k = i; k < cols_; ++k) smat.m[k][j] -= mul * smat.m[k][i]; - for (uint k = 0; k < cols_; ++k) mtmp.m[k][j] -= mul * mtmp.m[k][i]; - if (sv != 0) (*sv)[j] -= mul * (*sv)[i]; - } - //cout << i << endl << smat << endl; - if (i < cols_ - 1) { - if (fabs(smat.m[i+1][i+1]) < Type(1E-100)) { - if (ok != 0) *ok = false; - return *this; - } - } - iddiv = smat.m[i][i]; - for (uint j = i; j < cols_; ++j) smat.m[j][i] /= iddiv; - for (uint j = 0; j < cols_; ++j) mtmp.m[j][i] /= iddiv; - if (sv != 0) (*sv)[i] /= iddiv; - } - for (uint i = cols_ - 1; i > 0; --i) { - for (uint j = 0; j < i; ++j) { - mul = smat.m[i][j]; - smat.m[i][j] -= mul; - for (uint k = 0; k < cols_; ++k) mtmp.m[k][j] -= mtmp.m[k][i] * mul; - if (sv != 0) (*sv)[j] -= mul * (*sv)[i]; - } - } - if (ok != 0) *ok = true; - m = mtmp.m; - return *this; - } - _CMatrix inverted(bool * ok = 0) {_CMatrix tm(*this); tm.invert(ok); return tm;} - _CMatrix transposed() {_CMatrix tm(rows_, cols_); PIMM_FOR_WB(c, r) tm[r][c] = m[c][r]; return tm;} - -private: - uint cols_, rows_; - PIVector > m; - -}; - -template -inline std::ostream & operator <<(std::ostream & s, const PIMathMatrix & m) {s << '{'; for (uint r = 0; r < m.rows(); ++r) { for (uint c = 0; c < m.cols(); ++c) { s << m[c][r]; if (c < m.cols() - 1 || r < m.rows() - 1) s << ", ";} if (r < m.rows() - 1) s << endl << ' ';} s << '}'; return s;} -template -inline PICout operator <<(PICout s, const PIMathMatrix & m) {s << '{'; for (uint r = 0; r < m.rows(); ++r) { for (uint c = 0; c < m.cols(); ++c) { s << m[c][r]; if (c < m.cols() - 1 || r < m.rows() - 1) s << ", ";} if (r < m.rows() - 1) s << NewLine << ' ';} s << '}'; return s;} - -/// Multiply matrices {CR x Rows0} on {Cols1 x CR}, result is {Cols1 x Rows0} -template -inline PIMathMatrix operator *(const PIMathMatrix & fm, - const PIMathMatrix & sm) { - uint cr = fm.cols(), rows0 = fm.rows(), cols1 = sm.cols(); - PIMathMatrix tm(cols1, rows0); - if (fm.cols() != sm.rows()) return tm; - Type t; - for (uint j = 0; j < rows0; ++j) { - for (uint i = 0; i < cols1; ++i) { - t = Type(0); - for (uint k = 0; k < cr; ++k) - t += fm[k][j] * sm[i][k]; - tm[i][j] = t; - } - } - return tm; -} - -/// Multiply matrix {Cols x Rows} on vector {Cols}, result is vector {Rows} -template -inline PIMathVector operator *(const PIMathMatrix & fm, - const PIMathVector & sv) { - uint c = fm.cols(), r = fm.rows(); - PIMathVector tv(r); - if (c != sv.size()) return tv; - Type t; - for (uint i = 0; i < r; ++i) { - t = Type(0); - for (uint j = 0; j < c; ++j) - t += fm[j][i] * sv[j]; - tv[i] = t; - } - return tv; -} - -typedef PIMathMatrix PIMathMatrixi; -typedef PIMathMatrix PIMathMatrixd; - -#undef PIMV_FOR -#undef PIMM_FOR -#undef PIMM_FOR_WB -#undef PIMM_FOR_I -#undef PIMM_FOR_I_WB -#undef PIMM_FOR_C -#undef PIMM_FOR_R - - -/// Differential evaluations - -struct TransferFunction { // Для задания передаточной функции - PIVector vector_Bm, vector_An; -}; - -// Класс, служащий для перевода передаточной функции в систему ОДУ первого порядка -// реализованы след. методы решения дифф. ур-ний: -// Эйлера -// Рунге-Кутта 4-го порядка -// Адамса-Бэшфортса-Моултона 2, 3, 4 порядков -class PIP_EXPORT Solver -{ -public: - enum Method {Global = -1, - Eyler_1 = 01, - Eyler_2 = 02, - EylerKoshi = 03, - RungeKutta_4 = 14, - AdamsBashfortMoulton_2 = 22, - AdamsBashfortMoulton_3 = 23, - AdamsBashfortMoulton_4 = 24, - PolynomialApproximation_2 = 32, - PolynomialApproximation_3 = 33, - PolynomialApproximation_4 = 34, - PolynomialApproximation_5 = 35 - }; - - Solver() {times.resize(4); step = 0;} - - void solve(double u, double h); - void fromTF(const TransferFunction & TF); - void setMethod(Method m) {method = m;} - void setTime(double time) {times.pop_back(); times.push_front(time);} - - void solveEyler1(double u, double h); - void solveEyler2(double u, double h); - void solveRK4(double u, double h); - void solveABM2(double u, double h); - void solveABM3(double u, double h); - void solveABM4(double u, double h); - void solvePA(double u, double h, uint deg); - void solvePA2(double u, double h) {if (step > 0) solvePA(u, h, 2); else solveEyler1(u, h);} - void solvePA3(double u, double h) {if (step > 1) solvePA(u, h, 3); else solvePA2(u, h);} - void solvePA4(double u, double h) {if (step > 2) solvePA(u, h, 4); else solvePA3(u, h);} - void solvePA5(double u, double h) {if (step > 3) solvePA(u, h, 5); else solvePA4(u, h);} - - PIMathVectord X; - static Method method_global; - static const char methods_desc[]; - -private: - void moveF() {for (uint i = F.size() - 1; i > 0; --i) F[i] = F[i - 1];} - - PIMathMatrixd A, M; - PIMathVectord d, a1, b1; - PIMathVectord k1, k2, k3, k4, xx; - PIMathVectord XX, Y, pY; - PIVector F; - PIVector times; - uint size, step; - Method method; - double sum, td, ct, lp, dh, t, x1, x0; - bool ok; - -}; - - - -class PIP_EXPORT PIFFT -{ -public: - PIFFT(); - // const PIVector & getIndexes() {return indexes;} - // const PIVector & getCoefs() {return coefs;} - PIVector * calcFFT(const PIVector &val); - PIVector * calcFFT(const PIVector &val); - PIVector * calcFFTinverse(const PIVector &val); - PIVector * calcHilbert(const PIVector &val); - PIVector getAmplitude(); -private: - // PIVector indexes; - // PIVector coefs; - PIVector result; - // uint iterations; - bool prepared; - // uint out_size; - typedef ptrdiff_t ae_int_t; - void calc_coefs(uint cnt2); - void calc_indexes(uint cnt2, uint deep2); - complexd coef(uint n, uint k); - - struct ftplan { - PIVector plan; - PIVector precomputed; - PIVector tmpbuf; - PIVector stackbuf; - }; - - ftplan curplan; - - void fftc1d(const PIVector &a, uint n); - void fftc1r(const PIVector &a, uint n); - void fftc1dinv(const PIVector &a, uint n); - - void createPlan(uint n); - void ftbasegeneratecomplexfftplan(uint n, ftplan *plan); - void ftbase_ftbasegenerateplanrec(int n, int tasktype, ftplan *plan, int *plansize, int *precomputedsize, int *planarraysize, int *tmpmemsize, int *stackmemsize, ae_int_t stackptr, int debugi=0); - void ftbase_ftbaseprecomputeplanrec(ftplan *plan, int entryoffset, ae_int_t stackptr); - void ftbasefactorize(int n, int *n1, int *n2); - void ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int *best); - int ftbasefindsmooth(int n); - void ftbaseexecuteplan(PIVector *a, int aoffset, int n, ftplan *plan); - void ftbaseexecuteplanrec(PIVector *a, int aoffset, ftplan *plan, int entryoffset, ae_int_t stackptr); - void ftbase_internalcomplexlintranspose(PIVector *a, int m, int n, int astart, PIVector *buf); - void ftbase_ffticltrec(PIVector *a, int astart, int astride, PIVector *b, int bstart, int bstride, int m, int n); - void ftbase_internalreallintranspose(PIVector *a, int m, int n, int astart, PIVector *buf); - void ftbase_fftirltrec(PIVector *a, int astart, int astride, PIVector *b, int bstart, int bstride, int m, int n); - void ftbase_ffttwcalc(PIVector *a, int aoffset, int n1, int n2); -}; - - -template -class PIP_EXPORT PIStatistic { -public: - PIStatistic() {mean = variance = skewness = kurtosis = T();} - - static T calculateMean(const PIVector & val) { - T ret = T(); - int n = val.size(); - if (n < 1) - return ret; - for (int i = 0; i < n; i++) - ret += val[i]; - return ret / n; - } - bool calculate(const PIVector & val, const T & given_mean) { - T v = T(), v1 = T(), v2 = T(), stddev = T(), var = T(); - int i, n = val.size(); - if (n < 2) - return false; - mean = given_mean; - variance = skewness = kurtosis = T(); - /* - * Variance (using corrected two-pass algorithm) - */ - for (i = 0; i < n; i++) - v1 += sqr(val[i] - mean); - for (i = 0; i < n; i++) - v2 += val[i] - mean; - v2 = sqr(v2) / n; - variance = v1 / n; - var = (v1 / n - v2) / (n - 1); - if (var < T()) - var = T(); - stddev = sqrt(var); - /* - * Skewness and kurtosis - */ - if (stddev != T()) { - for (i = 0; i < n; i++) { - v = (val[i] - mean) / stddev; - v2 = sqr(v); - skewness = skewness + v2 * v; - kurtosis = kurtosis + sqr(v2); - } - skewness /= n; - kurtosis = kurtosis / n - 3.; - } - return true; - } - bool calculate(const PIVector & val) {return calculate(val, calculateMean(val));} - - T mean; - T variance; - T skewness; - T kurtosis; -}; - -typedef PIStatistic PIStatistici; -typedef PIStatistic PIStatisticf; -typedef PIStatistic PIStatisticd; - - -template -bool OLS_Linear(const PIVector > & input, T * out_a, T * out_b) { - if (input.size_s() < 2) - return false; - int n = input.size_s(); - T a_t0 = T(), a_t1 = T(), a_t2 = T(), a_t3 = T(), a_t4 = T(), a = T(), b = T(); - for (int i = 0; i < n; ++i) { - const PIPair & cv(input[i]); - a_t0 += cv.first * cv.second; - a_t1 += cv.first; - a_t2 += cv.second; - a_t3 += cv.first * cv.first; - } - a_t4 = n * a_t3 - a_t1 * a_t1; - if (a_t4 != T()) - a = (n * a_t0 - a_t1 * a_t2) / a_t4; - b = (a_t2 - a * a_t1) / n; - if (out_a != 0) *out_a = a; - if (out_b != 0) *out_b = b; - return true; -} - - -template -bool WLS_Linear(const PIVector > & input, const PIVector & weights, T * out_a, T * out_b) { - if (input.size_s() < 2) - return false; - if (input.size_s() != weights.size_s()) - return false; - int n = input.size_s(); - T a_t0 = T(), a_t1 = T(), a_t2 = T(), a_t3 = T(), a_t4 = T(), a_n = T(), a = T(), b = T(); - for (int i = 0; i < n; ++i) { - T cp = weights[i]; - const PIPair & cv(input[i]); - a_t0 += cv.first * cv.second * cp; - a_t1 += cv.first * cp; - a_t2 += cv.second * cp; - a_t3 += cv.first * cv.first * cp; - a_n += cp; - } - a_t4 = a_n * a_t3 - a_t1 * a_t1; - if (a_t4 != T()) - a = (a_n * a_t0 - a_t1 * a_t2) / a_t4; - b = (a_t2 - a * a_t1) / a_n; - if (out_a != 0) *out_a = a; - if (out_b != 0) *out_b = b; - return true; -} - -#endif // PIMATH_H diff --git a/pimonitor.cpp b/pimonitor.cpp deleted file mode 100644 index 73ea3f1a..00000000 --- a/pimonitor.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - PIP - Platform Independent Primitives - Counter of some PIP types - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pimonitor.h" - -PIMonitor piMonitor; - -PIMonitor::PIMonitor() { - containers = strings = threads = timers = serials = ethernets = files = objects = 0; -} diff --git a/pimonitor.h b/pimonitor.h deleted file mode 100644 index 288e9634..00000000 --- a/pimonitor.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - PIP - Platform Independent Primitives - Counter of some PIP types - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIMONITOR_H -#define PIMONITOR_H - -#include "pip_export.h" - -#if defined(DOXYGEN) || defined(__GNUC__) -# undef PIP_EXPORT -# define PIP_EXPORT -#endif - -class PIP_EXPORT PIMonitor -{ -public: - PIMonitor(); - - int containers, strings, threads, timers, serials, ethernets, files, objects; - -}; - -#endif // PIMONITOR_H diff --git a/pimultiprotocol.cpp b/pimultiprotocol.cpp deleted file mode 100644 index 422263cf..00000000 --- a/pimultiprotocol.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - PIP - Platform Independent Primitives - Multiprotocol - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pimultiprotocol.h" - diff --git a/pimultiprotocol.h b/pimultiprotocol.h deleted file mode 100644 index d7bc65d8..00000000 --- a/pimultiprotocol.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - PIP - Platform Independent Primitives - Multiprotocol - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIMULTIPROTOCOL_H -#define PIMULTIPROTOCOL_H - -#include "piprotocol.h" - -class PIMultiProtocol: public PIMultiProtocolBase -{ -public: - PIMultiProtocol() {;} - virtual ~PIMultiProtocol() {clear();} - - void addProtocol(PIProtocol & prot) {prots.push_back(&prot); prot.setMultiProtocolOwner(this); prot.new_mp_prot = false;} - void addProtocol(PIProtocol * prot) {prots.push_back(prot); prot->setMultiProtocolOwner(this); prot->new_mp_prot = false;} - void addProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0, - void * recDataPtr = 0, int recDataSize = 0, void * sendDataPtr = 0, int sendDataSize = 0) {; - prots.push_back(new PIProtocol(config, name, recHeaderPtr, recHeaderSize, recDataPtr, recDataSize, sendDataPtr, sendDataSize)); - prots.back()->setMultiProtocolOwner(this); - prots.back()->new_mp_prot = true; - } - PIProtocol * protocol(const PIString & name) {piForeach (PIProtocol * i, prots) if (i->name() == name) return i; return 0;} - PIProtocol * protocol(const int index) {return prots[index];} - PIProtocol * operator [](const int index) {return prots[index];} - - void startSend() {piForeach (PIProtocol * i, prots) i->startSend();} - void startReceive() {piForeach (PIProtocol * i, prots) i->startReceive();} - void start() {piForeach (PIProtocol * i, prots) i->start();} - - void stopSend() {piForeach (PIProtocol * i, prots) i->stopSend();} - void stopReceive() {piForeach (PIProtocol * i, prots) i->stopReceive();} - void stop() {piForeach (PIProtocol * i, prots) i->stop();} - - PIProtocol::Quality worseQuality() const {PIProtocol::Quality cq = PIProtocol::Good; piForeachC (PIProtocol * i, prots) if (cq > i->quality()) cq = i->quality(); return cq;} - PIProtocol::Quality bestQuality() const {PIProtocol::Quality cq = PIProtocol::Unknown; piForeachC (PIProtocol * i, prots) if (cq < i->quality()) cq = i->quality(); return cq;} - - int count() const {return prots.size_s();} - void clear() {stop(); piForeach (PIProtocol * i, prots) if (i->new_mp_prot) delete i; prots.clear();} - -private: - PIVector prots; - -}; - -class PIRepeater: public PIMultiProtocol { -public: - PIRepeater(const PIString & config, const PIString & name_) { - PIConfig conf(config, PIIODevice::ReadOnly); - if (!conf.isOpened()) { - piCoutObj << "[PIRepeater \"" << name_ << "\"] Can`t open \"" << config << "\"!"; - return; - } - PIConfig::Entry & b(conf.getValue(name_)); - if (b.childCount() != 2) { - piCoutObj << "[PIRepeater \"" << name_ << "\"] \"" << config << "\" should consist 2 nodes!"; - return; - } - addProtocol(config, b.child(0)->fullName()); - addProtocol(config, b.child(1)->fullName()); - start(); - } - - PIString firstChannelName() {if (count() == 2) return protocol(0)->receiverDeviceName() + " -> " + protocol(1)->senderDeviceName(); return "Config error";} - PIString secondChannelName() {if (count() == 2) return protocol(1)->receiverDeviceName() + " -> " + protocol(0)->senderDeviceName(); return "Config error";} - - ullong receiveCount() {if (count() == 2) return protocol(0)->receiveCount(); return 0;} - const ullong * receiveCount_ptr() {if (count() == 2) return protocol(0)->receiveCount_ptr(); return 0;} - ullong sendCount() {if (count() == 2) return protocol(0)->sendCount(); return 0;} - const ullong * sendCount_ptr() {if (count() == 2) return protocol(0)->sendCount_ptr(); return 0;} - -private: - void received(PIProtocol * prot, bool , uchar * data, int size) {if (prot == protocol(0)) protocol(1)->send(data, size); else protocol(0)->send(data, size);} - -}; - -#endif // PIMULTIPROTOCOL_H diff --git a/pimutex.cpp b/pimutex.cpp deleted file mode 100644 index 37f19baf..00000000 --- a/pimutex.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - PIP - Platform Independent Primitives - Mutex - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pimutex.h" - - -/** \class PIMutex - * \brief Mutex - * \details - * \section PIMutex_sec0 Synopsis - * %PIMutex provides synchronization blocks between several threads. - * Using mutex guarantees execution of some code only one of threads. - * Mutex contains logic state and functions to change it: \a lock(), - * \a unlock() and \a tryLock(). - * - * \section PIMutex_sec1 Usage - * Block of code that should to be executed only one thread simultaniously - * should to be started with \a lock() and ended with \a unlock(). - * \snippet pimutex.cpp main - * "mutex" in this example is one for all threads. - * - * */ - - -PIMutex::PIMutex() { -#ifdef WINDOWS - mutex = CreateMutex(0, false, 0); -#else - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutex_init(&mutex, &attr); - pthread_mutexattr_destroy(&attr); -#endif -} - - -PIMutex::~PIMutex() { -#ifdef WINDOWS - if (mutex != 0) CloseHandle(mutex); -#else - pthread_mutex_destroy(&mutex); -#endif -} diff --git a/pimutex.h b/pimutex.h deleted file mode 100644 index e8f82eb5..00000000 --- a/pimutex.h +++ /dev/null @@ -1,93 +0,0 @@ -/*! \file pimutex.h - * \brief Mutex -*/ -/* - PIP - Platform Independent Primitives - Mutex - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIMUTEX_H -#define PIMUTEX_H - -#include "piincludes.h" - -class PIP_EXPORT PIMutex -{ -public: - - //! Constructs unlocked mutex - PIMutex(); - - ~PIMutex(); - - - //! \brief Lock mutex - //! \details If mutex is unlocked it set to locked state and returns immediate. - //! If mutex is already locked function blocks until mutex will be unlocked - void lock() { -#ifdef WINDOWS - WaitForSingleObject(mutex, INFINITE); -#else - pthread_mutex_lock(&mutex); -#endif - } - - - //! \brief Unlock mutex - //! \details In any case this function returns immediate - void unlock() { -#ifdef WINDOWS - ReleaseMutex(mutex); -#else - pthread_mutex_unlock(&mutex); -#endif - } - - - //! \brief Try to lock mutex - //! \details If mutex is unlocked it set to locked state and returns "true" immediate. - //! If mutex is already locked function returns immediate an returns "false" - bool tryLock() { -#ifdef WINDOWS - return (WaitForSingleObject(mutex, 0) == WAIT_OBJECT_0); -#else - return (pthread_mutex_trylock(&mutex) == 0); -#endif - } - -private: -#ifdef WINDOWS - void * -#else - pthread_mutex_t -#endif - mutex; - -}; - - -class PIP_EXPORT PIMutexLocker -{ -public: - PIMutexLocker(PIMutex * m): mutex(m) {mutex->lock();} - PIMutexLocker(PIMutex & m): mutex(&m) {mutex->lock();} - ~PIMutexLocker() {mutex->unlock();} -private: - PIMutex * mutex; -}; - -#endif // PIMUTEX_H diff --git a/piobject.cpp b/piobject.cpp deleted file mode 100644 index 46d74ed5..00000000 --- a/piobject.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - PIP - Platform Independent Primitives - Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "piobject.h" - -PIVector PIObject::objects; - - -/** \class PIObject - * \brief This is base class for any classes which use events -> handlers mechanism. - * \details - * \section PIObject_sec0 Events and Event handlers - * %PIObject provide notification mechanism similar Qt but implemented - * on language capabilities without any special preprocessors or compilers. - * Any class inherits PIObject should use macro \a PIOBJECT() immediate - * after declaration to proper compile. - * - * Event is a some abstract event that can be raised at any time. - * Event is a function but declared with special macro \a EVENT(). - * To raise event simply execute event function. - * - * Event handler is a function but declared with special macro - * \a EVENT_HANDLER(). You can use event handlers as ordinary functions. - * - * Main goal of this mechanism is perform abstract connections between - * various objects. This functionality provide macro \a CONNECT() which - * connect some event of first object to some event handler or event of - * second object. Each event can be connected any times to any event handlers. - * - * \image html events_handlers.png - * - * Example: \snippet piobject.cpp main - * Result: -\code{.cpp} -handler B: 2 , 0.5 -handler A: event to handler -handler A: event to event -\endcode - */ - - -PIObject::PIObject(const PIString & name): emitter_(0) { - piMonitor.objects++; - setName(name); - setDebug(true); - objects << this; -} - - -void PIObject::piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h) { - PIObject * o = findByName(src); - if (o == 0) { - piCout << "[PIObject] Can`t find object with name \"" << src << "\"!"; - return; - } - o->connections << Connection(ev_h, 0, sig, dest); -} - - -void PIObject::piConnect(PIObject * src, const PIString & sig, const PIString & dest, void * ev_h) { - PIObject * o = findByName(dest); - if (o == 0) { - piCout << "[PIObject] Can`t find object with name \"" << dest << "\"!"; - return; - } - src->connections << Connection(ev_h, 0, sig, o); -} - - -void PIObject::piConnect(const PIString & src, const PIString & sig, const PIString & dest, void * ev_h) { - PIObject * s = findByName(src); - if (s == 0) { - piCout << "[PIObject] Can`t find object with name \"" << src << "\"!"; - return; - } - PIObject * d = findByName(dest); - if (d == 0) { - piCout << "[PIObject] Can`t find object with name \"" << dest << "\"!"; - return; - } - s->connections << Connection(ev_h, 0, sig, d); -} - -/* -PIStringList PIObject::events() { - PIStringList l; - for (PIMap::const_iterator i = signals_.begin(); i != signals_.end(); i++) - l << (*i).first; - return l; -} - - -PIStringList PIObject::eventHandlers() { - PIStringList l; - for (PIMap::const_iterator i = slots_.begin(); i != slots_.end(); i++) - l << (*i).first; - return l; -} -*/ diff --git a/piobject.h b/piobject.h deleted file mode 100644 index aff78ff1..00000000 --- a/piobject.h +++ /dev/null @@ -1,535 +0,0 @@ -/*! \file piobject.h - * \brief Base object - * - * This file declare PIObject class and associated macros -*/ -/* - PIP - Platform Independent Primitives - Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIOBJECT_H -#define PIOBJECT_H - -#include "pivariant.h" -#include "pimutex.h" - - -#ifdef DOXYGEN - - -/// \relatesalso PIObject \brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER and correct piCoutObj output -#define PIOBJECT(name) - - -/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name() -#define EVENT_HANDLER0(ret, name) ret name() - -/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0) -#define EVENT_HANDLER1(ret, name, type0, var0) ret name(type0 var0) - -/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1) -#define EVENT_HANDLER2(ret, name, type0, var0, type1, var1) ret name(type0 var0, type1 var1) - -/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2) -#define EVENT_HANDLER3(ret, name, type0, var0, type1, var1, type2, var2) ret name(type0 var0, type1 var1, type2 var2) - -/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2, type3 var3) -#define EVENT_HANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) ret name(type0 var0, type1 var1, type2 var2, type3 var3) - -/// \relatesalso PIObject \brief EVENT_HANDLER is synonym of EVENT_HANDLER0 -#define EVENT_HANDLER EVENT_HANDLER0 - - -/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name() -#define EVENT_VHANDLER0(ret, name) virtual ret name() - -/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0) -#define EVENT_VHANDLER1(ret, name, type0, var0) virtual ret name(type0 var0) - -/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1) -#define EVENT_VHANDLER2(ret, name, type0, var0, type1, var1) virtual ret name(type0 var0, type1 var1) - -/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2) -#define EVENT_VHANDLER3(ret, name, type0, var0, type1, var1, type2, var2) virtual ret name(type0 var0, type1 var1, type2 var2) - -/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3) -#define EVENT_VHANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3) - -/// \relatesalso PIObject \brief EVENT_VHANDLER is synonym of EVENT_VHANDLER0 -#define EVENT_VHANDLER EVENT_VHANDLER0 - - -/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(); -#define EVENT0(name) void name(); - -/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0); -#define EVENT1(name, type0, var0) void name(type0 var0); - -/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1); -#define EVENT2(name, type0, var0, type1, var1) void name(type0 var0, type1 var1); - -/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2); -#define EVENT3(name, type0, var0, type1, var1, type2, var2) void name(type0 var0, type1 var1, type2 var2); - -/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3); -#define EVENT4(name, type0, var0, type1, var1, type2, var2, type3, var3) void name(type0 var0, type1 var1, type2 var2, type3 var3); - -/// \relatesalso PIObject \brief EVENT is synonym of EVENT0 -#define EVENT EVENT0 - - -#define RAISE_EVENT0(src, event) -#define RAISE_EVENT1(src, event, v0) -#define RAISE_EVENT2(src, event, v0, v1) -#define RAISE_EVENT3(src, event, v0, v1, v2) -#define RAISE_EVENT4(src, event, v0, v1, v2, v3) -#define RAISE_EVENT RAISE_EVENT0 - - -/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists -#define CONNECT0(ret, src, event, dest, handler) - -/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists -#define CONNECT1(ret, type0, src, event, dest, handler) - -/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists -#define CONNECT2(ret, type0, type1, src, event, dest, handler) - -/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists -#define CONNECT3(ret, type0, type1, type2, src, event, dest, handler) - -/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists -#define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler) - -/// \relatesalso PIObject \brief CONNECT is synonym of CONNECT0 -#define CONNECT CONNECT0 - - -/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists -#define WEAK_CONNECT0(ret, src, event, dest, handler) - -/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists -#define WEAK_CONNECT1(ret, type0, src, event, dest, handler) - -/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists -#define WEAK_CONNECT2(ret, type0, type1, src, event, dest, handler) - -/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists -#define WEAK_CONNECT3(ret, type0, type1, type2, src, event, dest, handler) - -/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists -#define WEAK_CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler) - -/// \relatesalso PIObject \brief WEAK_CONNECT is synonym of WEAK_CONNECT0 -#define WEAK_CONNECT WEAK_CONNECT0 - - -/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\" -#define DISCONNECT0(ret, src, event, dest, handler) - -/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\" -#define DISCONNECT1(ret, type0, src, event, dest, handler) - -/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\" -#define DISCONNECT2(ret, type0, type1, src, event, dest, handler) - -/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\" -#define DISCONNECT3(ret, type0, type1, type2, src, event, dest, handler) - -/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\" -#define DISCONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler) - -/// \relatesalso PIObject \brief DISCONNECT is synonym of DISCONNECT0 -#define DISCONNECT DISCONNECT0 - - -/// \relatesalso PIObject \brief Returns pointer to events handler \"handler\" -#define HANDLER(handler) - - -#else - - -#define PIOBJECT(obj) typedef obj __PIObject__; public: virtual const char * className() const {return #obj;} private: - -#define EVENT_HANDLER0(ret, name) static ret __stat_eh_##name##__(void * o) {return ((__PIObject__*)o)->name();} ret name() -#define EVENT_HANDLER1(ret, name, a0, n0) static ret __stat_eh_##name##__(void * o, a0 n0) {return ((__PIObject__*)o)->name(n0);} ret name(a0 n0) -#define EVENT_HANDLER2(ret, name, a0, n0, a1, n1) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1) {return ((__PIObject__*)o)->name(n0, n1);} ret name(a0 n0, a1 n1) -#define EVENT_HANDLER3(ret, name, a0, n0, a1, n1, a2, n2) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)o)->name(n0, n1, n2);} ret name(a0 n0, a1 n1, a2 n2) -#define EVENT_HANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)o)->name(n0, n1, n2, n3);} ret name(a0 n0, a1 n1, a2 n2, a3 n3) -#define EVENT_HANDLER EVENT_HANDLER0 - -#define EVENT_VHANDLER0(ret, name) static ret __stat_eh_##name##__(void * o) {return ((__PIObject__*)o)->name();} virtual ret name() -#define EVENT_VHANDLER1(ret, name, a0, n0) static ret __stat_eh_##name##__(void * o, a0 n0) {return ((__PIObject__*)o)->name(n0);} virtual ret name(a0 n0) -#define EVENT_VHANDLER2(ret, name, a0, n0, a1, n1) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1) {return ((__PIObject__*)o)->name(n0, n1);} virtual ret name(a0 n0, a1 n1) -#define EVENT_VHANDLER3(ret, name, a0, n0, a1, n1, a2, n2) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)o)->name(n0, n1, n2);} virtual ret name(a0 n0, a1 n1, a2 n2) -#define EVENT_VHANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)o)->name(n0, n1, n2, n3);} virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3) -#define EVENT_VHANDLER EVENT_VHANDLER0 - -#define EVENT0(name) EVENT_HANDLER0(void, name) {PIObject::raiseEvent(this, #name);} -#define EVENT1(name, a0, n0) EVENT_HANDLER1(void, name, a0, n0) {PIObject::raiseEvent(this, #name, n0);} -#define EVENT2(name, a0, n0, a1, n1) EVENT_HANDLER2(void, name, a0, n0, a1, n1) {PIObject::raiseEvent(this, #name, n0, n1);} -#define EVENT3(name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) {PIObject::raiseEvent(this, #name, n0, n1, n2);} -#define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) {PIObject::raiseEvent(this, #name, n0, n1, n2, n3);} -#define EVENT EVENT0 - -#define RAISE_EVENT0(src, event) (src)->event(); -#define RAISE_EVENT1(src, event, v0) (src)->event(v0); -#define RAISE_EVENT2(src, event, v0, v1) (src)->event(v0, v1); -#define RAISE_EVENT3(src, event, v0, v1, v2) (src)->event(v0, v1, v2); -#define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3); -#define RAISE_EVENT RAISE_EVENT0 - -#define CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__)); -#define CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__)); -#define CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__)); -#define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__)); -#define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__)); -#define CONNECT CONNECT0 - -#define WEAK_CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__)); -#define WEAK_CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__)); -#define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__)); -#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__)); -#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__)); -#define WEAK_CONNECT WEAK_CONNECT0 - -#define DISCONNECT0(ret, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__)); -#define DISCONNECT1(ret, a0, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__)); -#define DISCONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__)); -#define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__)); -#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__)); -#define DISCONNECT DISCONNECT0 - -#define HANDLER(handler) __stat_eh_##handler##__ - -#endif - -typedef void (*Handler)(void * ); - -class PIP_EXPORT PIObject -{ - friend class PIObjectManager; -public: - - //! Contructs PIObject with name "name" - PIObject(const PIString & name = PIString()); - - virtual ~PIObject() {piMonitor.objects--; objects.removeAll(this);} - - - //! Returns object name - PIString name() const {return property("name").toString();} - - //! Returns object class name - virtual const char * className() const {return "PIObject";} - - //! Return if debug of this object is active - bool debug() const {return property("debug").toBool();} - - - //! Set object name - void setName(const PIString & name) {setProperty("name", name);} - - //! Set object debug active - void setDebug(bool debug) {setProperty("debug", debug);} - - //! Returns properties of the object - const PIMap & properties() const {return properties_;} - - //! Returns properties count of the object - int propertiesCount() const {return properties_.size_s();} - - //! Returns property with name "name" - PIVariant property(const PIString & name) const {if (!properties_.contains(name)) return PIVariant(); return properties_.value(name);} - - //! Set property with name "name" to "value". If there is no such property in object it will be added - void setProperty(const PIString & name, const PIVariant & value) {properties_[name] = value; propertyChanged(name);} - - //! Returns if property with name "name" exists - bool isPropertyExists(const PIString & name) const {return properties_.contains(name);} - - /* - PIStringList events(); - PIStringList eventHandlers(); - - /// Events - void addEvent(const PIString & name) { - signals_.insert(NamedFunction(0, name, PIStringList()), name); - } - template - void addEvent(const PIString & name) { - signals_.insert(NamedFunction(0, name, PIStringList(typeid(T0).name())), name); - } - template - void addEvent(const PIString & name) { - signals_.insert(NamedFunction(0, name, PIStringList(typeid(T0).name(), typeid(T1).name())), name); - } - template - void addEvent(const PIString & name) { - signals_.insert(NamedFunction(0, name, PIStringList(typeid(T0).name(), typeid(T1).name(), typeid(T2).name())), name); - } - template - void addEvent(const PIString & name) { - signals_.insert(NamedFunction(0, name, PIStringList(typeid(T0).name(), typeid(T1).name(), typeid(T2).name(), typeid(T3).name())), name); - } - - /// Event handlers - void addEventHandler(const PIString & name, void * func) { - slots_.insert(NamedFunction(func, name, PIStringList()), name); - } - template - void addEventHandler(const PIString & name, void * func) { - slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name())), name); - } - template - void addEventHandler(const PIString & name, void * func) { - slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name(), typeid(T1).name())), name); - } - template - void addEventHandler(const PIString & name, void * func) { - slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name(), typeid(T1).name(), typeid(T2).name())), name); - } - template - void addEventHandler(const PIString & name, void * func) { - slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name(), typeid(T1).name(), typeid(T2).name(), typeid(T3).name())), name); - } - */ - // / Direct connect - static void piConnect(PIObject * src, const PIString & sig, void * dest, void * ev_h) {src->connections << Connection(ev_h, 0, sig, dest);} - static void piConnect(PIObject * src, const PIString & sig, void * dest, void * ev_h, void * e_h) {src->connections << Connection(ev_h, e_h, sig, dest);} - - static void piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h); - static void piConnect(PIObject * src, const PIString & sig, const PIString & dest, void * ev_h); - static void piConnect(const PIString & src, const PIString & sig, const PIString & dest, void * ev_h); - - static void piDisconnect(PIObject * src, const PIString & sig, void * dest, void * ev_h) { - for (int i = 0; i < src->connections.size_s(); ++i) { - Connection & cc(src->connections[i]); - if (cc.event == sig && cc.dest == dest && cc.slot == ev_h) { - src->connections.remove(i); - i--; - } - } - } - static void piDisconnect(PIObject * src, const PIString & sig, void * dest) { - for (int i = 0; i < src->connections.size_s(); ++i) { - Connection & cc(src->connections[i]); - if (cc.event == sig && cc.dest == dest) { - src->connections.remove(i); - i--; - } - } - } - - //! Disconnect object "src" from all connections with event name "sig" - static void piDisconnect(PIObject * src, const PIString & sig) { - for (int i = 0; i < src->connections.size_s(); ++i) { - Connection & cc(src->connections[i]); - if (cc.event == sig) { - src->connections.remove(i); - i--; - } - } - } - - //! Disconnect object "src" from all connections, i.e. all connections where object "src" is emitter - static void piDisconnect(PIObject * src) {src->connections.clear();} - //static void piConnect(PIObject & src, const PIString & sig, PIObject * dest, void * ev_h) {src.connections << Connection(ev_h, sig, dest);} - //static void piConnect(PIObject * src, const PIString & sig, PIObject & dest, void * ev_h) {src->connections << Connection(ev_h, sig, &dest);} - //static void piConnect(PIObject & src, const PIString & sig, PIObject & dest, void * ev_h) {src.connections << Connection(ev_h, sig, &dest);} - - /*/// Connect through manager - static bool piConnect(const PIString & srcObject, const PIString & event, const PIString & destObject, const PIString & handler, bool force = false) { - PIObject * src = findByName(srcObject); - if (src == 0) { - cout << "PIObject::piConnect: can`t find PIObject with \"" << srcObject << "\" name!" << endl; - return false; - } - PIObject * dest = findByName(destObject); - if (dest == 0) { - cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; - return false; - } - return PIObject::piConnect(src, event, dest, handler, force); - }*/ - - // / Raise events - static void raiseEvent(PIObject * sender, const PIString & event) { - for (int j = 0; j < sender->connections.size_s(); ++j) { - Connection & i(sender->connections[j]); - if (i.event != event) continue; - //((PIObject*)(i.dest))->mutex_.lock(); - ((PIObject*)(i.dest))->emitter_ = sender; - ((void(*)(void * ))i.slot)(i.dest); - ((PIObject*)(i.dest))->emitter_ = 0; - //((PIObject*)(i.dest))->mutex_.unlock(); - } - } - template - static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0()) { - for (int j = 0; j < sender->connections.size_s(); ++j) { - Connection & i(sender->connections[j]); - if (i.event != event) continue; - //((PIObject*)(i.dest))->mutex_.lock(); - ((PIObject*)(i.dest))->emitter_ = sender; - ((void(*)(void * , T0))i.slot)(i.dest, v0); - ((PIObject*)(i.dest))->emitter_ = 0; - //((PIObject*)(i.dest))->mutex_.unlock(); - } - } - template - static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1()) { - for (int j = 0; j < sender->connections.size_s(); ++j) { - Connection & i(sender->connections[j]); - if (i.event != event) continue; - //((PIObject*)(i.dest))->mutex_.lock(); - ((PIObject*)(i.dest))->emitter_ = sender; - ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); - ((PIObject*)(i.dest))->emitter_ = 0; - //((PIObject*)(i.dest))->mutex_.unlock(); - } - } - template - static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) { - for (int j = 0; j < sender->connections.size_s(); ++j) { - Connection & i(sender->connections[j]); - if (i.event != event) continue; - //((PIObject*)(i.dest))->mutex_.lock(); - ((PIObject*)(i.dest))->emitter_ = sender; - ((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2); - ((PIObject*)(i.dest))->emitter_ = 0; - //((PIObject*)(i.dest))->mutex_.unlock(); - } - } - template - static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) { - for (int j = 0; j < sender->connections.size_s(); ++j) { - Connection & i(sender->connections[j]); - if (i.event != event) continue; - //((PIObject*)(i.dest))->mutex_.lock(); - ((PIObject*)(i.dest))->emitter_ = sender; - ((void(*)(void * , T0, T1, T2, T3))i.slot)(i.dest, v0, v1, v2, v3); - ((PIObject*)(i.dest))->emitter_ = 0; - //((PIObject*)(i.dest))->mutex_.unlock(); - } - } - /* - /// Raise events (static) - static void raiseEvent(PIObject * destObject, const PIString & name) { - destObject->raiseEvent(name); - } - template - static void raiseEvent(PIObject * destObject, const PIString & name, const T0 & v0 = T0()) { - destObject->raiseEvent(name, v0); - } - template - static void raiseEvent(PIObject * destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1()) { - destObject->raiseEvent(name, v0, v1); - } - template - static void raiseEvent(PIObject * destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) { - destObject->raiseEvent(name, v0, v1, v2); - } - template - static void raiseEvent(PIObject * destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) { - destObject->raiseEvent(name, v0, v1, v2, v3); - } - */ - // / Raise events through manager - static void raiseEvent(const PIString & destObject, const PIString & name) { - PIObject * dest = findByName(destObject); - if (dest == 0) { - cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; - return; - } - raiseEvent(dest, name); - } - template - static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0()) { - PIObject * dest = findByName(destObject); - if (dest == 0) { - cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; - return; - } - raiseEvent(dest, name, v0); - } - template - static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1()) { - PIObject * dest = findByName(destObject); - if (dest == 0) { - cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; - return; - } - raiseEvent(dest, name, v0, v1); - } - template - static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) { - PIObject * dest = findByName(destObject); - if (dest == 0) { - cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; - return; - } - raiseEvent(name, dest, v0, v1, v2); - } - template - static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) { - PIObject * dest = findByName(destObject); - if (dest == 0) { - cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; - return; - } - raiseEvent(name,dest , v0, v1, v2, v3); - } - - //! Returns PIObject* with name "name" or 0, if there is no object found - static PIObject * findByName(const PIString & name) { - piForeach (PIObject * i, PIObject::objects) { - if (i->name() != name) continue; - return i; - } - return 0; - }; - -protected: - - //! Returns PIObject* which has raised an event. This value is correct only in definition of some event handler - PIObject * emitter() const {return emitter_;} - - //! Virtual function executes after property with name "name" has been changed - virtual void propertyChanged(const PIString & name) {} - -private: - struct Connection { - Connection(void * sl = 0, void * si = 0, const PIString & e = PIString(), void * o = 0) {slot = sl; signal = si; event = e; dest = o;} - void * slot; - void * signal; - PIString event; - void * dest; - }; - - PIVector connections; - PIMap properties_; - - static PIVector objects; - PIMutex mutex_; - PIObject * emitter_; - -}; - -#endif // PIOBJECT_H diff --git a/pip.cbp b/pip.cbp new file mode 100644 index 00000000..ef30a2e9 --- /dev/null +++ b/pip.cbp @@ -0,0 +1,663 @@ + + + + + + diff --git a/pip.h b/pip.h deleted file mode 100644 index a2f12005..00000000 --- a/pip.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - PIP - Platform Independent Primitives - All includes - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pitimer.h" -#include "pivariant.h" -#include "piconsole.h" -#include "picli.h" -#include "pievaluator.h" -#include "pimultiprotocol.h" -#include "picodec.h" -#include "pisignals.h" -#include "piobject.h" -#include "pisystemmonitor.h" -#include "pipeer.h" -#include "picrc.h" -#include "pistatemachine.h" -#include "picollection.h" -#include "piserial.h" -#include "pibinarylog.h" -#include "piusb.h" diff --git a/pip.pro b/pip.pro deleted file mode 100644 index c6954533..00000000 --- a/pip.pro +++ /dev/null @@ -1,130 +0,0 @@ -###################################################################### -# Automatically generated by qmake (2.01a) ?? ???. 5 22:55:18 2011 -###################################################################### - -TEMPLATE = lib -TARGET = pip -DEPENDPATH += . -INCLUDEPATH += . -QT -= core gui -CONFIG -= qt -CONFIG += dll -VERSION = 0.4.0 - -# Input -HEADERS += \ - pivariant.h \ - pitimer.h \ - pithread.h \ - pisystemtests.h \ - pisystemmonitor.h \ - pistring.h \ - pisignals.h \ - piserial.h \ - piprotocol.h \ - piprocess.h \ - pipeer.h \ - pipacketextractor.h \ - pip.h \ - piobject.h \ - pimutex.h \ - pimultiprotocol.h \ - pimonitor.h \ - pimath.h \ - pikbdlistener.h \ - piiodevice.h \ - piincludes.h \ - pigeometry.h \ - pifile.h \ - pievaluator.h \ - piethernet.h \ - pidir.h \ - picrc.h \ - picontainers.h \ - piconsole.h \ - piconfig.h \ - picodec.h \ - picli.h \ - pichar.h \ - pibytearray.h \ - pibitarray.h \ - picollection.h \ - pidiagnostics.h \ - pibinarylog.h \ - picodeparser.h \ - picodeinfo.h \ - piusb.h \ - piconnection.h -SOURCES += main.cpp \ - pivariant.cpp \ - pitimer.cpp \ - pithread.cpp \ - pisystemtests.cpp \ - pisystemmonitor.cpp \ - pistring.cpp \ - pisignals.cpp \ - piserial.cpp \ - piprotocol.cpp \ - piprocess.cpp \ - pipeer.cpp \ - pipacketextractor.cpp \ - piobject.cpp \ - pimonitor.cpp \ - pimath.cpp \ - pikbdlistener.cpp \ - piiodevice.cpp \ - piincludes.cpp \ - pifile.cpp \ - pievaluator.cpp \ - piethernet.cpp \ - pidir.cpp \ - piconsole.cpp \ - piconfig.cpp \ - picodec.cpp \ - picli.cpp \ - pibytearray.cpp \ - picollection.cpp \ - pidiagnostics.cpp \ - pibinarylog.cpp \ - picodeparser.cpp \ - picodeinfo.cpp \ - piusb.cpp \ - piconnection.cpp -win32 { - LIBS += -lws2_32 -lIphlpapi -} else { - android { - } else { - LIBS = -lpthread -lrt - } -} - -OTHER_FILES += \ - android/AndroidManifest.xml \ - android/res/layout/splash.xml \ - android/res/values/libs.xml \ - android/res/values/strings.xml \ - android/res/values-de/strings.xml \ - android/res/values-el/strings.xml \ - android/res/values-es/strings.xml \ - android/res/values-et/strings.xml \ - android/res/values-fa/strings.xml \ - android/res/values-fr/strings.xml \ - android/res/values-id/strings.xml \ - android/res/values-it/strings.xml \ - android/res/values-ja/strings.xml \ - android/res/values-ms/strings.xml \ - android/res/values-nb/strings.xml \ - android/res/values-nl/strings.xml \ - android/res/values-pl/strings.xml \ - android/res/values-pt-rBR/strings.xml \ - android/res/values-ro/strings.xml \ - android/res/values-rs/strings.xml \ - android/res/values-ru/strings.xml \ - android/res/values-zh-rCN/strings.xml \ - android/res/values-zh-rTW/strings.xml \ - android/src/org/kde/necessitas/ministro/IMinistro.aidl \ - android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl \ - android/src/org/qtproject/qt5/android/bindings/QtActivity.java \ - android/src/org/qtproject/qt5/android/bindings/QtApplication.java \ - android/version.xml diff --git a/pip.pro.user b/pip.pro.user deleted file mode 100644 index b5855fd8..00000000 --- a/pip.pro.user +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - true - 1 - true - 0 - true - 0 - 8 - true - 1 - true - true - true - false - - - - ProjectExplorer.Project.PluginSettings - - - - ProjectExplorer.Project.Target.0 - - Desktop - Desktop - Qt4ProjectManager.Target.DesktopTarget - 0 - 0 - 0 - - ProjectExplorer.ToolChain.Mingw:C:/MinGW/bin//g++.exe.x86-windows-msys-pe-32bit.C:/Qt/qtcreator-2.4.1/pythongdb/gdb-i686-pc-mingw32.exe - - - qmake - - QtProjectManager.QMakeBuildStep - false - true - - false - - - Сборка - - Qt4ProjectManager.MakeStep - false - - - - 2 - Сборка - - ProjectExplorer.BuildSteps.Build - - - - Сборка - - Qt4ProjectManager.MakeStep - true - clean - - - 1 - Очистка - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Qt 4.8.0 (4.8.0) Релиз - - Qt4ProjectManager.Qt4BuildConfiguration - 0 - E:/pprojects/pip - 6 - false - - 1 - - - 0 - Установка - - ProjectExplorer.BuildSteps.Deploy - - 1 - Без установки - - ProjectExplorer.DefaultDeployConfiguration - - 1 - - true - true - - - false - false - false - false - false - false - false - false - true - true - 0.01 - 0.01 - 10 - 10 - true - true - 25 - 25 - - - true - true - valgrind - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - pip - - Qt4ProjectManager.Qt4RunConfiguration - 2 - - pip.pro - false - false - - - 3768 - true - false - false - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.EnvironmentId - {e0680b61-7ce7-4775-a872-e83c6b7b3dfe} - - - ProjectExplorer.Project.Updater.FileVersion - 10 - - diff --git a/pip_export.h b/pip_export.h deleted file mode 100644 index 4c1e544d..00000000 --- a/pip_export.h +++ /dev/null @@ -1,35 +0,0 @@ - -#ifndef PIP_EXPORT_H -#define PIP_EXPORT_H - -#ifdef PIP_STATIC_DEFINE -# define PIP_EXPORT -# define PIP_NO_EXPORT -#else -# ifndef PIP_EXPORT -# ifdef pip_EXPORTS - /* We are building this library */ -# define PIP_EXPORT __attribute__((visibility("default"))) -# else - /* We are using this library */ -# define PIP_EXPORT __attribute__((visibility("default"))) -# endif -# endif - -# ifndef PIP_NO_EXPORT -# define PIP_NO_EXPORT __attribute__((visibility("hidden"))) -# endif -#endif - -#ifndef PIP_DEPRECATED -# define PIP_DEPRECATED __attribute__ ((__deprecated__)) -# define PIP_DEPRECATED_EXPORT PIP_EXPORT __attribute__ ((__deprecated__)) -# define PIP_DEPRECATED_NO_EXPORT PIP_NO_EXPORT __attribute__ ((__deprecated__)) -#endif - -#define DEFINE_NO_DEPRECATED 0 -#if DEFINE_NO_DEPRECATED -# define PIP_NO_DEPRECATED -#endif - -#endif diff --git a/pip_resource_win.rc b/pip_resource_win.rc index 660cbd18..dabf6177 100644 --- a/pip_resource_win.rc +++ b/pip_resource_win.rc @@ -1,12 +1,14 @@ -# if defined(UNDER_CE) +#if defined(UNDER_CE) # include -# else +#else # include -# endif +#endif +#include +#include VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,4,0,0 - PRODUCTVERSION 0,4,0,0 + FILEVERSION PIP_VERSION_MAJOR,PIP_VERSION_MINOR,PIP_VERSION_REVISION,0 + PRODUCTVERSION PIP_VERSION_MAJOR,PIP_VERSION_MINOR,PIP_VERSION_REVISION,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS VOS__WINDOWS32 @@ -19,7 +21,7 @@ VS_VERSION_INFO VERSIONINFO BEGIN VALUE "CompanyName", "Peri4\0" VALUE "FileDescription", "Platform-Independent Primitives\0" - VALUE "FileVersion", "0.4.0_beta2\0" + VALUE "FileVersion", __PIP_VERSION_STR__ VALUE "LegalCopyright", "\0" VALUE "OriginalFilename", "libpip.dll\0" VALUE "ProductName", "PIP\0" diff --git a/pipacketextractor.cpp b/pipacketextractor.cpp deleted file mode 100644 index 188f43f4..00000000 --- a/pipacketextractor.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* - PIP - Platform Independent Primitives - Packets extractor - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pipacketextractor.h" - - -/** \class PIPacketExtractor - * \brief Packets extractor - * \details - * \section PIPacketExtractor_main Synopsis - * This class implements packet recognition by various algorithms and custom - * validating from data stream. Stream is formed from child %PIIODevice - * passed from contructor or with function \a setDevice(). - * - * \section PIPacketExtractor_work Principle of work - * %PIPacketExtractor works with child %PIIODevice. \a read and \a write - * functions directly call child device functions. You should start threaded - * read of \b extractor (not child device) to proper work. Extractor read data - * from child device, try to detect packet from readed data and raise - * \a packetReceived() event on success. - * - * \section PIPacketExtractor_algorithms Algorithms - * There are 6 algorithms: \n - * * PIPacketExtractor::None \n - * Packet is successfully received on every read without any validation. \n \n - * * PIPacketExtractor::Header \n - * Wait for at least \a header() bytes + \a payloadSize(), then validate - * header with virtual function \a validateHeader() and if it fail, shifts - * for next 1 byte. If header is successfully validated check payload with - * function \a validatePayload() and if it fail, shifts for next 1 byte. If - * all validations were successful raise \a packetReceived() event. \n \n - * * PIPacketExtractor::Footer \n - * This algorithm similar to previous, but instead of \a header() first validate - * \a footer() at after \a payloadSize() bytes with function \a validateFooter(). \n \n - * * PIPacketExtractor::HeaderAndFooter \n - * Wait for at least \a header() bytes + \a footer() bytes, then validate - * header with virtual function \a validateHeader() and if it fail, shifts - * for next 1 byte. If header is successfully validated check footer with - * function \a validateFooter() and if it fail, shifts footer position for - * next 1 byte. Then validate payload and if it fail, search header again, - * starts from next byte of previous header. If all validations were successful - * raise \a packetReceived() event. \n \n - * * PIPacketExtractor::Size \n - * Wait for at least \a packetSize() bytes, then validate packet with function - * \a validatePayload() and if it fail, shifts for next 1 byte. If validating - * was successfull raise \a packetReceived() event. \n \n - * * PIPacketExtractor::Timeout \n - * Wait for first read, then read for \a timeout() milliseconds and raise - * \a packetReceived() event. \n - * - * \section PIPacketExtractor_control Control validating - * There are three parameters: - * * header content - * * header size - * * payload size - * - * Extractor can detect packet with compare your header with readed data. - * It is default implementation of function \a packetHeaderValidate(). - * If header validating passed, function \a packetValidate() will be called. - * If either of this function return \b false extractor shifts by one byte - * and takes next header. If both functions returns \b true extractor shifts - * by whole packet size. - * \image html packet_detection.png - * - * */ - -REGISTER_DEVICE(PIPacketExtractor); - - -PIPacketExtractor::PIPacketExtractor(PIIODevice * device_, PIPacketExtractor::SplitMode mode) { - init_(); - setDevice(device_); - setSplitMode(mode); -} - - -void PIPacketExtractor::init_() { - ret_func_header = ret_func_footer = 0; - setPayloadSize(0); - setTimeout(100); - setThreadedReadBufferSize(65536); - setBufferSize(65536); - setDevice(0); - setPacketSize(0); - setSplitMode(None); - allReaded = addSize = curInd = missed = footerInd = 0; - header_found = false; -} - - -void PIPacketExtractor::propertyChanged(const PIString &) { - packetSize_ = property("packetSize").toInt(); - mode_ = (SplitMode)(property("splitMode").toInt()); - dataSize = property("payloadSize").toInt(); - src_header = property("header").toByteArray(); - src_footer = property("footer").toByteArray(); - packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize(); -} - - -void PIPacketExtractor::setDevice(PIIODevice * device_) { - dev = device_; - if (dev == 0) return; -} - - -void PIPacketExtractor::setPayloadSize(int size) { - setProperty("payloadSize", size); - dataSize = size; - packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize(); -} - - -void PIPacketExtractor::setHeader(const PIByteArray & data) { - setProperty("header", data); - src_header = data; - packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize(); -} - - -void PIPacketExtractor::setFooter(const PIByteArray & data) { - setProperty("footer", data); - src_footer = data; - packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize(); -} - - -bool PIPacketExtractor::threadedRead(uchar * readed, int size_) { - //piCoutObj << "readed" << size_; - int ss; - switch (mode_) { - case PIPacketExtractor::None: - if (validatePayload(readed, size_)) - packetReceived(readed, size_); - break; - case PIPacketExtractor::Header: - tmpbuf.append(readed, size_); - ss = src_header.size_s() + dataSize; - while (tmpbuf.size_s() >= ss) { - while (!validateHeader(src_header.data(), tmpbuf.data(), src_header.size_s())) { - tmpbuf.pop_front(); - ++missed; - if (tmpbuf.size_s() < ss) return true; - } - while (!validatePayload(tmpbuf.data(src_header.size_s()), dataSize)) { - tmpbuf.pop_front(); - ++missed; - if (tmpbuf.size_s() < ss) return true; - } - packetReceived(tmpbuf.data(), ss); - tmpbuf.remove(0, ss); - } - break; - case PIPacketExtractor::Footer: - /*memcpy(buffer.data(allReaded), readed, size_); - allReaded += size_; - footer_ = (mode_ == PIPacketExtractor::Footer); - while (allReaded >= packetSize_hf + addSize && allReaded > 0) { - if (!src_header.isEmpty()) { - if (allReaded + curInd >= buffer_size) { - memcpy(sbuffer.data(), buffer.data(), buffer_size); - memcpy(buffer.data(), sbuffer.data(buffer_size - packetSize_hf), allReaded); - allReaded = packetSize_hf; - addSize = curInd = 0; - } - bool brk = false; - while (!validateHeader((uchar * )(footer_ ? src_footer.data() : src_header.data()), buffer.data(curInd + (footer_ ? dataSize : 0)), footer_ ? src_footer.size_s() : src_header.size_s())) { - ++curInd; ++missed; - if (packetSize_hf > 0) missed_packets = missed / packetSize_hf; - if (curInd > addSize) { - addSize += packetSize_hf; - brk = true; - break; - } - } - if (brk) continue; - //memcpy(mheader.data(), buffer.data(curInd + (footer_ ? dataSize : 0)), src_header.size_s()); - if (!src_header.isEmpty()) memcpy(src_header.data(), buffer.data(curInd), src_header.size_s()); - if (!validatePayload(buffer.data(curInd + src_header.size_s()), dataSize)) { - ++curInd; ++missed; - if (packetSize_hf > 0) missed_packets = missed / packetSize_hf; - continue; - } - packetReceived(buffer.data(curInd), packetSize_hf); - memcpy(sbuffer.data(), buffer.data(), allReaded); - memcpy(buffer.data(), sbuffer.data(packetSize_hf + curInd), allReaded); - allReaded -= packetSize_hf + curInd; - curInd = addSize = 0; - } else { - if (dataSize == 0) { - if (validatePayload(buffer.data(), size_)) - packetReceived(buffer.data(), size_); - memcpy(sbuffer.data(), buffer.data(), allReaded); - memcpy(buffer.data(), sbuffer.data(size_), allReaded); - allReaded -= size_; - } else { - if (validatePayload(buffer.data(), dataSize)) - packetReceived(buffer.data(), dataSize); - memcpy(sbuffer.data(), buffer.data(), allReaded); - memcpy(buffer.data(), sbuffer.data(packetSize_hf), allReaded); - allReaded -= packetSize_hf; - } - } - }*/ - tmpbuf.append(readed, size_); - ss = src_footer.size_s() + dataSize; - while (tmpbuf.size_s() >= ss) { - while (!validateFooter(src_footer.data(), tmpbuf.data(dataSize), src_footer.size_s())) { - tmpbuf.pop_front(); - ++missed; - if (tmpbuf.size_s() < ss) return true; - } - while (!validatePayload(tmpbuf.data(), dataSize)) { - tmpbuf.pop_front(); - ++missed; - if (tmpbuf.size_s() < ss) return true; - } - packetReceived(tmpbuf.data(), ss); - tmpbuf.remove(0, ss); - } - break; - case PIPacketExtractor::HeaderAndFooter: - tmpbuf.append(readed, size_); - ss = src_header.size_s() + src_footer.size_s(); - while (tmpbuf.size_s() >= ss) { - if (!header_found) { - if (tmpbuf.size_s() < ss) return true; - while (!validateHeader(src_header.data(), tmpbuf.data(), src_header.size_s())) { - tmpbuf.pop_front(); - ++missed; - if (tmpbuf.size_s() < ss) return true; - } - header_found = true; - footerInd = src_header.size_s(); - } else { - if (tmpbuf.size_s() < footerInd + src_footer.size_s()) return true; - while (!validateFooter(src_footer.data(), tmpbuf.data(footerInd), src_footer.size_s())) { - ++footerInd; - if (tmpbuf.size_s() < footerInd + src_footer.size_s()) return true; - } - //piCout << "footer found at" << footerInd; - header_found = false; - if (!validatePayload(tmpbuf.data(src_header.size_s()), footerInd - src_header.size_s())) { - tmpbuf.pop_front(); - ++missed; - continue; - } - packetReceived(tmpbuf.data(), footerInd + src_footer.size_s()); - tmpbuf.remove(0, footerInd + src_footer.size_s()); - footerInd = src_header.size_s(); - } - } - break; - case PIPacketExtractor::Size: - tmpbuf.append(readed, size_); - if (packetSize_ <= 0) { - tmpbuf.clear(); - return true; - } - while (tmpbuf.size_s() >= packetSize_) { - if (!validatePayload(tmpbuf.data(), packetSize_)) { - tmpbuf.pop_front(); - ++missed; - missed_packets = missed / packetSize_; - continue; - } - packetReceived(tmpbuf.data(), packetSize_); - tmpbuf.remove(0, packetSize_); - } - break; - case PIPacketExtractor::Timeout: - memcpy(buffer.data(), readed, size_); - trbuf = dev->readForTime(time_); - memcpy(buffer.data(size_), trbuf.data(), trbuf.size()); - if (size_ + trbuf.size() > 0) - packetReceived(buffer.data(), size_ + trbuf.size()); - break; - }; - return true; -} - - -PIString PIPacketExtractor::constructFullPath() const { - return fullPathPrefix() + "://"; -} diff --git a/pipacketextractor.h b/pipacketextractor.h deleted file mode 100644 index e9b0c0d4..00000000 --- a/pipacketextractor.h +++ /dev/null @@ -1,187 +0,0 @@ -/*! \file pipacketextractor.h - * \brief Packets extractor -*/ -/* - PIP - Platform Independent Primitives - Packets extractor - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - - -#ifndef PIPACKETEXTRACTOR_H -#define PIPACKETEXTRACTOR_H - -#include "piiodevice.h" - -// Pass data, recHeaderPtr, received_data, recHeaderSize. Return true if packet is correct nor return false. -typedef bool (*PacketExtractorCheckFunc)(void * , uchar * , uchar * , int ); - -class PIP_EXPORT PIPacketExtractor: public PIIODevice -{ - PIIODEVICE(PIPacketExtractor) - friend class PIConnection; -public: - - //! Extract algorithms - enum SplitMode { - None /** No data processing */ , - Header /** Detect packets with \a header() and following \a payloadSize() */ , - Footer /** Detect packets with \a footer() and leading \a payloadSize() */ , - HeaderAndFooter /** Detect packets with \a header() and \a footer() without \a payloadSize() */ , - Size /** Detect packets with \a packetSize() */ , - Timeout /** Wait for first read, then read for \a timeout() milliseconds */ - }; - - //! Contructs extractor with child device "device_" and extract algorithm "mode" - PIPacketExtractor(PIIODevice * device_ = 0, SplitMode mode = None); - - virtual ~PIPacketExtractor() {stop();} - - - //! Returns child %device - PIIODevice * device() {return dev;} - - //! Set child %device to "device_" - void setDevice(PIIODevice * device_); - - - //! Returns buffer size - int bufferSize() const {return buffer_size;} - - //! Set buffer size to "new_size" bytes, should be at least greater than whole packet size - void setBufferSize(int new_size) {buffer_size = new_size; buffer.resize(buffer_size); sbuffer.resize(buffer_size); memset(buffer.data(), 0, buffer.size()); memset(sbuffer.data(), 0, sbuffer.size());} - - void setHeaderCheckSlot(PacketExtractorCheckFunc f) {ret_func_header = f;} - void setFooterCheckSlot(PacketExtractorCheckFunc f) {ret_func_footer = f;} - void setPayloadCheckSlot(ReadRetFunc f) {ret_func_ = f;} - - - //! Set extract algorithm - void setSplitMode(SplitMode mode) {setProperty("splitMode", int(mode)); mode_ = mode;} - - //! Set payload size, used for PIPacketExtractor::Header and PIPacketExtractor::Footer algorithms - void setPayloadSize(int size); - - //! Set header data, used for PIPacketExtractor::Header and PIPacketExtractor::HeaderAndFooter algorithms - void setHeader(const PIByteArray & data); - - //! Set footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms - void setFooter(const PIByteArray & data); - - //! Set packet size, used for PIPacketExtractor::Size algorithm - void setPacketSize(int size) {setProperty("packetSize", size); packetSize_ = size;} - - //! Set timeout in milliseconds, used for PIPacketExtractor::Timeout algorithm - void setTimeout(double msecs) {setProperty("timeout", msecs); time_ = msecs;} - - - //! Returns current extract algorithm - SplitMode splitMode() const {return (SplitMode)(property("splitMode").toInt());} - - //! Returns current payload size, used for PIPacketExtractor::Header and PIPacketExtractor::Footer algorithms - int payloadSize() const {return property("payloadSize").toInt();} - - //! Returns current header data, used for PIPacketExtractor::Header and PIPacketExtractor::HeaderAndFooter algorithms - PIByteArray header() const {return src_header;} - - //! Returns current footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms - PIByteArray footer() const {return src_footer;} - - //! Returns current packet size, used for PIPacketExtractor::Size algorithm - int packetSize() const {return property("packetSize").toInt();} - - //! Returns current timeout in milliseconds, used for PIPacketExtractor::Timeout algorithm - double timeout() const {return property("timeout").toDouble();} - - - //! Returns missed by validating functions bytes count - ullong missedBytes() const {return missed;} - - // //! Returns missed by validating functions packets count, = missedBytes() / packetSize - ullong missedPackets() const {/*if (packetSize_hf == 0) return missed; return missed / packetSize_hf*/; return missed_packets;} - - //! Returns pointer to \a missedBytes() count. Useful for output to PIConsole - const ullong * missedBytes_ptr() const {return &missed;} - - // //! Returns pointer to \a missedPackets() count. Useful for output to PIConsole - const ullong * missedPackets_ptr() const {return &missed_packets;} - - - // //! Returns last successfully validated header as byte array - PIByteArray lastHeader() {return mheader;} - - - //! Directly call \a read() function of child %device - int read(void * read_to, int max_size) {if (dev == 0) return -1; return dev->read(read_to, max_size);} - - //! Directly call \a write() function of child %device - int write(const void * data, int max_size) {if (dev == 0) return -1; return dev->write(data, max_size);} - - PIString constructFullPath() const; - - EVENT2(packetReceived, uchar * , data, int, size) - -//! \events -//! \{ - - //! \fn void packetReceived(uchar * data, int size) - //! \brief Raise on successfull \a packetValidate() function - -//! \} - -protected: - - /** \brief Function to validate header - * \param src Your header content - * \param rec Received header - * \param size Header size - * \details Default implementation returns by-byte "src" with "rec" compare result */ - virtual bool validateHeader(uchar * src, uchar * rec, int size) {if (ret_func_header != 0) return ret_func_header(ret_data_, src, rec, size); for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} - - /** \brief Function to validate footer - * \param src Your footer content - * \param rec Received footer - * \param size Footer size - * \details Default implementation returns by-byte "src" with "rec" compare result */ - virtual bool validateFooter(uchar * src, uchar * rec, int size) {if (ret_func_footer != 0) return ret_func_footer(ret_data_, src, rec, size); for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} - - /** \brief Function to validate payload - * \param rec Received payload - * \param size payload size - * \details Default implementation returns \b true */ - virtual bool validatePayload(uchar * rec, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, rec, size); return true;} - -private: - void init_(); - void propertyChanged(const PIString & ); - bool threadedRead(uchar * readed, int size); - PIString fullPathPrefix() const {return "pckext";} - bool openDevice() {if (dev == 0) return false; return dev->open();} - - PIIODevice * dev; - PIByteArray mheader, buffer, sbuffer, tmpbuf, src_header, src_footer, trbuf; - PacketExtractorCheckFunc ret_func_header, ret_func_footer; - SplitMode mode_; - void * data; - int buffer_size, dataSize, packetSize_hf, allReaded, addSize, curInd, footerInd, packetSize_; - double time_; - bool header_found; - ullong missed, missed_packets; - - -}; - -#endif // PIPACKETEXTRACTOR_H diff --git a/pipeer.cpp b/pipeer.cpp deleted file mode 100644 index c672b18a..00000000 --- a/pipeer.cpp +++ /dev/null @@ -1,515 +0,0 @@ -/* - PIP - Platform Independent Primitives - Peer - named I/O ethernet node - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pipeer.h" - -#define _PIPEER_PORT_SYNC_START 13313 -#define _PIPEER_PORT_SYNC_END 13353 -#define _PIPEER_IP_MULTICAST "230.13.3.12" -#define _PIPEER_MSG_SIZE 8192 - -PIPeer::PIPeer(const PIString & name_): PIObject() { - rec_mc = rec_bc = false; - setName(name_); - self_info.name = name_; - self_info.dist = 0; - eth_send = 0; - //joinMulticastGroup("239.240.241.242"); - srand(uint(PITimer::elapsed_system_m())); - //id_ = name() + "_" + PIString::fromNumber(rand()); - CONNECT2(void, void * , int, &timer, timeout, this, timerEvent); - PIStringList sl = PIEthernet::allAddresses(); - sl.removeAll("127.0.0.1"); sl << "127.0.0.1"; - initMulticasts(sl); - initEths(sl); - sendSelfInfo(); - timer.addDelimiter(5); - timer.start(1000); -} - - -PIPeer::~PIPeer() { - piForeach (PIEthernet * i, mc_eths) - i->stopThreadedRead(); - if (eth_send != 0) - eth_send->stopThreadedRead(); - sendSelfRemove(); - destroyMulticasts(); - piForeach (PIEthernet * i, eths) - delete i; - eths.clear(); - if (eth_send != 0) - delete eth_send; -} - - -void PIPeer::timerEvent(void * data, int delim) { - switch (delim) { - case 5: // 5 s - syncPeers(); - break; - } - //send("broadcast", 9); -} - - -void PIPeer::initEths(const PIStringList & al) { - PIEthernet * ce; - PIEthernet::InterfaceList il = PIEthernet::interfaces(); - const PIEthernet::Interface * cint = 0; - piForeachC (PIString & a, al) { - ce = new PIEthernet(); - ce->setParameters(0); - ce->setDebug(false); - for (int p = _PIPEER_PORT_SYNC_START; p < 65536; ++p) { - ce->setReadAddress(a, p); - if (ce->open()) { - eths << ce; - cint = il.getByAddress(a); - self_info.addresses << ce->path(); - self_info.netmasks << (cint == 0 ? "255.255.255.0" : cint->netmask); - CONNECT2(bool, void * , int, ce, threadedReadEvent, this, dataRead); - ce->startThreadedRead(); - //piCout << "dc binded to" << ce->path(); - //piCout << "add eth" << ta; - break; - } - } - } - eth_send = new PIEthernet(); - eth_send->setParameters(0); - eth_send->setDebug(false); -} - - -void PIPeer::initMulticasts(const PIStringList & al) { - destroyMulticasts(); - PIEthernet * ce; - PIEthernet::InterfaceList il = PIEthernet::interfaces(); - const PIEthernet::Interface * cint; - PIStringList nal = al; - PIString nm; - nal << "main" << "bc"; - rec_mc = rec_bc = false; - piForeachC (PIString & a, nal) { - bool is_main = (a == "main"); - bool is_bc = (a == "bc"); - ce = new PIEthernet(); - ce->setParameters((is_main || is_bc) ? PIEthernet::Broadcast : 0); - ce->setDebug(false); - //cint = il.getByAddress(a); - //nm = (cint == 0) ? "255.255.255.0" : cint->netmask; - ce->setSendIP(is_bc ? "255.255.255.255" : _PIPEER_IP_MULTICAST); - //piCout << "mc try" << a << nm << ce->sendIP(); - for (int p = _PIPEER_PORT_SYNC_START; p < _PIPEER_PORT_SYNC_END; ++p) { - ce->setReadAddress(((is_main || is_bc) ? "255.255.255.255" : a) + ":" + PIString::fromNumber(p)); - ce->close(); - if (!ce->open()) continue; - if (is_main) if (!ce->joinMulticastGroup(_PIPEER_IP_MULTICAST)) continue; - //piCout << "mc binded to" << ce->path(); - ce->setName(is_main ? "no_send" : ""); - mc_eths << ce; - if (is_main || is_bc) { - if (is_main) rec_mc = true; - if (is_bc) rec_bc = true; - CONNECT2(bool, void * , int, ce, threadedReadEvent, this, multicastRead); - ce->startThreadedRead(); - if (is_bc) ce->setParameter(PIEthernet::Broadcast, false); - } - break; - } - } - piForeachC (PIString & a, al) { - ce = new PIEthernet(); - ce->setParameters(PIEthernet::Broadcast); - ce->setDebug(false); - cint = il.getByAddress(a); - nm = (cint == 0) ? "255.255.255.0" : cint->netmask; - ce->setSendIP(PIEthernet::getBroadcast(a, nm)); - //piCout << "mc BC try" << a << nm << ce->sendIP(); - for (int p = _PIPEER_PORT_SYNC_START; p < _PIPEER_PORT_SYNC_END; ++p) { - ce->setReadAddress(a + ":" + PIString::fromNumber(p)); - ce->close(); - if (!ce->open()) continue; - //piCout << "BC binded to" << ce->path(); - mc_eths << ce; - break; - } - } - if (!rec_mc) piCoutObj << "Can`t find suitable network interface for multicast receive, check for exists at least one interface with multicasting enabled!"; - if (!rec_bc) piCoutObj << "Can`t find suitable network interface for broadcast receive, check for exists at least one interface with broadcasting enabled!"; -} - - -void PIPeer::destroyMulticasts() { - piForeach (PIEthernet * i, mc_eths) { - i->leaveMulticastGroup(_PIPEER_IP_MULTICAST); - delete i; - } - mc_eths.clear(); -} - - -PIPeer::PeerInfo * PIPeer::quickestPeer(const PIString & to) { - if (!addresses_map.contains(to)) return 0; - //piCout << "*** search quickest peer" << to; - PIVector tp = addresses_map[to]; - PeerInfo * dp = 0; - int mping = 99999; - for (int i = 0; i < tp.size_s(); ++i) { - if (mping > tp[i]->ping) { - mping = tp[i]->ping; - dp = tp[i]; - } - } - //piCout << "*** search quickest peer: found" << dp->name; - return dp; -} - - -bool PIPeer::send(const PIString & to, const void * data, int size) { - PeerInfo * dp = quickestPeer(to); - if (dp == 0) { - //piCoutObj << "Can`t find peer \"" << to << "\"!"; - return false; - } - PIByteArray ba; - ba << int(4) << self_info.name << to << int(0) << size; - PIByteArray fmsg(data, size), cmsg; - int msg_count = (size - 1) / _PIPEER_MSG_SIZE + 1; - //piCout << "[PIPeer] send" << size << "bytes in" << msg_count << "packets ..."; - for (int i = 0; i < msg_count; ++i) { - int csize = (i == msg_count - 1) ? ((size - 1) % _PIPEER_MSG_SIZE + 1) : _PIPEER_MSG_SIZE; - cmsg.clear(); - cmsg.append(ba); - cmsg << msg_count << i; - cmsg.append(fmsg.data(i * _PIPEER_MSG_SIZE), csize); - if (!sendToNeighbour(dp, cmsg)) return false; - } - //piCout << "[PIPeer] send" << size << "bytes ok"; - return true; -} - - -bool PIPeer::dataRead(uchar * readed, int size) { - if (size < 16) return true; - PIByteArray ba(readed, size), sba; - int type, cnt, rec_size; - PIString from, to; - ba >> type; - //piCout << "[PIPeer \"" + name_ + "\"] Received packet" << type; - if (type != 4) return true; - PIMutexLocker locker(eth_mutex); - diag_d.received(size); - ba >> from >> to >> cnt >> rec_size; - //piCout << "[PIPeer \"" + name_ + "\"] Received packet" << /*type << from << to << cnt <<*/ rec_size; - if (type == 4) { // data packet - if (to == self_info.name) { // my packet - int msg_count, cmsg; - ba >> msg_count >> cmsg; - //piCout << "[PIPeer \"" + name_ + "\"] Received packet" << type << from << to << cnt << rec_size << msg_count << cmsg; - if (cmsg == 0 && msg_count == 1) { - dataReceived(from, ba); - dataReceivedEvent(from, ba); - return true; - } - PeerInfo * fp = const_cast(getPeerByName(from)); - if (fp == 0) return true; - PeerData & pd(fp->_data); - if (cmsg == 0) { - //piCout << "[PIPeer \"" + name_ + "\"] Packet clear" << rec_size; - pd.clear(); - pd.msg_count = msg_count; - } - //piCout << "[PIPeer \"" + name_ + "\"] Packet add" << cmsg << ba.size_s(); - pd.addData(ba); - if (pd.isFullReceived()) { - dataReceived(from, pd.data); - dataReceivedEvent(from, pd.data); - //piCout << "[PIPeer \"" + name_ + "\"] Packet received" << pd.data.size_s(); - } - return true; - } - PeerInfo * dp = quickestPeer(to); - if (dp == 0) { - //piCoutObj << "Can`t find peer \"" << to << "\"!"; - return true; - } - cnt++; - if (cnt > 100 || from == dp->name) return true; - sba << type << from << to << cnt << rec_size; - sba.append(ba); - //piCoutObj << "Translate data packet" << type << from << to << cnt << rec_size; - sendToNeighbour(dp, sba); - } - return true; -} - - -bool PIPeer::multicastRead(uchar * data, int size) { - if (size < 8) return true; - int type; - PIByteArray ba(data, size); - ba >> type; - if (type <= 0 || type >= 4) return true; - PeerInfo pi; - PIVector rpeers; - ba >> pi.name; - //piCout << "read type" << type << "from" << pi.name; - if (pi.name == name()) return true; - PIMutexLocker locker(mc_mutex); - diag_s.received(size); - //piCout << "analyz ..."; - switch (type) { - case 1: // new peer accepted - //piCout << "new peer packet ..."; - if (hasPeer(pi.name)) break; - ba >> pi.dist >> pi.addresses >> pi.netmasks >> pi.neighbours; - pi.sync = 0; - if (pi.dist == 0) { - pi.addNeighbour(self_info.name); - self_info.addNeighbour(pi.name); - } - peers << pi; - //piCoutObj << "new peer \"" << pi.name << "\"" << " dist " << pi.dist; - pi.dist++; - sendSelfInfo(); - sendPeerInfo(pi); - findNearestAddresses(); - peerConnected(pi.name); - peerConnectedEvent(pi.name); - //piCout << "new peer packet ok"; - break; - case 2: // remove peer accepted - //piCout << "remove peer packet ..."; - if (removePeer(pi.name)) { - //piCoutObj << "remove peer \"" << pi.name << "\""; - if (pi.dist == 0) { - pi.removeNeighbour(self_info.name); - self_info.removeNeighbour(pi.name); - } - sendPeerRemove(pi.name); - findNearestAddresses(); - peerDisconnected(pi.name); - peerDisconnectedEvent(pi.name); - } - //piCout << "remove peer packet ok"; - break; - case 3: // sync peers - //piCout << "sync packet ..."; - ba >> pi.addresses >> pi.netmasks >> pi.neighbours >> rpeers; - rpeers << pi; - //piCout << "[PIPeer \"" + name_ + "\"] rec sync " << rpeers.size_s() << " peers"; - for (uint i = 0; i < rpeers.size(); ++i) { - PeerInfo & rpeer(rpeers[i]); - //piCout << " to sync " << rpeer.name; - if (rpeer.name == name()) continue; - bool exist = false; - for (uint j = 0; j < peers.size(); ++j) { - PeerInfo & peer(peers[j]); - if (peer.name == rpeer.name) { - //piCout << "synced " << peer.name; - peer.addresses = rpeer.addresses; - peer.netmasks = rpeer.netmasks; - peer.addNeighbours(rpeer.neighbours); - rpeer.neighbours = peer.neighbours; - if (peer.name == pi.name) peer.sync = 0; - exist = true; - break; - } - } - if (exist) continue; - peers << rpeer; - peers.back().dist++; - findNearestAddresses(); - peerConnected(rpeer.name); - peerConnectedEvent(rpeer.name); - } - //piCout << "***";; - //piCout << self_info.name << self_info.neighbours; - piForeach (PeerInfo & i, peers) { - if (i.dist == 0) { - self_info.addNeighbour(i.name); - i.addNeighbour(self_info.name); - } - //piCout << i.name << i.neighbours; - } - break; - } - return true; -} - - -bool PIPeer::sendToNeighbour(PIPeer::PeerInfo * peer, const PIByteArray & ba) { - if (peer->_neth == 0) return false; - //piCout << "[PIPeer] sendToNeighbour" << (eth_send->readAddress()) << peer->_naddress << ba.size_s() << "bytes ..."; - //bool ok = peer->_neth->send(peer->_naddress, ba.data(), ba.size_s()); - bool ok = eth_send->send(peer->_naddress, ba.data(), ba.size_s()); - //piCout << "[PIPeer] sendToNeighbour" << (ok ? "ok" : "fail"); - if (ok) diag_d.sended(ba.size_s()); - return ok; -} - - -void PIPeer::sendMulticast(const PIByteArray & ba) { - //piCout << "send muticast ..."; - piForeach (PIEthernet * e, mc_eths) { - if (e->name() == "no_send") continue; - for (int p = _PIPEER_PORT_SYNC_START; p < _PIPEER_PORT_SYNC_END; ++p) { - e->setSendPort(p); - //errorClear(); - //piCout << "send to" << e->path() << e->sendAddress();// << e->send(ba); - //piCout << PIEthernet::ethErrorString(); - e->send(ba); - diag_s.sended(ba.size_s()); - } - } - //piCout << "send muticast ok"; -} - - -void PIPeer::sendPeerInfo(const PeerInfo & info) { - PIByteArray ba; - ba << int(1) << info.name << info.dist << info.addresses << info.netmasks << info.neighbours; - sendMulticast(ba); -} - - -void PIPeer::sendPeerRemove(const PIString & peer) { - PIByteArray ba; - ba << int(2) << peer; - sendMulticast(ba); -} - - -void PIPeer::syncPeers() { - //piCout << "[PIPeer \"" + name_ + "\"] sync " << peers.size_s() << " peers"; - PIString pn; - bool change = false; - for (uint i = 0; i < peers.size(); ++i) { - PeerInfo & cp(peers[i]); - if (cp.sync > 3 && cp.dist == 0) { - pn = cp.name; - //piCoutObj << "sync: remove " << pn; - peers.remove(i); - sendPeerRemove(pn); - --i; - piForeach (PeerInfo & p, peers) - p.removeNeighbour(pn); - self_info.removeNeighbour(pn); - peerDisconnected(pn); - peerDisconnectedEvent(pn); - change = true; - continue; - } - cp.sync++; - } - if (change) findNearestAddresses(); - PIByteArray ba; - ba << int(3) << self_info.name << self_info.addresses << self_info.netmasks << self_info.neighbours << peers; - sendMulticast(ba); -} - - -void PIPeer::findNearestAddresses() { - //piCout << "[PIPeer \"" + name_ + "\"] findNearestAddresses"; - addresses_map.clear(); - int max_dist = -1; - static PIMap peers_; - peers_.clear(); - self_info._nuses.resize(self_info.neighbours.size()); - self_info._nuses.fill(0); - self_info._first = &self_info; - peers_[self_info.name] = &self_info; - piForeach (PeerInfo & i, peers) { - i._nuses.resize(i.neighbours.size()); - i._nuses.fill(0); - i._first = 0; - peers_[i.name] = &i; - if (max_dist < i.dist) - max_dist = i.dist; - if (i.dist > 0) continue; - i._naddress.clear(); - i._neth = 0; - PIString mma, ma; - bool af = false; - for (int mi = 0; mi < self_info.addresses.size_s(); ++mi) { - PIString & m(self_info.addresses[mi]), & mmask(self_info.netmasks[mi]); - if (af) break; - ma = m; - //mma = m.left(m.findLast(".")); - mma = PIEthernet::applyMask(m, mmask); - for (int ii = 0; ii < i.addresses.size_s(); ++ii) { - PIString & r(i.addresses[ii]), & rmask(i.netmasks[ii]); - if (mma == PIEthernet::applyMask(r, rmask)) { - i._naddress = r; - //piCout << "_naddress" << i.name << "=" << r; - af = true; - break; - } - } - } - if (!af) continue; - //piCout << " peer" << i.name << ma; - piForeach (PIEthernet * e, eths) - if (e->readAddress() == ma) { - i._neth = e; - break; - } - //piCout << i.name << i._naddress; - } - PIVector cwave, nwave; - PeerInfo * npeer; - cwave << &self_info; - for (int d = 0; d <= max_dist; ++d) { - if (cwave.isEmpty()) break; - nwave.clear(); - piForeach (PeerInfo * p, cwave) { - int ns = p->neighbours.size_s(); - for (int n = 0; n < ns; ++n) { - if (p->_nuses[n] >= ns) continue; - p->_nuses[n]++; - npeer = peers_[p->neighbours[n]]; - if (npeer == 0) continue; - if (d == 0) npeer->_first = npeer; - else { - if (d == 1) npeer->_first = p; - else npeer->_first = p->_first; - } - nwave << npeer; - } - } - cwave = nwave; - //piCout << "wave" << d; - for (int i = 0; i < cwave.size_s(); ++i) { - //piCout << " peer" << cwave[i]->name << Hex << (uint)(cwave[i]->_first); - if (cwave[i]->_first == 0) {cwave.remove(i); --i; continue;} - if (addresses_map.contains(cwave[i]->name)) {cwave.remove(i); --i; continue;} - } - for (int i = 0; i < cwave.size_s(); ++i) { - PIVector & pl(addresses_map[cwave[i]->name]); - if (!pl.contains(cwave[i]->_first)) - pl << cwave[i]->_first; - } - } - /*piCout << " ** addresses map **"; - piForeachC (napair & i, addresses_map) - piCout << i.first << i.second; - piCout << " ** addresses map end **";*/ -} diff --git a/pipeer.h b/pipeer.h deleted file mode 100644 index 841174e7..00000000 --- a/pipeer.h +++ /dev/null @@ -1,167 +0,0 @@ -/*! \file pipeer.h - * \brief Peering net node -*/ -/* - PIP - Platform Independent Primitives - Peer - named I/O ethernet node, forming self-organized peering network - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIPEER_H -#define PIPEER_H - -#include "piethernet.h" -#include "pidiagnostics.h" - -class PIP_EXPORT PIPeer: public PIObject -{ - PIOBJECT(PIPeer) -private: - struct PeerData { - PeerData() {msg_count = msg_rec = 0;} - void clear() {msg_count = msg_rec = 0; data.clear();} - bool isEmpty() const {return msg_count == 0;} - bool isFullReceived() const {return msg_count == msg_rec;} - void addData(const PIByteArray & ba) {data.append(ba); msg_rec++;} - void setData(const PIByteArray & ba) {data = ba; msg_rec = 0; msg_count = (data.size_s() - 1) / 4096 + 1;} - PIByteArray data; - int msg_count; - int msg_rec; - }; - -public: - PIPeer(const PIString & name); - virtual ~PIPeer(); - - class PeerInfo { - friend class PIPeer; - friend PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v); - friend PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v); - public: - PeerInfo() {dist = sync = ping = 0; _neth = 0; _first = 0;} - - PIString name; - PIStringList addresses; - int dist; - int ping; - - bool isNeighbour() const {return dist == 0;} - - protected: - void addNeighbour(const PIString & n) {if (!neighbours.contains(n)) neighbours << n;} - void addNeighbours(const PIStringList & l) {piForeachC (PIString & n, l) if (!neighbours.contains(n)) neighbours << n;} - void removeNeighbour(const PIString & n) {neighbours.removeAll(n);} - - PIString nearest_address; - PIStringList netmasks; - PIStringList neighbours; - int sync; - PIString _naddress; - PIEthernet * _neth; - PIVector _nuses; - PeerInfo * _first; - PeerData _data; - - }; - - friend PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v); - friend PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v); - - bool send(const PIString & to, const PIByteArray & data) {return send(to, data.data(), data.size_s());} - bool send(const PIString & to, const PIString & data) {return send(to, data.data(), data.size_s());} - bool send(const PIString & to, const void * data, int size); - bool send(const PeerInfo & to, const PIByteArray & data) {return send(to.name, data.data(), data.size_s());} - bool send(const PeerInfo & to, const PIString & data) {return send(to.name, data.data(), data.size_s());} - bool send(const PeerInfo & to, const void * data, int size) {return send(to.name, data, size);} - bool send(const PeerInfo * to, const PIByteArray & data) {if (to == 0) return false; return send(to->name, data.data(), data.size_s());} - bool send(const PeerInfo * to, const PIString & data) {if (to == 0) return false; return send(to->name, data.data(), data.size_s());} - bool send(const PeerInfo * to, const void * data, int size) {if (to == 0) return false; return send(to->name, data, size);} - void sendToAll(const PIByteArray & data) {piForeachC (PeerInfo & i, peers) send(i.name, data.data(), data.size_s());} - void sendToAll(const PIString & data) {piForeachC (PeerInfo & i, peers) send(i.name, data.data(), data.size_s());} - void sendToAll(const void * data, int size) {piForeachC (PeerInfo & i, peers) send(i.name, data, size);} - - bool isMulticastReceive() const {return rec_mc;} - bool isBroadcastReceive() const {return rec_bc;} - - PIDiagnostics & diagnosticService() {return diag_s;} - PIDiagnostics & diagnosticData() {return diag_d;} - - const PIVector & allPeers() const {return peers;} - bool isPeerExists(const PIString & name) const {return getPeerByName(name) != 0;} - - const PeerInfo * getPeerByName(const PIString & name) const {piForeachC (PeerInfo & i, peers) if (i.name == name) return &i; return 0;} - - void lock() {mc_mutex.lock();} - void unlock() {mc_mutex.unlock();} - - EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data); - EVENT1(peerConnectedEvent, const PIString &, name); - EVENT1(peerDisconnectedEvent, const PIString &, name); - -protected: - virtual void dataReceived(const PIString & from, const PIByteArray & data) {;} - virtual void peerConnected(const PIString & name) {;} - virtual void peerDisconnected(const PIString & name) {;} - - EVENT_HANDLER2(bool, dataRead, uchar *, readed, int, size); - EVENT_HANDLER2(bool, multicastRead, uchar *, readed, int, size); - -private: - EVENT_HANDLER2(void, timerEvent, void * , data, int, delim); - - bool hasPeer(const PIString & name) {piForeachC (PeerInfo & i, peers) if (i.name == name) return true; return false;} - bool removePeer(const PIString & name) {for (uint i = 0; i < peers.size(); ++i) if (peers[i].name == name) {peers.remove(i); return true;} return false;} - - void sendPeerInfo(const PeerInfo & info); - void sendPeerRemove(const PIString & peer); - void sendSelfInfo() {sendPeerInfo(self_info);} - void sendSelfRemove() {sendPeerRemove(name());} - void syncPeers(); - void findNearestAddresses(); - void initEths(const PIStringList & al); - void initMulticasts(const PIStringList & al); - void destroyMulticasts(); - void sendMulticast(const PIByteArray & ba); - - PeerInfo * quickestPeer(const PIString & to); - bool sendToNeighbour(PeerInfo * peer, const PIByteArray & ba); - - struct PeerPacket { - int header; // 1 - new peer, 2 - remove peer, 3 - sync peers, 4 - data - // Data packet: 4, from, to, ticks, data_size, data - }; - - typedef std::pair > napair; - - PIVector eths; - PIVector mc_eths; - PIEthernet * eth_send; - PITimer timer; - PIMutex mc_mutex, eth_mutex; - bool rec_mc, rec_bc; - - PeerInfo self_info; - PIVector peers; - PIMap > addresses_map; // map {"to" = list of nearest peers} - PIDiagnostics diag_s, diag_d; - //PIString id_; - -}; - -inline PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v) {s << v.name << v.addresses << v.netmasks << v.dist << v.neighbours; return s;} -inline PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v) {s >> v.name >> v.addresses >> v.netmasks >> v.dist >> v.neighbours; return s;} - -#endif // PIPEER_H diff --git a/piprocess.cpp b/piprocess.cpp deleted file mode 100644 index 3f237575..00000000 --- a/piprocess.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - PIP - Platform Independent Primitives - Process - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "piprocess.h" - - -PIProcess::PIProcess(): PIThread() { - exit_code = -1; -#ifdef WINDOWS - pi.dwProcessId = 0; -#else - pid = 0; -#endif - 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 - as = 0; -#ifdef WINDOWS - //args.pop_front(); - piForeachC (PIString & i, args) - as += i.lengthAscii() + 1; - char * a = new char[as]; - memset(a, ' ', as - 1); - as = 0; - for (int i = 0; i < args.size_s(); ++i) { - str = args[i].stdString(); - memcpy(&a[as], str.c_str(), str.size()); - as += str.length() + 1; - } - a[as - 1] = 0; -#else - 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; -#endif - /// environment convertion - char ** e = new char*[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(PIIODevice::ReadWrite); - t_in = true; - } - //f_in.open(PIIODevice::ReadWrite); f_in.close(); - if (f_out.path().isEmpty()) { - f_out = PIFile::openTemporary(PIIODevice::ReadWrite); - t_out = true; - } - //f_out.open(PIIODevice::WriteOnly); f_out.close(); - if (f_err.path().isEmpty()) { - f_err = PIFile::openTemporary(PIIODevice::ReadWrite); - t_err = true; - } - //f_err.open(PIIODevice::WriteOnly); f_err.close(); - - str = args.front().stdString(); - is_exec = true; - execStarted(PIString(str)); -#ifndef WINDOWS - pid = fork(); - if (pid == 0) { -#endif - tf_in = tf_out = tf_err = 0; - //cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl; - //cout << f_out.path() << endl; - if (g_in) tf_in = freopen(f_in.path().data(), "r", stdin); - if (g_out) tf_out = freopen(f_out.path().data(), "w", stdout); - if (g_err) tf_err = freopen(f_err.path().data(), "w", stderr); -#ifndef WINDOWS - if (!wd.isEmpty()) as = chdir(wd.data()); -#endif -#ifdef WINDOWS - GetStartupInfoA(&si); - memset(&pi, 0, sizeof(pi)); - if(CreateProcessA(0, // No module name (use command line) - a, // Command line - 0, // Process handle not inheritable - 0, // Thread handle not inheritable - false, // Set handle inheritance to FALSE - 0, // No creation flags - 0,//e, // Use environment - wd.isEmpty() ? 0 : wd.data(), // Use working directory - &si, // Pointer to STARTUPINFO structure - &pi)) // Pointer to PROCESS_INFORMATION structure - { - WaitForSingleObject(pi.hProcess, INFINITE); - CloseHandle(pi.hProcess); - } else - piCoutObj << "\"CreateProcess\" error, " << errorString(); -#else - - //cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl; - if (execve(str.c_str(), a, e) < 0) - piCoutObj << "\"execve\" error, " << errorString(); - } else { - msleep(1); - //cout << "wait" << endl; - wait(&exit_code); - /*if (tf_in != 0) fclose(tf_in); - if (tf_out != 0) fclose(tf_out); - if (tf_err != 0) fclose(tf_err);*/ - pid = 0; - //cout << "wait done" << endl; - } -#endif - execFinished(PIString(str), exit_code); - is_exec = false; - for (int i = 0; i < env.size_s(); ++i) - delete e[i]; - delete e; -#ifdef WINDOWS - delete a; -#else - for (int i = 0; i < args.size_s(); ++i) - delete a[i]; -#endif - //cout << "end " << tf_in << ", " << tf_out << ", " << tf_err << 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 deleted file mode 100644 index ae6f03d9..00000000 --- a/piprocess.h +++ /dev/null @@ -1,130 +0,0 @@ -/*! \file piprocess.h - * \brief Process -*/ -/* - PIP - Platform Independent Primitives - Process - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIPROCESS_H -#define PIPROCESS_H - -#include "pithread.h" -#include "pifile.h" -#ifdef WINDOWS -//# include <.h> -#else -# include -#endif - -/// events: -/// execStarted(PIString program) -/// execFinished(PIString program, int exit_code) -/// -/// handlers: -/// bool exec(const PIString & program) -/// bool exec(const PIString & program, const PIString & arg1) -/// bool exec(const PIString & program, const PIString & arg1, const PIString & arg2) -/// bool exec(const PIString & program, const PIString & arg1, const PIString & arg2, const PIString & arg3) -/// bool exec(const PIString & program, const PIStringList & args) -/// void terminate() -/// bool waitForFinish(int timeout_msecs = 60000) -class PIP_EXPORT PIProcess: private PIThread -{ - PIOBJECT(PIProcess) -public: - PIProcess(); - virtual ~PIProcess(); - - int exitCode() const {return exit_code;} - int pID() const { -#ifdef WINDOWS - return pi.dwProcessId; -#else - return pid; -#endif - } - - 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("");} - PIString workingDirectory() const {return wd;} - void setWorkingDirectory(const PIString & path) {wd = path;} - void resetWorkingDirectory() {wd.clear();} - PIByteArray readOutput() {f_out.open(PIIODevice::ReadOnly); return f_out.readAll();} - PIByteArray readError() {f_err.open(PIIODevice::ReadOnly); 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); - - EVENT_HANDLER1(void, exec, const PIString & , program) {args.clear(); args << program; exec_();} - EVENT_HANDLER2(void, exec, const PIString & , program, const PIString & , arg) {args.clear(); args << program << arg; exec_();} - EVENT_HANDLER3(void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2) {args.clear(); args << program << arg1 << arg2; exec_();} - EVENT_HANDLER4(void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2, const PIString & , arg3) {args.clear(); args << program << arg1 << arg2 << arg3; exec_();} - EVENT_HANDLER2(void, exec, const PIString & , program, const PIStringList & , args_) {args << program << args_; exec_();} - EVENT_HANDLER(void, terminate) { -#ifdef WINDOWS - if (is_exec) if (!TerminateProcess(pi.hProcess, 0)) return; pi.dwProcessId = 0; -#else - if (is_exec) kill(pid, SIGKILL); pid = 0; -#endif - } - EVENT_HANDLER(bool, waitForFinish) {return waitForFinish(60000);} - EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs) {return PIThread::waitForFinish(timeout_msecs);} - - EVENT1(execStarted, PIString, program) - EVENT2(execFinished, PIString, program, int, exit_code) - - static PIStringList currentEnvironment() {PIStringList l; int i = 0; while (environ[i] != 0) {l << environ[i]; ++i;} return l;} - static int currentPID() { -#ifdef WINDOWS - return GetCurrentProcessId(); -#else - return getpid(); -#endif - } - -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; -#ifdef WINDOWS - STARTUPINFOA si; - PROCESS_INFORMATION pi; -#else - pid_t pid; -#endif - FILE * tf_in, * tf_out, * tf_err; - int exit_code, sz, as; - bool is_exec; - -}; - -#endif // PIPROCESS_H diff --git a/piprotocol.cpp b/piprotocol.cpp deleted file mode 100644 index 18f89325..00000000 --- a/piprotocol.cpp +++ /dev/null @@ -1,777 +0,0 @@ -/* - PIP - Platform Independent Primitives - Protocol, input/output channel (COM, UDP) - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "piprotocol.h" - - -/** \class PIProtocol - * \brief - * \details - * \section PIProtocol_sec0 Synopsis - * - * - * - * */ - - -PIProtocol::PIProtocol(const PIString & config, const PIString & name_, void * recHeaderPtr, int recHeaderSize, void * recDataPtr, int recDataSize, void * sendDataPtr_, int sendDataSize_): PIObject() { - init(); - protName = name_; - PIObject::setName(name_); - PIConfig conf(config, PIIODevice::ReadOnly); - if (!conf.isOpened()) { - piCoutObj << "Can`t open \"" << config << "\"!"; - devReceiverState = devSenderState = "Config error"; - return; - } - PIConfig::Entry & b(conf.getValue(name_)), - & rb(b.getValue("receiver")), - & sb(b.getValue("sender")); - - init_receiver(b, rb, config); - init_sender(b, sb, config); - - headerPtr = (uchar * )recHeaderPtr; - headerSize = recHeaderSize; - dataPtr = (uchar * )recDataPtr; - dataSize = recDataSize; - sendDataPtr = (uchar * )sendDataPtr_; - sendDataSize = sendDataSize_; - packet_ext->setHeader(PIByteArray(recHeaderPtr, recHeaderSize)); - packet_ext->setPayloadSize(recDataSize); - packet_ext->setPacketSize(recDataSize); - packet_ext->setSplitMode(PIPacketExtractor::Header); - bool null_h = (recHeaderPtr == 0 || recHeaderSize == 0), null_d = (recDataPtr == 0 || recDataSize == 0); - if (null_h && null_d) packet_ext->setSplitMode(PIPacketExtractor::None); - else { - if (null_h) packet_ext->setSplitMode(PIPacketExtractor::Size); - } -} - - -PIProtocol::~PIProtocol() { - //cout << "prot " << protName << " delete\n"; - if (history_write_rec) { - if (history_file_rec.isEmpty()) { - history_file_rec.close(); - history_file_rec.remove(); - } - history_file_rec.close(); - } - if (history_write_send) { - if (history_file_send.isEmpty()) { - history_file_send.close(); - history_file_send.remove(); - } - history_file_send.close(); - } - delete diagTimer; - delete sendTimer; - delete secTimer; - delete packet_ext; - if (eth != 0) delete eth; - if (ser != 0) delete ser; -} - - -void PIProtocol::init() { - packet_ext = new PIPacketExtractor(0, PIPacketExtractor::Header); - packet_ext->setThreadedReadData(this); - packet_ext->setThreadedReadSlot(receiveEvent); - packet_ext->setHeaderCheckSlot(headerValidateEvent); - work = new_mp_prot = history_write_rec = history_write_send = false; - eth = 0; - ser = 0; - ret_func = 0; - mp_owner = 0; - net_diag = PIProtocol::Unknown; - cur_pckt = 0; - packets[0] = packets[1] = pckt_cnt = pckt_cnt_max = 0; - diagTimer = 0; - timeout_ = 3.f; - sendTimer = new PITimer(sendEvent, this); - diagTimer = new PITimer(diagEvent, this); - secTimer = new PITimer(secEvent, this); - wrong_count = receive_count = send_count = missed_count = 0; - packets_in_sec = packets_out_sec = bytes_in_sec = bytes_out_sec = 0; - immediate_freq = integral_freq = ifreq = 0.f; - headerPtr = dataPtr = sendDataPtr = 0; - headerSize = dataSize = sendDataSize = 0; - type_rec = type_send = PIProtocol::None; - devSenderState = devReceiverState = "Unknown"; - devSenderName = devReceiverName = "no device"; - history_rsize_rec = history_rsize_send = "no file"; - secTimer->start(1000.); - /*addEvent("receiver started"); - addEvent("receiver stopped"); - addEvent("sender started"); - addEvent("sender stopped"); - addEvent("received"); - addEvent("quality changed"); - addEventHandler(HANDLER(PIProtocol, startReceive)); - addEventHandler(HANDLER(PIProtocol, startSend)); - addEventHandler(HANDLER(PIProtocol, start)); - addEventHandler(HANDLER(PIProtocol, stopReceive)); - addEventHandler(HANDLER(PIProtocol, stopSend)); - addEventHandler(HANDLER(PIProtocol, stop));*/ -} - - -void PIProtocol::init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config) { - int ps, gps; - bool ok, gok, flag, gflag, has_dev = false; - float freq, gfreq; - PIFlags pp(0); - PIString dev, gdev; - - if (sb.isEntryExists("ip") && sb.isEntryExists("device")) { - piCoutObj << "Ambiguous sender type in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - dev = sb.getValue("ip", "", &ok); - gdev = b.getValue("ip", "", &gok); - has_dev = false; - if (ok || gok) { - if (gok && !ok) dev = gdev; - if (gok && ok && (dev != gdev)) { - piCoutObj << "Ambiguous sender type in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - ps = sb.getValue("port", 0, &ok); - gps = b.getValue("port", 0, &gok); - if (ok || gok) { - if (gok && !ok) ps = gps; - if (gok && ok && (ps != gps)) { - piCoutObj << "Ambiguous send port in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - type_send = PIProtocol::Ethernet; - if (eth == 0) eth = new PIEthernet(); - setSenderAddress(dev, ps); - //setReceiverAddress(dev, ps); - has_dev = true; - flag = sb.getValue("reconnectEnabled", true, &ok); - gflag = b.getValue("reconnectEnabled", true, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - eth->setReopenEnabled(flag); - } - freq = sb.getValue("reconnectTimeout", 1., &ok); - gfreq = b.getValue("reconnectTimeout", 1., &gok); - if (ok || gok) { - if (gok && !ok) freq = gfreq; - if (gok && ok && (freq != gfreq)) { - piCoutObj << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - eth->setReopenTimeout(freq * 1000); - } - /*if (sendDataPtr_ == 0) - piCoutObj << "Warning: null send data pointer!"; - if (sendDataSize_ == 0) - piCoutObj << "Warning: null send data size!";*/ - } else { - piCoutObj << "Can`t find \"" << name() << ".sender.port\" or \"" << name() << ".port\" in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - } - dev = sb.getValue("device", "", &ok); - gdev = b.getValue("device", "", &gok); - if (ok || gok) { - if (gok && !ok) dev = gdev; - if (gok && ok && (dev != gdev)) { - piCoutObj << "Ambiguous sender type in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - ps = sb.getValue("speed", 0, &ok); - gps = b.getValue("speed", 0, &gok); - if (ok || gok) { - if (gok && !ok) ps = gps; - if (gok && ok && (ps != gps)) { - piCoutObj << "Ambiguous send \"speed\" in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - flag = sb.getValue("parity", false, &ok); - gflag = b.getValue("parity", false, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous send \"parity\" in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - pp.setFlag(PISerial::ParityControl, flag); - } - flag = sb.getValue("twoStopBits", false, &ok); - gflag = b.getValue("twoStopBits", false, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - pp.setFlag(PISerial::TwoStopBits, flag); - } - } else { - piCoutObj << "Can`t find \"" << name() << ".sender.speed\" or \"" << name() << ".speed\" in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - type_send = PIProtocol::Serial; - if (ser == 0) ser = new PISerial(dev); - setSenderDevice(dev, (PISerial::Speed)ps); - ser->setOutSpeed((PISerial::Speed)ps); - ser->setParameters(pp); - has_dev = true; - /*if (sendDataPtr_ == 0) - piCoutObj << "Warning: null send data pointer!"; - if (sendDataSize_ == 0) - piCoutObj << "Warning: null send data size!";*/ - } - history_write_send = sb.getValue("writeHistory", false, &ok); - bool ghist = b.getValue("writeHistory", false, &gok); - if (ok || gok) { - if (gok && !ok) history_write_send = ghist; - if (gok && ok && (history_write_send != ghist)) { - piCoutObj << "Ambiguous sender history in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - if (history_write_send) { - history_path_send = sb.getValue("historyFile", "./history_" + protName + "_send_" + - PIDate::current().toString("__dd_mm_yyyy_") + - PITime::current().toString("_hh_mm_ss_")).value(); - history_id_send = sb.getValue("historyID", 0, &ok); - if (!ok) { - history_id_send = ushort(protName.toByteArray().checksumPlain32()) + 1; - piCoutObj << "Warning: no sender history ID defined, write with ID = " << history_id_send; - } - history_file_send.open(history_path_send, PIIODevice::WriteOnly); - } - } - freq = sb.getValue("frequency", -1.f, &ok); - gfreq = b.getValue("frequency", -1.f, &gok); - if (gok && !ok) freq = gfreq; - if (gok && ok && (freq != gfreq)) { - piCoutObj << "Ambiguous sender frequency in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - if (freq > 0.f && !has_dev) - piCoutObj << "Warning: no sender device and not null send frequency!"; - setSenderFrequency(freq); -} - - -void PIProtocol::init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config) { - int ps, gps; - bool ok, gok, flag, gflag, has_dev = false; - float freq, gfreq; - PIFlags pp(0); - PIString dev, gdev; - - if (rb.isEntryExists("ip") && rb.isEntryExists("device")) { - piCoutObj << "Ambiguous receiver type in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - dev = rb.getValue("ip", "", &ok); - gdev = b.getValue("ip", "", &gok); - if (ok || gok) { - if (gok && !ok) dev = gdev; - if (gok && ok && (dev != gdev)) { - piCoutObj << "Ambiguous receiver type in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - ps = rb.getValue("port", 0, &ok); - gps = b.getValue("port", 0, &gok); - if (ok || gok) { - if (gok && !ok) ps = gps; - if (gok && ok && (ps != gps)) { - piCoutObj << "Ambiguous receive port in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - type_rec = PIProtocol::Ethernet; - eth = new PIEthernet(); - packet_ext->setDevice(eth); - //setSenderAddress(dev, ps); - setReceiverAddress(dev, ps); - has_dev = true; - flag = rb.getValue("reconnectEnabled", true, &ok); - gflag = b.getValue("reconnectEnabled", true, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - eth->setReopenEnabled(flag); - } - freq = rb.getValue("reconnectTimeout", 1., &ok); - gfreq = b.getValue("reconnectTimeout", 1., &gok); - if (ok || gok) { - if (gok && !ok) freq = gfreq; - if (gok && ok && (freq != gfreq)) { - piCoutObj << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - eth->setReopenTimeout(freq * 1000); - } - /*if (recDataPtr == 0) - piCoutObj << "Warning: null receive data pointer!"; - if (recDataSize == 0) - piCoutObj << "Warning: null receive data size!";*/ - } else { - piCoutObj << "Can`t find \"" << name() << ".receiver.port\" or \"" << name() << ".port\" in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - } - dev = rb.getValue("device", "", &ok); - gdev = b.getValue("device", "", &gok); - if (ok || gok) { - if (gok && !ok) dev = gdev; - if (gok && ok && (dev != gdev)) { - piCoutObj << "Ambiguous receiver type in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - ps = rb.getValue("speed", 0, &ok); - gps = b.getValue("speed", 0, &gok); - if (ok || gok) { - if (gok && !ok) ps = gps; - if (gok && ok && (ps != gps)) { - piCoutObj << "Ambiguous receive \"speed\" in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - flag = rb.getValue("parity", false, &ok); - gflag = b.getValue("parity", false, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous receive \"parity\" in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - pp.setFlag(PISerial::ParityControl, flag); - } - flag = rb.getValue("twoStopBits", false, &ok); - gflag = b.getValue("twoStopBits", false, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - pp.setFlag(PISerial::TwoStopBits, flag); - } - type_rec = PIProtocol::Serial; - type_send = PIProtocol::Serial; - ser = new PISerial(dev); - packet_ext->setDevice(ser); - //setSenderDevice(dev, (PISerial::Speed)ps); - setReceiverDevice(dev, (PISerial::Speed)ps); - ser->setInSpeed((PISerial::Speed)ps); - ser->setParameters(pp); - ps = rb.getValue("vtime", 1, &ok); - gps = b.getValue("vtime", 1, &gok); - if (ok || gok) { - if (gok && !ok) ps = gps; - if (gok && ok && (ps != gps)) { - piCoutObj << "Ambiguous receive \"vtime\" in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - ser->setVTime(ps); - } - has_dev = true; - /*if (recDataPtr == 0) - piCoutObj << "Warning: null receive data pointer!"; - if (recDataSize == 0) - piCoutObj << "Warning: null receive data size!";*/ - } else { - piCoutObj << "Can`t find \"" << name() << ".receiver.speed\" or \"" << name() << ".speed\" in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - } - history_write_rec = rb.getValue("writeHistory", false, &ok); - bool ghist = b.getValue("writeHistory", false, &gok); - if (ok || gok) { - if (gok && !ok) history_write_rec = ghist; - if (gok && ok && (history_write_rec != ghist)) { - piCoutObj << "Ambiguous receiver history in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - if (history_write_rec) { - history_path_rec = rb.getValue("historyFile", "./history_" + protName + "_rec_" + - PIDate::current().toString("__dd_mm_yyyy_") + - PITime::current().toString("_hh_mm_ss_")).value(); - history_id_rec = rb.getValue("historyID", 0, &ok); - if (!ok) { - history_id_rec = ushort(protName.toByteArray().checksumPlain32()); - piCoutObj << "Warning: no receiver history ID defined, write with ID = " << history_id_rec; - } - history_file_rec.open(history_path_rec, PIIODevice::WriteOnly); - } - } - freq = rb.getValue("frequency", -1.f, &ok); - gfreq = b.getValue("frequency", -1.f, &gok); - if (gok && !ok) freq = gfreq; - if (gok && ok && (freq != gfreq)) { - piCoutObj << "Ambiguous expected frequency in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - if (freq > 0.f && !has_dev) - piCoutObj << "Warning: no receiver device and not null expected frequency!"; - float tm = b.getValue("disconnectTimeout", 3.f); - if (tm <= 0.f) - piCoutObj << "Warning: diconnect timeout <= 0 s!"; - timeout_ = (tm < 0.f) ? 0.f : tm; - setExpectedFrequency(freq); -} - - -void PIProtocol::setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force) { - if (force) { - type_send = type_rec = PIProtocol::Serial; - if (ser == 0) { - ser = new PISerial(); - packet_ext->setDevice(ser); - } - } - if (type_rec == PIProtocol::Serial && ser != 0) { - ser->setDevice(device); - ser->setSpeed(speed); - devReceiverName = device; - devSenderName = device; - } -} - - -void PIProtocol::setReceiverAddress(const PIString & ip, int port, bool force) { - if (force) { - type_rec = PIProtocol::Ethernet; - if (eth == 0) { - eth = new PIEthernet(); - packet_ext->setDevice(eth); - } - } - if (type_rec == PIProtocol::Ethernet && eth != 0) { - eth->setReadAddress(ip, port); - if (ip.trimmed().isEmpty()) devReceiverName = "no ip"; - else devReceiverName = ip + ":" + PIString::fromNumber(port); - } -} - - -void PIProtocol::setSenderDevice(const PIString & device, PISerial::Speed speed, bool force) { - if (force) { - type_send = type_rec = PIProtocol::Serial; - if (ser == 0) ser = new PISerial(); - } - if (type_send == PIProtocol::Serial && ser != 0) { - ser->setDevice(device); - ser->setSpeed(speed); - ser->open(); - devSenderName = device; - } -} - - -void PIProtocol::setSenderAddress(const PIString & ip, int port, bool force) { - if (force) { - type_send = PIProtocol::Ethernet; - if (eth == 0) eth = new PIEthernet(); - } - if (type_send == PIProtocol::Ethernet && eth != 0) { - eth->setSendAddress(ip, port); - if (ip.isEmpty()) devSenderName = "no ip"; - else devSenderName = ip + ":" + PIString::fromNumber(port); - } -} - - -void PIProtocol::setSenderIP(const PIString & ip, bool force) { - if (force) { - type_send = PIProtocol::Ethernet; - if (eth == 0) eth = new PIEthernet(); - } - if (type_send == PIProtocol::Ethernet && eth != 0) { - eth->setSendIP(ip); - if (ip.isEmpty()) devSenderName = "no ip"; - else devSenderName = ip + ":" + PIString::fromNumber(eth->sendPort()); - } -} - - -void PIProtocol::setSenderPort(int port, bool force) { - if (force) { - type_send = PIProtocol::Ethernet; - if (eth == 0) eth = new PIEthernet(); - } - if (type_send == PIProtocol::Ethernet && eth != 0) { - eth->setSendPort(port); - if (eth->sendIP().isEmpty()) devSenderName = "no ip"; - else devSenderName = eth->sendIP() + ":" + PIString::fromNumber(port); - } -} - - -void PIProtocol::setExpectedFrequency(float frequency) { - exp_freq = frequency; - changeDisconnectTimeout(); -} - - -void PIProtocol::changeDisconnectTimeout() { - pckt_cnt_max = int(round(timeout_ * exp_freq)); - if (pckt_cnt_max < 3) pckt_cnt_max = 3; - last_packets.resize(pckt_cnt_max); -} - - -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(); - packet_ext->startThreadedRead(); - msleep(1); - check_state(); - if (exp_freq <= 0.f) return; - setExpectedFrequency(exp_freq); - diagTimer->start(1000. / exp_freq); - diagTimer->reset(); - receiverStarted(); -} - - -void PIProtocol::startSend(float frequency) { - //cout << "** start send " << send_freq << ", " << frequency << endl; - if (frequency > 0.f) send_freq = frequency; - msleep(1); - check_state(); - if (send_freq <= 0.f) return; - sendTimer->start(1000. / send_freq); - diagTimer->reset(); - senderStarted(); -} - - -void PIProtocol::stopReceive() { - //if (type_rec == PIProtocol::Serial) ser->stop(); - //if (type_rec == PIProtocol::Ethernet) eth->stop(); - packet_ext->stop(); - diagTimer->stop(); - receiverStopped(); -} - - -bool PIProtocol::receiveEvent(void * t, uchar * data, int size) { - PIProtocol * p = (PIProtocol * )t; - if (!p->receive(data, size)) return false; - p->work = true; - //p->lock(); - if (p->validate()) { - if (p->history_write_rec) { - p->history_file_rec.writeToBinLog(p->history_id_rec, data, size); - p->history_rsize_rec.setReadableSize(p->history_file_rec.pos()); - } - p->received(true); - //p->unlock(); - p->ifreq = p->diagTimer->elapsed_m(); - if (p->ifreq > 0.) p->ifreq = 1000. / p->ifreq; - p->diagTimer->reset(); - p->receive_count++; - p->packets_in_sec++; - p->bytes_in_sec += size; - p->cur_pckt = 1; - if (p->ret_func != 0) p->ret_func(p); - if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, true, data, size); - return true; - } - p->received(false); - //p->unlock(); - p->wrong_count++; - if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, false, data, size); - return false; -} - - -void PIProtocol::diagEvent(void * t, int) { - PIProtocol * p = (PIProtocol * )t; - p->calc_freq(); - p->calc_diag(); - p->check_state(); - if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets(); -} - - -void PIProtocol::secEvent(void * t, int ) { - PIProtocol * p = (PIProtocol * )t; - p->speedIn = PIString::readableSize(p->bytes_in_sec) + "/s"; - p->speedOut = PIString::readableSize(p->bytes_out_sec) + "/s"; - p->bytes_in_sec = p->bytes_out_sec = p->packets_in_sec = p->packets_out_sec = 0; - if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets(); -} - - -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()]--; - if (!last_packets.isEmpty()) 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) { - qualityChanged(diag, net_diag); - net_diag = diag; - } -} - - -void PIProtocol::calc_freq() { - float tf;// = float(1000.f / diagTimer->elapsed_m()); - tf = immediate_freq = ifreq; - ifreq = 0.f; - if (last_freq.size_s() >= pckt_cnt_max && last_freq.size_s() > 0) 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]; - integral_freq = tf / last_freq.size(); -} - - -void PIProtocol::check_state() { - if (type_rec == PIProtocol::Serial) { - if (ser != 0) { - if (ser->isOpened()) devReceiverState = "Opened"; - else devReceiverState = "Not opened"; - } - else devReceiverState = "Not exists"; - } - if (type_rec == PIProtocol::Ethernet) { - if (eth != 0) { - if (eth->isOpened()) devReceiverState = "Opened"; - else devReceiverState = "Not opened"; - } - else devReceiverState = "Not exists"; - } - if (type_send == PIProtocol::Serial) { - if (ser != 0) { - if (ser->isOpened()) devSenderState = "Opened"; - else devSenderState = "Not opened"; - } - else devSenderState = "Not exists"; - } - if (type_send == PIProtocol::Ethernet) { - if (eth != 0) { - if (eth->isOpened()) devSenderState = "Opened"; - else devSenderState = "Not opened"; - } - else devSenderState = "Not exists"; - } -} - - -void PIProtocol::send(const void * data, int size, bool direct) { - if (!direct) { - if (data == 0 || size == 0) return; - if (!aboutSend()) return; - } - if (history_write_send) { - history_file_send.writeToBinLog(history_id_send, data, size); - history_rsize_send.setReadableSize(history_file_send.pos()); - } - if (type_send == PIProtocol::Serial) - if (ser->send(data, size)) { - send_count++; - packets_out_sec++; - bytes_out_sec += size; - } - if (type_send == PIProtocol::Ethernet) - if (eth->send(data, size)) { - send_count++; - packets_out_sec++; - bytes_out_sec += size; - } -} - - -void PIProtocol::send() { - //lock(); - //memcpy(packet, sendDataPtr, sendDataSize); - //unlock(); - //cout << "**send" << endl; - if (!aboutSend()) return; - if (sendDataPtr == 0 || sendDataSize == 0) return; - if (history_write_send) { - history_file_send.writeToBinLog(history_id_send, sendDataPtr, sendDataSize); - history_rsize_send.setReadableSize(history_file_send.pos()); - } - if (type_send == PIProtocol::Serial) - if (ser->send(sendDataPtr, sendDataSize)) { - send_count++; - packets_out_sec++; - bytes_out_sec += sendDataSize; - } - if (type_send == PIProtocol::Ethernet) - if (eth->send(sendDataPtr, sendDataSize)) { - send_count++; - packets_out_sec++; - bytes_out_sec += sendDataSize; - } -} diff --git a/piprotocol.h b/piprotocol.h deleted file mode 100644 index 2025636a..00000000 --- a/piprotocol.h +++ /dev/null @@ -1,248 +0,0 @@ -/*! \file piprotocol.h - * \brief Highly configurable from file I/O channel -*/ -/* - PIP - Platform Independent Primitives - Protocol, input/output channel (COM, UDP) - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIPROTOCOL_H -#define PIPROTOCOL_H - -#include "piserial.h" -#include "piethernet.h" -#include "pipacketextractor.h" -#include "pitimer.h" -#include "piconfig.h" -#include "math.h" - -class PIProtocol; - -class PIP_EXPORT PIMultiProtocolBase: protected PIObject -{ - PIOBJECT(PIMultiProtocolBase) - friend class PIProtocol; -public: - PIMultiProtocolBase() {;} - virtual ~PIMultiProtocolBase() {;} - -protected: - virtual void received(PIProtocol * prot, bool corrected, uchar * data, int size) {;} - -private: - static void receiveEvent(PIMultiProtocolBase * p, PIProtocol * prot, bool corrected, uchar * data, int size) {p->mutex_receive.lock(); p->received(prot, corrected, data, size); p->mutex_receive.unlock();} - - PIMutex mutex_receive; - -}; - -typedef void (*ReceiveFunc)(void * ); - -/// events: -/// void receiverStarted() -/// void receiverStopped() -/// void senderStarted() -/// void senderStopped() -/// void received(bool validate_is_ok) -/// void qualityChanged(PIProtocol::Quality old_quality, PIProtocol::Quality new_quality) -/// -/// handlers: -/// void startReceive(float exp_frequency = -1.f) -/// void stopReceive() -/// void startSend(float frequency = -1.f) -/// void stopSend() -/// void start() -/// void stop() -/// void send() -/// void send(const void * data, int size, bool direct = false) -class PIP_EXPORT PIProtocol: public PIObject -{ - PIOBJECT(PIProtocol) - friend class PIMultiProtocolBase; - friend class PIMultiProtocol; - enum Type {None, Serial, Ethernet}; -public: - - //! Contructs an empty unconfigured protocol - PIProtocol(): PIObject() {init();} - - //! Contructs protocol configured from file "config", config file section "name" - 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 - - virtual ~PIProtocol(); - - //! Connection quality - enum Quality { - Unknown /** Unknown, no one packet received yet */ = 1, - Failure /** No connection, no one correct packet received for last period */ = 2, - Bad /** Bad connection, correct packets received <= 20% */ = 3, - Average /** Average connection, correct packets received > 20% and <= 80% */ = 4, - Good /** Good connection, correct packets received > 80% */ = 5 - }; - - EVENT_HANDLER0(void, startReceive) {startReceive(-1.f);} - EVENT_HANDLER1(void, startReceive, float, exp_frequency); // if "frequency = -1" used last passed value - EVENT_HANDLER0(void, stopReceive); - void setExpectedFrequency(float frequency); // for connection quality diagnostic - void setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial - void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize); packet_ext->setPacketSize(dataSize);} - void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize); packet_ext->setPacketSize(dataSize);} - void setReceiverAddress(const PIString & ip, int port, bool force = false); // for Ethernet - void setReceiverParameters(PIFlags parameters) {if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial - void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;} - float expectedFrequency() const {return exp_freq;} - - EVENT_HANDLER0(void, startSend) {startSend(-1.f);} // if "frequency = -1" used last passed value - EVENT_HANDLER1(void, startSend, float, frequency); // if "frequency = -1" used last passed value - EVENT_HANDLER0(void, stopSend) {sendTimer->stop(); senderStopped();} - void setSenderFrequency(float frequency) {send_freq = frequency;} - void setSenderDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial - void setSenderData(void * dataPtr, int dataSize) {sendDataPtr = (uchar * )dataPtr; sendDataSize = dataSize;} - void setSenderAddress(const PIString & ip, int port, bool force = false); // for Ethernet - void setSenderIP(const PIString & ip, bool force = false); // for Ethernet - void setSenderPort(int port, bool force = false); // for Ethernet - void setSenderParameters(PIFlags parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial - float senderFrequency() const {return send_freq;} - - EVENT_HANDLER0(void, start) {startReceive(); startSend();} - EVENT_HANDLER0(void, stop) {stopReceive(); stopSend();} - EVENT_HANDLER0(void, send); - EVENT_HANDLER2(void, send, const void *, data, int, size) {send(data, size, false);} - EVENT_HANDLER3(void, send, const void *, data, int, size, bool, direct); - - void setName(const PIString & name) {protName = name; PIObject::setName(name);} - PIString name() const {return protName;} - void setDisconnectTimeout(float timeout) {timeout_ = timeout; changeDisconnectTimeout();} - float disconnectTimeout() const {return timeout_;} - const float * disconnectTimeout_ptr() const {return &timeout_;} - float immediateFrequency() const {return immediate_freq;} - float integralFrequency() const {return integral_freq;} - const float * immediateFrequency_ptr() const {return &immediate_freq;} - const float * integralFrequency_ptr() const {return &integral_freq;} - ullong receiveCountPerSec() const {return packets_in_sec;} - const ullong * receiveCountPerSec_ptr() const {return &packets_in_sec;} - ullong sendCountPerSec() const {return packets_out_sec;} - const ullong * sendCountPerSec_ptr() const {return &packets_out_sec;} - ullong receiveBytesPerSec() const {return bytes_in_sec;} - const ullong * receiveBytesPerSec_ptr() const {return &bytes_in_sec;} - ullong sendBytesPerSec() const {return bytes_out_sec;} - const ullong * sendBytesPerSec_ptr() const {return &bytes_out_sec;} - ullong receiveCount() const {return receive_count;} - const ullong * receiveCount_ptr() const {return &receive_count;} - ullong wrongCount() const {return wrong_count;} - const ullong * wrongCount_ptr() const {return &wrong_count;} - ullong sendCount() const {return send_count;} - const ullong * sendCount_ptr() const {return &send_count;} - ullong missedCount() const {return missed_count;} - const ullong * missedCount_ptr() const {return &missed_count;} - PIProtocol::Quality quality() const {return net_diag;} // receive quality - const int * quality_ptr() const {return (int * )&net_diag;} // receive quality pointer - PIString receiverDeviceName() const {return devReceiverName;} - PIString senderDeviceName() const {return devSenderName;} - PIString receiverDeviceState() const {return devReceiverState;} - const PIString * receiverDeviceState_ptr() const {return &devReceiverState;} - PIString senderDeviceState() const {return devSenderState;} - const PIString * senderDeviceState_ptr() const {return &devSenderState;} - PIString receiveSpeed() const {return speedIn;} - const PIString * receiveSpeed_ptr() const {return &speedIn;} - PIString sendSpeed() const {return speedOut;} - const PIString * sendSpeed_ptr() const {return &speedOut;} - PIString receiverHistorySize() const {return history_rsize_rec;} - const PIString * receiverHistorySize_ptr() const {return &history_rsize_rec;} - PIString senderHistorySize() const {return history_rsize_send;} - const PIString * senderHistorySize_ptr() const {return &history_rsize_send;} - bool writeReceiverHistory() const {return history_write_rec;} - const bool * writeReceiverHistory_ptr() const {return &history_write_rec;} - bool writeSenderHistory() const {return history_write_send;} - const bool * writeSenderHistory_ptr() const {return &history_write_send;} - - void * receiveData() {return dataPtr;} - void * sendData() {return sendDataPtr;} - - PIPacketExtractor * packetExtractor() {return packet_ext;} - PIByteArray lastHeader() {return packet_ext->lastHeader();} - - EVENT0(receiverStarted) - EVENT0(receiverStopped) - EVENT0(senderStarted) - EVENT0(senderStopped) - EVENT1(received, bool, validate_is_ok) - EVENT2(qualityChanged, PIProtocol::Quality, new_quality, PIProtocol::Quality, old_quality) - -protected: - virtual bool receive(uchar * data, int size) {if (dataPtr != 0) 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 bool headerValidate(uchar * src, uchar * rec, int size) {for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} // function for validate header (COM-port and headerSize > 0) - 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]; - return ~(c + 1); - } - 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]; - return ~(c + 1); - } - virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending - - void init(); - void init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config); - void init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config); - void check_state(); - void calc_freq(); - void calc_diag(); - - PISerial * ser; - PIEthernet * eth; - uint dataSize, headerSize, sendDataSize; - uchar * dataPtr, * headerPtr, * sendDataPtr; - -private: - static void sendEvent(void * e, int) {((PIProtocol * )e)->send();} - static bool receiveEvent(void * t, uchar * data, int size); - static bool headerValidateEvent(void * t, uchar * src, uchar * rec, int size) {return ((PIProtocol * )t)->headerValidate(src, rec, size);} - static void diagEvent(void * t, int); - static void secEvent(void * t, int); - - void setMultiProtocolOwner(PIMultiProtocolBase * mp) {mp_owner = mp;} - PIMultiProtocolBase * multiProtocolOwner() const {return mp_owner;} - void changeDisconnectTimeout(); - - ReceiveFunc ret_func; - PIPacketExtractor * packet_ext; - PITimer * diagTimer, * sendTimer, * secTimer; - PIMultiProtocolBase * mp_owner; - PIProtocol::Type type_send, type_rec; - PIProtocol::Quality net_diag; - PIDeque last_freq; - PIDeque last_packets; - PIString protName, devReceiverName, devReceiverState, devSenderName, devSenderState, speedIn, speedOut; - PIString history_path_rec, history_path_send, history_rsize_rec, history_rsize_send; - PIFile history_file_rec, history_file_send; - ushort history_id_rec, history_id_send; - bool work, new_mp_prot, history_write_rec, history_write_send; - float exp_freq, send_freq, ifreq, immediate_freq, integral_freq, timeout_; - int packets[2], pckt_cnt, pckt_cnt_max; - char cur_pckt; - ullong wrong_count, receive_count, send_count, missed_count, packets_in_sec, packets_out_sec, bytes_in_sec, bytes_out_sec; - -}; - -#endif // PIPROTOCOL_H diff --git a/piqueue.h b/piqueue.h deleted file mode 100644 index 23f808ea..00000000 --- a/piqueue.h +++ /dev/null @@ -1,41 +0,0 @@ -/*! \file picontainers.h - * \brief Queue container - * - * This file declare PIQueue -*/ -/* - PIP - Platform Independent Primitives - Queue container - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIQUEUE_H -#define PIQUEUE_H - -#include "pivector.h" - -template -class PIP_EXPORT PIQueue: public PIVector { -public: - PIQueue() {;} - PIVector & enqueue(const T & v) {PIVector::push_front(v); return *this;} - T dequeue() {return PIVector::take_back();} - T & head() {return PIVector::back();} - const T & head() const {return PIVector::back();} - PIVector toVector() {PIVector v(PIVector::size()); for (uint i = 0; i < PIVector::size(); ++i) v[i] = PIVector::at(i); return v;} -}; - -#endif // PIQUEUE_H diff --git a/piserial.cpp b/piserial.cpp deleted file mode 100644 index 44fb89cb..00000000 --- a/piserial.cpp +++ /dev/null @@ -1,664 +0,0 @@ -/* - PIP - Platform Independent Primitives - COM - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "piserial.h" -#include "piconfig.h" -#include "pidir.h" - - -/*! \class PISerial - * \brief Serial device - * - * \section PISerial_sec0 Synopsis - * This class provide access to serial device, e.g. COM port. It can read, - * write, wait for write. There are several read and write functions. - * - * - */ - -REGISTER_DEVICE(PISerial); - - -PISerial::PISerial(): PIIODevice("", ReadWrite) { - _init(); -} - - -PISerial::PISerial(const PIString & device_, PISerial::Speed speed_, PIFlags params_): PIIODevice(device_, ReadWrite) { - _init(); - setPath(device_); - setSpeed(speed_); - setParameters(params_); -} - - -PISerial::~PISerial() { - piMonitor.serials--; -} - - -void PISerial::_init() { - fd = -1; - piMonitor.serials++; - setPriority(piHigh); - block_read = true; - vtime = 1; -#ifdef WINDOWS - block_write = true; - hCom = 0; -#endif - setParameters(0); - setSpeed(S115200); - setDataBitsCount(8); - //init(); -} - - -void PISerial::setParameter(PISerial::Parameters parameter, bool on) { - PIFlags cp = (PIFlags)(property("parameters").toInt()); - cp.setFlag(parameter, on); - setParameters(cp); -} - - -bool PISerial::isParameterSet(PISerial::Parameters parameter) const { - PIFlags cp = (PIFlags)(property("parameters").toInt()); - return cp[parameter]; -} - - -bool PISerial::setPin(int number, bool on) { - switch (number) { - case 1: return setCAR(on); break; - case 2: return setSR(on); break; - case 3: return setST(on); break; - case 4: return setDTR(on); break; - case 5: - piCoutObj << "Pin number 5 is ground"; - return false; - case 6: return setDSR(on); break; - case 7: return setRTS(on); break; - case 8: return setCTS(on); break; - case 9: return setRNG(on); break; - default: - piCoutObj << "Pin number " << number << " doesn`t exists!"; - return false; - } - return false; -} - - -bool PISerial::isPin(int number) const { - switch (number) { - case 1: return isCAR(); break; - case 2: return isSR(); break; - case 3: return isST(); break; - case 4: return isDTR(); break; - case 5: return false; - case 6: return isDSR(); break; - case 7: return isRTS(); break; - case 8: return isCTS(); break; - case 9: return isRNG(); break; - default: - piCoutObj << "Pin number " << number << " doesn`t exists!"; - return false; - } - return false; -} - - -bool PISerial::setBit(int bit, bool on, const PIString & bname) { -#ifndef WINDOWS - if (fd < 0) { - piCoutObj << "setBit" << bname << " error: \"" << path() << "\" is not opened!"; - return false; - } - if (ioctl(fd, on ? TIOCMBIS : TIOCMBIC, &bit) < 0) { - piCoutObj << "setBit" << bname << " error: " << errorString(); - return false; - } - return true; -#else - piCoutObj << "setBit" << bname << " doesn`t implemented on Windows, sorry :-("; - return false; -#endif -} - - -bool PISerial::isBit(int bit, const PIString & bname) const { -#ifndef WINDOWS - if (fd < 0) { - piCoutObj << "isBit" << bname << " error: \"" << path() << "\" is not opened!"; - return false; - } - int ret = 0; - if (ioctl(fd, TIOCMGET, &ret) < 0) - piCoutObj << "isBit" << bname << " error: " << errorString(); - return ret & bit; -#else - piCoutObj << "isBit" << bname << " doesn`t implemented on Windows, sorry :-("; - return false; -#endif -} - - -bool PISerial::closeDevice() { - if (!isInitialized()) return true; - if (isRunning()) { - stop(); - PIThread::terminate(); - } - if (fd != -1) { -#ifdef WINDOWS - SetCommState(hCom, &sdesc); - SetCommMask(hCom, mask); - CloseHandle(hCom); - hCom = 0; -#else - tcsetattr(fd, TCSANOW, &sdesc); - ::close(fd); -#endif - fd = -1; - } - return true; -} - - -int PISerial::convertSpeed(PISerial::Speed speed) { - switch (speed) { - case S50: return B50; - case S75: return B75; - 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; - case S1500000: return B1500000; - case S2000000: return B2000000; - case S2500000: return B2500000; - case S3000000: return B3000000; - case S3500000: return B3500000; - case S4000000: return B4000000; - default: break; - } - return B115200; -} - - -/** \brief Advanced read function -* \details Read to pointer "read_to" no more than "max_size" and no longer -* than "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be -* wait forever until "max_size" will be readed. If size <= 0 function -* immediate returns \b false. For read data with unknown size use function -* \a readData(). -* \returns \b True if readed bytes count = "max_size", else \b false -* \sa \a readData() */ -bool PISerial::read(void * data, int size, double timeout_ms) { - if (data == 0 || size <= 0) return false; - int ret, all = 0; - if (timeout_ms > 0.) { - setReadIsBlocking(false); - all = read(data, 1); - timer.reset(); - while (all < size && timer.elapsed_m() < timeout_ms) { - ret = read(&((uchar * )data)[all], size - all); - if (ret > 0) all += ret; - else msleep(1); - } - received(data, all); - return (all == size); - } else { - setReadIsBlocking(true); - all = read(data, 1); - while (all < size) { - ret = read(&((uchar * )data)[all], size - all); - if (ret > 0) all += ret; - } - received(data, all); - return (all == size); - } - return false; -} - - -/** \brief Advanced read function -* \details Read all or no more than "size" and no longer than -* "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be -* wait forever until "size" will be readed. If "size" <= 0 -* function will be read all until "timeout_ms" elaped. \n If size <= 0 -* and "timeout_ms" <= 0 function immediate returns empty string. -* \n This function similar to \a readData() but returns data as string. -* \sa \a readData() */ -PIString PISerial::read(int size, double timeout_ms) { - PIString str; - if (size <= 0 && timeout_ms <= 0.) return str; - int ret, all = 0; - uchar td[1024]; - if (timeout_ms > 0.) { - setReadIsBlocking(false); - timer.reset(); - if (size <= 0) { - while (timer.elapsed_m() < timeout_ms) { - ret = read(td, 1024); - if (ret <= 0) msleep(1); - else str << PIString((char*)td, ret); - } - } else { - while (all < size && timer.elapsed_m() < timeout_ms) { - ret = read(td, size - all); - if (ret <= 0) msleep(1); - else { - str << PIString((char*)td, ret); - all += ret; - } - } - } - } else { - setReadIsBlocking(true); - all = read(td, 1); - str << PIString((char*)td, all); - while (all < size) { - ret = read(td, size - all); - if (ret <= 0) msleep(1); - else { - str << PIString((char*)td, ret); - all += ret; - } - } - } - received(str.data(), str.size_s()); - return str; -} - - -/** \brief Advanced read function -* \details Read all or no more than "size" and no longer than -* "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be -* wait forever until "size" will be readed. If "size" <= 0 -* function will be read all until "timeout_ms" elaped. \n If size <= 0 -* and "timeout_ms" <= 0 function immediate returns empty byte array. -* \n This function similar to \a read() but returns data as byte array. -* \sa \a read() */ -PIByteArray PISerial::readData(int size, double timeout_ms) { - PIByteArray str; - if (size <= 0 && timeout_ms <= 0.) return str; - int ret, all = 0; - uchar td[1024]; - if (timeout_ms > 0.) { - setReadIsBlocking(false); - timer.reset(); - if (size <= 0) { - while (timer.elapsed_m() < timeout_ms) { - ret = read(td, 1024); - if (ret <= 0) msleep(1); - else str.append(td, ret); - } - } else { - while (all < size && timer.elapsed_m() < timeout_ms) { - ret = read(td, size - all); - if (ret <= 0) msleep(1); - else { - str.append(td, ret); - all += ret; - } - } - } - } else { - setReadIsBlocking(true); - all = read(td, 1); - str.append(td, all); - while (all < size) { - ret = read(td, size - all); - if (ret <= 0) msleep(1); - else { - str.append(td, ret); - all += ret; - } - } - } - received(str.data(), str.size_s()); - return str; -} - - -bool PISerial::openDevice() { - //piCout << "ser open" << path(); - if (path().isEmpty()) return false; -#ifdef WINDOWS - DWORD ds = 0, sm = 0; - if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;} - if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;} - PIString wp = "//./" + path(); - hCom = CreateFileA(wp.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); - if (hCom == INVALID_HANDLE_VALUE) { - piCoutObj << "Unable to open \"" << path() << "\""; - fd = -1; - return false; - } - fd = 0; -#else - int om = 0; - switch (mode()) { - case PIIODevice::ReadOnly: om = O_RDONLY; break; - case PIIODevice::WriteOnly: om = O_WRONLY; break; - case PIIODevice::ReadWrite: om = O_RDWR; break; - } - //cout << "init ser " << path_ << " mode " << om << " param " << params << endl; - fd = ::open(path().data(), O_NOCTTY | om); - if (fd == -1) { - piCoutObj << "Unable to open \"" << path() << "\""; - return false; - } - tcgetattr(fd, &desc); - sdesc = desc; - //piCoutObj << "Initialized " << path_; -#endif - applySettings(); - return true; -} - - -void PISerial::applySettings() { -#ifdef WINDOWS - if (fd == -1) return; - COMMTIMEOUTS times; - times.ReadIntervalTimeout = block_read ? vtime : MAXDWORD; - times.ReadTotalTimeoutConstant = block_read ? 0 : 1; - times.ReadTotalTimeoutMultiplier = block_read ? 0 : MAXDWORD; - times.WriteTotalTimeoutConstant = 0; - times.WriteTotalTimeoutMultiplier = block_write ? 0 : 1; - if (SetCommTimeouts(hCom, ×) == -1) - piCoutObj << "Unable to set timeouts for \"" << path() << "\""; - GetCommMask(hCom, &mask); - SetCommMask(hCom, EV_RXCHAR); - GetCommState(hCom, &sdesc); - desc = sdesc; - desc.DCBlength = sizeof(desc); - desc.BaudRate = convertSpeed(outSpeed()); - if (dataBitsCount() >= 5 && dataBitsCount() <= 8) - desc.ByteSize = dataBitsCount(); - else - desc.ByteSize = 8; - PIFlags params = parameters(); - if (params[PISerial::ParityControl]) { - desc.fParity = 1; - desc.Parity = params[PISerial::ParityOdd] ? 1 : 2; - } - desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT; - if (SetCommState(hCom, &desc) == -1) { - piCoutObj << "Unable to set comm state for \"" << path() << "\""; - return; - } -#else - if (fd == -1) return; - tcgetattr(fd, &desc); - desc.c_oflag = desc.c_lflag = desc.c_cflag = 0; - desc.c_iflag = IGNBRK; - desc.c_cflag = CLOCAL | HUPCL; - switch (dataBitsCount()) { - case 5: desc.c_cflag |= (CSIZE & CS5); break; - case 6: desc.c_cflag |= (CSIZE & CS6); break; - case 7: desc.c_cflag |= (CSIZE & CS7); break; - case 8: default: desc.c_cflag |= (CSIZE & CS8); break; - }; - if (isReadable()) desc.c_cflag |= CREAD; - PIFlags params = parameters(); - if (params[PISerial::TwoStopBits]) desc.c_cflag |= CSTOPB; - if (params[PISerial::ParityControl]) { - desc.c_iflag |= INPCK; - desc.c_cflag |= PARENB; - if (params[PISerial::ParityOdd]) desc.c_cflag |= PARODD; - } - desc.c_cc[VMIN] = 1; - desc.c_cc[VTIME] = vtime; - - cfsetispeed(&desc, convertSpeed(inSpeed())); - cfsetospeed(&desc, convertSpeed(outSpeed())); - - tcflush(fd, TCIOFLUSH); - fcntl(fd, F_SETFL, block_read ? 0 : O_NONBLOCK); - - if(tcsetattr(fd, TCSANOW, &desc) < 0) { - piCoutObj << "Can`t set attributes for \"" << path() << "\""; - return; - } -#endif -} - - -void PISerial::setReadIsBlocking(bool yes) { - block_read = yes; -#ifdef WINDOWS - COMMTIMEOUTS times; - times.ReadIntervalTimeout = block_read ? vtime : MAXDWORD; - times.ReadTotalTimeoutConstant = block_read ? 0 : 1; - times.ReadTotalTimeoutMultiplier = block_read ? 0 : MAXDWORD; - times.WriteTotalTimeoutConstant = 0; - times.WriteTotalTimeoutMultiplier = block_write ? 0 : 1; - if (isOpened()) SetCommTimeouts(hCom, ×); -#else - if (isOpened()) fcntl(fd, F_SETFL, yes ? 0 : O_NONBLOCK); -#endif -} - - -/** \brief Basic read function -* \details Read to pointer "read_to" no more than "max_size". If read is -* set to blocking this function will be wait at least one byte. -* \returns Readed bytes count -* \sa \a readData() */ -int PISerial::read(void * read_to, int max_size) { -#ifdef WINDOWS - if (!canRead()) return -1; - WaitCommEvent(hCom, 0, 0); - ReadFile(hCom, read_to, max_size, &readed, 0); - return readed; -#else - if (!canRead()) return -1; - return ::read(fd, read_to, max_size); -#endif -} - - -int PISerial::write(const void * data, int max_size, bool wait) { - //piCoutObj << "send " << max_size << ": " << PIString((char*)data, max_size); - if (fd == -1 || !canWrite()) { - //piCoutObj << "Can`t write to uninitialized COM"; - return -1; - } -#ifdef WINDOWS - if (block_write != wait) { - block_write = wait; - setReadIsBlocking(block_read); - } - DWORD wrote; - WriteFile(hCom, data, max_size, &wrote, 0); -#else - int wrote; - wrote = ::write(fd, data, max_size); - if (wait) tcdrain(fd); -#endif - return (int)wrote; - //piCoutObj << "Error while sending"; - //piCoutObj << "Wrote " << wrote << " bytes in " << path_; -} - - -bool PISerial::configureDevice(const void * e_main, const void * e_parent) { - PIConfig::Entry * em = (PIConfig::Entry * )e_main; - PIConfig::Entry * ep = (PIConfig::Entry * )e_parent; - setDevice(readDeviceSetting("device", device(), em, ep)); - setSpeed((PISerial::Speed)(readDeviceSetting("speed", (int)outSpeed(), em, ep))); - setDataBitsCount(readDeviceSetting("dataBitsCount", dataBitsCount(), em, ep)); - setParameter(PISerial::ParityControl, readDeviceSetting("parityControl", isParameterSet(PISerial::ParityControl), em, ep)); - setParameter(PISerial::ParityOdd, readDeviceSetting("parityOdd", isParameterSet(PISerial::ParityOdd), em, ep)); - setParameter(PISerial::TwoStopBits, readDeviceSetting("twoStopBits", isParameterSet(PISerial::TwoStopBits), em, ep)); - return true; -} - - -PIString PISerial::constructFullPath() const { - PIString ret(fullPathPrefix() + "://"); - ret << path() << ":" << int(inSpeed()) << ":" << dataBitsCount(); - if (parameters()[ParityControl]) { - if (parameters()[ParityOdd]) ret << ":O"; - else ret << ":E"; - } else ret << ":N"; - if (parameters()[TwoStopBits]) ret << ":2"; - else ret << ":1"; - return ret; -} - - -void PISerial::configureFromFullPath(const PIString & full_path) { - PIStringList pl = full_path.split(":"); - for (int i = 0; i < pl.size_s(); ++i) { - PIString p(pl[i]); - switch (i) { - case 0: setPath(p); break; - case 1: setSpeed((Speed)(p.toInt())); break; - case 2: setDataBitsCount(p.toInt()); break; - case 3: - p = p.toLowerCase(); - if (p != "n") setParameter(ParityControl); - if (p == "o") setParameter(ParityOdd); - break; - case 4: if (p.toInt() == 2) setParameter(TwoStopBits); break; - } - } -} - - -PIVector PISerial::availableSpeeds() { - PIVector spds; - spds << 50 << 75 << 110 << 300 << 600 << 1200 << 2400 << 4800 << - 9600 << 19200 << 38400 << 57600 << 115200 << 1500000 << - 2000000 << 2500000 << 3000000 << 3500000 << 4000000; - return spds; -} - - -PIStringList PISerial::availableDevices(bool test) { - PIStringList dl; -#ifdef WINDOWS - HKEY key = 0; - RegOpenKey(HKEY_LOCAL_MACHINE, (LPCTSTR)"HARDWARE\\DEVICEMAP\\SERIALCOMM", &key); - if (key != 0) { - char name[1024], data[1024]; - DWORD name_len = 1024, data_len = 1024, type = 0, index = 0; - LONG ret; - while ((ret = RegEnumValue(key, index, (LPTSTR)name, &name_len, NULL, &type, (uchar * )data, &data_len)) != ERROR_NO_MORE_ITEMS) { - dl << PIString(data); - index++; - } - RegCloseKey(key); - } -#else -# ifndef ANDROID - PIStringList prefixes; -# ifdef QNX - prefixes << "ser"; -# else - prefixes << "ttyS" << "ttyO" << "ttyUSB" << "ttyACM" << "ttyGS" - << "ttyMI" << "ttymxc" << "ttyAMA" << "rfcomm" << "ircomm"; -# ifdef FREE_BSD - prefixes << "cu"; -# endif - PIFile file_prefixes("/proc/tty/drivers", PIIODevice::ReadOnly); - if (file_prefixes.open()) { - PIString fc = file_prefixes.readAll(true), line, cpref; - PIStringList words; - file_prefixes.close(); - while (!fc.isEmpty()) { - words.clear(); - line = fc.takeLine(); - if (line.isEmpty()) break; - while (!line.isEmpty()) - words << line.takeWord(); - if (words.size_s() < 2) break; - if (words.back() != "serial") continue; - cpref = words[1]; - int li = cpref.findLast("/"); - if (li > 0) cpref.cutLeft(li + 1); - prefixes << cpref; - } - prefixes.removeDuplicates(); - } -# endif - PIDir dir("/dev"); - PIVector de = dir.entries(); - piForeachC (PIDir::DirEntry & e, de) { - piForeachC (PIString & p, prefixes) { - if (e.name.left(p.size_s()) != p) continue; - dl << "/dev/" + e.name; - } - } -# endif -#endif - if (test) { - for (int i = 0; i < dl.size_s(); ++i) { -#ifdef WINDOWS - void * hCom = CreateFileA(dl[i].data(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); - if (hCom == INVALID_HANDLE_VALUE) { -#else - int fd = ::open(dl[i].data(), O_NOCTTY | O_RDONLY); - if (fd == -1) { -#endif - dl.remove(i); - --i; - continue; - } - int void_ = 0; - bool rok = true; -#ifdef WINDOWS - /*COMMTIMEOUTS times; - times.ReadIntervalTimeout = MAXDWORD; - times.ReadTotalTimeoutConstant = 0; - times.ReadTotalTimeoutMultiplier = 0; - times.WriteTotalTimeoutConstant = 1; - times.WriteTotalTimeoutMultiplier = 0; - SetCommTimeouts(hCom, ×); - if (ReadFile(hCom, &void_, 1, &readed_, 0) == 0) - rok = GetLastError() == ;*/ -#else - fcntl(fd, F_SETFL, O_NONBLOCK); - if (::read(fd, &void_, 1) == -1) - rok = errno != EIO; - -#endif - if (!rok) { - dl.remove(i); - --i; - continue; - } -#ifdef WINDOWS - CloseHandle(hCom); -#else - ::close(fd); -#endif - } - } - return dl; -} diff --git a/piserial.h b/piserial.h deleted file mode 100644 index 5d6ae328..00000000 --- a/piserial.h +++ /dev/null @@ -1,310 +0,0 @@ -/*! \file piserial.h - * \brief Serial device -*/ -/* - PIP - Platform Independent Primitives - COM - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PISERIAL_H -#define PISERIAL_H - -#include "pitimer.h" -#include "piiodevice.h" -#ifndef WINDOWS -# include -# include -# include -# ifndef B50 -# define B50 0000001 -# endif -# ifndef B75 -# define B75 0000002 -# endif -# ifndef B1500000 -# define B1500000 0010012 -# endif -# ifndef B2000000 -# define B2000000 0010013 -# endif -# ifndef B2500000 -# define B2500000 0010014 -# endif -# ifndef B3000000 -# define B3000000 0010015 -# endif -# ifndef B3500000 -# define B3500000 0010016 -# endif -# ifndef B4000000 -# define B4000000 0010017 -# endif -#else -# define TIOCM_LE 1 -# define TIOCM_DTR 4 -# define TIOCM_RTS 7 -# define TIOCM_CTS 8 -# define TIOCM_ST 3 -# define TIOCM_SR 2 -# define TIOCM_CAR 1 -# define TIOCM_RNG 9 -# define TIOCM_DSR 6 -# define B50 50 -# define B75 75 -# define B110 110 -# define B300 300 -# define B600 600 -# define B1200 1200 -# define B2400 2400 -# define B4800 4800 -# define B9600 9600 -# define B14400 14400 -# define B19200 19200 -# define B38400 38400 -# define B57600 57600 -# define B115200 115200 -# define B128000 128000 -# define B256000 256000 -# define B1500000 1500000 -# define B2000000 2000000 -# define B2500000 2500000 -# define B3000000 3000000 -# define B3500000 3500000 -# define B4000000 4000000 -#endif -#ifndef CRTSCTS -# define CRTSCTS 020000000000 -#endif - - -class PIP_EXPORT PISerial: public PIIODevice -{ - PIIODEVICE(PISerial) -public: - - //! Contructs an empty %PISerial - PISerial(); - - //! \brief Parameters of PISerial - enum Parameters { - ParityControl /*! Enable parity check and generate */ = 0x1, - ParityOdd /*! Parity is odd instead of even */ = 0x2, - TwoStopBits /*! Two stop bits instead of one */ = 0x4 - }; - - //! \brief Speed of PISerial - enum Speed { - S50 /*! 50 baud */ = 50, - S75 /*! 75 baud */ = 75, - S110 /*! 110 baud */ = 110, - S300 /*! 300 baud */ = 300, - S600 /*! 600 baud */ = 600, - S1200 /*! 1200 baud */ = 1200, - S2400 /*! 2400 baud */ = 2400, - S4800 /*! 4800 baud */ = 4800, - S9600 /*! 9600 baud */ = 9600, - S19200 /*! 19200 baud */ = 19200, - S38400 /*! 38400 baud */ = 38400, - S57600 /*! 57600 baud */ = 57600, - S115200 /*! 115200 baud */ = 115200, - S1500000 = 1500000, // Linux only - S2000000 = 2000000, // Linux only - S2500000 = 2500000, // Linux only - S3000000 = 3000000, // Linux only - S3500000 = 3500000, // Linux only - S4000000 = 4000000 // Linux only - }; - - //! Contructs %PISerial with device name "device", speed "speed" and parameters "params" - PISerial(const PIString & device, PISerial::Speed speed = S115200, PIFlags params = 0); - - ~PISerial(); - - - //! Set both input and output speed to "speed" - void setSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); setProperty("inSpeed", (int)speed); applySettings();} - - //! Set output speed to "speed" - void setOutSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); applySettings();} - - //! Set input speed to "speed" - void setInSpeed(PISerial::Speed speed) {setProperty("inSpeed", (int)speed); applySettings();} - - //! Set device name to "dev" - void setDevice(const PIString & dev) {setPath(dev); if (isOpened()) {close(); open();};} - - - //! Set parameters to "parameters_" - void setParameters(PIFlags parameters_) {setProperty("parameters", (int)parameters_); applySettings();} - - //! Set parameter "parameter" to "on" state - void setParameter(PISerial::Parameters parameter, bool on = true); - - //! Returns if parameter "parameter" is set - bool isParameterSet(PISerial::Parameters parameter) const; - - //! Returns parameters - PIFlags parameters() const {return (PIFlags)(property("parameters").toInt());} - - - //! Set data bits count. Valid range is from 5 to 8, befault is 8 - void setDataBitsCount(int bits) {setProperty("dataBitsCount", bits); applySettings();} - - //! Returns data bits count - int dataBitsCount() const {return property("dataBitsCount").toInt();} - - - //! Set pin number "number" to logic level "on". Valid numbers are 4 (DTR) and 7 (RTS) - bool setPin(int number, bool on); - - //! Returns pin number "number" logic level. Valid numbers range is from 1 to 9 - bool isPin(int number) const; - - bool setLE(bool on) {return setBit(TIOCM_LE, on, "LE");} // useless function, just formally - bool setDTR(bool on) {return setBit(TIOCM_DTR, on, "DTR");} - bool setRTS(bool on) {return setBit(TIOCM_RTS, on, "RTS");} - bool setCTS(bool on) {return setBit(TIOCM_CTS, on, "CTS");} // useless function, just formally - bool setST(bool on) {return setBit(TIOCM_ST, on, "ST");} // useless function, just formally - bool setSR(bool on) {return setBit(TIOCM_SR, on, "SR");} // useless function, just formally - bool setCAR(bool on) {return setBit(TIOCM_CAR, on, "CAR");} // useless function, just formally - bool setRNG(bool on) {return setBit(TIOCM_RNG, on, "RNG");} // useless function, just formally - bool setDSR(bool on) {return setBit(TIOCM_DSR, on, "DSR");} // useless function, just formally - - bool isLE() const {return isBit(TIOCM_LE, "LE");} - bool isDTR() const {return isBit(TIOCM_DTR, "DTR");} - bool isRTS() const {return isBit(TIOCM_RTS, "RTS");} - bool isCTS() const {return isBit(TIOCM_CTS, "CTS");} - bool isST() const {return isBit(TIOCM_ST, "ST");} - bool isSR() const {return isBit(TIOCM_SR, "SR");} - bool isCAR() const {return isBit(TIOCM_CAR, "CAR");} - bool isRNG() const {return isBit(TIOCM_RNG, "RNG");} - bool isDSR() const {return isBit(TIOCM_DSR, "DSR");} - - void setVTime(int t) {vtime = t; applySettings();} - - - //! Set read is blocking for function read(void * read_to, int max_size) - void setReadIsBlocking(bool yes); - - - //! Returns device name - PIString device() const {return path();} - - //! Returns output speed - PISerial::Speed outSpeed() const {return (PISerial::Speed)(property("outSpeed").toInt());} - - //! Returns input speed - PISerial::Speed inSpeed() const {return (PISerial::Speed)(property("inSpeed").toInt());} - - int VTime() const {return vtime;} - - - //! Discard all buffered input and output data - void flush() { -#ifndef WINDOWS - if (fd != -1) tcflush(fd, TCIOFLUSH); -#endif - } - - int read(void * read_to, int max_size); - bool read(void * read_to, int max_size, double timeout_ms); - PIString read(int size = -1, double timeout_ms = 1000.); - PIByteArray readData(int size = -1, double timeout_ms = 1000.); - - - //! \brief Write to device data "data" with maximum size "max_size" and wait for data written if "wait" is \b true. - //! \returns sended bytes count - int write(const void * data, int max_size, bool wait = false); - - //! \brief Write to device data "data" with maximum size "size" and wait for data written if "wait" is \b true. - //! \returns \b true if sended bytes count = "size" - bool send(const void * data, int size, bool wait = false) {return (write(data, size, wait) == size);} - - //! \brief Write to device string "data" and wait for data written if "wait" is \b true. - //! \returns \b true if sended bytes count = size of string - bool send(const PIString & data, bool wait = false) {return (write(data.data(), data.lengthAscii(), wait) == data.size_s());} - - //! \brief Write to device byte array "data" and wait for data written if "wait" is \b true. - //! \returns \b true if sended bytes count = size of string - bool send(const PIByteArray & data, bool wait = false) {return (write(data.data(), data.size_s(), wait) == data.size_s());} - - PIString constructFullPath() const; - - - //! \brief Returns all available speeds for serial devices - static PIVector availableSpeeds(); - - //! \brief Returns all available system devices. If "test" each device will be tried to open - static PIStringList availableDevices(bool test = false); - -//! \ioparams -//! \{ -#ifdef DOXYGEN - //! \brief device, default "" - string device; - - //! \brief input/output speed, default 115200 - int speed; - - //! \brief dataBitsCount, default 8 - int dataBitsCount; - - //! \brief parityControl, default false - bool parityControl; - - //! \brief parityOdd, default false - bool parityOdd; - - //! \brief twoStopBits, default false - bool twoStopBits; -#endif -//! \} - -protected: - PIString fullPathPrefix() const {return "ser";} - void configureFromFullPath(const PIString & full_path); - bool configureDevice(const void * e_main, const void * e_parent = 0); - int write(const void * data, int max_size) {return write(data, max_size, true);} - - //! Executes when any read function was successful. Default implementation does nothing - virtual void received(const void * data, int size) {;} - - void _init(); - void applySettings(); - int convertSpeed(PISerial::Speed speed); - bool setBit(int bit, bool on, const PIString & bname); - bool isBit(int bit, const PIString & bname) const; - - bool openDevice(); - bool closeDevice(); - -#ifdef WINDOWS - DCB desc, sdesc; - void * hCom; - DWORD readed, mask; - bool block_write; -#else - termios desc, sdesc; - uint readed; -#endif - int fd, vtime; - bool block_read; - PITimer timer; - -}; - -#endif // PISERIAL_H diff --git a/pisignals.cpp b/pisignals.cpp deleted file mode 100644 index b67ec964..00000000 --- a/pisignals.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - PIP - Platform Independent Primitives - Signals - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pisignals.h" - -PISignals::SignalEvent PISignals::ret_func; - - -void PISignals::grabSignals(PIFlags signals_) { - if (signals_[PISignals::Interrupt]) signal(signalCode(PISignals::Interrupt), PISignals::signal_event); - if (signals_[PISignals::Illegal]) signal(signalCode(PISignals::Illegal), PISignals::signal_event); - if (signals_[PISignals::Abort]) signal(signalCode(PISignals::Abort), PISignals::signal_event); - if (signals_[PISignals::FPE]) signal(signalCode(PISignals::FPE), PISignals::signal_event); - if (signals_[PISignals::SegFault]) signal(signalCode(PISignals::SegFault), PISignals::signal_event); - if (signals_[PISignals::Termination]) signal(signalCode(PISignals::Termination), PISignals::signal_event); -#ifndef WINDOWS - if (signals_[PISignals::Hangup]) signal(signalCode(PISignals::Hangup), PISignals::signal_event); - if (signals_[PISignals::Quit]) signal(signalCode(PISignals::Quit), PISignals::signal_event); - if (signals_[PISignals::Kill]) signal(signalCode(PISignals::Kill), PISignals::signal_event); - if (signals_[PISignals::BrokenPipe]) signal(signalCode(PISignals::BrokenPipe), PISignals::signal_event); - if (signals_[PISignals::Timer]) signal(signalCode(PISignals::Timer), PISignals::signal_event); - if (signals_[PISignals::UserDefined1]) signal(signalCode(PISignals::UserDefined1), PISignals::signal_event); - if (signals_[PISignals::UserDefined2]) signal(signalCode(PISignals::UserDefined2), PISignals::signal_event); - if (signals_[PISignals::ChildStopped]) signal(signalCode(PISignals::ChildStopped), PISignals::signal_event); - if (signals_[PISignals::Continue]) signal(signalCode(PISignals::Continue), PISignals::signal_event); - if (signals_[PISignals::StopProcess]) signal(signalCode(PISignals::StopProcess), PISignals::signal_event); - if (signals_[PISignals::StopTTY]) signal(signalCode(PISignals::StopTTY), PISignals::signal_event); - if (signals_[PISignals::StopTTYInput]) signal(signalCode(PISignals::StopTTYInput), PISignals::signal_event); - if (signals_[PISignals::StopTTYOutput]) signal(signalCode(PISignals::StopTTYOutput), PISignals::signal_event); -#endif -} - - -int PISignals::signalCode(PISignals::Signal signal) { - switch (signal) { - case PISignals::Interrupt: return SIGINT; - case PISignals::Illegal: return SIGILL; - case PISignals::Abort: return SIGABRT; - case PISignals::FPE: return SIGFPE; - case PISignals::SegFault: return SIGSEGV; - case PISignals::Termination: return SIGTERM; -#ifndef WINDOWS - case PISignals::Hangup: return SIGHUP; - case PISignals::Quit: return SIGQUIT; - case PISignals::Kill: return SIGKILL; - case PISignals::BrokenPipe: return SIGPIPE; - case PISignals::Timer: return SIGALRM; - case PISignals::UserDefined1: return SIGUSR1; - case PISignals::UserDefined2: return SIGUSR2; - case PISignals::ChildStopped: return SIGCHLD; - case PISignals::Continue: return SIGCONT; - case PISignals::StopProcess: return SIGSTOP; - case PISignals::StopTTY: return SIGTSTP; - case PISignals::StopTTYInput: return SIGTTIN; - case PISignals::StopTTYOutput:return SIGTTOU; -#endif - default:; - } - return 0; -} - - -PISignals::Signal PISignals::signalFromCode(int signal) { - switch (signal) { - case SIGINT: return PISignals::Interrupt; - case SIGILL: return PISignals::Illegal; - case SIGABRT: return PISignals::Abort; - case SIGFPE: return PISignals::FPE; - case SIGSEGV: return PISignals::SegFault; - case SIGTERM: return PISignals::Termination; -#ifndef WINDOWS - case SIGHUP: return PISignals::Hangup; - case SIGQUIT: return PISignals::Quit; - case SIGKILL: return PISignals::Kill; - case SIGPIPE: return PISignals::BrokenPipe; - case SIGALRM: return PISignals::Timer; - case SIGUSR1: return PISignals::UserDefined1; - case SIGUSR2: return PISignals::UserDefined2; - case SIGCHLD: return PISignals::ChildStopped; - case SIGCONT: return PISignals::Continue; - case SIGSTOP: return PISignals::StopProcess; - case SIGTSTP: return PISignals::StopTTY; - case SIGTTIN: return PISignals::StopTTYInput; - case SIGTTOU: return PISignals::StopTTYOutput; -#endif - default:; - } - return PISignals::Termination; -} - - -void PISignals::signal_event(int signal) { - if (PISignals::ret_func == 0) return; - PISignals::ret_func(PISignals::signalFromCode(signal)); -} diff --git a/pisignals.h b/pisignals.h deleted file mode 100644 index 859cf35d..00000000 --- a/pisignals.h +++ /dev/null @@ -1,76 +0,0 @@ -/*! \file pisignals.h - * \brief System signals -*/ -/* - PIP - Platform Independent Primitives - Signals - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PISIGNALS_H -#define PISIGNALS_H - -#include "picontainers.h" -#include - -class PIP_EXPORT PISignals -{ -public: - enum Signal { - Interrupt /** Interrupt from keyboard */ = 0x01, // Term Interrupt from keyboard - Illegal /** Illegal Instruction */ = 0x02, // Core Illegal Instruction - Abort /** Abort signal */ = 0x04, // Core Abort signal from abort - FPE /** Floating point exception */ = 0x08, // Core Floating point exception - SegFault /** Invalid memory reference */ = 0x10, // Core Invalid memory reference - Termination /** Termination signal */ = 0x20, // Term Termination signal -#ifndef WINDOWS - Hangup = 0x40, // Term Hangup detected on controlling terminal or death of controlling process - Quit = 0x80, // Core Quit from keyboard - Kill = 0x100, // Term Kill signal - BrokenPipe = 0x200, // Term Broken pipe: write to pipe with no readers - Timer = 0x400, // Term Timer signal from alarm - UserDefined1 = 0x800, // Term User-defined signal 1 - UserDefined2 = 0x1000, // Term User-defined signal 2 - ChildStopped = 0x2000, // Ign Child stopped or terminated - Continue = 0x4000, // Cont Continue if stopped - StopProcess = 0x8000, // Stop Stop process - StopTTY = 0x10000, // Stop Stop typed at tty - StopTTYInput = 0x20000, // Stop tty input for background process - StopTTYOutput = 0x40000, // Stop tty output for background process -#endif - All = 0xFFFFF - }; - - typedef void (*SignalEvent)(PISignals::Signal); - // slot is any function format "void (PISignals::Signal)" - static void setSlot(SignalEvent slot) {ret_func = slot;} - static void grabSignals(PIFlags signals_); - static void raiseSignal(PISignals::Signal signal) {raise(signalCode(signal));} - -private: - PISignals() {ret_func = 0;} - ~PISignals() {} - - static int signalCode(PISignals::Signal signal); - static PISignals::Signal signalFromCode(int signal); - static void signal_event(int signal); - - static SignalEvent ret_func; - -}; - - -#endif // PISIGNALS_H diff --git a/pistack.h b/pistack.h deleted file mode 100644 index 113de2ca..00000000 --- a/pistack.h +++ /dev/null @@ -1,41 +0,0 @@ -/*! \file picontainers.h - * \brief Stack container - * - * This file declare PIStack -*/ -/* - PIP - Platform Independent Primitives - Stack container - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PISTACK_H -#define PISTACK_H - -#include "pivector.h" - -template -class PIP_EXPORT PIStack: public PIVector { -public: - PIStack() {;} - PIVector & push(const T & v) {PIVector::push_back(v); return *this;} - T pop() {return PIVector::take_back();} - T & top() {return PIVector::back();} - const T & top() const {return PIVector::back();} - PIVector toVector() {PIVector v(PIVector::size()); for (uint i = 0; i < PIVector::size(); ++i) v[i] = PIVector::at(i); return v;} -}; - -#endif // PISTACK_H diff --git a/pistatemachine.h b/pistatemachine.h deleted file mode 100644 index 8f54de3c..00000000 --- a/pistatemachine.h +++ /dev/null @@ -1,333 +0,0 @@ -/*! \file pistatemachine.h - * \brief Base class for custom state machine -*/ -/* - PIP - Platform Independent Primitives - State machine - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PISTATEMACHINE_H -#define PISTATEMACHINE_H - -#include "piobject.h" - -/*! \brief Base class for custom state machine - * - * \section PIStateMachine_synopsis Synopsis - * This class provide functionality of state machine. - * You should inherit from this class, implement \a execution() - * and \a transition() functions, set rules and periodically - * call \a tick() function to proper work of machine. - * - * \section PIStateMachine_prepare Prepare for work - * %State machine operates with "state", "rule" and "condition". - * * "State" is some class (by default \c int), associated name and - * optional "handler" - pointer to function executed on every \a tick(); - * * "Rule" define rule of transition from one machine state to other. - * It is also has optional "handler"; - * * "Condition" is a part of rule and define possibility of transition. - * - * First of all you should define states of your machine by function - * \a addState(). Then you should define transition rules for machine - * by function \a addRule(). Finally you can set initial state by function - * \a setInitialState() and provide periodically execution of function - * \a tick(). - * - * \section PIStateMachine_principle Principle of work - * At any time the state machine is in some state. You can ask machine - * to enter in new state by function \a switchToState(). If all conditions - * done machine switch it state immediately, else machine remember request - * and will be try switch to the new state every tick. Successfull state - * switching execute function \a transition(), every tick execute - * function \a execution() with current state. On successfull transition - * if rule "handler" is not null it execute. Every \a tick() if current - * state "handler" is not null it execute. - * - * \section PIStateMachine_conditions Conditions - * Each rule has transition condition. Condition is array of pairs - * (string, number). It means that every condition by name "string" - * should be performed as least "number" times. Empty condition always - * permits transition. - * - * %State machine have current performed conditions. You can read this - * conditions by function \a currentConditions() and perform new - * conditions by functions \a performCondition() and \a performConditions(). - * Currend conditions can de erased by function \a resetConditions(). - * - * \section PIStateMachine_example Example - * This is simple example demonstrates all features: - * \snippet pistatemachine.cpp main -*/ -template -class PIP_EXPORT PIStateMachine: public PIObject -{ - PIOBJECT(PIStateMachine) -public: - //! Constructs an empty state machine - PIStateMachine(void * _parent = 0) {if (_parent == 0) parent_ = this; else parent_ = _parent; resetConditions();} - ~PIStateMachine() {;} - - //! %Condition is a pair (string, number) - typedef PIPair Condition; - - //! %Rule of transition between states of machine - struct Rule { - //! Constuctor - Rule() {handler = 0;} - //! Constuctor - Rule(Type f, Type t, const PIStringList & c = PIStringList(), Handler h = 0, bool at = false, bool rac = false) { - from = f; - to = t; - for (int i = 0; i < c.size_s(); ++i) - conditions << Condition(c[i], 1); - autoTransition = at; - resetAllConditions = rac; - handler = h; - } - //! Source state - Type from; - //! Destination state - Type to; - //! %Conditions of transition - PIVector conditions; - //! Automatic transition - bool autoTransition; - //! Reset or not all performed conditions of machine on transition - bool resetAllConditions; - //! Pointer to function executed on transition - Handler handler; - //! Add condition of transition - void addCondition(const PIString & name, int times = 1) {if (times > 0) conditions << Condition(name, times);} - bool operator ==(const Rule & other) const {return (from == other.from) && (to == other.to);} - bool operator !=(const Rule & other) const {return (from != other.from) || (to != other.to);} - }; - - //! %State of machine - struct State { - //! Constuctor - State() {handler = 0;} - //! Constuctor - State(Type v, const PIString & n = "", Handler h = 0) {value = v; name = n; handler = h;} - //! %State value - Type value; - //! %State name - PIString name; - //! Pointer to function executed on tick - Handler handler; - bool operator ==(const State & other) const {return value == other.value;} - bool operator !=(const State & other) const {return value != other.value;} - }; - - void * parent() const {return parent_;} - void setParent(void * parent) {parent_ = parent;} - - //! Add state of machine - void addState(Type value, const PIString & name = "", Handler handler = 0) {if (states_.contains(State(value, name))) return; states_ << State(value, name, handler);} - - //! States count - int statesCount() const {return states_.size_s();} - - //! Remove all states - void clearStates() {states_.clear();} - - - //! Add rule of transition - void addRule(Type from, Type to, const PIString & condition, Handler handler = 0, bool autoTransition = false, bool resetAllConditions = false) {if (rules_.contains(Rule(from, to))) return; rules_ << Rule(from, to, PIStringList(condition), handler, autoTransition, resetAllConditions);} - - //! Add rule of transition - void addRule(Type from, Type to, Handler handler, bool autoTransition = false, bool resetAllConditions = false) {if (rules_.contains(Rule(from, to))) return; rules_ << Rule(from, to, PIStringList(), handler, autoTransition, resetAllConditions);} - - //! Add rule of transition - void addRule(Type from, Type to, const PIStringList & conditions = PIStringList(), Handler handler = 0, bool autoTransition = false, bool resetAllConditions = false) {if (rules_.contains(Rule(from, to))) return; rules_ << Rule(from, to, conditions, handler, autoTransition, resetAllConditions);} - - //! Add rule of transition - void addRule(const Rule & rule) {if (rules_.contains(rule)) return; rules_ << rule;} - - //! Rules count - int rulesCount() const {return rules_.size_s();} - - //! Remove all rules - void clearRules() {rules_.clear();} - - - //! Setup initial state. \a reset() will set machine state to "value" - void setInitialState(Type value) { - for (int i = 0; i < states_.size_s(); ++i) - if (states_[i].value == value) { - init_ = state_ = states_[i]; - return; - } - } - - /** \brief Try to switch machine state to state "to" - * \details If there is rule of transition exists and this rule conditions - * is performed then machine switched to new state immediately. Otherwise machine - * will be try to enter to new state every \a tick(). - * \return \c true if state switched immediately, otherwise \c false */ - bool switchToState(Type to) { - switch_to = to; - for (int i = 0; i < rules_.size_s(); ++i) { - Rule & r(rules_[i]); - if ((r.from != state_.value) || (r.to != to)) continue; - if (!checkConditions(r)) continue; - State ts = findState(to); - if (r.handler != 0 && parent_ != 0) r.handler(parent_); - transition(state_, ts); - state_ = ts; - resetConditions(r); - return true; - } - return false; - } - - //! Reset machine state to initial and clear all conditions - void reset() {state_ = init_; resetConditions();} - - //! Returns current state of machine - const State & currentState() const {return state_;} - - - //! Reset all performed conditions - void resetConditions() {cond.clear();} - - //! Reset performed condition with name "name" - void resetCondition(const PIString & name) { - for (int i = 0; i < cond.size_s(); ++i) - if (cond[i].first == name) { - cond.remove(i); - i--; - } - } - - //! Perform condition with name "name" "times" times. - void performCondition(const PIString & name, int times = 1) { - if (times <= 0) return; - for (int i = 0; i < cond.size_s(); ++i) - if (cond[i].first == name) { - cond[i].second += times; - return; - } - cond << Condition(name, times); - } - - //! Perform every condition with name from "names" one time. - void performConditions(const PIStringList & names) { - bool ok; - for (int n = 0; n < names.size_s(); ++n) { - ok = false; - for (int i = 0; i < cond.size_s(); ++i) { - if (cond[i].first == names[n]) { - cond[i].second++; - ok = true; - break; - } - } - if (ok) continue; - cond << Condition(names[n], 1); - } - } - - //! Returns all current performed conditions - const PIVector & currentConditions() const {return cond;} - - Type * currentState_ptr() {return &state_.value;} - int * conditionsCount_ptr() {static int c = 0; c = cond.size_s(); return &c;} - -//! \handlers -//! \{ - - //! \fn void tick() - //! \brief Main function of machine. Execute \a execution() and check if need to switch state - - //! \fn void tick(void * data, int delim) - //! \brief Main function of machine. Execute \a execution() and check if need to switch state - -//! \} - - EVENT_HANDLER(void, tick) {tick(0, 0);} - EVENT_HANDLER2(void, tick, void * , data, int, delim) { - execution(state_); - if (state_.handler != 0 && parent_ != 0) state_.handler(parent_); - if (switch_to != state_.value) switchToState(switch_to); - else { - piForeachC (Rule & r, rules_) { - if (!r.autoTransition || r.from != state_.value) continue; - if (checkConditions(r)) { - switchToState(r.to); - break; - } - } - } - } - -protected: - - //! Reimplement this function to process current state of machine - virtual void execution(const State & state) {;} - - //! Reimplement this function to process switching current state of machine - virtual void transition(const State & from, const State & to) {;} - -private: - State findState(Type value) { - for (int i = 0; i < states_.size_s(); ++i) - if (states_[i].value == value) - return states_[i]; - return State(); - } - bool checkConditions(const Rule & rule) { - //if (cond.size_s() < rule.conditions.size_s()) return false; - int oc = 0; - for (int i = 0; i < cond.size_s(); ++i) { - PIString & rn(cond[i].first); - for (int j = 0; j < rule.conditions.size_s(); ++j) { - if (rn != rule.conditions[j].first) continue; - if (cond[i].second < rule.conditions[j].second) return false; - oc++; - } - } - return (rule.conditions.size_s() == oc); - } - void resetConditions(const Rule & rule) { - if (rule.resetAllConditions) { - cond.clear(); - return; - } - for (int i = 0; i < cond.size_s(); ++i) { - PIString & rn(cond[i].first); - for (int j = 0; j < rule.conditions.size_s(); ++j) { - if (rn != rule.conditions[j].first) continue; - cond[i].second -= rule.conditions[j].second; - if (cond[i].second <= 0) { - cond.remove(i); - i--; - } - } - } - } - - PIVector states_; - PIVector rules_; - State init_, state_; - Type switch_to; - void * parent_; - PIVector cond; - -}; - - -#endif // PISTATEMACHINE_H diff --git a/pistring.cpp b/pistring.cpp deleted file mode 100644 index 12cc7407..00000000 --- a/pistring.cpp +++ /dev/null @@ -1,764 +0,0 @@ -/* - PIP - Platform Independent Primitives - String - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pistring.h" - - -/*! \class PIString - * \brief String class - * \details PIP use this class for use string information. - * - * \section PIString_sec0 Synopsis - * This class based on \a PIVector to store information. - * String is a sequence of \a PIChar and can contain multibyte - * symbols. Therefore real memory size of string is symbols count * 4. - * String can be constucted from many types of data and can be converted - * to many types. There are man operators and handly functions to use - * string as you wish. - * - * \section PIString_sec1 To/from data convertions - * Most common constructor is \a PIString(const char * str), where "str" - * is null-terminated string, e.g. \c "string". This is 7 chars with last char = 0. - * Also you can constructs \a PIString from single \a PIChar, \a PIByteArray, - * other \a PIString or sequency of the same characters with custom length.\n \n - * This class has implicit conversions to const char * and - * \c std::string. Also there are functions to make same convertions: - * * \a data() - to const char * , - * * \a stdString() - to \c std::string, - * * \a toByteArray() - to \a PIByteArray. - * - * \section PIString_sec2 Numeric operations - * You can get symbolic representation of any numeric value with function - * \a setNumber(any integer value, int base = 10, bool * ok = 0). Default - * arguments are set for decimal base system, but you can choose any system - * from 2 to 40. There are the same static functions \a fromNumber(), that - * returns \a PIString. \n - * Also there is function \a setReadableSize() which is set human-readable - * size in bytes, Kb, Mb, Gb or Pb. Static analog is \a readableSize(). - * - */ - - -const char PIString::toBaseN[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^'}; -const int PIString::fromBaseN[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - - -void PIString::appendFromChars(const char * c, int s) { - int sz; - wchar_t wc; - for (int i = 0; i < s; ++i) { - if (/*isascii(c[i])*/c[i] >= 0) { - push_back(PIChar(c[i])); - continue; - } - sz = mbtowc(&wc, &(c[i]), 4); - //cout << sz << endl; - 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) { - int l = 0; - while (str[l] != '\0') ++l; - appendFromChars(str, l); - return *this; -} - - -PIString & PIString::operator +=(const wchar_t * str) { - //cout << "wc" << endl; - int l = 0, sz; - char * c = new char[MB_CUR_MAX]; - while (str[l] != 0) ++l; - for (int i = 0; i < l; ++i) { - sz = wctomb(c, str[i]); - switch (sz) { - case 4: - push_back(PIChar(*(int*)c)); - continue; - case 3: - push_back(PIChar(*(int*)c)); - back().ch &= 0xFFFFFF; - continue; - case 2: - push_back(PIChar(*(short * )c)); - continue; - default: - push_back(PIChar(c[0])); - break; - } - } - delete[] c; - return *this; -} - - -#ifdef HAS_LOCALE -PIString & PIString::operator +=(const wstring & str) { - uint l = str.size(); - for (uint i = 0; i < l; ++i) push_back(str[i]); - return *this; -} -#endif - - -PIString & PIString::operator +=(const PIString & str) { - //uint l = str.size(); - *((PIDeque*)this) << *((PIDeque*)&str); - return *this; -} - - -bool PIString::operator ==(const PIString & str) const { - uint l = str.size(); - if (size() != l) return false; - for (uint i = 0; i < l; ++i) - if (str[i] != at(i)) - return false; - return true; -} - - -bool PIString::operator !=(const PIString & str) const { - uint l = str.size(); - if (size() != l) return true; - for (uint i = 0; i < l; ++i) - if (str[i] != at(i)) - return true; - return false; -} - - -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; - if (l == 0) return PIString(); - if (s < 0) { - l += s; - s = 0; - } - if (l < 0) { - //for (uint i = s; i < size(); ++i) - // str += at(i); - return PIString(&(at(s)), size() - s); - } else { - if (l > length() - s) - l = length() - s; - //for (int i = s; i < s + l; ++i) - // str += at(i); - return PIString(&(at(s)), l); - } - return PIString(); -} - - -PIString & PIString::cutMid(const int start, const int len) { - int s = start, l = len; - if (l == 0) return *this; - if (s < 0) { - l += s; - s = 0; - } - if (l < 0) - remove(s, size() - s); - else { - if (l > length() - s) - l = length() - s; - remove(s, l); - } - return *this; -} - - -PIString & PIString::trim() { - int st = 0, fn = 0; - for (int i = 0; i < length(); ++i) - if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) - {st = i; break;} - for (int i = length() - 1; i >= 0; --i) - if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) - {fn = i; break;} - //*this = mid(st, fn - st + 1); - if (fn < size_s() - 1) cutRight(size_s() - fn - 1); - if (st > 0) cutLeft(st); - return *this; -} - - -PIString PIString::trimmed() const { - int st = 0, fn = 0; - for (int i = 0; i < length(); ++i) - if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) - {st = i; break;} - for (int i = length() - 1; i >= 0; --i) - if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) - {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) { - //piCout << "replace" << what << with; - if (what.isEmpty()) { - if (ok != 0) *ok = false; - return *this; - } - 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) { - if (what.isEmpty() || what == with) return *this; - 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]); - PIDeque::insert(index, *((const PIDeque*)&str)); - 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); - ts.cutLeft(ci + delim.length()); - ci = ts.find(delim); - } - if (ts.length() > 0) sl << ts; - return sl; -} - - -int PIString::find(const char str, const int start) const { - for (int i = start; i < length(); ++i) - if (at(i) == str) - return i; - return -1; -} - - -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) - return i; - return -1; -} - - -int PIString::findLast(const char str, const int start) const { - for (int i = length() - 1; i >= start; --i) - if (at(i) == str) - return i; - return -1; -} - - -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) - return i; - return -1; -} - - -int PIString::findWord(const PIString & word, const int start) const { - int f = start - 1, tl = length(), wl = word.length(); - while ((f = find(word, f + 1)) >= 0) { - bool ok = true; - PIChar c; - if (f > 0) {c = (*this)[f - 1]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {ok = false; continue;}} - if (f + wl < tl) {c = (*this)[f + wl]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {ok = false; continue;}} - if (ok) return f; - } - return -1; -} - - -int PIString::findCWord(const PIString & word, const int start) const { - int f = start - 1, tl = length(), wl = word.length(); - while ((f = find(word, f + 1)) >= 0) { - bool ok = true; - PIChar c; - if (f > 0) {c = (*this)[f - 1]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {ok = false; continue;}} - if (f + wl < tl) {c = (*this)[f + wl]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {ok = false; continue;}} - if (ok) return f; - } - return -1; -} - - -bool PIString::startsWith(const PIString & str) const { - if (size() < str.size()) return false; - return str == left(str.size()); -} - - -bool PIString::endsWith(const PIString & str) const { - if (size() < str.size()) return false; - return str == right(str.size()); -} - - -PIString PIString::takeSymbol() { - PIString ret; - int sz = size_s(), ss = -1; - for (int i = 0; i < sz; ++i) { - PIChar c = at(i); - if (c == ' ' || c == '\t' || c == '\n' || c == '\r') - continue; - ss = i; - break; - } - if (ss < 0) return ret; - ret = mid(ss, 1); - cutLeft(ss + 1); - return ret; -} - - -PIString PIString::takeWord() { - int sz = size_s(), ws = -1, we = -1; - for (int i = 0; i < sz; ++i) { - PIChar c = at(i); - if (c == ' ' || c == '\t' || c == '\n' || c == '\r') { - if (we < 0 && ws >= 0) { - we = i; - break; - } - } else { - if (ws < 0) ws = i; - if (we >= 0) break; - } - } - PIString ret = mid(ws, we - ws); - cutLeft(we < 0 ? sz : we); - return ret; -} - - -PIString PIString::takeCWord() { - PIString ret; - int sz = size_s(), ws = -1, we = -1; - for (int i = 0; i < sz; ++i) { - PIChar c = at(i); - if (c == ' ' || c == '\t' || c == '\n' || c == '\r') { - if (we < 0 && ws >= 0) { - we = i; - break; - } - } else { - if (ws < 0) { - if (c.isAlpha() || c == '_') - ws = i; - else - return ret; - } else { - if (!c.isAlpha() && !c.isDigit() && c != '_') { - we = i; - break; - } - } - if (we >= 0) break; - } - } - ret = mid(ws, we - ws); - cutLeft(we < 0 ? sz : we); - return ret; -} - - -PIString PIString::takeLine() { - int sz = size_s(), le = -1; - for (int i = 0; i < sz; ++i) { - PIChar c = at(i); - if (c == '\n') { - le = i; - break; - } - } - PIString ret = left(le); - if (!ret.isEmpty()) - if (ret.back() == '\r') - ret.cutRight(1); - cutLeft(le < 0 ? sz : le + 1); - return ret; -} - - -PIString PIString::takeNumber() { - PIString ret; - int sz = size_s(), ls = -1, le = -1, phase = 0; - for (int i = 0; i < sz; ++i) { - if (phase > 7) break; - PIChar c = at(i); - //piCout << "char " << c << "phase" << phase; - switch (phase) { - case 0: // trim - if (c == ' ' || c == '\t' || c == '\n' || c == '\r') - continue; - phase = 7; - case 7: // sign - if (c == '-' || c == '+') {ls = i; phase = 1; break;} - case 1: // search start - if (c >= '0' && c <= '9') {le = i; if (ls < 0) ls = i; phase = 2; break;} - if (c == '.') {le = i; if (ls < 0) ls = i; phase = 3; break;} - phase = 9; - break; - case 2: // integer - if (c == '.') {le = i; phase = 3; break;} - if (c == 'e' || c == 'E') {le = i; phase = 4; break;} - if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c == 'x') {le = i; break;} - phase = 6; - break; - case 3: // point - if (c == 'e' || c == 'E') {le = i; phase = 4; break;} - if (c >= '0' && c <= '9') {le = i; break;} - phase = 6; - break; - case 4: // exp - if ((c >= '0' && c <= '9') || c == '-' || c == '+') {le = i; phase = 5; break;} - phase = 6; - break; - case 5: // power - if (c >= '0' && c <= '9') {le = i; break;} - phase = 6; - break; - case 6: // suffix - if (c == 'f' || c == 's' || c == 'u' || c == 'l' || c == 'L') {le = i; break;} - phase = 9; - break; - } - if (phase == 6) { - if (c == 'f' || c == 's' || c == 'u' || c == 'l' || c == 'L') le = i; - else phase = 9; - } - } - //piCout << ls << le; - if (le < ls) return ret; - ret = mid(ls, le - ls + 1); - cutLeft(le + 1); - return ret; -} - - -PIString PIString::takeRange(const PIChar & start, const PIChar & end, const PIChar & shield) { - PIString ret; - bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end); - int sz = size_s(), ls = -1, le = -1, cnt = 0; - for (int i = 0; i < sz; ++i) { - PIChar c = at(i); - if (c == shield) {++i; continue;} - if (trim_) { - if (c == ' ' || c == '\t' || c == '\n' || c == '\r') - continue; - trim_ = false; - } - if (eq) { - if (c == start) { - if (cnt == 0) ls = i; - else {le = i; cnt = 0; break;} - cnt++; - } - } else { - if (c == start) { - if (cnt == 0) ls = i; - cnt++; - } - if (c == end) { - cnt--; - if (cnt == 0) le = i; - } - } - if (cnt <= 0) break; - } - //piCout << ls << le << cnt; - if (le < ls || ls < 0 || le < 0 || cnt != 0) return ret; - ret = mid(ls + 1, le - ls - 1); - cutLeft(le + 1); - return ret; -} - - -PIString PIString::toUpperCase() const { - PIString str(*this); - int l = str.size(); - for (int i = 0; i < l; ++i) str[i] = str[i].toUpper(); - return str; -} - - -PIString PIString::toLowerCase() const { - PIString str(*this); - int l = str.size(); - for (int i = 0; i < l; ++i) str[i] = str[i].toLower(); - return str; -} - - -int PIString::lengthAscii() const { - int j = 0; - for (int i = 0; i < size_s(); ++i, ++j) - if (!at(i).isAscii()) ++j; - return j; -} - - -const char * PIString::data() const { - data_.clear(); - uint wc; - uchar tc; - //printf("PIString::data %d\n", size_s()); - for (int i = 0, j = 0; i < size_s(); ++i) { - wc = uint(at(i).toInt()); - //printf("__%d_%d\n", i, wc); - while (tc = wc & 0xFF, tc) { - data_.push_back(uchar(tc)); ++j; - wc >>= 8; - //printf("____%d\n", wc); - } - /*if (at(i).isAscii()) - data_.push_back(uchar(at(i).toAscii())); - else { - data_.push_back((at(i).toCharPtr()[0])); ++j; - data_.push_back((at(i).toCharPtr()[1])); - }*/ - } - data_.push_back(uchar('\0')); - return (const char * )data_.data(); -} - - -string PIString::convertToStd() const { - string s; - uint wc; - uchar tc; - if (size() > 0) { - for (int i = 0; i < length(); ++i) { - wc = uint(at(i).toInt()); - while (tc = wc & 0xFF, tc) { - s.push_back(char(tc)); - wc >>= 8; - } - /*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().toLowerCase().toNativeDecimalPoints()); - short v; - if (s.left(2) == "0x") {sscanf(s.data(), "%hx", &v); return v;} - if (s.left(1) == "0") {sscanf(s.data(), "%ho", &v); return v;} - sscanf(s.data(), "%hd", &v); - return v; -} - - -int PIString::toInt() const { - PIString s(trimmed().toLowerCase().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().toLowerCase().toNativeDecimalPoints()); - long v; - if (s.left(2) == "0x") {sscanf(s.data(), "%lx", &v); return v;} - if (s.left(1) == "0") {sscanf(s.data(), "%lo", &v); return v;} - sscanf(s.data(), "%ld", &v); - return v; -} - - -llong PIString::toLLong() const { - PIString s(trimmed().toLowerCase().toNativeDecimalPoints()); - llong v; - if (s.left(2) == "0x") {sscanf(s.data(), "%llx", &v); return v;} - if (s.left(1) == "0") {sscanf(s.data(), "%llo", &v); return v;} - sscanf(s.data(), "%lld", &v); - return v; -} -*/ - -PIString & PIString::setReadableSize(llong bytes) { - clear(); - if (bytes < 1024) {*this += (PIString::fromNumber(bytes) + " B"); return *this;} - double fres = bytes / 1024.; - llong res = bytes / 1024; - fres -= res; - if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " kB"); return *this;} - fres = res / 1024.; - res /= 1024; - fres -= res; - if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " MB"); return *this;} - fres = res / 1024.; - res /= 1024; - fres -= res; - if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " GB"); return *this;} - fres = res / 1024.; - res /= 1024; - fres -= res; - if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " TB"); return *this;} - fres = res / 1024.; - res /= 1024; - fres -= res; - *this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " PB"); - return *this; -} - - -inline char chrUpr(char c) { - if (c >= 'a' && c <= 'z') return c + 'A' - 'a'; - //if (c >= 'а' && c <= 'я') return c + 'А' - 'а'; - return c; -} - - -inline char chrLwr(char c) { - if (c >= 'A' && c <= 'Z') return c + 'a' - 'A'; - //if (c >= 'А' && c <= 'Я') return c + 'а' - 'А'; - return c; -} - - - -PIStringList& PIStringList::removeDuplicates() { - PIStringList l; - PIString s; - bool ae; - for (int i = 0; i < size_s(); ++i) { - ae = false; - s = at(i); - for (int j = 0; j < l.size_s(); ++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 deleted file mode 100644 index 2fce77c9..00000000 --- a/pistring.h +++ /dev/null @@ -1,901 +0,0 @@ -/*! \file pistring.h - * \brief String - * - * This file declare string and string list classes -*/ -/* - PIP - Platform Independent Primitives - String - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PISTRING_H -#define PISTRING_H - -#include "pibytearray.h" -#include "pichar.h" -#include "math.h" - -class PIStringList; - -class PIP_EXPORT PIString: public PIDeque -{ -public: - //! Contructs an empty string - PIString(): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--;} - - //inline PIString & operator +=(const char c) {push_back(c); return *this;} - PIString & operator +=(const PIChar & c) {push_back(c); return *this;} - PIString & operator +=(const char * str); - PIString & operator +=(const wchar_t * 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); -#ifdef HAS_LOCALE - PIString & operator +=(const wstring & str); -#endif - - //PIString(const char c) {*this += c;} - PIString(const PIString & o): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += o;} - - - //! Contructs string with single symbol "c" - PIString(const PIChar & c): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += c;} - PIString(const char c): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += PIChar(c);} - - /*! \brief Contructs string from c-string "str" - * \details "str" should be null-terminated\n - * Example: \snippet pistring.cpp PIString(char * ) */ - PIString(const char * str): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} - - /*! \brief Contructs string from \c wchar_t c-string "str" - * \details "str" should be null-terminated\n - * Example: \snippet pistring.cpp PIString(wchar_t * ) */ - PIString(const wchar_t * str): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} - - //! Contructs string from std::string "str" - PIString(const string & str): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} - - #ifdef HAS_LOCALE - PIString(const wstring & str): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} -#endif - - //! Contructs string from byte array "ba" - PIString(const PIByteArray & ba): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += ba;} - - //! \brief Contructs string from "len" characters of buffer "str" - PIString(const PIChar * str, const int len): PIDeque(str, size_t(len)) {/*reserve(256); */piMonitor.strings++; piMonitor.containers--;} - - /*! \brief Contructs string from "len" characters of buffer "str" - * \details Example: \snippet pistring.cpp PIString(char * , int) */ - PIString(const char * str, const int len): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += string(str, len);} - - /*! \brief Contructs string as sequence of characters "c" of buffer with length "len" - * \details Example: \snippet pistring.cpp PIString(int, char) */ - PIString(const int len, const char c): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} - - /*! \brief Contructs string as sequence of symbols "c" of buffer with length "len" - * \details Example: \snippet pistring.cpp PIString(int, PIChar) */ - PIString(const int len, const PIChar & c): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} - - - PIString(const short & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const ushort & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const int & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const uint & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const long & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const ulong & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const llong & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const ullong & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const float & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - PIString(const double & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} - - - //~PIString() {piMonitor.strings--; piMonitor.containers++;} - - - PIString & operator =(const PIString & o) {clear(); *this += o; return *this;} - - /*! \brief Return c-string representation of string - * \details Converts content of string to c-string and return - * pointer to first char. This buffer is valid until new convertion - * or execution \a data() or \a toByteArray().\n - * Example: \snippet pistring.cpp PIString::char* */ - operator const char*() {return data();} - - //! Return std::string representation of string - 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;} - - //! Return symbol at index "pos" - PIChar operator [](const int pos) const {return at(pos);} - - //! Return reference to symbol at index "pos" - PIChar & operator [](const int pos) {return at(pos);} - - //! Compare operator - bool operator ==(const PIString & str) const; - - //! Compare operator - bool operator ==(const PIChar c) const {return *this == PIString(c);} - //inline bool operator ==(const char c) const {return *this == PIString(c);} - - //! Compare operator - bool operator ==(const char * str) const {return *this == PIString(str);} - - //! Compare operator - bool operator ==(const string & str) const {return *this == PIString(str);} - - - //! Compare operator - bool operator !=(const PIString & str) const; - - //! Compare operator - bool operator !=(const PIChar c) const {return *this != PIString(c);} - //inline bool operator !=(const char c) const {return *this != PIString(c);} - - //! Compare operator - bool operator !=(const char * str) const {return *this != PIString(str);} - - //! Compare operator - bool operator !=(const string & str) const {return *this != PIString(str);} - - - //! Compare operator - bool operator <(const PIString & str) const; - - //! Compare operator - bool operator <(const PIChar c) const {return *this < PIString(c);} - //inline bool operator <(const char c) const {return *this < PIString(c);} - - //! Compare operator - bool operator <(const char * str) const {return *this < PIString(str);} - - //! Compare operator - bool operator <(const string & str) const {return *this < PIString(str);} - - - //! Compare operator - bool operator >(const PIString & str) const; - - //! Compare operator - bool operator >(const PIChar c) const {return *this > PIString(c);} - //inline bool operator >(const char c) const {return *this > PIString(c);} - - //! Compare operator - bool operator >(const char * str) const {return *this > PIString(str);} - - //! Compare operator - bool operator >(const string & str) const {return *this > PIString(str);} - - - //! Compare operator - bool operator <=(const PIString & str) const {return !(*this > str);} - - //! Compare operator - bool operator <=(const PIChar c) const {return *this <= PIString(c);} - //inline bool operator <=(const char c) const {return *this <= PIString(c);} - - //! Compare operator - bool operator <=(const char * str) const {return *this <= PIString(str);} - - //! Compare operator - bool operator <=(const string & str) const {return *this <= PIString(str);} - - - //! Compare operator - bool operator >=(const PIString & str) const {return !(*this < str);} - - //! Compare operator - bool operator >=(const PIChar c) const {return *this >= PIString(c);} - //inline bool operator >=(const char c) const {return *this >= PIString(c);} - - //! Compare operator - bool operator >=(const char * str) const {return *this >= PIString(str);} - - //! Compare operator - bool operator >=(const string & str) const {return *this >= PIString(str);} - - - operator short() const {return toShort();} - operator ushort() const {return toUShort();} - operator int() const {return toInt();} - operator uint() const {return toUInt();} - operator long() const {return toLong();} - operator ulong() const {return toULong();} - operator llong() const {return toLLong();} - operator ullong() const {return toULLong();} - operator float() const {return toFloat();} - operator double() const {return toDouble();} - - - /*! \brief Append string "str" at the end of string - * \details Example: \snippet pistring.cpp PIString::<<(PIString) */ - PIString & operator <<(const PIString & str) {*this += str; return *this;} - //inline PIString & operator <<(const char c) {*this += c; return *this;} - - /*! \brief Append symbol "c" at the end of string - * \details Example: \snippet pistring.cpp PIString::<<(PIChar) */ - PIString & operator <<(const PIChar & c) {*this += c; return *this;} - - /*! \brief Append c-string "str" at the end of string - * \details Example: \snippet pistring.cpp PIString::<<(char * ) */ - PIString & operator <<(const char * str) {*this += str; return *this;} - - /*! \brief Append \c wchar_t c-string "str" at the end of string - * \details Example: \snippet pistring.cpp PIString::<<(wchar_t * ) */ - PIString & operator <<(const wchar_t * str) {*this += str; return *this;} - - //! Append std::string "str" at the end of string - PIString & operator <<(const string & str) {*this += str; return *this;} - - /*! \brief Append string representation of "num" at the end of string - * \details Example: \snippet pistring.cpp PIString::<<(int) */ - PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;} - PIString & operator <<(const uint & num) {*this += PIString::fromNumber(num); return *this;} - - /*! \brief Append string representation of "num" at the end of string - * \details Example: \snippet pistring.cpp PIString::<<(int) */ - PIString & operator <<(const short & num) {*this += PIString::fromNumber(num); return *this;} - PIString & operator <<(const ushort & num) {*this += PIString::fromNumber(num); return *this;} - - /*! \brief Append string representation of "num" at the end of string - * \details Example: \snippet pistring.cpp PIString::<<(int) */ - PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;} - PIString & operator <<(const ulong & num) {*this += PIString::fromNumber(num); return *this;} - - PIString & operator <<(const llong & num) {*this += PIString::fromNumber(num); return *this;} - PIString & operator <<(const ullong & num) {*this += PIString::fromNumber(num); return *this;} - - /*! \brief Append string representation of "num" at the end of string - * \details Example: \snippet pistring.cpp PIString::<<(int) */ - PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;} - - /*! \brief Append string representation of "num" at the end of string - * \details Example: \snippet pistring.cpp PIString::<<(int) */ - PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;} - - - //! \brief Insert string "str" at the begin of string - PIString & prepend(const PIString & str) {insert(0, str); return *this;} - - //! \brief Insert string "str" at the end of string - PIString & append(const PIString & str) {*this += str; return *this;} - - - /*! \brief Return part of string from symbol at index "start" and maximum length "len" - * \details All variants demonstrated in example: \snippet pistring.cpp PIString::mid - * \sa \a left(), \a right() */ - PIString mid(const int start, const int len = -1) const; - - /*! \brief Return part of string from left and maximum length "len" - * \details Example: \snippet pistring.cpp PIString::left - * \sa \a mid(), \a right() */ - PIString left(const int len) const {return len <= 0 ? PIString() : mid(0, len);} - - /*! \brief Return part of string from right and maximum length "len" - * \details Example: \snippet pistring.cpp PIString::right - * \sa \a mid(), \a left() */ - PIString right(const int len) const {return len <= 0 ? PIString() : mid(size() - len, len);} - - /*! \brief Remove part of string from symbol as index "start" and maximum length "len" - * and return this string - * \details All variants demonstrated in example: \snippet pistring.cpp PIString::cutMid - * \sa \a cutLeft(), \a cutRight() */ - PIString & cutMid(const int start, const int len); - - /*! \brief Remove part of string from left and maximum length "len" and return this string - * \details Example: \snippet pistring.cpp PIString::cutLeft - * \sa \a cutMid(), \a cutRight() */ - PIString & cutLeft(const int len) {return len <= 0 ? *this : cutMid(0, len);} - - /*! \brief Remove part of string from right and maximum length "len" and return this string - * \details Example: \snippet pistring.cpp PIString::cutRight - * \sa \a cutMid(), \a cutLeft() */ - PIString & cutRight(const int len) {return len <= 0 ? *this : cutMid(size() - len, len);} - - /*! \brief Remove spaces at the start and at the end of string and return this string - * \details Example: \snippet pistring.cpp PIString::trim - * \sa \a trimmed() */ - PIString & trim(); - - /*! \brief Return copy of this string without spaces at the start and at the end - * \details Example: \snippet pistring.cpp PIString::trimmed - * \sa \a trim() */ - PIString trimmed() const; - - /*! \brief Replace part of string from index "from" and maximum length "len" - * with string "with" and return this string - * \details Example: \snippet pistring.cpp PIString::replace_0 - * \sa \a replaced(), \a replaceAll() */ - PIString & replace(const int from, const int count, const PIString & with); - - /*! \brief Replace part copy of this string from index "from" and maximum length "len" - * with string "with" and return copied string - * \details Example: \snippet pistring.cpp PIString::replaced_0 - * \sa \a replace(), \a replaceAll() */ - PIString replaced(const int from, const int count, const PIString & with) const {PIString str(*this); str.replace(from, count, with); return str;} - - /*! \brief Replace first founded substring "what" with string "with" and return this string - * \details If "ok" is not null, it set to "true" if something was replaced\n - * Example: \snippet pistring.cpp PIString::replace_1 - * \sa \a replaced(), \a replaceAll() */ - PIString & replace(const PIString & what, const PIString & with, bool * ok = 0); - - /*! \brief Replace first founded substring "what" with string "with" and return copied string - * \details If "ok" is not null, it set to "true" if something was replaced\n - * Example: \snippet pistring.cpp PIString::replaced_1 - * \sa \a replaced(), \a replaceAll() */ - PIString replaced(const PIString & what, const PIString & with, bool * ok = 0) const {PIString str(*this); str.replace(what, with, ok); return str;} - - /*! \brief Replace all founded substrings "what" with strings "with" and return this string - * \details Example: \snippet pistring.cpp PIString::replaceAll - * \sa \a replace(), \a replaced() */ - 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;} - - /*! \brief Repeat content of string "times" times and return this string - * \details Example: \snippet pistring.cpp PIString::repeat */ - PIString & repeat(int times) {PIString ss(*this); times--; piForTimes (times) *this += ss; return *this;} - - /*! \brief Returns repeated "times" times string - * \details Example: \snippet pistring.cpp PIString::repeated */ - PIString repeated(int times) const {PIString ss(*this); return ss.repeat(times);} - - /*! \brief Insert symbol "c" after index "index" and return this string - * \details Example: \snippet pistring.cpp PIString::insert_0 */ - PIString & insert(const int index, const PIChar & c) {PIDeque::insert(index, c); return *this;} - - /*! \brief Insert symbol "c" after index "index" and return this string - * \details Example: \snippet pistring.cpp PIString::insert_1 */ - PIString & insert(const int index, const char & c) {return insert(index, PIChar(c));} - - /*! \brief Insert string "str" after index "index" and return this string - * \details Example: \snippet pistring.cpp PIString::insert_2 */ - PIString & insert(const int index, const PIString & str); - - /*! \brief Insert string "str" after index "index" and return this string - * \details Example: \snippet pistring.cpp PIString::insert_2 */ - PIString & insert(const int index, const char * c) {return insert(index, PIString(c));} - - /*! \brief Enlarge string to length "len" by addition sequence of symbols - * "c" at the end of string, and return this string - * \details Example: \snippet pistring.cpp PIString::expandRightTo - * \sa \a expandLeftTo() */ - PIString & expandRightTo(const int len, const PIChar & c) {if (len > length()) resize(len, c); return *this;} - - /*! \brief Enlarge string to length "len" by addition sequence of symbols - * "c" at the beginning of string, and return this string - * \details Example: \snippet pistring.cpp PIString::expandLeftTo - * \sa \a expandRightTo() */ - PIString & expandLeftTo(const int len, const PIChar & c) {if (len > length()) insert(0, PIString(len - length(), c)); return *this;} - - /*! \brief Reverse string and return this string - * \details Example: \snippet pistring.cpp PIString::reverse - * \sa \a reversed() */ - PIString & reverse() {PIString str(*this); clear(); piForeachR (const PIChar & c, str) push_back(c); return *this;} - - /*! \brief Reverse copy of this string and return it - * \details Example: \snippet pistring.cpp PIString::reversed - * \sa \a reverse() */ - PIString reversed() const {PIString str(*this); str.reverse(); return str;} - - - /*! \brief Take a part of string from symbol at index "start" and maximum length "len" and return it - * \details Example: \snippet pistring.cpp PIString::takeMid - * \sa \a takeLeft, \a takeRight() */ - PIString takeMid(const int start, const int len = -1) {PIString ret(mid(start, len)); cutMid(start, len); return ret;} - - /*! \brief Take a part from the begin of string with maximum length "len" and return it - * \details Example: \snippet pistring.cpp PIString::takeLeft - * \sa \a takeMid(), \a takeRight() */ - PIString takeLeft(const int len) {PIString ret(left(len)); cutLeft(len); return ret;} - - /*! \brief Take a part from the end of string with maximum length "len" and return it - * \details Example: \snippet pistring.cpp PIString::takeRight - * \sa \a takeMid(), \a takeLeft() */ - PIString takeRight(const int len) {PIString ret(right(len)); cutRight(len); return ret;} - - /*! \brief Take a symbol from the begin of this string and return it - * \details Example: \snippet pistring.cpp PIString::takeSymbol - * \sa \a takeWord(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */ - PIString takeSymbol(); - - /*! \brief Take a word from the begin of this string and return it - * \details Example: \snippet pistring.cpp PIString::takeWord - * \sa \a takeSymbol(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */ - PIString takeWord(); - - /*! \brief Take a word with letters, numbers and '_' symbols from the - * begin of this string and return it - * \details Example: \snippet pistring.cpp PIString::takeCWord - * \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber(), \a takeRange() */ - PIString takeCWord(); - - /*! \brief Take a line from the begin of this string and return it - * \details Example: \snippet pistring.cpp PIString::takeLine - * \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeNumber(), \a takeRange() */ - PIString takeLine(); - - /*! \brief Take a number with C-format from the begin of this string and return it - * \details Example: \snippet pistring.cpp PIString::takeNumber - * \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeLine(), \a takeRange() */ - PIString takeNumber(); - - /*! \brief Take a range between "start" and "end" symbols from the begin of this - * string and return it. - * \details "Shield" symbol prevent analysis of the next symbol. - * Example: \snippet pistring.cpp PIString::takeRange - * \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber() */ - PIString takeRange(const PIChar & start, const PIChar & end, const PIChar & shield = '\\'); - - //const char * data() {return convertToStd().c_str();} - - - /*! \brief Return real bytes count of this string - * \details It`s equivalent length of char sequence - * returned by function \a data() \n - * Example: \snippet pistring.cpp PIString::lengthAscii - * \sa \a data() */ - int lengthAscii() const; - - /*! \brief Return \c char * representation of this string - * \details This function fill buffer by sequence - * of chars. Minimum length of this buffer is count - * of symbols. Returned \c char * is valid until next - * execution of this function.\n - * Example: \snippet pistring.cpp PIString::data - * \sa \a lengthAscii() */ - const char * data() const; - - //! \brief Return \c std::string representation of this string - std::string stdString() const {return convertToStd();} -#ifdef HAS_LOCALE - wstring stdWString() const {return convertToWString();} -#endif - - //! \brief Return \a PIByteArray contains \a data() of this string - PIByteArray toByteArray() const {const char * d = data(); return PIByteArray(d, lengthAscii());} - - /*! \brief Split string with delimiter "delim" to \a PIStringList and return it - * \details Example: \snippet pistring.cpp PIString::split */ - PIStringList split(const PIString & delim) const; - - - //! \brief Convert each symbol in copyed string to upper case and return it - PIString toUpperCase() const; - - //! \brief Convert each symbol in copyed string to lower case and return it - PIString toLowerCase() const; -#ifdef HAS_LOCALE - PIString toNativeDecimalPoints() const {PIString s(*this); if (currentLocale == 0) return s; return s.replaceAll(".", currentLocale->decimal_point).replaceAll(",", currentLocale->decimal_point);} -#else - PIString toNativeDecimalPoints() const {return PIString(*this).replaceAll(",", ".");} -#endif - - - //! \brief Search substring "str" from symbol at index "start" and return first occur position - //! \details Example: \snippet pistring.cpp PIString::find - int find(const char str, const int start = 0) const; - - //! \brief Search substring "str" from symbol at index "start" and return first occur position - //! \details Example: \snippet pistring.cpp PIString::find - int find(const PIString str, const int start = 0) const; - - //! \brief Search substring "str" from symbol at index "start" and return first occur position - //! \details Example: \snippet pistring.cpp PIString::find - int find(const char * str, const int start = 0) const {return find(PIString(str), start);} - - //! \brief Search substring "str" from symbol at index "start" and return first occur position - //! \details Example: \snippet pistring.cpp PIString::find - int find(const string str, const int start = 0) const {return find(PIString(str), start);} - - //! \brief Search substring "str" from symbol at index "start" and return last occur position - //! \details Example: \snippet pistring.cpp PIString::findLast - int findLast(const char str, const int start = 0) const; - - //! \brief Search substring "str" from symbol at index "start" and return last occur position - //! \details Example: \snippet pistring.cpp PIString::findLast - int findLast(const PIString str, const int start = 0) const; - - //! \brief Search substring "str" from symbol at index "start" and return last occur position - //! \details Example: \snippet pistring.cpp PIString::findLast - int findLast(const char * str, const int start = 0) const {return findLast(PIString(str), start);} - - //! \brief Search substring "str" from symbol at index "start" and return last occur position - //! \details Example: \snippet pistring.cpp PIString::findLast - int findLast(const string str, const int start = 0) const {return findLast(PIString(str), start);} - - //! \brief Search word "word" from symbol at index "start" and return first occur position. - //! \details Example: \snippet pistring.cpp PIString::findWord - int findWord(const PIString & word, const int start = 0) const; - - //! \brief Search C-style word "word" from symbol at index "start" and return first occur position. - //! \details Example: \snippet pistring.cpp PIString::findCWord - int findCWord(const PIString & word, const int start = 0) const; - - //! \brief Return if string starts with "str" - bool startsWith(const PIString & str) const; - - //! \brief Return if string ends with "str" - bool endsWith(const PIString & str) const; - - //! \brief Return symbols length of string - int length() const {return size();} - - //! \brief Return \c true if string is empty, i.e. length = 0 - bool isEmpty() const {return (size() == 0 || *this == "");} - - - //! \brief Return \c true if string equal "true", "yes", "on" or positive not null numeric value - bool toBool() const {PIString s(*this); if (atof(s.toNativeDecimalPoints().data()) > 0. || s.trimmed().toLowerCase() == "true" || s.trimmed().toLowerCase() == "yes" || s.trimmed().toLowerCase() == "on") return true; return false;} - - //! \brief Return \c char numeric value of string - char toChar() const; - - //! \brief Return \c short numeric value of string in base "base" - //! \details Example: \snippet pistring.cpp PIString::toNumber - short toShort(int base = -1, bool * ok = 0) const {return short(toNumberBase(*this, base, ok));} - - //! \brief Return \c ushort numeric value of string in base "base" - //! \details Example: \snippet pistring.cpp PIString::toNumber - ushort toUShort(int base = -1, bool * ok = 0) const {return ushort(toNumberBase(*this, base, ok));} - - //! \brief Return \c int numeric value of string in base "base" - //! \details Example: \snippet pistring.cpp PIString::toNumber - int toInt(int base = -1, bool * ok = 0) const {return int(toNumberBase(*this, base, ok));} - - //! \brief Return \c uint numeric value of string in base "base" - //! \details Example: \snippet pistring.cpp PIString::toNumber - uint toUInt(int base = -1, bool * ok = 0) const {return uint(toNumberBase(*this, base, ok));} - - //! \brief Return \c long numeric value of string in base "base" - //! \details Example: \snippet pistring.cpp PIString::toNumber - long toLong(int base = -1, bool * ok = 0) const {return long(toNumberBase(*this, base, ok));} - - //! \brief Return \c ulong numeric value of string in base "base" - //! \details Example: \snippet pistring.cpp PIString::toNumber - ulong toULong(int base = -1, bool * ok = 0) const {return ulong(toNumberBase(*this, base, ok));} - - //! \brief Return \c llong numeric value of string in base "base" - //! \details Example: \snippet pistring.cpp PIString::toNumber - llong toLLong(int base = -1, bool * ok = 0) const {return toNumberBase(*this, base, ok);} - - //! \brief Return \c ullong numeric value of string in base "base" - //! \details Example: \snippet pistring.cpp PIString::toNumber - ullong toULLong(int base = -1, bool * ok = 0) const {return ullong(toNumberBase(*this, base, ok));} - - //! \brief Return \c float numeric value of string - //! \details Example: \snippet pistring.cpp PIString::toFloat - float toFloat() const {return (float)atof(toNativeDecimalPoints().data());} - - //! \brief Return \c double numeric value of string - //! \details Example: \snippet pistring.cpp PIString::toFloat - double toDouble() const {return atof(toNativeDecimalPoints().data());} - - //! \brief Return \c ldouble numeric value of string - //! \details Example: \snippet pistring.cpp PIString::toFloat - ldouble toLDouble() const {return atof(toNativeDecimalPoints().data());} - - //inline PIString & setNumber(const char value) {clear(); *this += itos(value); return *this;} - - //! \brief Set string content to numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::setNumber - PIString & setNumber(const short value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} - - //! \brief Set string content to numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::setNumber - PIString & setNumber(const ushort value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} - - //! \brief Set string content to numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::setNumber - PIString & setNumber(const int value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} - - //! \brief Set string content to numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::setNumber - PIString & setNumber(const uint value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} - - //! \brief Set string content to numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::setNumber - PIString & setNumber(const long value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} - - //! \brief Set string content to numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::setNumber - PIString & setNumber(const ulong value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} - - //! \brief Set string content to numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::setNumber - PIString & setNumber(const llong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} - - //! \brief Set string content to numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::setNumber - PIString & setNumber(const ullong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} - - //! \brief Set string content to numeric representation of "value" - //! \details Example: \snippet pistring.cpp PIString::setFloat - PIString & setNumber(const float value) {clear(); *this += ftos(value); return *this;} - - //! \brief Set string content to numeric representation of "value" - //! \details Example: \snippet pistring.cpp PIString::setFloat - PIString & setNumber(const double & value) {clear(); *this += dtos(value); return *this;} - - //! \brief Set string content to numeric representation of "value" - //! \details Example: \snippet pistring.cpp PIString::setFloat - PIString & setNumber(const ldouble & value) {clear(); *this += dtos(value); return *this;} - - //! \brief Set string content to human readable size in B/kB/MB/GB/TB - //! \details Example: \snippet pistring.cpp PIString::setReadableSize - PIString & setReadableSize(llong bytes); - - //inline static PIString fromNumber(const char value) {return PIString(itos(value));} - - //! \brief Return string contains numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::fromNumber - static PIString fromNumber(const short value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);} - - //! \brief Return string contains numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::fromNumber - static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);} - - //! \brief Return string contains numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::fromNumber - static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);} - - //! \brief Return string contains numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::fromNumber - static PIString fromNumber(const uint value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);} - - //! \brief Return string contains numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::fromNumber - static PIString fromNumber(const long value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);} - - //! \brief Return string contains numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::fromNumber - static PIString fromNumber(const ulong value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);} - - //! \brief Return string contains numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::fromNumber - static PIString fromNumber(const llong & value, int base = 10, bool * ok = 0) {return fromNumberBaseS(value, base, ok);} - - //! \brief Return string contains numeric representation of "value" in base "base" - //! \details Example: \snippet pistring.cpp PIString::fromNumber - static PIString fromNumber(const ullong & value, int base = 10, bool * ok = 0) {return fromNumberBaseU(value, base, ok);} - - //! \brief Return string contains numeric representation of "value" - //! \details Example: \snippet pistring.cpp PIString::fromFloat - static PIString fromNumber(const float value) {return PIString(ftos(value));} - - //! \brief Return string contains numeric representation of "value" - //! \details Example: \snippet pistring.cpp PIString::fromFloat - static PIString fromNumber(const double & value) {return PIString(dtos(value));} - - //! \brief Return string contains numeric representation of "value" - //! \details Example: \snippet pistring.cpp PIString::fromFloat - static PIString fromNumber(const ldouble & value) {return PIString(dtos(value));} - - //! \brief Return "true" or "false" - static PIString fromBool(const bool value) {return PIString(value ? "true" : "false");} - - //! \brief Return string contains human readable size in B/kB/MB/GB/TB - //! \details Example: \snippet pistring.cpp PIString::readableSize - static PIString readableSize(llong bytes) {PIString s; s.setReadableSize(bytes); return s;} - - PIString & removeAll(char v) {replaceAll(v, ""); return *this;} - PIString & removeAll(const PIString & v) {replaceAll(v, ""); return *this;} - -private: - static const char toBaseN[]; - static const int fromBaseN[]; - - static PIString fromNumberBaseS(const llong value, int base = 10, bool * ok = 0) { - if (value == 0) return PIString("0"); - if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();} - if (ok != 0) *ok = true; - if (base == 10) return itos(value); - PIString ret; - llong v = value < 0 ? -value : value, cn; - int b = base; - while (v >= llong(base)) { - cn = v % b; - v /= b; - //cout << int(cn) << ", " << int(v) << endl; - ret.push_front(PIChar(toBaseN[cn])); - } - if (v > 0) ret.push_front(PIChar(toBaseN[v])); - if (value < 0) ret.push_front('-'); - return ret; - } - static PIString fromNumberBaseU(const ullong value, int base = 10, bool * ok = 0) { - if (value == 0) return PIString("0"); - if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();} - if (ok != 0) *ok = true; - if (base == 10) return itos(value); - PIString ret; - ullong v = value, cn; - int b = base; - while (v >= ullong(base)) { - cn = v % b; - v /= b; - //cout << int(cn) << ", " << int(v) << endl; - ret.push_front(PIChar(toBaseN[cn])); - } - if (v > 0) ret.push_front(PIChar(toBaseN[v])); - return ret; - } - static llong toNumberBase(const PIString & value, int base = -1, bool * ok = 0) { - PIString v = value.trimmed(); - if (base < 0) { - int ind = v.find("0x"); - if (ind == 0 || ind == 1) {v.remove(ind, 2); base = 16;} - else base = 10; - } else - if (base < 2 || base > 40) {if (ok != 0) *ok = false; return 0;} - //v.reverse(); - if (ok != 0) *ok = true; - PIVector digits; - llong ret = 0, m = 1; - bool neg = false; - int cs; - for (int i = 0; i < v.size_s(); ++i) { - if (v[i] == PIChar('-')) {neg = !neg; continue;} - cs = fromBaseN[int(v[i].toAscii())]; - if (cs < 0 || cs >= base) break; - digits << cs; - } - for (int i = digits.size_s() - 1; i >= 0; --i) { - ret += digits[i] * m; - m *= base; - } - if (neg) ret = -ret; - /*piForeachC (PIChar & i, v) { - if (i == PIChar('-')) {ret = -ret; continue;} - cs = fromBaseN[int(i.toAscii())]; - cout << i << " = " << cs << endl; - if (cs < 0 || cs >= base) return ret; - ret += cs * m; - m *= base; - }*/ - return ret; - } - void appendFromChars(const char * c, int s); - string convertToStd() const; -#ifdef HAS_LOCALE - wstring convertToWString() const {wstring s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toWChar()); return s;} -#endif - - mutable PIByteArray data_; - //string std_string; - //wstring std_wstring; - -}; - - -//! \relatesalso PIString \brief Output operator to std::ostream (cout) -inline std::ostream & operator <<(std::ostream & s, const PIString & v) {for (int i = 0; i < v.length(); ++i) s << v[i]; return s;} - -//! \relatesalso PIString \brief Input operator from std::istream (cin) -inline std::istream & operator >>(std::istream & s, PIString & v) {string ss; s >> ss; v << PIString(ss); return s;} - -//! \relatesalso PIString \relatesalso PICout \brief Output operator to PICout -inline PICout operator <<(PICout s, const PIString & v) {s.space(); s.quote(); s.setControl(0, true); for (int i = 0; i < v.length(); ++i) s << v[i]; s.restoreControl(); s.quote(); return s;} - - -//! \relatesalso PIString \relatesalso PIByteArray \brief Output operator to PIByteArray -inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {int l = v.lengthAscii(); s << l; if (l <= 0) return s; int os = s.size_s(); s.enlarge(l); memcpy(s.data(os), v.data(), l); return s;} - -//! \relatesalso PIString \relatesalso PIByteArray \brief Input operator from PIByteArray -inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {if (s.size() < 4) {v.clear(); return s;} int l; s >> l; if (l <= 0) return s; v = PIString((const char * )s.data(), l); s.remove(0, l); return s;} - - -//! \relatesalso PIString \brief Return concatenated string -inline PIString operator +(const PIString & str, const PIString & f) {PIString s(str); s += f; return s;} - -//inline PIString operator +(const PIString & f, const char c) {PIString s(f); s.push_back(c); return s;} - -//! \relatesalso PIString \brief Return concatenated string -inline PIString operator +(const PIString & f, const char * str) {PIString s(f); s += str; return s;} - -//! \relatesalso PIString \brief Return concatenated string -inline PIString operator +(const PIString & f, const string & str) {PIString s(f); s += str; return s;} - -//inline PIString operator +(const char c, const PIString & f) {return PIString(c) + f;} - -//! \relatesalso PIString \brief Return concatenated string -inline PIString operator +(const char * str, const PIString & f) {return PIString(str) + f;} - -//! \relatesalso PIString \brief Return concatenated string -inline PIString operator +(const string & str, const PIString & f) {return PIString(str) + f;} - -inline char chrUpr(char c); -inline char chrLwr(char c); - - -/*!\brief Strings array class - * \details This class is based on \a PIVector and - * expand it functionality. */ -class PIP_EXPORT PIStringList: public PIDeque -{ -public: - - //! Contructs empty strings list - PIStringList() {;} - - //! Contructs strings list with one string "str" - PIStringList(const PIString & str) {push_back(str);} - - //! Contructs empty strings list with strings "s0" and "s1" - PIStringList(const PIString & s0, const PIString & s1) {push_back(s0); push_back(s1);} - - //! Contructs empty strings list with strings "s0", "s1" and "s2" - PIStringList(const PIString & s0, const PIString & s1, const PIString & s2) {push_back(s0); push_back(s1); push_back(s2);} - - //! Contructs empty strings list with strings "s0", "s1", "s2" and "s3" - PIStringList(const PIString & s0, const PIString & s1, const PIString & s2, const PIString & s3) {push_back(s0); push_back(s1); push_back(s2); push_back(s3);} - - PIStringList(const PIStringList & o): PIDeque() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];} - - - //! \brief Join all strings in one with delimiter "delim" and return it - //! \details Example: \snippet pistring.cpp PIStringList::join - 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;} - - //! \brief Remove all strings equal "value" and return this - //! \details Example: \snippet pistring.cpp PIStringList::removeStrings - 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) {PIDeque::remove(num); return *this;} - PIStringList & remove(uint num, uint count) {PIDeque::remove(num, count); return *this;} - - //! \brief Remove duplicated strings and return this - //! \details Example: \snippet pistring.cpp PIStringList::removeDuplicates - PIStringList & removeDuplicates(); - - //! \brief Trim all strings - //! \details Example: \snippet pistring.cpp PIStringList::trim - PIStringList & trim() {for (uint i = 0; i < size(); ++i) at(i).trim(); return *this;} - - //! Return sum of lengths of all strings - uint contentSize() {uint s = 0; for (uint i = 0; i < size(); ++i) s += at(i).size(); return s;} - - PIStringList & operator =(const PIStringList & o) {clear(); for (uint i = 0; i < o.size(); ++i) *this << o[i]; return *this;} - - PIStringList & operator <<(const PIString & str) {push_back(str); return *this;} - PIStringList & operator <<(const PIStringList & sl) {piForeachC (PIString & i, sl) push_back(i); return *this;} - //inline PIStringList & operator <<(const char c) {push_back(PIString(c)); return *this;} - 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;} - -}; - - -//! \relatesalso PIStringList \relatesalso PIByteArray \brief Output operator to PIByteArray -inline PIByteArray & operator <<(PIByteArray & s, const PIStringList & v) {s << v.size_s(); for (int i = 0; i < v.size_s(); ++i) s << v[i]; return s;} - -//! \relatesalso PIStringList \relatesalso PIByteArray \brief Input operator from PIByteArray -inline PIByteArray & operator >>(PIByteArray & s, PIStringList & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} - - -//! \relatesalso PIStringList \brief Output operator to std::ostream (cout) -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;} - -//! \relatesalso PIStringList \relatesalso PICout \brief Output operator to PICout -inline PICout operator <<(PICout s, const PIStringList & v) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < v.size(); ++i) {s << '\"' << v[i] << '\"'; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;} - -#endif // PISTRING_H diff --git a/pisystemmonitor.cpp b/pisystemmonitor.cpp deleted file mode 100644 index 0f4d97dc..00000000 --- a/pisystemmonitor.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - PIP - Platform Independent Primitives - Process resource monitor - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pisystemmonitor.h" - - -PISystemMonitor::PISystemMonitor(): PIThread() { - pID_ = cycle = 0; - cpu_count = 1; -#ifndef WINDOWS -# ifdef QNX - page_size = 4096; -# else - page_size = getpagesize(); -# endif - cpu_count = sysconf(_SC_NPROCESSORS_ONLN); - if (cpu_count < 1) cpu_count = 1; -#endif -} - - -bool PISystemMonitor::startOnProcess(int pID) { - stop(); - pID_ = pID; -#ifndef WINDOWS - file.open("/proc/" + PIString::fromNumber(pID_) + "/stat", PIIODevice::ReadOnly); - filem.open("/proc/" + PIString::fromNumber(pID_) + "/statm", PIIODevice::ReadOnly); - if (!file.isOpened()) { - piCoutObj << "Can`t find process with ID = " << pID_ << "!"; - return false; - } - cycle = -1; -#endif - return start(25); -} - - -void PISystemMonitor::run() { -#ifndef WINDOWS - file.seekToBegin(); - PIString str(file.readAll(true)); - int si = str.find('(') + 1, fi = 0, cc = 1; - for (int i = si; i < str.size_s(); ++i) { - if (str[i] == '(') cc++; - if (str[i] == ')') cc--; - if (cc <= 0) { - fi = i; - break; - } - } - stat.exec_name = str.mid(si, fi - si); - str.cutMid(si - 1, fi - si + 3); - PIStringList sl = str.split(" "); - if (sl.size_s() < 18) return; - stat.ID = sl[0].toInt(); - stat.state = sl[1]; - stat.parent_ID = sl[2].toInt(); - stat.group_ID = sl[3].toInt(); - stat.session_ID = sl[4].toInt(); - if (cycle < 0) { - cpu_u_prev = cpu_u_cur = sl[12].toLLong(); - cpu_s_prev = cpu_s_cur = sl[13].toLLong(); - } - cycle++; - if (cycle >= 40) { - cpu_u_prev = cpu_u_cur; - cpu_s_prev = cpu_s_cur; - cpu_u_cur = sl[12].toLLong(); - cpu_s_cur = sl[13].toLLong(); - stat.cpu_load_system = cpu_s_cur - cpu_s_prev; - stat.cpu_load_user = cpu_u_cur - cpu_u_prev; - if (stat.cpu_load_system > 100) stat.cpu_load_system = 100; - if (stat.cpu_load_user > 100) stat.cpu_load_user = 100; - stat.cpu_load_system /= cpu_count; - stat.cpu_load_user /= cpu_count; - cycle = 0; - } - stat.priority = sl[16].toInt(); - stat.threads = sl[18].toInt(); - - filem.seekToBegin(); - str = filem.readAll(true); - sl = str.split(" "); - if (sl.size_s() < 5) return; - stat.virtual_memsize = sl[0].toLong() * page_size; - stat.resident_memsize = sl[1].toLong() * page_size; - stat.share_memsize = sl[2].toLong() * page_size; - stat.data_memsize = sl[5].toLong() * page_size; - stat.physical_memsize = stat.resident_memsize - stat.share_memsize; - - stat.physical_memsize_readable = PIString::readableSize(stat.physical_memsize); - stat.resident_memsize_readable = PIString::readableSize(stat.resident_memsize); - stat.share_memsize_readable = PIString::readableSize(stat.share_memsize); - stat.virtual_memsize_readable = PIString::readableSize(stat.virtual_memsize); - stat.data_memsize_readable = PIString::readableSize(stat.data_memsize); -#endif -} diff --git a/pisystemmonitor.h b/pisystemmonitor.h deleted file mode 100644 index d74cd200..00000000 --- a/pisystemmonitor.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - PIP - Platform Independent Primitives - Process resource monitor - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PISYSTEMMONITOR_H -#define PISYSTEMMONITOR_H - -#include "pithread.h" -#include "piprocess.h" - -class PIP_EXPORT PISystemMonitor: public PIThread -{ -public: - PISystemMonitor(); - - struct ProcessStats { - PIString exec_name; - PIString state; - int ID; - int parent_ID; - int group_ID; - int session_ID; - int priority; - int threads; - ulong physical_memsize; - ulong resident_memsize; - ulong share_memsize; - ulong virtual_memsize; - ulong data_memsize; - PIString physical_memsize_readable; - PIString resident_memsize_readable; - PIString share_memsize_readable; - PIString virtual_memsize_readable; - PIString data_memsize_readable; - float cpu_load_system; - float cpu_load_user; - }; - - bool startOnProcess(int pID); - bool startOnSelf() {return startOnProcess(PIProcess::currentPID());} - const ProcessStats & statistic() const {return stat;} - -private: - void run(); - - PIFile file, filem; - ProcessStats stat; - int pID_, page_size, cpu_count, cycle; -#ifndef WINDOWS - llong cpu_u_cur, cpu_u_prev, cpu_s_cur, cpu_s_prev; -#endif - -}; - -#endif // PISYSTEMMONITOR_H diff --git a/pisystemtests.cpp b/pisystemtests.cpp deleted file mode 100644 index dcc1a8c6..00000000 --- a/pisystemtests.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - PIP - Platform Independent Primitives - System tests results (see system_test folder) - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pisystemtests.h" - - -namespace PISystemTests { - long time_resolution_ns = 1; - long time_elapsed_ns = 0; - long usleep_offset_us = 60; - - PISystemTestReader pisystestreader; - -}; - - -PISystemTests::PISystemTestReader::PISystemTestReader() { -#ifndef WINDOWS - PIConfig conf("/etc/pip.conf", PIIODevice::ReadOnly); - conf.setReopenEnabled(false); - time_resolution_ns = conf.getValue("time_resolution_ns", 1); - time_elapsed_ns = conf.getValue("time_elapsed_ns", 0); - usleep_offset_us = conf.getValue("usleep_offset_us", 60); -#endif -} diff --git a/pisystemtests.h b/pisystemtests.h deleted file mode 100644 index ddf602d9..00000000 --- a/pisystemtests.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - PIP - Platform Independent Primitives - System tests results (see system_test folder) - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PISYSTEMTESTS_H -#define PISYSTEMTESTS_H - -#include "piconfig.h" - -namespace PISystemTests { - PIP_EXPORT extern long time_resolution_ns; - PIP_EXPORT extern long time_elapsed_ns; - PIP_EXPORT extern long usleep_offset_us; - - class PISystemTestReader { - public: - PISystemTestReader(); - }; - - extern PISystemTestReader pisystestreader; - -}; - -#endif // PISYSTEMTESTS_H diff --git a/pithread.cpp b/pithread.cpp deleted file mode 100644 index fafe7d3d..00000000 --- a/pithread.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* - PIP - Platform Independent Primitives - Thread - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pithread.h" -#include "pisystemtests.h" - - -/*! \class PIThread - * \brief Thread class - * \details This class allow you exec your code in separate thread. - * - * \section PIThread_sec0 Synopsis - * Multithreading allow you to write program which will be executed - * in several threads simultaneously. This trend allow you to use all - * cores of modern processors, but there are many dangers. - * - * This class provide virtual functions \a begin(), \a run() and \a end(), - * which describes start, execution and finish work of some process. - * These functions executes in \b separate thread. When you execute - * \a start(), %PIThread create separate system thread and sequentially - * executes function \a begin(), \a run() and \a end(). You can - * reimplement each function and write your own code to execute. - * Scheme of functions executing: -\code{.cpp} -begin(); -event started(); -while (isRunning()) { - run(); - ThreadFunc(); - msleep(timer_delay); -} -event stopped(); -end(); -\endcode - * Unlike from directly using "pthread" or some similar you doesn`t need - * to write your own main thread cycle and sleep at every cycle end. - * %PIThread make it for you, and your job is to set sleep value from - * contructor or when starting thread, and reimplement \a begin(), \a run() - * and \a end() functions. - * - * \section PIThread_sec1 Using without subclassing - * You can use %PIThread without subclassing by using "ThreadFunc" pointer - * that can be set from constructor or by overloaded function \a start(ThreadFunc func, int timer_delay). - * If "func" if not null this function will be executed as \a run(). ThreadFunc is any static - * function with format void func(void * data). "Data" is custom data set from constructor or - * with function \a setData(). \n Also you can connect to event \a started(), but - * in this case you should to white your thread main cycle, because this event raised only one time. - * - * \section PIThread_sec2 Locking - * %PIThread has inrternal mutex that can be locked and unlocked every \a run() if you set this flag - * with function \a needLockRun(bool). Also you can access to this mutex by functions \a lock(), \a unlock() - * and \a mutex(). Using this functions together with needLockRun(true) can guarantee one-thread access to - * some data. - * - */ - - -PIThread::PIThread(void * data, ThreadFunc func, bool startNow, int timer_delay): PIObject() { - piMonitor.threads++; - thread = 0; - data_ = data; - ret_func = func; - running = lockRun = false; - priority_ = piNormal; - timer = timer_delay; - if (startNow) start(timer_delay); -} - - -PIThread::PIThread(bool startNow, int timer_delay): PIObject() { - piMonitor.threads++; - thread = 0; - ret_func = 0; - running = lockRun = false; - priority_ = piNormal; - timer = timer_delay; - if (startNow) start(timer_delay); -} - - -PIThread::~PIThread() { - piMonitor.threads--; - if (!running || thread == 0) return; -#ifndef WINDOWS -# ifdef ANDROID - pthread_kill(thread, SIGSTOP); -# else - pthread_cancel(thread); -# endif -#else - TerminateThread(thread, 0); - CloseHandle(thread); -#endif -} - - -bool PIThread::start(int timer_delay) { - if (running) return false; - terminating = running = false; - timer = timer_delay; -#ifndef WINDOWS - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setschedparam(&attr, &sparam); - if (pthread_create(&thread, &attr, thread_function, this) == 0) { - setPriority(priority_); - running = true; - return true; - } -#else - thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)thread_function, this, 0, 0); - if (thread != 0) { - setPriority(priority_); - running = true; - return true; - } -#endif - return false; -} - - -bool PIThread::startOnce() { - if (running) return false; - terminating = running = false; -#ifndef WINDOWS - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setschedparam(&attr, &sparam); - if (pthread_create(&thread, &attr, thread_function_once, this) == 0) { - setPriority(priority_); - running = true; - return true; - } -#else - thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)thread_function_once, this, 0, 0); - if (thread != 0) { - setPriority(priority_); - running = true; - return false; - } -#endif - return false; -} - - -void PIThread::terminate() { - if (thread == 0) return; - running = false; -#ifndef WINDOWS -# ifdef ANDROID - pthread_kill(thread, SIGSTOP); -# else - pthread_cancel(thread); -# endif -#else - TerminateThread(thread, 0); - CloseHandle(thread); -#endif - thread = 0; - end(); -} - - -void * PIThread::thread_function(void * t) { -#ifndef WINDOWS -# ifndef ANDROID - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); -# endif -#else - __PISetTimerResolution(); -#endif - PIThread & ct = *((PIThread * )t); - ct.running = true; - ct.begin(); - ct.started(); - while (!ct.terminating) { - if (ct.lockRun) ct.mutex_.lock(); - ct.run(); - if (ct.ret_func != 0) ct.ret_func(ct.data_); - if (ct.lockRun) ct.mutex_.unlock(); - if (ct.timer > 0) msleep(ct.timer); - } - ct.stopped(); - ct.end(); - ct.running = false; - //cout << "thread " << t << " exiting ... " << endl; -#ifndef WINDOWS - pthread_exit(0); -#else - ExitThread(0); -#endif - return 0; -} - - -void * PIThread::thread_function_once(void * t) { -#ifndef WINDOWS -# ifndef ANDROID - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); -# endif -#else - __PISetTimerResolution(); -#endif - PIThread & ct = *((PIThread * )t); - ct.running = true; - ct.begin(); - ct.started(); - if (ct.lockRun) ct.mutex_.lock(); - ct.run(); - if (ct.ret_func != 0) ct.ret_func(ct.data_); - if (ct.lockRun) ct.mutex_.unlock(); - ct.stopped(); - ct.end(); - ct.running = false; - //cout << "thread " << t << " exiting ... " << endl; -#ifndef WINDOWS - pthread_exit(0); -#else - ExitThread(0); -#endif - return 0; -} - - -void PIThread::setPriority(PIThread::Priority prior) { - priority_ = prior; -#ifndef WINDOWS -# ifndef LINUX - sparam.sched_priority = (int)priority_; -# else - sparam.__sched_priority = (int)priority_; -# endif - if (!running) return; - pthread_getschedparam(thread, &policy, &sparam); - pthread_setschedparam(thread, policy, &sparam); -#else - if (!running) return; - SetThreadPriority(thread, -(int)priority_); -#endif -} - - -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 deleted file mode 100644 index 0bef0650..00000000 --- a/pithread.h +++ /dev/null @@ -1,219 +0,0 @@ -/*! \file pithread.h - * \brief Thread - * - * This file declare thread class and some wait functions -*/ -/* - PIP - Platform Independent Primitives - Thread - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PITHREAD_H -#define PITHREAD_H - -#include -#include "pimutex.h" -#include "piobject.h" - -typedef void (*ThreadFunc)(void * ); - -class PIP_EXPORT PIThread: public PIObject -{ - PIOBJECT(PIThread) -public: - - //! Contructs thread with custom data "data", external function "func" and main cycle delay "timer_delay". - PIThread(void * data, ThreadFunc func, bool startNow = false, int timer_delay = -1); - - //! Contructs thread with main cycle delay "timer_delay". - PIThread(bool startNow = false, int timer_delay = -1); - virtual ~PIThread(); - -#ifdef DOXYGEN - //! Priority of thread - enum Priority {piHighest /** Highest */, - piHigh /** High */, - piNormal /** Normal, default */, - piLow /** Low */, - piLowerst /** Lowest */ - }; -#else -# ifdef QNX - enum Priority {piHighest = 12, - piHigh = 11, - piNormal = 10, - piLow = 9, - piLowerst = 8 }; -# else - enum Priority {piHighest = -2, - piHigh = -1, - piNormal = 0, - piLow = 1, - piLowerst = 2 }; -# endif -#endif - - EVENT_HANDLER0(bool, start) {return start(-1);} - EVENT_HANDLER1(bool, start, int, timer_delay); - EVENT_HANDLER1(bool, start, ThreadFunc, func) {ret_func = func; return start(-1);} - EVENT_HANDLER2(bool, start, ThreadFunc, func, int, timer_delay) {ret_func = func; return start(timer_delay);} - EVENT_HANDLER0(bool, startOnce); - EVENT_HANDLER1(bool, startOnce, ThreadFunc, func) {ret_func = func; return startOnce();} - EVENT_HANDLER0(void, stop) {stop(false);} - EVENT_HANDLER1(void, stop, bool, wait) {terminating = true; if (wait) waitForFinish();} - EVENT_HANDLER0(void, terminate); - - //! \brief Set common data passed to external function - void setData(void * d) {data_ = d;} - - //! \brief Set external function that will be executed after every \a run() - void setSlot(ThreadFunc func) {ret_func = func;} - - //! \brief Set priority of thread - void setPriority(PIThread::Priority prior); - - //! \brief Returns common data passed to external function - void * data() const {return data_;} - - //! \brief Return priority of thread - PIThread::Priority priority() const {return priority_;} - - //! \brief Return \c true if thread is running - bool isRunning() const {return running;} - - bool isStopping() const {return running && terminating;} - - EVENT_HANDLER0(bool, waitForStart) {return waitForStart(-1);} - EVENT_HANDLER1(bool, waitForStart, int, timeout_msecs); - EVENT_HANDLER0(bool, waitForFinish) {return waitForFinish(-1);} - EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs); - - //! \brief Set necessity of lock every \a run with internal mutex - void needLockRun(bool need) {lockRun = need;} - EVENT_HANDLER0(void, lock) {mutex_.lock();} - EVENT_HANDLER0(void, unlock) {mutex_.unlock();} - - //! \brief Return internal mutex - PIMutex & mutex() {return mutex_;} - - EVENT(started) - EVENT(stopped) - -//! \handlers -//! \{ - - /** \fn bool start(int timer_delay = -1) - * \brief Start thread - * \details Start execution of \a run() in internal loop with - * "timer_delay" delay in milliseconds. If "timer_delay" <= 0 - * there is no delay in loop. Thread also exec external function - * set by \a setSlot() if it`s not null - * - * \return \c false if thread already started or can`t start thread */ - - /** \fn bool start(ThreadFunc func, int timer_delay = -1) - * \brief Start thread - * \details Overloaded function. Set external function "func" before start - * - * \return \c false if thread already started or can`t start thread */ - - /** \fn bool startOnce() - * \brief Start thread without internal loop - * \details Start execution of \a run() once. Thread also exec - * external function set by \a setSlot() if it`s not null - * - * \return \c false if thread already started or can`t start thread */ - - /** \fn bool startOnce(ThreadFunc func) - * \brief Start thread without internal loop - * \details Overloaded function. Set external function "func" before start - * - * \return \c false if thread already started or can`t start thread */ - - /** \fn void stop(bool wait = false) - * \brief Stop thread - * \details Stop execution of thread and wait for it finish - * if "wait" is \c true. This function can block for infinite - * time if "wait" is \c true and any of thread function is - * busy forever */ - - /** \fn void terminate() - * \brief Strongly stop thread - * \details Stop execution of thread immediately */ - - /** \fn bool waitForStart(int timeout_msecs = -1) - * \brief Wait for thread start - * \details This function block until thread finish for "timeout_msecs" - * or forever if "timeout_msecs" < 0 - * - * \return \c false if timeout is exceeded */ - - /** \fn bool waitForFinish(int timeout_msecs = -1) - * \brief Wait for thread finish - * \details This function block until thread start for "timeout_msecs" - * or forever if "timeout_msecs" < 0 - * - * \return \c false if timeout is exceeded */ - - //! \fn void lock() - //! \brief Lock internal mutex - - //! \fn void unlock() - //! \brief Unlock internal mutex - -//! \} -//! \events -//! \{ - - //! \fn void started() - //! \brief Raise on thread start - - //! \fn void stopped() - //! \brief Raise on thread stop - -//! \} - -protected: - static void * thread_function(void * t); - static void * thread_function_once(void * t); - - - //! Function executed once at the start of thread. - virtual void begin() {;} - - //! Function executed at every "timer_delay" msecs until thread was stopped. - virtual void run() {;} - - //! Function executed once at the end of thread. - virtual void end() {;} - - volatile bool terminating, running, lockRun; - int timer, policy; - void * data_; - PIMutex mutex_; - PIThread::Priority priority_; - ThreadFunc ret_func; -#ifndef WINDOWS - pthread_t thread; - sched_param sparam; -#else - void * thread; -#endif - -}; - -#endif // PITHREAD_H diff --git a/pitime.cpp b/pitime.cpp deleted file mode 100644 index 78d7ea56..00000000 --- a/pitime.cpp +++ /dev/null @@ -1,363 +0,0 @@ -/* - PIP - Platform Independent Primitives - Timer - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pitime.h" -#include "pisystemtests.h" - - -/*! \class PISystemTime - * \brief System time - * - * \section PISystemTime_sec0 Synopsis - * This class provide arithmetic functions for POSIX system time. - * This time represents as seconds and nanosecons in integer formats. - * You can take current system time with function \a PISystemTime::current(), - * compare times, sum or subtract two times, convert time to/from - * seconds, milliseconds, microseconds or nanoseconds. - * \section PISystemTime_sec1 Example - * \snippet pitimer.cpp system_time -*/ - - -void piUSleep(int usecs) { - if (usecs <= 0) return; -#ifdef WINDOWS - if (usecs > 0) Sleep(usecs / 1000); -#else - usecs -= PISystemTests::usleep_offset_us; - if (usecs > 0) usleep(usecs); -#endif -} - - -bool operator ==(const PITime & t0, const PITime & t1) { - return (t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds); -} - - -bool operator <(const PITime & t0, const PITime & t1) { - if (t0.hours == t1.hours) { - if (t0.minutes == t1.minutes) { - return t0.seconds < t1.seconds; - } else return t0.minutes < t1.minutes; - } else return t0.hours < t1.hours; -} - - -bool operator >(const PITime & t0, const PITime & t1) { - if (t0.hours == t1.hours) { - if (t0.minutes == t1.minutes) { - return t0.seconds > t1.seconds; - } else return t0.minutes > t1.minutes; - } else return t0.hours > t1.hours; -} - -bool operator ==(const PIDate & t0, const PIDate & t1) { - return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day); -} - - -bool operator <(const PIDate & t0, const PIDate & t1) { - if (t0.year == t1.year) { - if (t0.month == t1.month) { - return t0.day < t1.day; - } else return t0.month < t1.month; - } else return t0.year < t1.year; -} - - -bool operator >(const PIDate & t0, const PIDate & t1) { - if (t0.year == t1.year) { - if (t0.month == t1.month) { - return t0.day > t1.day; - } else return t0.month > t1.month; - } else return t0.year > t1.year; -} - -bool operator ==(const PIDateTime & t0, const PIDateTime & t1) { - return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day && - t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds); -} - - -bool operator <(const PIDateTime & t0, const PIDateTime & t1) { - if (t0.year == t1.year) { - if (t0.month == t1.month) { - if (t0.day == t1.day) { - if (t0.hours == t1.hours) { - if (t0.minutes == t1.minutes) { - return t0.seconds < t1.seconds; - } else return t0.minutes < t1.minutes; - } else return t0.hours < t1.hours; - } else return t0.day < t1.day; - } else return t0.month < t1.month; - } else return t0.year < t1.year; -} - - -bool operator >(const PIDateTime & t0, const PIDateTime & t1) { - if (t0.year == t1.year) { - if (t0.month == t1.month) { - if (t0.day == t1.day) { - if (t0.hours == t1.hours) { - if (t0.minutes == t1.minutes) { - return t0.seconds > t1.seconds; - } else return t0.minutes > t1.minutes; - } else return t0.hours > t1.hours; - } else return t0.day > t1.day; - } else return t0.month > t1.month; - } else return t0.year > t1.year; -} - - -PITime PITime::current() { - time_t rt = ::time(0); - tm * pt = localtime(&rt); - PITime t; - t.seconds = pt->tm_sec; - t.minutes = pt->tm_min; - t.hours = pt->tm_hour; - return t; -} - - -PIDate PIDate::current() { - time_t rt = ::time(0); - tm * pt = localtime(&rt); - PIDate d; - d.day = pt->tm_mday; - d.month = pt->tm_mon + 1; - d.year = pt->tm_year + 1900; - return d; -} - - -PIDateTime PIDateTime::current() { - time_t rt = ::time(0); - tm * pt = localtime(&rt); - PIDateTime dt; - dt.milliseconds = 0; - dt.seconds = pt->tm_sec; - dt.minutes = pt->tm_min; - dt.hours = pt->tm_hour; - dt.day = pt->tm_mday; - dt.month = pt->tm_mon + 1; - dt.year = pt->tm_year + 1900; - return dt; -} - - -PISystemTime PISystemTime::abs() const { - if (seconds < 0) - return PISystemTime(piAbsl(seconds) - 1, 1e+9 - piAbsl(nanoseconds)); - else - return PISystemTime(piAbsl(seconds), piAbsl(nanoseconds)); -} - - -PISystemTime PISystemTime::current(bool precise_but_not_system) { -#ifdef WINDOWS - if (precise_but_not_system) { - llong qpc(0); - if (__pi_perf_freq > 0) { - qpc = __PIQueryPerformanceCounter(); - return PISystemTime::fromSeconds(qpc / double(__pi_perf_freq)); - } - return PISystemTime(); - } else { - FILETIME ft, sft; -# if (_WIN32_WINNT >= 0x0602) - GetSystemTimePreciseAsFileTime(&ft); -# else - GetSystemTimeAsFileTime(&ft); -# endif - sft.dwHighDateTime = ft.dwHighDateTime - __pi_ftjan1970.dwHighDateTime; - if (ft.dwLowDateTime < __pi_ftjan1970.dwLowDateTime) { - sft.dwLowDateTime = ft.dwLowDateTime + (0xFFFFFFFF - __pi_ftjan1970.dwLowDateTime); - sft.dwHighDateTime++; - } else - sft.dwLowDateTime = ft.dwLowDateTime - __pi_ftjan1970.dwLowDateTime; - ullong lt = ullong(sft.dwHighDateTime) * 0x100000000U + ullong(sft.dwLowDateTime); - return PISystemTime(lt / 10000000U, (lt % 10000000U) * 100U); - } - //long t_cur = GetCurrentTime(); - //return PISystemTime(t_cur / 1000, (t_cur % 1000) * 1000000); -#else -# ifdef MAC_OS - mach_timespec_t t_cur; - clock_get_time(__pi_mac_clock, &t_cur); -# else - timespec t_cur; - clock_gettime(0, &t_cur); -# endif - return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec); -#endif -} - - -PIString PITime::toString(const PIString & format) const { - PIString ts = format; - ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0')); - ts.replace("h", PIString::fromNumber(hours)); - ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0')); - ts.replace("m", PIString::fromNumber(minutes)); - ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0')); - ts.replace("s", PIString::fromNumber(seconds)); - ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0')); - ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0')); - ts.replace("z", PIString::fromNumber(milliseconds)); - return ts; -} - - -PIString PIDate::toString(const PIString & format) const { - PIString ts = format; - ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0')); - ts.replace("yy", PIString::fromNumber(year).right(2)); - ts.replace("y", PIString::fromNumber(year).right(1)); - ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0')); - ts.replace("M", PIString::fromNumber(month)); - ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0')); - ts.replace("d", PIString::fromNumber(day)); - return ts; -} - - -PIString PIDateTime::toString(const PIString & format) const { - PIString ts = format; - ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0')); - ts.replace("yy", PIString::fromNumber(year).right(2)); - ts.replace("y", PIString::fromNumber(year).right(1)); - ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0')); - ts.replace("M", PIString::fromNumber(month)); - ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0')); - ts.replace("d", PIString::fromNumber(day)); - ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0')); - ts.replace("h", PIString::fromNumber(hours)); - ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0')); - ts.replace("m", PIString::fromNumber(minutes)); - ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0')); - ts.replace("s", PIString::fromNumber(seconds)); - ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0')); - ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0')); - ts.replace("z", PIString::fromNumber(milliseconds)); - return ts; -} - - -time_t PIDateTime::toSecondSinceEpoch() const { - tm pt; - memset(&pt, 0, sizeof(pt)); - pt.tm_sec = seconds; - pt.tm_min = minutes; - pt.tm_hour = hours; - pt.tm_mday = day; - pt.tm_mon = month - 1; - pt.tm_year = piMaxi(year - 1900, 71); - return mktime(&pt); -} - - -PIDateTime PIDateTime::fromSecondSinceEpoch(const time_t sec) { - tm * pt = localtime(&sec); - PIDateTime dt; - dt.seconds = pt->tm_sec; - dt.minutes = pt->tm_min; - dt.hours = pt->tm_hour; - dt.day = pt->tm_mday; - dt.month = pt->tm_mon + 1; - dt.year = pt->tm_year + 1900; - return dt; - -} - - -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; -} - - -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).right(2)); - ts.replace("y", PIString::fromNumber(date.year).right(1)); - 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; -} - - -PIString datetime2string(const PIDateTime & date, const PIString & format) { - PIString ts = format; - ts.replace("hh", PIString::fromNumber(date.hours).expandLeftTo(2, '0')); - ts.replace("h", PIString::fromNumber(date.hours)); - ts.replace("mm", PIString::fromNumber(date.minutes).expandLeftTo(2, '0')); - ts.replace("m", PIString::fromNumber(date.minutes)); - ts.replace("ss", PIString::fromNumber(date.seconds).expandLeftTo(2, '0')); - ts.replace("s", PIString::fromNumber(date.seconds)); - ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0')); - ts.replace("yy", PIString::fromNumber(date.year).right(2)); - ts.replace("y", PIString::fromNumber(date.year).right(1)); - 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; -} - - - -PITimeMeasurer::PITimeMeasurer() { - reset(); -} - - -double PITimeMeasurer::elapsed_n() { - return (PISystemTime::current(true) - t_st).toNanoseconds() - PISystemTests::time_elapsed_ns; -} - - -double PITimeMeasurer::elapsed_u() { - return (PISystemTime::current(true) - t_st).toMicroseconds() - PISystemTests::time_elapsed_ns / 1.E+3; -} - - -double PITimeMeasurer::elapsed_m() { - return (PISystemTime::current(true) - t_st).toMilliseconds() - PISystemTests::time_elapsed_ns / 1.E+6; -} - - -double PITimeMeasurer::elapsed_s() { - return (PISystemTime::current(true) - t_st).toSeconds() - PISystemTests::time_elapsed_ns / 1.E+9; -} - - -PISystemTime PITimeMeasurer::elapsed() { - return (PISystemTime::current(true) - t_st); -} diff --git a/pitime.h b/pitime.h deleted file mode 100644 index b50e3df9..00000000 --- a/pitime.h +++ /dev/null @@ -1,315 +0,0 @@ -/*! \file pitime.h - * \brief Time structs -*/ -/* - PIP - Platform Independent Primitives - Time structs - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PITIME_H -#define PITIME_H - -#include -#include -#include "pistring.h" - -#ifdef DOXYGEN -//! \brief Sleep for "msecs" milliseconds -void msleep(int msecs); -#else -# ifdef WINDOWS -inline void msleep(int msecs) {Sleep(msecs);} -# else -inline void msleep(int msecs) {usleep(msecs * 1000);} -# endif -#endif - -/*! \brief Precise sleep for "usecs" microseconds - * \details This function consider \c "usleep" offset - * on QNX/Linux/Mac, which is calculated with - * \a pip_sys_test program. If there is correct - * offset value in system config, this function - * wait \b exactly "usecs" microseconds. */ -void piUSleep(int usecs); // on !Windows consider constant "usleep" offset - -/*! \brief Precise sleep for "msecs" milliseconds - * \details This function exec \a piUSleep (msecs * 1000). */ -inline void piMSleep(double msecs) {piUSleep(msecs * 1000);} // on !Windows consider constant "usleep" offset - -/*! \brief Precise sleep for "secs" seconds - * \details This function exec \a piUSleep (msecs * 1000000). */ -inline void piSleep(double secs) {piUSleep(secs * 1000000);} // on !Windows consider constant "usleep" offset - -class PIP_EXPORT PISystemTime { -public: - - //! Contructs system time with s = ns = 0 - PISystemTime() {seconds = nanoseconds = 0;} - - //! Contructs system time with s = "s" and ns = "ns" - PISystemTime(long s, long ns) {seconds = s; nanoseconds = ns; checkOverflows();} - - //! Contructs system time from another - PISystemTime(const PISystemTime & t) {seconds = t.seconds; nanoseconds = t.nanoseconds;} - - //! Returns stored system time value in seconds - double toSeconds() const {return double(seconds) + nanoseconds / 1.e+9;} - - //! Returns stored system time value in milliseconds - double toMilliseconds() const {return seconds * 1.e+3 + nanoseconds / 1.e+6;} - - //! Returns stored system time value in microseconds - double toMicroseconds() const {return seconds * 1.e+6 + nanoseconds / 1.e+3;} - - //! Returns stored system time value in nanoseconds - double toNanoseconds() const {return seconds * 1.e+9 + double(nanoseconds);} - - - //! Add to stored system time "v" seconds - PISystemTime & addSeconds(double v) {*this += fromSeconds(v); return *this;} - - //! Add to stored system time "v" milliseconds - PISystemTime & addMilliseconds(double v) {*this += fromMilliseconds(v); return *this;} - - //! Add to stored system time "v" microseconds - PISystemTime & addMicroseconds(double v) {*this += fromMicroseconds(v); return *this;} - - //! Add to stored system time "v" nanoseconds - PISystemTime & addNanoseconds(double v) {*this += fromNanoseconds(v); return *this;} - - - //! Sleep for stored value. \warning Use this function to sleep for difference of system times or constructs system time. - //! If you call this function on system time returned with \a PISystemTime::current() thread will be sleep almost forever. - void sleep() {piUSleep(piFloord(toMicroseconds()));} // wait self value, useful to wait some dT = (t1 - t0) - - - //! Returns copy of this system time with absolutely values of s and ns - PISystemTime abs() const; - - //! Returns sum of this system time with "t" - PISystemTime operator +(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds += t.seconds; tt.nanoseconds += t.nanoseconds; tt.checkOverflows(); return tt;} - - //! Returns difference between this system time and "t" - PISystemTime operator -(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds -= t.seconds; tt.nanoseconds -= t.nanoseconds; tt.checkOverflows(); return tt;} - - //! Returns multiplication between this system time and "t" - PISystemTime operator *(const double & v) const {return fromMilliseconds(toMilliseconds() * v);} - - //! Returns division between this system time and "t" - PISystemTime operator /(const double & v) const {return fromMilliseconds(toMilliseconds() / v);} - - //! Add to stored value system time "t" - PISystemTime & operator +=(const PISystemTime & t) {seconds += t.seconds; nanoseconds += t.nanoseconds; checkOverflows(); return *this;} - - //! Subtract from stored value system time "t" - PISystemTime & operator -=(const PISystemTime & t) {seconds -= t.seconds; nanoseconds -= t.nanoseconds; checkOverflows(); return *this;} - - //! Multiply stored value system time by "v" - PISystemTime & operator *=(const double & v) {*this = fromMilliseconds(toMilliseconds() * v); return *this;} - - //! Divide stored value system time by "v" - PISystemTime & operator /=(const double & v) {*this = fromMilliseconds(toMilliseconds() / v); return *this;} - - - //! Compare system times - bool operator ==(const PISystemTime & t) const {return ((seconds == t.seconds) && (nanoseconds == t.nanoseconds));} - - //! Compare system times - bool operator !=(const PISystemTime & t) const {return ((seconds != t.seconds) || (nanoseconds != t.nanoseconds));} - - //! Compare system times - bool operator >(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds > t.nanoseconds; return seconds > t.seconds;} - - //! Compare system times - bool operator <(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds < t.nanoseconds; return seconds < t.seconds;} - - //! Compare system times - bool operator >=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds >= t.nanoseconds; return seconds >= t.seconds;} - - //! Compare system times - bool operator <=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds <= t.nanoseconds; return seconds <= t.seconds;} - - - //! Contructs system time from seconds "v" - static PISystemTime fromSeconds(double v) {long s = piFloord(v); return PISystemTime(s, (v - s) * 1000000000);} - - //! Contructs system time from milliseconds "v" - static PISystemTime fromMilliseconds(double v) {long s = piFloord(v / 1000.); return PISystemTime(s, (v / 1000. - s) * 1000000000);} - - //! Contructs system time from microseconds "v" - static PISystemTime fromMicroseconds(double v) {long s = piFloord(v / 1000000.); return PISystemTime(s, (v / 1000000. - s) * 1000000000);} - - //! Contructs system time from nanoseconds "v" - static PISystemTime fromNanoseconds(double v) {long s = piFloord(v / 1000000000.); return PISystemTime(s, (v / 1000000000. - s) * 1000000000);} - - //! Returns current system time - static PISystemTime current(bool precise_but_not_system = false); - - //! Seconds of stored system time - long seconds; - - //! Nanoseconds of stored system time - long nanoseconds; - -private: - void checkOverflows() {while (nanoseconds >= 1000000000) {nanoseconds -= 1000000000; seconds++;} while (nanoseconds < 0) {nanoseconds += 1000000000; seconds--;}} - -}; - -//! \relatesalso PICout \relatesalso PIByteArray \brief Output operator to PICout -inline PICout operator <<(PICout s, const PISystemTime & v) {s.space(); s.setControl(0, true); s << "(" << v.seconds << " s, " << v.nanoseconds << " ns)"; s.restoreControl(); return s;} - -//! \relatesalso PISystemTime \relatesalso PIByteArray \brief Output operator to PIByteArray -inline PIByteArray & operator <<(PIByteArray & s, const PISystemTime & v) {s << v.seconds << v.nanoseconds; return s;} - -//! \relatesalso PISystemTime \relatesalso PIByteArray \brief Input operator from PIByteArray -inline PIByteArray & operator >>(PIByteArray & s, PISystemTime & v) {s >> v.seconds >> v.nanoseconds; return s;} - -struct PIP_EXPORT PITime { - PITime(int hours_ = 0, int minutes_ = 0, int seconds_ = 0, int milliseconds_ = 0): hours(hours_), minutes(minutes_), seconds(seconds_), milliseconds(milliseconds_) {;} - int hours; - int minutes; - int seconds; - int milliseconds; - PIString toString(const PIString & format = "h:mm:ss") const; - static PITime current(); -}; -PIP_EXPORT bool operator ==(const PITime & t0, const PITime & t1); -PIP_EXPORT bool operator <(const PITime & t0, const PITime & t1); -PIP_EXPORT bool operator >(const PITime & t0, const PITime & t1); -inline bool operator !=(const PITime & t0, const PITime & t1) {return !(t0 == t1);} -inline bool operator <=(const PITime & t0, const PITime & t1) {return !(t0 > t1);} -inline bool operator >=(const PITime & t0, const PITime & t1) {return !(t0 < t1);} - -struct PIP_EXPORT PIDate { - PIDate(int year_ = 0, int month_ = 0, int day_ = 0): year(year_), month(month_), day(day_) {;} - int year; - int month; - int day; - PIString toString(const PIString & format = "d.MM.yyyy") const; - static PIDate current(); -}; -PIP_EXPORT bool operator ==(const PIDate & t0, const PIDate & t1); -PIP_EXPORT bool operator <(const PIDate & t0, const PIDate & t1); -PIP_EXPORT bool operator >(const PIDate & t0, const PIDate & t1); -inline bool operator !=(const PIDate & t0, const PIDate & t1) {return !(t0 == t1);} -inline bool operator <=(const PIDate & t0, const PIDate & t1) {return !(t0 > t1);} -inline bool operator >=(const PIDate & t0, const PIDate & t1) {return !(t0 < t1);} - -struct PIP_EXPORT PIDateTime { - PIDateTime() {year = month = day = hours = minutes = seconds = milliseconds = 0;} - PIDateTime(const PITime & time) {year = month = day = 0; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;} - PIDateTime(const PIDate & date) {year = date.year; month = date.month; day = date.day; hours = minutes = seconds = milliseconds = 0;} - PIDateTime(const PIDate & date, const PITime & time) {year = date.year; month = date.month; day = date.day; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;} - int year; - int month; - int day; - int hours; - int minutes; - int seconds; - int milliseconds; - PIDateTime normalized() const {return PIDateTime::fromSecondSinceEpoch(toSecondSinceEpoch());} - void normalize() {*this = normalized();} - PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy") const; - time_t toSecondSinceEpoch() const; - PISystemTime toSystemTime() const {return PISystemTime(int(toSecondSinceEpoch()), milliseconds * 1000000);} - PIDate date() const {return PIDate(year, month, day);} - PITime time() const {return PITime(hours, minutes, seconds, milliseconds);} - void setDate(const PIDate & d) {year = d.year; month = d.month; day = d.day;} - void setTime(const PITime & t) {hours = t.hours; minutes = t.minutes; seconds = t.seconds; milliseconds = t.milliseconds;} - void operator +=(const PIDateTime & d1) {year += d1.year; month += d1.month; day += d1.day; hours += d1.hours; minutes += d1.minutes; seconds += d1.seconds; normalize();} - void operator -=(const PIDateTime & d1) {year -= d1.year; month -= d1.month; day -= d1.day; hours -= d1.hours; minutes -= d1.minutes; seconds -= d1.seconds; normalize();} - static PIDateTime fromSecondSinceEpoch(const time_t sec); - static PIDateTime fromSystemTime(const PISystemTime & st) {PIDateTime dt = fromSecondSinceEpoch(st.seconds); dt.milliseconds = piClampi(st.nanoseconds / 1000000, 0, 999); return dt;} - static PIDateTime current(); -}; -inline PIDateTime operator +(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td += d1; return td.normalized();} -inline PIDateTime operator -(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td -= d1; return td.normalized();} -PIP_EXPORT bool operator ==(const PIDateTime & t0, const PIDateTime & t1); -PIP_EXPORT bool operator <(const PIDateTime & t0, const PIDateTime & t1); -PIP_EXPORT bool operator >(const PIDateTime & t0, const PIDateTime & t1); -inline bool operator !=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 == t1);} -inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);} -inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);} - -DEPRECATED inline PITime currentTime() {return PITime::current();} // obsolete, use PITime::current() instead -DEPRECATED inline PIDate currentDate() {return PIDate::current();} // obsolete, use PIDate::current() instead -DEPRECATED inline PIDateTime currentDateTime() {return PIDateTime::current();} // obsolete, use PIDateTime::current() instead - -//! \brief Returns current system time \deprecated Use \a PISystemTime::current() instead -DEPRECATED inline PISystemTime currentSystemTime() {return PISystemTime::current();} // obsolete, use PISystemTime::current() instead -DEPRECATED PIP_EXPORT PIString time2string(const PITime & time, const PIString & format = "h:mm:ss"); // obsolete, use PITime.toString() instead -DEPRECATED PIP_EXPORT PIString date2string(const PIDate & date, const PIString & format = "d.MM.yyyy"); // obsolete, use PITime.toString() instead -DEPRECATED PIP_EXPORT PIString datetime2string(const PIDateTime & datetime, const PIString & format = "h:mm:ss d.MM.yyyy"); // obsolete, use PIDateTime.toString() instead - - -class PITimeMeasurer { -public: - PITimeMeasurer(); - - /** \brief Set internal time mark to current system time - * \details This function used for set start time mark. Later - * you can find out elapsed time from this time mark to any - * moment of time with \a elapsed_s(), \a elapsed_m(), - * \a elapsed_u() or \a elapsed_n() functions. - * \sa \a elapsed_s(), \a elapsed_m(), \a elapsed_u(), \a elapsed_n() */ - void reset() {t_st = PISystemTime::current(true);} - - //! \brief Returns nanoseconds elapsed from last \a reset() execution or from timer measurer creation. - double elapsed_n(); - - //! \brief Returns microseconds elapsed from last \a reset() execution or from timer measurer creation. - double elapsed_u(); - - //! \brief Returns milliseconds elapsed from last \a reset() execution or from timer measurer creation. - double elapsed_m(); - - //! \brief Returns seconds elapsed from last \a reset() execution or from timer measurer creation. - double elapsed_s(); - - //! \brief Returns PISystemTime elapsed from last \a reset() execution or from timer measurer creation. - PISystemTime elapsed(); - - double reset_time_n() {return t_st.toNanoseconds();} - double reset_time_u() {return t_st.toMicroseconds();} - double reset_time_m() {return t_st.toMilliseconds();} - double reset_time_s() {return t_st.toSeconds();} - - //! \brief Returns time mark of last \a reset() execution or timer measurer creation. - PISystemTime reset_time() {return t_st;} - - //! \brief Returns nanoseconds representation of current system time. - static double elapsed_system_n() {return PISystemTime::current(true).toNanoseconds();} - - //! \brief Returns microseconds representation of current system time. - static double elapsed_system_u() {return PISystemTime::current(true).toMicroseconds();} - - //! \brief Returns milliseconds representation of current system time. - static double elapsed_system_m() {return PISystemTime::current(true).toMilliseconds();} - - //! \brief Returns seconds representation of current system time. - static double elapsed_system_s() {return PISystemTime::current(true).toSeconds();} - - //! \brief Returns time mark of current system time. - static PISystemTime elapsed_system() {return PISystemTime::current(true);} - -private: - PISystemTime t_st, t_cur; - -}; - -#endif // PITIME_H diff --git a/pitimer.cpp b/pitimer.cpp deleted file mode 100644 index 9d2248df..00000000 --- a/pitimer.cpp +++ /dev/null @@ -1,579 +0,0 @@ -/* - PIP - Platform Independent Primitives - Timer - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pitimer.h" -#include "pisystemtests.h" - - -/*! \class PITimer - * \brief Timer - * - * \section PITimer_sec0 Synopsis - * This class implements timer function. PIP timers supports 3 way to tick notify, - * frequency delimiters and time measurements. - * \section PITimer_sec1 Notify variants - * Notify variants: - * * "slot" - static function with format void func(void * data, int delimiter); - * * event - \a void timeout(void * data, int delimiter); - * * virtual function - \a void tick(void * data, int delimiter). - * All this variant are equivalent, use most applicable. - * \section PITimer_sec2 Frequency delimiters - * Frequency delimiter is an integer number and "slot" function. If "slot" function is null - * timer main "slot" will be used. Each delimiter numbers tick timer will be execute - * delimiters or timer main "slot" function with \b delimiter value = delimiter number. - * Example: \snippet pitimer.cpp delimiter - * \section PITimer_sec3 Time measurements - * PITimer can be used as time measurer. Function \a reset() set time mark to current - * system time, then functions double elapsed_*() returns time elapsed from this mark. - * These functions can returns nano-, micro-, milli- and seconds with suffixes "n", "u", "m" - * and "s"; - * Example: \snippet pitimer.cpp elapsed -*/ - - -#ifdef PIP_TIMER_RT -PITimer::TimerPool * pool = 0; -#endif - - -PITimer::PITimer(TimerEvent slot, void * data_, bool threaded_) -#ifndef PIP_TIMER_RT -: PIThread() { -#else -: PIObject() { -#endif - ret_func = slot; - data = data_; - running_ = false; - interval_ = 0.; -#ifdef PIP_TIMER_RT - piMonitor.timers++; - ti = -1; - threaded = threaded_; - memset(&se, 0, sizeof(se)); - se.sigev_notify = SIGEV_THREAD; - se.sigev_value.sival_ptr = this; - se.sigev_notify_function = PITimer::timer_event; - se.sigev_notify_attributes = 0; - lockRun = false; -#else - deferred_ = false; -#endif - reset(); -} - - -PITimer::PITimer(bool threaded_) -#ifndef PIP_TIMER_RT -: PIThread() { -#else -: PIObject() { -#endif - ret_func = 0; - data = 0; - running_ = false; - interval_ = 0.; -#ifdef PIP_TIMER_RT - piMonitor.timers++; - ti = -1; - threaded = threaded_; - memset(&se, 0, sizeof(se)); - se.sigev_notify = SIGEV_THREAD; - se.sigev_value.sival_ptr = this; - se.sigev_notify_function = PITimer::timer_event; - se.sigev_notify_attributes = 0; - lockRun = false; -#else - deferred_ = false; -#endif - reset(); -} - - -PITimer::~PITimer() { -#ifdef PIP_TIMER_RT - piMonitor.timers--; -#endif - stop(); -} - - -#ifdef PIP_TIMER_RT -void PITimer::start(double msecs) { - if (ti != -1 || msecs < 0 || running_) return; - interval_ = msecs; - if (!threaded) { - ticks = int(msecs); - if (pool == 0) pool = new TimerPool(); - pool->add(this); - //cout << "not threaded timer start " << msecs << " msecs\n"; - if (!pool->isRunning()) pool->start(); - running_ = true; - return; - } - spec.it_interval.tv_nsec = ((int)(msecs * 1000) % 1000000) * 1000; - spec.it_interval.tv_sec = (time_t)(msecs / 1000); - spec.it_value = spec.it_interval; - ti = timer_create(CLOCK_REALTIME, &se, &timer); - //cout << "***create timer " << msecs << " msecs\n"; - if (ti == -1) { - piCoutObj << "Can`t create timer for " << msecs << " msecs: " << errorString(); - return; - } - timer_settime(timer, 0, &spec, 0); - running_ = true; -} - - -void PITimer::deferredStart(double interval_msecs, double delay_msecs) { - if (ti != -1 || interval_msecs < 0 || running_) return; - interval_ = interval_msecs; - spec.it_interval.tv_nsec = ((int)(interval_msecs * 1000) % 1000000) * 1000; - spec.it_interval.tv_sec = (time_t)(interval_msecs / 1000); - spec.it_value.tv_nsec = ((int)(delay_msecs * 1000) % 1000000) * 1000; - spec.it_value.tv_sec = (time_t)(delay_msecs / 1000); - ti = timer_create(CLOCK_REALTIME, &se, &timer); - //cout << "***create timer\n"; - if (ti == -1) { - piCoutObj << "Can`t create timer for " << interval_msecs << " msecs: " << errorString(); - return; - } - timer_settime(timer, 0, &spec, 0); - running_ = true; -} - - -void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_datetime) { - if (ti != -1 || interval_msecs < 0 || running_) return; - interval_ = interval_msecs; - spec.it_interval.tv_nsec = ((int)(interval_msecs * 1000) % 1000000) * 1000; - spec.it_interval.tv_sec = (time_t)(interval_msecs / 1000); - struct tm dtm; - memset(&dtm, 0, sizeof(dtm)); - dtm.tm_sec = start_datetime.seconds; - dtm.tm_min = start_datetime.minutes; - dtm.tm_hour = start_datetime.hours; - dtm.tm_mday = start_datetime.day; - dtm.tm_mon = start_datetime.month - 1; - dtm.tm_year = start_datetime.year - 1900; - spec.it_value.tv_nsec = 0; - spec.it_value.tv_sec = mktime(&dtm); - ti = timer_create(CLOCK_REALTIME, &se, &timer); - //cout << "***create timer\n"; - if (ti == -1) { - piCoutObj << "Can`t create timer for " << interval_msecs << " msecs: " << errorString(); - return; - } - timer_settime(timer, TIMER_ABSTIME, &spec, 0); - running_ = true; -} - - - -void PITimer::TimerPool::remove(PITimer * t) { - mutex.lock(); - for (int i = 0; i < timers.size_s(); ++i) - if (timers[i].first == t) { - timers.remove(i); - mutex.unlock(); - return; - } - mutex.unlock(); -} - - -void PITimer::TimerPool::begin() { - //cout << "pool begin\n"; - /*struct sigaction sa; - sa.sa_flags = 0; - sa.sa_handler = empty_handler; - sigemptyset(&sa.sa_mask); - if (sigaction(SIGALRM, &sa, 0) == -1) { - piCoutObj << "sigaction error: " << errorString(); - stop(); - return; - }*/ - sigemptyset(&ss); - sigaddset(&ss, SIGALRM); - memset(&se, 0, sizeof(se)); - se.sigev_notify = SIGEV_SIGNAL; - se.sigev_signo = SIGALRM; - spec.it_interval.tv_nsec = 1000000; - spec.it_interval.tv_sec = 0; - spec.it_value = spec.it_interval; - //cout << "***create pool timer\n"; - if (timer_create(CLOCK_REALTIME, &se, &timer) == -1) { - piCoutObj << "Can`t create timer for pool: " << errorString(); - stop(); - return; - } - if (timer_settime(timer, 0, &spec, 0) == -1) { - piCoutObj << "Can`t set timer for pool: " << errorString(); - stop(); - return; - } - ti = 1; -} - - -void PITimer::TimerPool::run() { - //cout << "wait ...\n"; - sigwait(&ss, &si); - //cout << "ok\n"; - mutex.lock(); - //cout << "* pool tick , pool = " << this <<", timers = " << timers.size()<<"\n"; - for (int i = 0; i < timers.size_s(); ++i) { - TimerPair & ct(timers[i]); - sv.sival_ptr = ct.first; - ct.second++; - //cout << "** pool tick for " << ct.first << ", cnt " << ct.second << ", " << ct.first->ticks << "\n"; - if (ct.second >= ct.first->ticks) { - //cout << "*** timer "<remove(this); - if (pool->isEmpty()) pool->terminate(); - } - } - if (ti != -1) timer_delete(timer); - ti = -1; - interval_ = 0.; -} - - -void PITimer::timer_event(sigval e) { - PITimer * ct = (PITimer * )e.sival_ptr; - if (!ct->running_) return; - if (ct->lockRun) ct->lock(); - if (ct->ret_func != 0) ct->ret_func(ct->data, 1); - ct->timeout(ct->data, 1); - ct->tick(ct->data, 1); - piForeach (TimerSlot & i, ct->ret_funcs) { - if (i.delim > ++(i.tick)) continue; - i.tick = 0; - if (i.slot != 0) i.slot(ct->data, i.delim); - else if (ct->ret_func != 0) ct->ret_func(ct->data, i.delim); - ct->timeout(ct->data, i.delim); - ct->tick(ct->data, i.delim); - } - if (ct->lockRun) ct->unlock(); -} - - -bool PITimer::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; -} - -#else - -void PITimer::start(double msecs) { - if (msecs < 0 || running_) return; - interval_ = msecs; - inc_time = PISystemTime::fromMilliseconds(msecs); - st_time = PISystemTime::current() + inc_time; - deferred_ = false; - running_ = true; - PIThread::start(); -} - - -void PITimer::deferredStart(double interval_msecs, double delay_msecs) { - //piCoutObj << "defStart exec with" << delay_msecs << interval_msecs; - if (interval_msecs < 0 || running_) return; - interval_ = interval_msecs; - PISystemTime cst = PISystemTime::current(); - inc_time = PISystemTime::fromMilliseconds(interval_msecs); - st_time = PISystemTime::current() + PISystemTime::fromMilliseconds(delay_msecs); - if (st_time < cst) st_time = cst; - running_ = deferred_ = true; - PIThread::start(); - //piCoutObj << "timer start def"; -} - - -void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_datetime) { - //piCoutObj << "defStart exec to" << start_datetime.toString() << interval_msecs; - if (interval_msecs < 0 || running_) return; - interval_ = interval_msecs; - PISystemTime cst = PISystemTime::current(); - inc_time = PISystemTime::fromMilliseconds(interval_msecs); - st_time = start_datetime.toSystemTime(); - if (st_time < cst) st_time = cst; - running_ = deferred_ = true; - PIThread::start(); - //piCoutObj << "timer start def"; -} - - -void PITimer::run() { - if (!running_) return; - while (deferred_) { - PISystemTime tst = st_time - PISystemTime::current(); - if (tst.seconds > 0) { - piMSleep(100); - if (!running_) return; - continue; - } - if (tst.nanoseconds > 100000000) { - piMSleep(100); - if (!running_) return; - continue; - } - tst.sleep(); - deferred_ = false; - if (!running_) return; - } -#ifdef WINDOWS - tt_st = __PIQueryPerformanceCounter(); -#else - (st_time - PISystemTime::current()).sleep(); - st_time += inc_time; -#endif - //if (lockRun) lock(); - if (ret_func != 0) ret_func(data, 1); - timeout(data, 1); - tick(data, 1); - piForeach (TimerSlot & i, ret_funcs) { - if (i.delim > ++(i.tick)) continue; - i.tick = 0; - if (i.slot != 0) i.slot(data, i.delim); - else if (ret_func != 0) ret_func(data, i.delim); - timeout(data, i.delim); - tick(data, i.delim); - } -#ifdef WINDOWS - tt_cur = __PIQueryPerformanceCounter(); - double cdelay = interval_ - ((tt_cur - tt_st) / double(__pi_perf_freq) * 1.E+3); - if (cdelay > 0.) Sleep(piRoundd(cdelay)); -#endif - //if (lockRun) unlock(); -} - -#endif - -double PITimer::elapsed_n() { -#ifdef WINDOWS - pc_cur = __PIQueryPerformanceCounter(); - return ((__pi_perf_freq > 0) ? ((pc_cur - pc_st) / double(__pi_perf_freq) * 1.E+9) : -1.); - //t_cur = GetCurrentTime(); - //return (t_cur - t_st) * 1000000.; -#else -# ifdef MAC_OS - clock_get_time(__pi_mac_clock, &t_cur); -# else - clock_gettime(0, &t_cur); -# endif - return (t_cur.tv_sec - t_st.tv_sec) * 1.e+9 + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns); -#endif -} - - -double PITimer::elapsed_u() { -#ifdef WINDOWS - pc_cur = __PIQueryPerformanceCounter(); - return ((__pi_perf_freq > 0) ? ((pc_cur - pc_st) / double(__pi_perf_freq) * 1.E+6) : -1.); - //t_cur = GetCurrentTime(); - //return (t_cur - t_st) * 1000.; -#else -# ifdef MAC_OS - clock_get_time(__pi_mac_clock, &t_cur); -# else - clock_gettime(0, &t_cur); -# endif - return (t_cur.tv_sec - t_st.tv_sec) * 1.e+6 + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns) / 1.e+3; -#endif -} - - -double PITimer::elapsed_m() { -#ifdef WINDOWS - pc_cur = __PIQueryPerformanceCounter(); - return ((__pi_perf_freq > 0) ? ((pc_cur - pc_st) / double(__pi_perf_freq) * 1.E+3) : -1.); - //t_cur = GetCurrentTime(); - //return (double)(t_cur - t_st); -#else -# ifdef MAC_OS - clock_get_time(__pi_mac_clock, &t_cur); -# else - clock_gettime(0, &t_cur); -# endif - return (t_cur.tv_sec - t_st.tv_sec) * 1.e+3 + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns) / 1.e+6; -#endif -} - - -double PITimer::elapsed_s() { -#ifdef WINDOWS - pc_cur = __PIQueryPerformanceCounter(); - return ((__pi_perf_freq > 0) ? ((pc_cur - pc_st) / double(__pi_perf_freq)) : -1.); - //t_cur = GetCurrentTime(); - //return (t_cur - t_st) / 1000.; -#else -# ifdef MAC_OS - clock_get_time(__pi_mac_clock, &t_cur); -# else - clock_gettime(0, &t_cur); -# endif - return (t_cur.tv_sec - t_st.tv_sec) + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns) / 1.e+9; -#endif -} - - -double PITimer::reset_time_n() { -#ifdef WINDOWS - return t_st * 1.e+6; -#else - return t_st.tv_sec * 1.e+9 + t_st.tv_nsec; -#endif -} - - -double PITimer::reset_time_u() { -#ifdef WINDOWS - return t_st * 1.e+3; -#else - return t_st.tv_sec * 1.e+6 + t_st.tv_nsec / 1.e+3; -#endif -} - - -double PITimer::reset_time_m() { -#ifdef WINDOWS - return (double)t_st; -#else - return t_st.tv_sec * 1.e+3 + t_st.tv_nsec / 1.e+6; -#endif -} - - -double PITimer::reset_time_s() { -#ifdef WINDOWS - return t_st / 1000.; -#else - return t_st.tv_sec + t_st.tv_nsec / 1.e+9; -#endif -} - - -PISystemTime PITimer::reset_time() { -#ifdef WINDOWS - return PISystemTime(t_st / 1000, (t_st % 1000) * 1000000); -#else - return PISystemTime(t_st.tv_sec, t_st.tv_nsec); -#endif -} - - -double PITimer::elapsed_system_n() { -#ifdef WINDOWS - llong pc_cur = __PIQueryPerformanceCounter(); - return ((__pi_perf_freq > 0) ? (pc_cur / double(__pi_perf_freq) * 1.E+9) : -1.); - //long t_cur = GetCurrentTime(); - //return (t_cur * 1000000.); -#else -# ifdef MAC_OS - mach_timespec_t t_cur; - clock_get_time(__pi_mac_clock, &t_cur); -# else - timespec t_cur; - clock_gettime(0, &t_cur); -# endif - return (t_cur.tv_sec * 1.e+9 + t_cur.tv_nsec); -#endif -} - - -double PITimer::elapsed_system_u() { -#ifdef WINDOWS - llong pc_cur = __PIQueryPerformanceCounter(); - return ((__pi_perf_freq > 0) ? (pc_cur / double(__pi_perf_freq) * 1.E+6) : -1.); - //long t_cur = GetCurrentTime(); - //return (t_cur * 1000.); -#else -# ifdef MAC_OS - mach_timespec_t t_cur; - clock_get_time(__pi_mac_clock, &t_cur); -# else - timespec t_cur; - clock_gettime(0, &t_cur); -# endif - return (t_cur.tv_sec * 1.e+6 + (t_cur.tv_nsec / 1.e+3)); -#endif -} - - -double PITimer::elapsed_system_m() { -#ifdef WINDOWS - llong pc_cur = __PIQueryPerformanceCounter(); - return ((__pi_perf_freq > 0) ? (pc_cur / double(__pi_perf_freq) * 1.E+3) : -1.); - //long t_cur = GetCurrentTime(); - //return (double)t_cur; -#else -# ifdef MAC_OS - mach_timespec_t t_cur; - clock_get_time(__pi_mac_clock, &t_cur); -# else - timespec t_cur; - clock_gettime(0, &t_cur); -# endif - return (t_cur.tv_sec * 1.e+3 + (t_cur.tv_nsec / 1.e+6)); -#endif -} - - -double PITimer::elapsed_system_s() { -#ifdef WINDOWS - llong pc_cur = __PIQueryPerformanceCounter(); - return ((__pi_perf_freq > 0) ? (pc_cur / double(__pi_perf_freq)) : -1.); - //long t_cur = GetCurrentTime(); - //return (t_cur / 1000.); -#else -# ifdef MAC_OS - mach_timespec_t t_cur; - clock_get_time(__pi_mac_clock, &t_cur); -# else - timespec t_cur; - clock_gettime(0, &t_cur); -# endif - return (t_cur.tv_sec + (t_cur.tv_nsec / 1.e+9)); -#endif -} diff --git a/pitimer.h b/pitimer.h deleted file mode 100644 index a7130a22..00000000 --- a/pitimer.h +++ /dev/null @@ -1,269 +0,0 @@ -/*! \file pitimer.h - * \brief Timer -*/ -/* - PIP - Platform Independent Primitives - Timer - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PITIMER_H -#define PITIMER_H - -#include "pithread.h" -#include "pitime.h" - -typedef void (*TimerEvent)(void * , int ); - -class PIP_EXPORT PITimer -#ifndef PIP_TIMER_RT -: public PIThread -#else -: public PIObject -#endif -{ - PIOBJECT(PITimer) -public: - - //! \brief Constructs timer with execution function \b slot and common data \b data. - PITimer(TimerEvent slot = 0, void * data = 0, bool threaded = true); - PITimer(bool threaded); - virtual ~PITimer(); - - - //! \brief Set custom data. - void setData(void * data_) {data = data_;} - - //! \brief Set timer execution function. - void setSlot(TimerEvent slot) {ret_func = slot;} - - //! \brief Returns current loop delay. - double interval() const {return interval_;} - - EVENT_HANDLER0(void, reset) { -# ifdef WINDOWS - //t_st = GetCurrentTime(); - pc_st = __PIQueryPerformanceCounter(); -# elif defined(MAC_OS) - clock_get_time(__pi_mac_clock, &t_st); -# else - clock_gettime(0, &t_st); -# endif - } - EVENT_HANDLER1(void, start, int, msecs) {start(double(msecs));} - EVENT_HANDLER1(void, start, double, msecs); - EVENT_HANDLER2(void, deferredStart, double, interval_msecs, double, delay_msecs); - EVENT_HANDLER2(void, deferredStart, double, interval_msecs, const PIDateTime &, start_datetime); -#ifndef PIP_TIMER_RT - EVENT_HANDLER0(void, stop) {running_ = false; PIThread::stop();} -#else - EVENT_HANDLER0(void, stop); - EVENT_HANDLER0(bool, waitForFinish) {return waitForFinish(-1);} - EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs); - bool isRunning() const {return running_;} - void needLockRun(bool need) {lockRun = need;} - EVENT_HANDLER0(void, lock) {mutex_.lock();} - EVENT_HANDLER0(void, unlock) {mutex_.unlock();} -#endif - - //! \brief Add frequency delimiter \b delim with optional delimiter slot \b slot. - void addDelimiter(int delim, TimerEvent slot = 0) {ret_funcs << TimerSlot(slot, delim);} - - //! \brief Remove all frequency delimiters \b delim. - void removeDelimiter(int delim) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].delim == delim) {ret_funcs.remove(i); i--;}} - - //! \brief Remove all frequency delimiters with slot \b slot. - void removeDelimiter(TimerEvent slot) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot) {ret_funcs.remove(i); i--;}} - - //! \brief Remove all frequency delimiters \b delim with slot \b slot. - void removeDelimiter(int delim, TimerEvent slot) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot && ret_funcs[i].delim == delim) {ret_funcs.remove(i); i--;}} - void setDelimiterValue(int delim, int value) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].delim == delim) ret_funcs[i].tick = value;} - void setDelimiterValue(TimerEvent slot, int value) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot) ret_funcs[i].tick = value;} - void setDelimiterValue(int delim, TimerEvent slot, int value) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot && ret_funcs[i].delim == delim) ret_funcs[i].tick = value;} - int delimiterValue(int delim) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].delim == delim) return ret_funcs[i].tick; return -1;} - int delimiterValue(int delim, TimerEvent slot) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot && ret_funcs[i].delim == delim) return ret_funcs[i].tick; return -1;} - EVENT_HANDLER0(void, clearDelimiters) {ret_funcs.clear();} - - - //! \brief Returns nanoseconds elapsed from last \a reset() execution or from timer creation. - double elapsed_n(); // nanoseconds - - //! \brief Returns microseconds elapsed from last \a reset() execution or from timer creation. - double elapsed_u(); // microseconds - - //! \brief Returns milliseconds elapsed from last \a reset() execution or from timer creation. - double elapsed_m(); // milliseconds - - //! \brief Returns seconds elapsed from last \a reset() execution or from timer creation. - double elapsed_s(); // seconds - - - double reset_time_n(); // nanoseconds - double reset_time_u(); // microseconds - double reset_time_m(); // milliseconds - double reset_time_s(); // seconds - - - //! \brief Returns time mark of last \a reset() execution or timer creation. - PISystemTime reset_time(); - - - //! \brief Returns nanoseconds representation of current system time. - static double elapsed_system_n(); // nanoseconds - - //! \brief Returns microseconds representation of current system time. - static double elapsed_system_u(); // microseconds - - //! \brief Returns milliseconds representation of current system time. - static double elapsed_system_m(); // milliseconds - - //! \brief Returns seconds representation of current system time. - static double elapsed_system_s(); // seconds - - -#ifdef PIP_TIMER_RT - class TimerPool: public PIThread { - public: - TimerPool(): PIThread() {/*cout << "+++++new pool\n"; */ti = -1;} - ~TimerPool() {stop();} - void add(PITimer * t) {mutex.lock(); timers << TimerPair(t, 0); mutex.unlock();} - void remove(PITimer * t); - bool isEmpty() const {return timers.isEmpty();} - typedef PIPair TimerPair; - private: - static void empty_handler(int) {} - void begin(); - void run(); - void end() {/*cout << "pool end\n"; */if (ti != -1) timer_delete(timer); ti = -1;} - int ti, si; - sigset_t ss; - sigevent se; - sigval sv; - itimerspec spec; - - timer_t timer; - PIVector timers; - PIMutex mutex; - }; - static void timer_event(sigval e); - int ticks; -#endif - - EVENT2(timeout, void * , data, int, delimiter) - -//! \handlers -//! \{ - - /** \fn void reset() - * \brief Set internal time mark to current system time - * \details This function used for set start time mark. Later - * you can find out elapsed time from this time mark to any - * moment of time with \a elapsed_s(), \a elapsed_m(), - * \a elapsed_u() or \a elapsed_n() function. - * \sa \a elapsed_s(), \a elapsed_m(), \a elapsed_u(), \a elapsed_n() */ - - /** \fn void start(int msecs) - * \brief Start timer with \b msecs loop delay - * \details Start execution of timer functions with frequency = 1 / msecs Hz. */ - - /** \fn void start(double msecs) - * \brief Start timer with \b msecs loop delay - * \details Start execution of timer functions with frequency = 1. / msecs Hz. - * Instead of \a start(int msecs) function this variant allow start timer - * with frequencies more than 1 kHz. */ - - //! \fn void stop() - //! \brief Stop timer - - /** \fn void deferredStart(double interval_msecs, double delay_msecs) - * \brief Start timer with \b interval_msecs loop delay after \b delay_msecs delay. - * \details Timer wait \b delay_msecs milliseconds and then normally starts with - * \b interval_msecs loop delay. - * \sa \a void start(double msecs), \a void deferredStart(double interval_msecs, const PIDateTime & start_datetime) */ - - /** \fn void deferredStart(double interval_msecs, const PIDateTime & start_datetime) - * \brief Start timer with \b interval_msecs loop delay after \b start_datetime date and time. - * \details Timer wait until \b start_datetime and then normally starts with - * \b interval_msecs loop delay. - * \sa \a void start(double msecs), \a void deferredStart(double interval_msecs, double delay_msecs) */ - - //! \fn void clearDelimiters() - //! \brief Remove all frequency delimiters. - -//! \} -//! \events -//! \{ - - /** \fn void timeout(void * data, int delimiter) - * \brief Raise on timer tick - * \details \b Data can be set with function \a setData(void * data) or from constructor. - * \b Delimiter if frequency delimiter, 1 for main loop. */ - - -//! \} - -protected: - //! Virtual timer execution function, similar to "slot" or event \a void timeout(void * data, int delimiter). - //! By default is empty. - virtual void tick(void * data, int delimiter) {;} - -private: -#ifndef PIP_TIMER_RT - void run(); - void end() {interval_ = 0.;} - - PISystemTime st_time, inc_time; - bool deferred_; -#else - bool threaded; - volatile bool lockRun; - PIMutex mutex_; - int ti; - itimerspec spec; - timer_t timer; - sigevent se; -#endif - bool running_; - double interval_; - -#ifdef WINDOWS - llong pc_st, pc_cur, tt_st, tt_cur; - long -#elif defined(MAC_OS) - mach_timespec_t -#else - timespec -#endif - t_st, t_cur; - - struct TimerSlot { - TimerSlot(TimerEvent slot_ = 0, int delim_ = 1) {slot = slot_; delim = delim_; tick = 0;} - TimerEvent slot; - int delim; - int tick; - }; - - void * data; - TimerEvent ret_func; - PIVector ret_funcs; - -}; - -#ifdef PIP_TIMER_RT -extern PITimer::TimerPool * pool; -#endif - -#endif // PITIMER_H diff --git a/piusb.cpp b/piusb.cpp deleted file mode 100644 index d1f6decb..00000000 --- a/piusb.cpp +++ /dev/null @@ -1,410 +0,0 @@ -#include "piusb.h" -#include "piconfig.h" - -#ifdef PIP_USB -# ifdef WINDOWS -# include -# else -# include -# endif -#endif - -REGISTER_DEVICE(PIUSB); - - -PIUSB::PIUSB(ushort vid, ushort pid): PIIODevice("", ReadWrite) { - vid_ = vid; - pid_ = pid; - intefrace_ = 0; - hdev = 0; - interface_claimed = -1; - setPath(PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0")); - setDeviceNumber(1); - setTimeoutRead(1000); - setTimeoutWrite(1000); -} - - -void PIUSB::Endpoint::parse() { - direction = Write; - transfer_type = Control; - synchronisation_type = NoSynchonisation; - usage_type = DataEndpoint; - direction = (Direction)((address >> 7) & 1); - transfer_type = (TransferType)(attributes & 3); - if (transfer_type == Isochronous) { - synchronisation_type = (SynchronisationType)((attributes >> 2) & 3); - usage_type = (UsageType)((attributes >> 4) & 3); - } -} - - -PIUSB::Endpoint PIUSB::getEndpointByAddress(uchar address) { - piForeachC (Endpoint & i, eps) - if (i.address == address) - return i; - return Endpoint(); -} - - -PIVector PIUSB::endpointsRead() { - PIVector ret; - piForeachC (Endpoint & i, eps) - if (i.direction == Endpoint::Read) - ret << i; - return ret; -} - - -PIVector PIUSB::endpointsWrite() { - PIVector ret; - piForeachC (Endpoint & i, eps) - if (i.direction == Endpoint::Write) - ret << i; - return ret; -} - - -bool PIUSB::setConfiguration(uchar value) { -#ifdef PIP_USB - if (hdev == 0) return false; - bool found = false; - piForeachC (Configuration & c, desc_.configurations) - if (c.value_to_select == value) {found = true; conf_ = c; break;} - if (!found) { - piCoutObj << "Can`t find configuration with \"value_to_select\" =" << value; - return false; - } - if (interface_claimed >= 0) - usb_release_interface(hdev, interface_claimed); - interface_claimed = -1; - return setInterface(conf_.interfaces.front().value_to_select); -#else - return false; -#endif -} - - -bool PIUSB::setInterface(uchar value) { -#ifdef PIP_USB - if (hdev == 0) return false; - bool found = false; - piForeachC (Interface & i, conf_.interfaces) - if (i.value_to_select == value) {found = true; iface_ = i; break;} - if (!found) { - piCoutObj << "Can`t find interface with \"value_to_select\" =" << value; - return false; - } - if (interface_claimed >= 0) - usb_release_interface(hdev, interface_claimed); - interface_claimed = -1; - if (usb_claim_interface(hdev, iface_.value_to_select) < 0) { - piCoutObj << "Error: Cant`t claim interface!"; - return false; - } - eps.clear(); - eps = iface_.endpoints; - ep_read = ep_write = Endpoint(); - for (int i = 0; i < eps.size_s(); ++i) { - if (eps[i].direction == Endpoint::Read && ep_read.isNull()) - ep_read = eps[i]; - if (eps[i].direction == Endpoint::Write && ep_write.isNull()) - ep_write = eps[i]; - } - interface_claimed = value; - return true; -#else - return false; -#endif -} - - -bool PIUSB::configureDevice(const void * e_main, const void * e_parent) { -#ifdef PIP_USB - PIConfig::Entry * em = (PIConfig::Entry * )e_main; - PIConfig::Entry * ep = (PIConfig::Entry * )e_parent; - PIString vp = readDeviceSetting("device", "", em, ep); - ushort v, p; - if (vp.isEmpty()) { - v = readDeviceSetting("vid", vendorID(), em, ep); - p = readDeviceSetting("pid", productID(), em, ep); - } else { - v = vp.left(vp.find(":")).toInt(16); - p = vp.right(vp.length() - vp.find(":") - 1).toInt(16); - } - setVendorID(v); - setProductID(p); - setDeviceNumber(readDeviceSetting("deviceNumber", deviceNumber(), em, ep)); - setConfiguration(readDeviceSetting("configuration", currentConfiguration().value_to_select, em, ep)); - setInterface(readDeviceSetting("interface", currentInterface().value_to_select, em, ep)); - setEndpointRead(Endpoint(readDeviceSetting("endpointRead", endpointRead().address, em, ep))); - setEndpointWrite(Endpoint(readDeviceSetting("endpointWrite", endpointWrite().address, em, ep))); - return true; -#else - return false; -#endif -} - - -bool PIUSB::openDevice() { -#ifdef PIP_USB - if (path().size_s() >= 8) { - vid_ = path().left(4).toInt(16); - pid_ = path().right(4).toInt(16); - } - if (hdev != 0) closeDevice(); - hdev = 0; - interface_claimed = -1; - ep_write = ep_read = Endpoint(); - usb_init(); - //usb_set_debug(4); - if (usb_find_busses() < 0) { - piCoutObj << "Error: Cant`t find busses!"; - return false; - } - if (usb_find_devices() < 0) { - piCoutObj << "Error: Cant`t find devices!"; - return false; - } - - //piCoutObj << "Search for device ... " << flush; - int cur_num = 1; - bool found = false; - struct usb_device * dev; - struct usb_bus * bus; - for (bus = usb_get_busses(); bus; bus = bus->next) { - for (dev = bus->devices; dev; dev = dev->next) { - if (dev->descriptor.idVendor == vid_ && dev->descriptor.idProduct == pid_) { - if (cur_num == deviceNumber()) { - struct usb_device_descriptor & dd(dev->descriptor); - desc_.usb_spec_number = dd.bcdUSB; - desc_.device_class = dd.bDeviceClass; - desc_.device_subclass = dd.bDeviceSubClass; - desc_.device_protocol = dd.bDeviceProtocol; - desc_.max_packet_size = dd.bMaxPacketSize0; - desc_.id_vendor = dd.idVendor; - desc_.id_product = dd.idProduct; - desc_.id_device_release = dd.bcdDevice; - desc_.index_manufacturer = dd.iManufacturer; - desc_.index_product = dd.iProduct; - desc_.index_serial = dd.iSerialNumber; - desc_.configurations.clear(); - for (int c = 0; c < dd.bNumConfigurations; ++c) { - desc_.configurations << Configuration(); - Configuration & conf(desc_.configurations.back()); - struct usb_config_descriptor & dc(dev->config[c]); - conf.index = c; - conf.value_to_select = dc.bConfigurationValue; - conf.attributes = dc.bmAttributes; - conf.max_power = ushort(dc.MaxPower) * 2; - conf.self_powered = (conf.attributes >> 6) & 1; - conf.remote_wakeup = (conf.attributes >> 5) & 1; - conf.interfaces.clear(); - for (int i = 0; i < dc.bNumInterfaces; ++i) { - conf.interfaces << Interface(); - Interface & infc(conf.interfaces.back()); - struct usb_interface_descriptor * di(dc.interface[c].altsetting); - infc.index = i; - infc.value_to_select = di->bAlternateSetting; - infc.class_code = di->bInterfaceClass; - infc.subclass_code = di->bInterfaceSubClass; - infc.protocol_code = di->bInterfaceProtocol; - infc.endpoints.clear(); - for (int e = 0; e < di->bNumEndpoints; ++e) { - infc.endpoints << Endpoint(di->endpoint[e].bEndpointAddress, - di->endpoint[e].bmAttributes, - di->endpoint[e].wMaxPacketSize); - } - } - } - if (!desc_.configurations.isEmpty()) - conf_ = desc_.configurations.front(); - - struct usb_interface_descriptor * is = dev->config->interface->altsetting; - int epn = is->bNumEndpoints; - eps.clear(); - for (int i = 0; i < epn; ++i) { - eps << Endpoint(is->endpoint[i].bEndpointAddress, - is->endpoint[i].bmAttributes, - is->endpoint[i].wMaxPacketSize); - if (eps.back().direction == Endpoint::Write && (eps.back().address == ep_write.address || ep_write.address == 0)) ep_write = eps.back(); - if (eps.back().direction == Endpoint::Read && (eps.back().address == ep_read.address || ep_read.address == 0)) ep_read = eps.back(); - } - - //piCoutObj << "Device found at address:" << "Bus: " << dev->bus->dirname << ", Device: " << dev->filename; - found = true; - break; - } else cur_num++; - } - } - if (found) break; - } - if (!found) { - piCoutObj << "Error: Cant`t find device!"; - return false; - } - //piCoutObj << "Open ... " << flush; - hdev = usb_open(dev); - if (hdev == 0) { - piCoutObj << "Error: Cant`t open device:" << usb_strerror(); - return false; - }// else piCoutObj << "ok"; - //usb_reset(hdev); - - //usb_set_configuration(hdev, 1); - //usb_set_altinterface(hdev, 0); - -# ifndef WINDOWS - char tbuff[256]; - //piCoutObj << "Check for bounded driver ... " << flush; - if (usb_get_driver_np(hdev, intefrace_, tbuff, sizeof(tbuff) - 1) >= 0) { - //piCoutObj << "yes" << "Found driver: " << tbuff; - //piCoutObj << "Detach driver ... " << flush; - if (usb_detach_kernel_driver_np(hdev, intefrace_)< 0) { - piCoutObj << "Error: Cant`t detach bounded driver!"; - return false; - }// else piCoutObj << "ok"; - }// else piCoutObj << "no"; -# endif - - //piCoutObj << "Claim interface ... " << flush; - if (usb_claim_interface(hdev, intefrace_) < 0) { - piCoutObj << "Error: Cant`t claim interface:" << usb_strerror(); - return false; - } // else piCoutObj << "ok"; - interface_claimed = intefrace_; - - return true; -#else - return false; -#endif -} - - -bool PIUSB::closeDevice() { -#ifdef PIP_USB - if (hdev == 0) return true; - //usb_reset(hdev); - usb_release_interface(hdev, intefrace_); - usb_close(hdev); - hdev = 0; - interface_claimed = -1; - return true; -#else - return false; -#endif -} - - -int PIUSB::read(void * read_to, int max_size) { -#ifdef PIP_USB - if (!opened_ || ep_read.isNull()) return -1; - switch (ep_read.transfer_type) { - case Endpoint::Bulk: /*piCoutObj << "bulk read" << max_size;*/ return usb_bulk_read(hdev, ep_read.address, (char * )read_to, max_size, timeout_r); break; - case Endpoint::Interrupt: return usb_interrupt_read(hdev, ep_read.address, (char * )read_to, max_size, timeout_r); break; - default: break; - } - return -1; -#else - return -1; -#endif -} - - -int PIUSB::write(const void * data, int max_size) { -#ifdef PIP_USB - if (!opened_ || ep_write.isNull()) return -1; - switch (ep_read.transfer_type) { - case Endpoint::Bulk: /*piCoutObj << "bulk write" << max_size;*/ return usb_bulk_write(hdev, ep_write.address, (char * )const_cast(data), max_size, timeout_w); break; - case Endpoint::Interrupt: return usb_interrupt_write(hdev, ep_read.address, (char * )data, max_size, timeout_w); break; - default: break; - } - return -1; -#else - return -1; -#endif -} - - -int PIUSB::controlWrite(const void * data, int max_size) { -#ifdef PIP_USB - if (!opened_) return -1; - //return usb_control_msg(hdev, ); - return -1; -#else - return -1; -#endif -} - - -void PIUSB::flush() { -#ifdef PIP_USB - if (!opened_) return; - if (!ep_read.isNull()) usb_resetep(hdev, ep_read.address); - if (!ep_write.isNull()) usb_resetep(hdev, ep_write.address); -#endif -} - - -PICout operator<<(PICout s, const PIUSB::Endpoint & v) { - s.setControl(0, true); - s << NewLine << "{" << NewLine; - if (v.isNull()) - s << " " << "Null Endpoint"; - else { - s << " " << "Address: " << v.address << NewLine; - s << " " << "Attributes: " << v.attributes << NewLine; - s << " " << "Direction: " << (v.direction == PIUSB::Endpoint::Write ? "Write" : "Read") << NewLine; - s << " " << "Transfer Type: "; - switch (v.transfer_type) { - case PIUSB::Endpoint::Control: s << "Control" << NewLine; break; - case PIUSB::Endpoint::Bulk: s << "Bulk" << NewLine; break; - case PIUSB::Endpoint::Interrupt: s << "Interrupt" << NewLine; break; - case PIUSB::Endpoint::Isochronous: s << "Isochronous" << NewLine; break; - default: break; - } - if (v.transfer_type == PIUSB::Endpoint::Isochronous) { - s << " " << "Synchronisation Type: "; - switch (v.synchronisation_type) { - case PIUSB::Endpoint::NoSynchonisation: s << "No Synchonisation" << NewLine; break; - case PIUSB::Endpoint::Asynchronous: s << "Asynchronous" << NewLine; break; - case PIUSB::Endpoint::Adaptive: s << "Adaptive" << NewLine; break; - case PIUSB::Endpoint::Synchronous: s << "Synchronous" << NewLine; break; - default: break; - } - s << " " << "Usage Type: "; - switch (v.usage_type) { - case PIUSB::Endpoint::DataEndpoint: s << "Data Endpoint" << NewLine; break; - case PIUSB::Endpoint::FeedbackEndpoint: s << "Feedback Endpoint" << NewLine; break; - case PIUSB::Endpoint::ExplicitFeedbackDataEndpoint: s << "Explicit Feedback Data Endpoint" << NewLine; break; - default: break; - } - } - s << " " << "Max Packet Size: " << v.max_packet_size << NewLine; - } - s << "}" << NewLine; - s.restoreControl(); - return s; -} - - -PIString PIUSB::constructFullPath() const { - PIString ret(fullPathPrefix() + "://"); - ret << PIString::fromNumber(vendorID(), 16).toLowerCase() << ":" << PIString::fromNumber(productID(), 16).toLowerCase() << ":" << deviceNumber() << ":" << endpointRead().address << ":" << endpointWrite().address; - return ret; -} - - -void PIUSB::configureFromFullPath(const PIString & full_path) { - PIStringList pl = full_path.split(":"); - for (int i = 0; i < pl.size_s(); ++i) { - PIString p(pl[i]); - switch (i) { - case 0: setVendorID(p.toUShort(16)); break; - case 1: setProductID(p.toUShort(16)); break; - case 2: setDeviceNumber(p.toInt()); break; - case 3: setEndpointRead(Endpoint(p.toInt())); break; - case 4: setEndpointWrite(Endpoint(p.toInt())); break; - } - } -} diff --git a/piusb.h b/piusb.h deleted file mode 100644 index 437c1b5b..00000000 --- a/piusb.h +++ /dev/null @@ -1,153 +0,0 @@ -/*! \file piusb.h - * \brief USB device -*/ -/* - PIP - Platform Independent Primitives - USB, based on libusb - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIUSB_H -#define PIUSB_H - -#include "piiodevice.h" - -struct usb_dev_handle; - -class PIP_EXPORT PIUSB: public PIIODevice -{ - PIIODEVICE(PIUSB) -public: - PIUSB(ushort vid = 0, ushort pid = 0); - - struct Endpoint { - Endpoint(uchar a = 0, uchar at = 0, ushort mps = 0) {address = a; attributes = at; max_packet_size = mps; parse();} - - enum Direction {Write = 0, Read = 1}; - enum TransferType {Control = 0, Isochronous = 1, Bulk = 2, Interrupt = 3}; - enum SynchronisationType {NoSynchonisation= 0, Asynchronous = 2, Adaptive = 1, Synchronous = 3}; - enum UsageType {DataEndpoint = 0, FeedbackEndpoint = 2, ExplicitFeedbackDataEndpoint = 1}; - - void parse(); - bool isNull() const {return address == 0;} - - uchar address; - uchar attributes; - ushort max_packet_size; - Direction direction; - TransferType transfer_type; - SynchronisationType synchronisation_type; - UsageType usage_type; - }; - - struct Interface { - Interface() {index = value_to_select = class_code = subclass_code = protocol_code = 0;} - uchar index; - uchar value_to_select; - ushort class_code; - ushort subclass_code; - ushort protocol_code; - PIVector endpoints; - }; - - struct Configuration { - Configuration() {index = value_to_select = attributes = max_power = 0; self_powered = remote_wakeup = false;} - uchar index; - uchar value_to_select; - uchar attributes; - ushort max_power; // mA - bool self_powered; - bool remote_wakeup; - PIVector interfaces; - }; - - struct Descriptor { - Descriptor() {memset(this, 0, sizeof(Descriptor));} - ushort usb_spec_number; - uchar device_class; - uchar device_subclass; - uchar device_protocol; - uchar max_packet_size; - ushort id_vendor; - ushort id_product; - ushort id_device_release; - uchar index_manufacturer; - uchar index_product; - uchar index_serial; - PIVector configurations; - }; - - const PIUSB::Descriptor & currentDescriptor() const {return desc_;} - const PIUSB::Configuration & currentConfiguration() const {return conf_;} - const PIUSB::Interface & currentInterface() const {return iface_;} - - ushort vendorID() const {return vid_;} - ushort productID() const {return pid_;} - - int deviceNumber() const {return property("deviceNumber").toInt();} - int timeoutRead() const {return property("timeoutRead").toInt();} - int timeoutWrite() const {return property("timeoutWrite").toInt();} - const PIUSB::Endpoint & endpointRead() const {return ep_read;} - const PIUSB::Endpoint & endpointWrite() const {return ep_write;} - - const PIVector & endpoints() const {return eps;} - PIVector endpointsRead(); - PIVector endpointsWrite(); - PIUSB::Endpoint getEndpointByAddress(uchar address); - - void setVendorID(ushort vid) {vid_ = vid; setPath(PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0"));} - void setProductID(ushort pid) {pid_ = pid; setPath(PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0"));} - - bool setConfiguration(uchar value); - bool setInterface(uchar value); - - void setEndpointRead(const PIUSB::Endpoint & ep) {ep_read = ep;} - void setEndpointWrite(const PIUSB::Endpoint & ep) {ep_write = ep;} - void setDeviceNumber(int dn) {setProperty("deviceNumber", dn);} - void setTimeoutRead(int t) {setProperty("timeoutRead", t);} - void setTimeoutWrite(int t) {setProperty("timeoutWrite", t);} - - int read(void * read_to, int max_size); - int write(const void * data, int max_size); - int controlWrite(const void * data, int max_size); - - void flush(); - - PIString constructFullPath() const; - -protected: - PIString fullPathPrefix() const {return "usb";} - void configureFromFullPath(const PIString & full_path); - bool configureDevice(const void * e_main, const void * e_parent = 0); - //bool init(); - bool openDevice(); - bool closeDevice(); - - PIVector eps; - ushort vid_, pid_; - int intefrace_, timeout_r, timeout_w; - int interface_claimed; - PIUSB::Endpoint ep_read, ep_write; - Descriptor desc_; - Configuration conf_; - Interface iface_; - usb_dev_handle * hdev; - -}; - -PICout operator <<(PICout s, const PIUSB::Endpoint & v); - -#endif // PIUSB_H diff --git a/pivariant.cpp b/pivariant.cpp deleted file mode 100644 index e9a4424a..00000000 --- a/pivariant.cpp +++ /dev/null @@ -1,534 +0,0 @@ -/* - PIP - Platform Independent Primitives - Variant type - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "pivariant.h" - - -/** \class PIVariant - * \brief Variant type - * \details - * \section PIVariant_sec0 Synopsis - * This class provides general type that can contains all standard types, some - * PIP types or custom type. In case of standard types this class also provides - * convertions between them. - * - * \section PIVariant_sec1 Usage - * %PIVariant useful if you want pass many variables with different types in - * single array, e.g.: - * \code{cpp} - * PIVector array; - * array << PIVariant(10) << PIVariant(1.61) << PIVariant(true) << PIVariant("0xFF"); - * piCout << array; - * piForeachC (PIVariant & i, array) - * piCout << i.toInt(); - * \endcode - * Result: - * \code{cpp} - * {PIVariant(Int, 10), PIVariant(Double, 1,61), PIVariant(Bool, true), PIVariant(String, 0xFF)} - * 10 - * 1 - * 1 - * 255 - * \endcode - * */ - - -PIVariant::PIVariant() { - type_ = PIVariant::Invalid; - memset(_vraw, 0, __PIVARIANT_UNION_SIZE__); -} - - -PIVariant & PIVariant::operator =(const PIVariant & v) { - type_ = v.type_; - memcpy(_vraw, v._vraw, __PIVARIANT_UNION_SIZE__); - _vbytearray = v._vbytearray; - _vbitarray = v._vbitarray; - _vstring = v._vstring; - _vstringlist = v._vstringlist; - _vcustom = v._vcustom; - return *this; -} - - -bool PIVariant::operator ==(const PIVariant & v) const { - if (type_ != v.type_) return false; - switch (type_) { - case PIVariant::Bool: - case PIVariant::Char: - case PIVariant::UChar: - case PIVariant::Short: - case PIVariant::UShort: - case PIVariant::Int: - case PIVariant::UInt: - case PIVariant::Long: - case PIVariant::ULong: return _vint == v._vint; - case PIVariant::LLong: - case PIVariant::ULLong: return _vllong == v._vllong; - case PIVariant::Float: return _vfloat == v._vfloat; - case PIVariant::Double: return _vdouble == v._vdouble; - case PIVariant::LDouble: return _vldouble == v._vldouble; - case PIVariant::Complexd: return _vcomplexd == _vvcomplexd(v); - case PIVariant::Complexld: return _vcomplexld == _vvcomplexld(v); - case PIVariant::BitArray: return _vbitarray == v._vbitarray; - case PIVariant::ByteArray: return _vbytearray == v._vbytearray; - case PIVariant::String: return _vstring == v._vstring; - case PIVariant::StringList: return _vstringlist == v._vstringlist; - case PIVariant::Time: return _vtime == _vvtime(v); - case PIVariant::Date: return _vdate == _vvdate(v); - case PIVariant::DateTime: return _vdatetime == _vvdatetime(v); - case PIVariant::SystemTime: return _vsystime == _vvsystime(v); - default: break; - }; - return false; -} - - -PIVariant::Type PIVariant::typeFromName(const PIString & tname) { - PIString s = tname.trimmed().toLowerCase().replaceAll(" ", ""); - if (s == "bool" || s == "boolean") return PIVariant::Bool; - if (s == "char" || s == "sbyte") return PIVariant::Char; - if (s == "short" || s == "shortint" || s == "signedshort" || s == "signedshortint" || s == "sword") return PIVariant::Short; - if (s == "int" || s == "signed" || s == "signedint") return PIVariant::Int; - if (s == "long" || s == "longint" || s == "signedlong" || s == "signedlongint" || s == "sdword") return PIVariant::Long; - if (s == "llong" || s == "longlong" || s == "longlongint" || s == "signedlonglong" || s == "signedlonglongint" || s == "sqword") return PIVariant::LLong; - if (s == "uchar" || s == "byte") return PIVariant::UChar; - if (s == "ushort" || s == "unsignedshort" || s == "unsignedshortint" || s == "word") return PIVariant::UShort; - if (s == "uint" || s == "unsigned" || s == "unsignedint") return PIVariant::UInt; - if (s == "ulong" || s == "unsignedlong" || s == "unsignedlongint" || s == "dword") return PIVariant::ULong; - if (s == "ullong" || s == "unsignedlonglong" || s == "unsignedlonglongint" || s == "qword") return PIVariant::ULLong; - if (s == "float") return PIVariant::Float; - if (s == "double" || s == "real") return PIVariant::Double; - if (s == "ldouble" || s == "longdouble") return PIVariant::LDouble; - if (s == "complexd" || s == "complex") return PIVariant::Complexd; - if (s == "complexld" || s == "complex" || s == "complex") return PIVariant::Complexld; - if (s == "pibitarray" || s == "bitarray") return PIVariant::BitArray; - if (s == "pibytearray" || s == "bytearray" || s == "vector" || s == "pivector" || s == "vector" || s == "pivector" || - s == "vector" || s == "pivector") return PIVariant::ByteArray; - if (s == "pistring" || s == "string") return PIVariant::String; - if (s == "pistringlist" || s == "vector" || s == "vector" || s == "pivector" || s == "pivector") return PIVariant::StringList; - if (s == "pitime" || s == "time") return PIVariant::Time; - if (s == "pidate" || s == "date") return PIVariant::Date; - if (s == "pidatetime" || s == "datetime") return PIVariant::DateTime; - if (s == "pisystemtime" || s == "systemtime") return PIVariant::SystemTime; - return PIVariant::Invalid; -} - - -PIString PIVariant::typeName(PIVariant::Type type) { - switch (type) { - case PIVariant::Bool: return "Bool"; - case PIVariant::Char: return "Char"; - case PIVariant::UChar: return "UChar"; - case PIVariant::Short: return "Short"; - case PIVariant::UShort: return "UShort"; - case PIVariant::Int: return "Int"; - case PIVariant::UInt: return "UInt"; - case PIVariant::Long: return "Long"; - case PIVariant::ULong: return "ULong"; - case PIVariant::LLong: return "LLong"; - case PIVariant::ULLong: return "ULLong"; - case PIVariant::Float: return "Float"; - case PIVariant::Double: return "Double"; - case PIVariant::LDouble: return "LDouble"; - case PIVariant::Complexd: return "Complexd"; - case PIVariant::Complexld: return "Complexld"; - case PIVariant::BitArray: return "BitArray"; - case PIVariant::ByteArray: return "ByteArray"; - case PIVariant::String: return "String"; - case PIVariant::StringList: return "StringList"; - case PIVariant::Time: return "Time"; - case PIVariant::Date: return "Date"; - case PIVariant::DateTime: return "DateTime"; - case PIVariant::SystemTime: return "SystemTime"; - case PIVariant::Custom: return "Custom"; - default: break; - } - return "Invalid"; -} - - -/** \brief Returns variant content as boolean - * \details In case of numeric types returns \b true if value != 0. \n - * In case of String type returns \a PIString::toBool(). \n - * In case of StringList type returns \b false if string list is empty, - * otherwise returns \a PIString::toBool() of first string. \n - * In case of other types returns \b false. */ -bool PIVariant::toBool() const { - switch (type_) { - case PIVariant::Bool: - case PIVariant::Char: - case PIVariant::UChar: - case PIVariant::Short: - case PIVariant::UShort: - case PIVariant::Int: - case PIVariant::UInt: - case PIVariant::Long: - case PIVariant::ULong: return _vint != 0; - case PIVariant::LLong: - case PIVariant::ULLong: return _vllong != 0; - case PIVariant::Float: return _vfloat != 0; - case PIVariant::Double: return _vdouble != 0; - case PIVariant::LDouble: return _vldouble != 0; - case PIVariant::Complexd: return _vcomplexd.real() != 0; - case PIVariant::Complexld: return _vcomplexld.real() != 0; - case PIVariant::String: return _vstring.toBool(); - case PIVariant::StringList: if (_vstringlist.isEmpty()) return false; return _vstringlist.front().toBool(); - default: break; - } - return false; -} - - - -/** \brief Returns variant content as int - * \details In case of numeric types returns integer value. \n - * In case of String type returns \a PIString::toInt(). \n - * In case of StringList type returns \b 0 if string list is empty, - * otherwise returns \a PIString::toInt() of first string. \n - * In case of other types returns \b 0. */ -int PIVariant::toInt() const { - switch (type_) { - case PIVariant::Bool: - case PIVariant::Char: - case PIVariant::UChar: - case PIVariant::Short: - case PIVariant::UShort: - case PIVariant::Int: - case PIVariant::UInt: - case PIVariant::Long: - case PIVariant::ULong: return _vint; - case PIVariant::LLong: - case PIVariant::ULLong: return _vllong; - case PIVariant::Float: return _vfloat; - case PIVariant::Double: return _vdouble; - case PIVariant::LDouble: return _vldouble; - case PIVariant::Complexd: return _vcomplexd.real(); - case PIVariant::Complexld: return _vcomplexld.real(); - case PIVariant::String: return _vstring.toInt(); - case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0; return _vstringlist.front().toInt(); - default: break; - } - return 0; -} - - -/** \brief Returns variant content as long long - * \details In case of numeric types returns integer value. \n - * In case of String type returns \a PIString::toLLong(). \n - * In case of StringList type returns \b 0L if string list is empty, - * otherwise returns \a PIString::toLLong() of first string. \n - * In case of other types returns \b 0L. */ -llong PIVariant::toLLong() const { - switch (type_) { - case PIVariant::Bool: - case PIVariant::Char: - case PIVariant::UChar: - case PIVariant::Short: - case PIVariant::UShort: - case PIVariant::Int: - case PIVariant::UInt: - case PIVariant::Long: - case PIVariant::ULong: return _vint; - case PIVariant::LLong: - case PIVariant::ULLong: return _vllong; - case PIVariant::Float: return _vfloat; - case PIVariant::Double: return _vdouble; - case PIVariant::LDouble: return _vldouble; - case PIVariant::Complexd: return _vcomplexd.real(); - case PIVariant::Complexld: return _vcomplexld.real(); - case PIVariant::String: return _vstring.toLLong(); - case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0L; return _vstringlist.front().toLLong(); - default: break; - } - return 0L; -} - - -/** \brief Returns variant content as float - * \details In case of numeric types returns float value. \n - * In case of String type returns \a PIString::toFloat(). \n - * In case of StringList type returns \b 0.f if string list is empty, - * otherwise returns \a PIString::toFloat() of first string. \n - * In case of other types returns \b 0.f. */ -float PIVariant::toFloat() const { - switch (type_) { - case PIVariant::Bool: - case PIVariant::Char: - case PIVariant::UChar: - case PIVariant::Short: - case PIVariant::UShort: - case PIVariant::Int: - case PIVariant::UInt: - case PIVariant::Long: - case PIVariant::ULong: return _vint; - case PIVariant::LLong: - case PIVariant::ULLong: return _vllong; - case PIVariant::Float: return _vfloat; - case PIVariant::Double: return _vdouble; - case PIVariant::LDouble: return _vldouble; - case PIVariant::Complexd: return _vcomplexd.real(); - case PIVariant::Complexld: return _vcomplexld.real(); - case PIVariant::String: return _vstring.toFloat(); - case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0.f; return _vstringlist.front().toFloat(); - default: break; - } - return 0.f; -} - - -/** \brief Returns variant content as double - * \details In case of numeric types returns double value. \n - * In case of String type returns \a PIString::toDouble(). \n - * In case of StringList type returns \b 0. if string list is empty, - * otherwise returns \a PIString::toDouble() of first string. \n - * In case of other types returns \b 0.. */ -double PIVariant::toDouble() const { - switch (type_) { - case PIVariant::Bool: - case PIVariant::Char: - case PIVariant::UChar: - case PIVariant::Short: - case PIVariant::UShort: - case PIVariant::Int: - case PIVariant::UInt: - case PIVariant::Long: - case PIVariant::ULong: return _vint; - case PIVariant::LLong: - case PIVariant::ULLong: return _vllong; - case PIVariant::Float: return _vfloat; - case PIVariant::Double: return _vdouble; - case PIVariant::LDouble: return _vldouble; - case PIVariant::Complexd: return _vcomplexd.real(); - case PIVariant::Complexld: return _vcomplexld.real(); - case PIVariant::String: return _vstring.toDouble(); - case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0.; return _vstringlist.front().toDouble(); - default: break; - } - return 0.; -} - - -/** \brief Returns variant content as long double - * \details In case of numeric types returns long double value. \n - * In case of String type returns \a PIString::toLDouble(). \n - * In case of StringList type returns \b 0. if string list is empty, - * otherwise returns \a PIString::toLDouble() of first string. \n - * In case of other types returns \b 0.. */ -ldouble PIVariant::toLDouble() const { - switch (type_) { - case PIVariant::Bool: - case PIVariant::Char: - case PIVariant::UChar: - case PIVariant::Short: - case PIVariant::UShort: - case PIVariant::Int: - case PIVariant::UInt: - case PIVariant::Long: - case PIVariant::ULong: return _vint; - case PIVariant::LLong: - case PIVariant::ULLong: return _vllong; - case PIVariant::Float: return _vfloat; - case PIVariant::Double: return _vdouble; - case PIVariant::LDouble: return _vldouble; - case PIVariant::Complexd: return _vcomplexd.real(); - case PIVariant::Complexld: return _vcomplexld.real(); - case PIVariant::String: return _vstring.toLDouble(); - case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0.; return _vstringlist.front().toLDouble(); - default: break; - } - return 0.; -} - - -/** \brief Returns variant content as complex - * \details In case of numeric types returns complex value. \n - * In case of String type returns \a PIString::toDouble(). \n - * In case of StringList type returns \b 0. if string list is empty, - * otherwise returns \a PIString::toDouble() of first string. \n - * In case of other types returns \b 0.. */ -complexd PIVariant::toComplexd() const { - switch (type_) { - case PIVariant::Bool: - case PIVariant::Char: - case PIVariant::UChar: - case PIVariant::Short: - case PIVariant::UShort: - case PIVariant::Int: - case PIVariant::UInt: - case PIVariant::Long: - case PIVariant::ULong: return _vint; - case PIVariant::LLong: - case PIVariant::ULLong: return _vllong; - case PIVariant::Float: return _vfloat; - case PIVariant::Double: return _vdouble; - case PIVariant::LDouble: return _vldouble; - case PIVariant::Complexd: return _vcomplexd.real(); - case PIVariant::Complexld: return _vcomplexld.real(); - case PIVariant::String: return _vstring.toDouble(); - case PIVariant::StringList: if (_vstringlist.isEmpty()) return complexd_0; return _vstringlist.front().toDouble(); - default: break; - } - return complexd_0; -} - - -/** \brief Returns variant content as long complex - * \details In case of numeric types returns long complex value. \n - * In case of String type returns \a PIString::toLDouble(). \n - * In case of StringList type returns \b 0. if string list is empty, - * otherwise returns \a PIString::toLDouble() of first string. \n - * In case of other types returns \b 0.. */ -complexld PIVariant::toComplexld() const { - switch (type_) { - case PIVariant::Bool: - case PIVariant::Char: - case PIVariant::UChar: - case PIVariant::Short: - case PIVariant::UShort: - case PIVariant::Int: - case PIVariant::UInt: - case PIVariant::Long: - case PIVariant::ULong: return _vint; - case PIVariant::LLong: - case PIVariant::ULLong: return _vllong; - case PIVariant::Float: return _vfloat; - case PIVariant::Double: return _vdouble; - case PIVariant::LDouble: return _vldouble; - case PIVariant::Complexd: return _vcomplexd.real(); - case PIVariant::Complexld: return _vcomplexld.real(); - case PIVariant::String: return _vstring.toLDouble(); - case PIVariant::StringList: if (_vstringlist.isEmpty()) return complexld_0; return _vstringlist.front().toLDouble(); - default: break; - } - return complexld_0; -} - - -/** \brief Returns variant content as time - * \details In case of Time type returns time value. \n - * In case of DateTime type returns time part of value. \n - * In case of other types returns \a PITime(). */ -PITime PIVariant::toTime() const { - if (type_ == PIVariant::Time) return _vtime; - if (type_ == PIVariant::DateTime) return _vtime; - return PITime(); -} - - -/** \brief Returns variant content as date - * \details In case of Date type returns date value. \n - * In case of DateTime type returns date part of value. \n - * In case of other types returns \a PIDate(). */ -PIDate PIVariant::toDate() const { - if (type_ == PIVariant::Date) return _vdate; - if (type_ == PIVariant::DateTime) return *((PIDate*)(&(_vdatetime.day))); - return PIDate(); -} - - -/** \brief Returns variant content as date and time - * \details In case of Time type returns time value with null date. \n - * In case of Date type returns date value with null time. \n - * In case of DateTime type returns date and time. \n - * In case of other types returns \a PIDateTime(). */ -PIDateTime PIVariant::toDateTime() const { - if (type_ == PIVariant::DateTime) return _vdatetime; - if (type_ == PIVariant::Time) return PIDateTime(_vtime); - if (type_ == PIVariant::Date) return PIDateTime(_vdate); - return PIDateTime(); -} - - -/** \brief Returns variant content as system time - * \details In case of SystemTime type returns system time. \n - * In case of other types returns \a PISystemTime::fromSeconds() from - * double value of variant content. */ -PISystemTime PIVariant::toSystemTime() const { - if (type_ == PIVariant::SystemTime) return _vsystime; - return PISystemTime::fromSeconds(toDouble()); -} - - -/** \brief Returns variant content as string - * \details In case of numeric types returns \a PIString::fromNumber(). \n - * In case of String type returns string value. \n - * In case of StringList type returns joined string ("(" + PIStringList::join("; ") + ")"). \n - * In case of BitArray or ByteArray types returns number of bits/bytes. \n - * In case of Time, Date or DateTime types returns toString() of this values. \n - * In case of SystemTime types returns second and nanoseconds of time - * ("(PISystemTime::seconds s, PISystemTime::nanoseconds ns)"). \n - * In case of other types returns \b "". */ -PIString PIVariant::toString() const { - switch (type_) { - case PIVariant::Bool: return _vint == 0 ? "false" : "true"; - case PIVariant::Char: - case PIVariant::UChar: - case PIVariant::Short: - case PIVariant::UShort: - case PIVariant::Int: - case PIVariant::UInt: - case PIVariant::Long: - case PIVariant::ULong: return PIString::fromNumber(_vint); - case PIVariant::LLong: - case PIVariant::ULLong: return PIString::fromNumber(_vllong); - case PIVariant::Float: return PIString::fromNumber(_vfloat); - case PIVariant::Double: return PIString::fromNumber(_vdouble); - case PIVariant::LDouble: return PIString::fromNumber(_vldouble); - case PIVariant::Complexd: return "(" + PIString::fromNumber(_vcomplexd.real()) + "; " + PIString::fromNumber(_vcomplexd.imag()) + ")"; - case PIVariant::Complexld: return "(" + PIString::fromNumber(_vcomplexld.real()) + "; " + PIString::fromNumber(_vcomplexld.imag()) + ")"; - case PIVariant::BitArray: return PIString::fromNumber(_vbitarray.bitSize()) + " bits"; - case PIVariant::ByteArray: return _vbytearray.toString(); - case PIVariant::String: return _vstring; - case PIVariant::StringList: return "(" + _vstringlist.join("; ") + ")"; - case PIVariant::Time: return _vtime.toString(); - case PIVariant::Date: return _vdate.toString(); - case PIVariant::DateTime: return _vdatetime.toString(); - case PIVariant::SystemTime: return "(" + PIString::fromNumber(_vsystime.seconds) + " s, " + PIString::fromNumber(_vsystime.nanoseconds) + " ns)"; - default: break; - } - return ""; -} - - -/** \brief Returns variant content as strings list - * \details In case of StringList type returns strings list value. \n - * In case of other types returns \a PIStringList with one string value of variant content. */ -PIStringList PIVariant::toStringList() const { - if (type_ == PIVariant::StringList) return _vstringlist; - return PIStringList(toString()); -} - - -/** \brief Returns variant content as bit array - * \details In case of BitArray type returns bit array value. \n - * In case of other types returns \a PIBitArray from \a toLLong() value. */ -PIBitArray PIVariant::toBitArray() const { - if (type_ == PIVariant::BitArray) return _vbitarray; - return PIBitArray(ullong(toLLong())); -} - - -/** \brief Returns variant content as byte array - * \details In case of ByteArray type returns byte array value. \n - * In case of other types returns empty \a PIByteArray. */ -PIByteArray PIVariant::toByteArray() const { - if (type_ == PIVariant::ByteArray) return _vbytearray; - return PIByteArray(); -} diff --git a/pivariant.h b/pivariant.h deleted file mode 100644 index 7cba2770..00000000 --- a/pivariant.h +++ /dev/null @@ -1,461 +0,0 @@ -/*! \file pivariant.h - * \brief Variant type - * - * This file declares PIVariant -*/ -/* - PIP - Platform Independent Primitives - Variant type - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIVARIANT_H -#define PIVARIANT_H - -#include "pistring.h" -#include "pibitarray.h" -#include "pitime.h" -#include "pimath.h" - -#define __PIVARIANT_UNION_SIZE__ 32 - -#define _vcomplexd (*((complexd*)_vraw)) -#define _vcomplexld (*((complexld*)_vraw)) -#define _vtime (*((PITime*)_vraw)) -#define _vdate (*((PIDate*)_vraw)) -#define _vdatetime (*((PIDateTime*)_vraw)) -#define _vsystime (*((PISystemTime*)_vraw)) - -#define _vvcomplexd(v) (*((complexd*)v._vraw)) -#define _vvcomplexld(v) (*((complexld*)v._vraw)) -#define _vvtime(v) (*((PITime*)v._vraw)) -#define _vvdate(v) (*((PIDate*)v._vraw)) -#define _vvdatetime(v) (*((PIDateTime*)v._vraw)) -#define _vvsystime(v) (*((PISystemTime*)v._vraw)) - -class PIP_EXPORT PIVariant { - friend PICout operator <<(PICout s, const PIVariant & v); -public: - - //! Type of %PIVariant content - enum Type { - Invalid /** Invalid type , default type of empty contructor */ = 0 , - Bool /** bool */ , - Char /** char */ , - UChar /** uchar */ , - Short /** short */ , - UShort /** ushort */ , - Int /** int */ , - UInt /** uint */ , - Long /** long */ , - ULong /** ulong */ , - LLong /** llong */ , - ULLong /** ullong */ , - Float /** float */ , - Double /** double */ , - LDouble /** ldouble */ , - Complexd /** complexd */ , - Complexld /** complexld */ , - BitArray /** PIBitArray */ , - ByteArray /** PIByteArray */ , - String /** PIString */ , - StringList /** PIStringList */ , - Time /** PITime */ , - Date /** PIDate */ , - DateTime /** PIDateTime */ , - SystemTime /** PISystemTime */ , - Custom /** Custom */ = 0xFF - }; - - //! Empty constructor, \a type() will be set to \a Invalid - PIVariant(); - - //! Constructs variant from string - PIVariant(const char * v) {setValue(PIString(v));} - - //! Constructs variant from boolean - PIVariant(const bool v) {setValue(v);} - - //! Constructs variant from char - PIVariant(const char v) {setValue(v);} - - //! Constructs variant from integer - PIVariant(const uchar v) {setValue(v);} - - //! Constructs variant from integer - PIVariant(const short v) {setValue(v);} - - //! Constructs variant from integer - PIVariant(const ushort v) {setValue(v);} - - //! Constructs variant from integer - PIVariant(const int & v) {setValue(v);} - - //! Constructs variant from integer - PIVariant(const uint & v) {setValue(v);} - - //! Constructs variant from integer - PIVariant(const long & v) {setValue(v);} - - //! Constructs variant from integer - PIVariant(const ulong & v) {setValue(v);} - - //! Constructs variant from integer - PIVariant(const llong & v) {setValue(v);} - - //! Constructs variant from integer - PIVariant(const ullong & v) {setValue(v);} - - //! Constructs variant from float - PIVariant(const float & v) {setValue(v);} - - //! Constructs variant from double - PIVariant(const double & v) {setValue(v);} - - //! Constructs variant from long double - PIVariant(const ldouble & v) {setValue(v);} - - //! Constructs variant from complex - PIVariant(const complexd & v) {setValue(v);} - - //! Constructs variant from complex - PIVariant(const complexld & v) {setValue(v);} - - //! Constructs variant from bit array - PIVariant(const PIBitArray & v) {setValue(v);} - - //! Constructs variant from byte array - PIVariant(const PIByteArray & v) {setValue(v);} - - //! Constructs variant from string - PIVariant(const PIString & v) {setValue(v);} - - //! Constructs variant from strings list - PIVariant(const PIStringList & v) {setValue(v);} - - //! Constructs variant from time - PIVariant(const PITime & v) {setValue(v);} - - //! Constructs variant from date - PIVariant(const PIDate & v) {setValue(v);} - - //! Constructs variant from date and time - PIVariant(const PIDateTime & v) {setValue(v);} - - //! Constructs variant from system time - PIVariant(const PISystemTime & v) {setValue(v);} - - - //! Set variant content and type to string - void setValue(const char * v) {setValue(PIString(v));} - - //! Set variant content and type to boolean - void setValue(const bool v) {type_ = PIVariant::Bool; _vint = (v ? 1 : 0);} - - //! Set variant content and type to char - void setValue(const char v) {type_ = PIVariant::Char; _vint = v;} - - //! Set variant content and type to integer - void setValue(const uchar v) {type_ = PIVariant::UChar; _vint = v;} - - //! Set variant content and type to integer - void setValue(const short v) {type_ = PIVariant::Short; _vint = v;} - - //! Set variant content and type to integer - void setValue(const ushort v) {type_ = PIVariant::UShort; _vint = v;} - - //! Set variant content and type to integer - void setValue(const int & v) {type_ = PIVariant::Int; _vint = v;} - - //! Set variant content and type to integer - void setValue(const uint & v) {type_ = PIVariant::UInt; _vint = v;} - - //! Set variant content and type to integer - void setValue(const long & v) {type_ = PIVariant::Long; _vint = v;} - - //! Set variant content and type to integer - void setValue(const ulong & v) {type_ = PIVariant::ULong; _vint = v;} - - //! Set variant content and type to integer - void setValue(const llong & v) {type_ = PIVariant::LLong; _vllong = v;} - - //! Set variant content and type to integer - void setValue(const ullong & v) {type_ = PIVariant::ULLong; _vllong = v;} - - //! Set variant content and type to float - void setValue(const float & v) {type_ = PIVariant::Float; _vfloat = v;} - - //! Set variant content and type to double - void setValue(const double & v) {type_ = PIVariant::Double; _vdouble = v;} - - //! Set variant content and type to long double - void setValue(const ldouble & v) {type_ = PIVariant::LDouble; _vldouble = v;} - - //! Set variant content and type to complex - void setValue(const complexd & v) {type_ = PIVariant::Complexd; _vcomplexd = v;} - - //! Set variant content and type to complex - void setValue(const complexld & v) {type_ = PIVariant::Complexld; _vcomplexld = v;} - - //! Set variant content and type to bit array - void setValue(const PIBitArray & v) {type_ = PIVariant::BitArray; _vbitarray = v;} - - //! Set variant content and type to byte array - void setValue(const PIByteArray & v) {type_ = PIVariant::ByteArray; _vbytearray = v;} - - //! Set variant content and type to string - void setValue(const PIString & v) {type_ = PIVariant::String; _vstring = v;} - - //! Set variant content and type to strings list - void setValue(const PIStringList & v) {type_ = PIVariant::StringList; _vstringlist = v;} - - //! Set variant content and type to time - void setValue(const PITime & v) {type_ = PIVariant::Time; _vtime = v;} - - //! Set variant content and type to date - void setValue(const PIDate & v) {type_ = PIVariant::Date; _vdate = v;} - - //! Set variant content and type to date and time - void setValue(const PIDateTime & v) {type_ = PIVariant::DateTime; _vdatetime = v;} - - //! Set variant content and type to system time - void setValue(const PISystemTime & v) {type_ = PIVariant::SystemTime; _vsystime = v;} - - - bool toBool() const; - int toInt() const; - llong toLLong() const; - float toFloat() const; - double toDouble() const; - ldouble toLDouble() const; - complexd toComplexd() const; - complexld toComplexld() const; - PITime toTime() const; - PIDate toDate() const; - PIDateTime toDateTime() const; - PISystemTime toSystemTime() const; - PIString toString() const; - PIStringList toStringList() const; - PIBitArray toBitArray() const; - PIByteArray toByteArray() const; - - - /** \brief Returns variant content as custom type - * \details In case of known types this function equivalent \a to function. \n - * Otherwise returns content as type T. */ - template - T toValue() const {if (_vcustom.size() != sizeof(T)) return T(); return *((T*)_vcustom.data());} - /* - operator bool() const {return toBool();} - operator char() const {return toInt();} - operator uchar() const {return toInt();} - operator short() const {return toInt();} - operator ushort() const {return toInt();} - operator int() const {return toInt();} - operator uint() const {return toInt();} - operator long() const {return toInt();} - operator ulong() const {return toInt();} - operator llong() const {return toLLong();} - operator ullong() const {return (ullong)toLLong();} - operator float() const {return toFloat();} - operator double() const {return toDouble();} - operator ldouble() const {return toLDouble();} - operator complexd() const {return toComplexd();} - operator complexld() const {return toComplexld();} - operator PITime() const {return toTime();} - operator PIDate() const {return toDate();} - operator PIDateTime() const {return toDateTime();} - operator PIString() const {return toString();} - operator PIStringList() const {return toStringList();} - operator PIBitArray() const {return toBitArray();} - operator PIByteArray() const {return toByteArray();} - operator const char*() const {return toString().data();} - operator void*() const {return (void*)(toLLong());} - */ - - //! Assign operator - PIVariant & operator =(const PIVariant & v); - //! Assign operator - PIVariant & operator =(const char * v) {setValue(PIString(v)); return *this;} - //! Assign operator - PIVariant & operator =(const bool v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const char v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const uchar v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const short v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const ushort v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const int & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const uint & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const long & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const ulong & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const llong & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const ullong & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const float & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const double & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const ldouble & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const complexd & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const complexld & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const PIBitArray & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const PIByteArray & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const PIString & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const PIStringList & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const PITime & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const PIDate & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const PIDateTime & v) {setValue(v); return *this;} - //! Assign operator - PIVariant & operator =(const PISystemTime & v) {setValue(v); return *this;} - - - //! Compare operator - bool operator ==(const PIVariant & v) const; - //! Compare operator - bool operator !=(const PIVariant & v) const {return !(*this == v);} - - - //! Returns type of variant content - PIVariant::Type type() const {return type_;} - - //! Returns type name of variant content - PIString typeName() const {return typeName(type_);} - - - //! Returns \b true if type is not Invalid - bool isValid() const {return type_ != PIVariant::Invalid;} - - - /** \brief Returns new variant from custom type - * \details In case of known types this function equivalent \a PIVariant(T) constructors. \n - * Otherwise returns variant with content \a v and type Custom. */ - template - static PIVariant fromValue(const T & v) {PIVariant ret; ret._vcustom.resize(sizeof(T)); new((T*)(ret._vcustom.data()))T(v); ret.type_ = PIVariant::Custom; return ret;} - - - //! Returns type from name - static PIVariant::Type typeFromName(const PIString & tname); - - //! Returns type name - static PIString typeName(PIVariant::Type type); - -private: - void destroy() {_vcustom.clear();} - - union { - int _vint; - llong _vllong; - float _vfloat; - double _vdouble; - ldouble _vldouble; - uchar _vraw[__PIVARIANT_UNION_SIZE__]; - /*complexd _vcomplexd; - complexld _vcomplexld; - PITime _vtime; - PIDate _vdate; - PIDateTime _vdatetime; - PISystemTime _vsystime;*/ - }; - PIBitArray _vbitarray; - PIByteArray _vbytearray; - PIString _vstring; - PIStringList _vstringlist; - PIByteArray _vcustom; - PIVariant::Type type_; - -}; - -template<> inline bool PIVariant::toValue() const {return toBool();} -template<> inline char PIVariant::toValue() const {return (char)toInt();} -template<> inline uchar PIVariant::toValue() const {return (uchar)toInt();} -template<> inline short PIVariant::toValue() const {return (short)toInt();} -template<> inline ushort PIVariant::toValue() const {return (ushort)toInt();} -template<> inline int PIVariant::toValue() const {return toInt();} -template<> inline uint PIVariant::toValue() const {return (uint)toInt();} -template<> inline long PIVariant::toValue() const {return (long)toInt();} -template<> inline ulong PIVariant::toValue() const {return (ulong)toInt();} -template<> inline llong PIVariant::toValue() const {return toLLong();} -template<> inline ullong PIVariant::toValue() const {return (ullong)toLLong();} -template<> inline float PIVariant::toValue() const {return toFloat();} -template<> inline double PIVariant::toValue() const {return toDouble();} -template<> inline ldouble PIVariant::toValue() const {return toLDouble();} -template<> inline complexd PIVariant::toValue() const {return toComplexd();} -template<> inline complexld PIVariant::toValue() const {return toComplexld();} -template<> inline void* PIVariant::toValue() const {return (void*)toLLong();} -template<> inline const char* PIVariant::toValue() const {return toString().data();} -template<> inline PITime PIVariant::toValue() const {return toTime();} -template<> inline PIDate PIVariant::toValue() const {return toDate();} -template<> inline PIDateTime PIVariant::toValue() const {return toDateTime();} -template<> inline PIString PIVariant::toValue() const {return toString();} -template<> inline PIStringList PIVariant::toValue() const {return toStringList();} -template<> inline PIBitArray PIVariant::toValue() const {return toBitArray();} -template<> inline PIByteArray PIVariant::toValue() const {return toByteArray();} - -//template<> inline PIVariant PIVariant::fromValue(const char * v) {return PIVariant(PIString(v));} -template<> inline PIVariant PIVariant::fromValue(const bool & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const char & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const uchar & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const short & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const ushort & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const int & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const uint & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const long & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const ulong & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const llong & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const ullong & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const float & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const double & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const ldouble & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const complexd & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const complexld & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const PIBitArray & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const PIByteArray & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const PIString & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const PIStringList & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const PITime & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const PIDate & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const PIDateTime & v) {return PIVariant(v);} -template<> inline PIVariant PIVariant::fromValue(const PISystemTime & v) {return PIVariant(v);} - -inline PICout operator <<(PICout s, const PIVariant & v) { - s.space(); s.setControl(0, true); - s << "PIVariant(" << PIVariant::typeName(v.type()) << ", "; - if (v.type() == PIVariant::Custom) s << v._vcustom.size() << " bytes"; - else s << v.toString(); - s << ")"; - s.restoreControl(); return s; -} - - -#endif // PIVARIANT_H diff --git a/pivector.h b/pivector.h deleted file mode 100644 index a380bbde..00000000 --- a/pivector.h +++ /dev/null @@ -1,527 +0,0 @@ -/*! \file pivector.h - * \brief Dynamic array of any type - * - * This file declares PIVector -*/ -/* - PIP - Platform Independent Primitives - Dynamic array of any type - Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PIVECTOR_H -#define PIVECTOR_H - -#include "piincludes.h" - - -#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN) - - -template -class PIVector { -public: - PIVector(): piv_data(0), piv_size(0), piv_rsize(0) { - //printf("new vector 1 %p (%s) ... !{\n", this, typeid(T).name()); - //printf("(s=%d, d=%p) }!\n", int(piv_size), piv_data); - } - PIVector(const PIVector & other): piv_data(0), piv_size(0), piv_rsize(0) { - //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name()); - alloc(other.piv_size); - newT(piv_data, other.piv_data, piv_size); - //printf("(s=%d, d=%p) }!\n", int(piv_size), piv_data); - } - PIVector(const T * data, size_t size): piv_data(0), piv_size(0), piv_rsize(0) { - //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name()); - alloc(size); - newT(piv_data, data, piv_size); - //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); - } - PIVector(size_t piv_size, const T & f = T()): piv_data(0), piv_size(0), piv_rsize(0) { - //printf("new vector 3 %p (%s) ... !{\n", this, typeid(T).name()); - resize(piv_size, f); - //printf("(s=%d, d=%p) }!\n", int(piv_size), piv_data); - } - ~PIVector() { - //printf("delete vector %p (%s) (s=%d, d=%p) ... ~{\n", this, typeid(T).name(), int(piv_size), piv_data); - deleteT(piv_data, piv_size); - dealloc(); - //deleteRaw(piv_tdata); - _reset(); - //printf("}~\n"); - } - - PIVector & operator =(const PIVector & other) { - if (this == &other) return *this; - bool tj, oj; - tj = (piv_size != 0 && piv_data == 0);// || (piv_size == 0 && piv_data != 0); - oj = (other.piv_size != 0 && other.piv_data == 0);// || (other.piv_size == 0 && other.piv_data != 0); - //printf("operator= (%p = %p) (s=%d, d=%p, o.s=%d, o.d=%p) (%d, %d) ... o[\n", this, &other, int(piv_size), piv_data, int(other.piv_size), other.piv_data, int(tj), int(oj)); - if (tj) { - printf("JUNK this\n"); - _reset(); - } else { - clear(); - } - /*if (piv_size == other.piv_size) { - for (size_t i = 0; i < piv_size; ++i) - piv_data[i] = other.piv_data[i]; - return *this; - }*/ - if (!oj) { - deleteT(piv_data, piv_size); - alloc(other.piv_size); - //zeroRaw(piv_data, piv_size); - for (size_t i = 0; i < piv_size; ++i) - elementNew(piv_data + i, other.piv_data[i]); //piv_data[i] = other.piv_data[i]; - } else { - printf("JUNK other\n"); - } - //printf("o]\n"); - return *this; - } - - typedef T value_type; - - class iterator { - friend class PIVector; - private: - iterator(PIVector * v, size_t p): parent(v), pos(p) {} - PIVector * parent; - size_t pos; - public: - iterator(): parent(0) {} - T & operator *() {return (*parent)[pos];} - const T & operator *() const {return (*parent)[pos];} - void operator ++() {++pos;} - void operator ++(int) {++pos;} - void operator --() {--pos;} - void operator --(int) {--pos;} - bool operator ==(const iterator & it) const {return (pos == it.pos);} - bool operator !=(const iterator & it) const {return (pos != it.pos);} - }; - - class const_iterator { - friend class PIVector; - private: - const_iterator(const PIVector * v, size_t p): parent(v), pos(p) {} - const PIVector * parent; - size_t pos; - public: - const_iterator(): parent(0) {} - //T & operator *() {return (*parent)[pos];} - const T & operator *() const {return (*parent)[pos];} - void operator ++() {++pos;} - void operator ++(int) {++pos;} - void operator --() {--pos;} - void operator --(int) {--pos;} - bool operator ==(const const_iterator & it) const {return (pos == it.pos);} - bool operator !=(const const_iterator & it) const {return (pos != it.pos);} - }; - - class reverse_iterator { - friend class PIVector; - private: - reverse_iterator(PIVector * v, size_t p): parent(v), pos(p) {} - PIVector * parent; - size_t pos; - public: - reverse_iterator(): parent(0) {} - T & operator *() {return (*parent)[pos];} - const T & operator *() const {return (*parent)[pos];} - void operator ++() {--pos;} - void operator ++(int) {--pos;} - void operator --() {++pos;} - void operator --(int) {++pos;} - bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);} - bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);} - }; - - class const_reverse_iterator { - friend class PIVector; - private: - const_reverse_iterator(const PIVector * v, size_t p): parent(v), pos(p) {} - const PIVector * parent; - size_t pos; - public: - const_reverse_iterator(): parent(0) {} - //T & operator *() {return (*parent)[pos];} - const T & operator *() const {return (*parent)[pos];} - void operator ++() {--pos;} - void operator ++(int) {--pos;} - void operator --() {++pos;} - void operator --(int) {++pos;} - bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);} - bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} - }; - - iterator begin() {return iterator(this, 0);} - iterator end() {return iterator(this, piv_size);} - const_iterator begin() const {return const_iterator(this, 0);} - const_iterator end() const {return const_iterator(this, piv_size);} - reverse_iterator rbegin() {return reverse_iterator(this, piv_size - 1);} - reverse_iterator rend() {return reverse_iterator(this, -1);} - const_reverse_iterator rbegin() const {return const_reverse_iterator(this, piv_size - 1);} - const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} - - size_t size() const {return piv_size;} - ssize_t size_s() const {return piv_size;} - size_t length() const {return piv_size;} - size_t capacity() const {return piv_rsize;} - bool isEmpty() const {return (piv_size == 0);} - - T & operator [](size_t index) {return piv_data[index];} - T & at(size_t index) {return piv_data[index];} - const T & operator [](size_t index) const {return piv_data[index];} - const T & at(size_t index) const {return piv_data[index];} - T & back() {return piv_data[piv_size - 1];} - const T & back() const {return piv_data[piv_size - 1];} - T & front() {return piv_data[0];} - const T & front() const {return piv_data[0];} - bool operator ==(const PIVector & t) const {if (piv_size != t.piv_size) return false; for (size_t i = 0; i < piv_size; ++i) if (t[i] != piv_data[i]) return false; return true;} - bool operator !=(const PIVector & t) const {if (piv_size != t.piv_size) return true; for (size_t i = 0; i < piv_size; ++i) if (t[i] != piv_data[i]) return true; return false;} - bool contains(const T & v) const {for (size_t i = 0; i < piv_size; ++i) if (v == piv_data[i]) return true; return false;} - int etries(const T & v) const {int ec = 0; for (size_t i = 0; i < piv_size; ++i) if (v == piv_data[i]) ++ec; return ec;} - - T * data(size_t index = 0) {return &(piv_data[index]);} - const T * data(size_t index = 0) const {return &(piv_data[index]);} - PIVector & clear() {resize(0); return *this;} - PIVector & fill(const T & f = T()) { - //if (sizeof(T) == 1) memset(piv_data, f, piv_size); - deleteT(piv_data, piv_size); - //zeroRaw(piv_data, piv_size); - for (size_t i = 0; i < piv_size; ++i) - elementNew(piv_data + i, f); - return *this; - } - PIVector & assign(const T & f = T()) {return fill(f);} - PIVector & assign(size_t new_size, const T & f) {resize(new_size); return fill(f);} - PIVector & resize(size_t new_size, const T & f = T()) { - if (new_size < piv_size) { - T * de = &(piv_data[new_size]); - deleteT(de, piv_size - new_size); - piv_size = new_size; - } - if (new_size > piv_size) { - size_t os = piv_size; - alloc(new_size); - //if (sizeof(T) == 1) memset(&(piv_data[os]), f, ds); - //zeroRaw(&(piv_data[os]), new_size - os); - for (size_t i = os; i < new_size; ++i) elementNew(piv_data + i, f); - } - return *this; - } - PIVector & reserve(size_t new_size) {if (new_size <= piv_rsize) return *this; size_t os = piv_size; alloc(new_size); piv_size = os; return *this;} - - PIVector & insert(size_t index, const T & v = T()) { - alloc(piv_size + 1); - if (index < piv_size - 1) { - size_t os = piv_size - index - 1; - memmove(&(piv_data[index + 1]), &(piv_data[index]), os * sizeof(T)); - } - //zeroRaw(&(piv_data[index]), 1); - elementNew(piv_data + index, v); - return *this; - } - PIVector & insert(size_t index, const PIVector & other) { - if (other.isEmpty()) return *this; - ssize_t os = piv_size - index; - alloc(piv_size + other.pid_size, true); - if (os > 0) - memmove(&(piv_data[index + other.piv_size]), &(piv_data[index]), os * sizeof(T)); - newT(piv_data + index, other.piv_data, other.piv_size); - return *this; - } - - PIVector & remove(size_t index, size_t count = 1) { - if (count == 0) return *this; - if (index + count >= piv_size) { - resize(index); - return *this; - } - size_t os = piv_size - index - count; - deleteT(&(piv_data[index]), count); - memmove(&(piv_data[index]), &(piv_data[index + count]), os * sizeof(T)); - piv_size -= count; - return *this; - } - - void swap(PIVector & other) { - piSwap(piv_data, other.piv_data); - piSwap(piv_size, other.piv_size); - piSwap(piv_rsize, other.piv_rsize); - } - - typedef int (*CompareFunc)(const T * , const T * ); - static int compare_func(const T * t0, const T * t1) {return (*t0) < (*t1) ? -1 : ((*t0) == (*t1) ? 0 : 1);} - PIVector & sort(CompareFunc compare = compare_func) {qsort(piv_data, piv_size, sizeof(T), (int(*)(const void * , const void * ))compare); return *this;} - - PIVector & enlarge(llong piv_size) {llong ns = size_s() + piv_size; if (ns <= 0) clear(); else resize(size_t(ns)); return *this;} - - PIVector & removeOne(const T & v) {for (size_t i = 0; i < piv_size; ++i) if (piv_data[i] == v) {remove(i); return *this;} return *this;} - PIVector & removeAll(const T & v) {for (llong i = 0; i < piv_size; ++i) if (piv_data[i] == v) {remove(i); --i;} return *this;} - - PIVector & push_back(const T & v) {alloc(piv_size + 1); elementNew(piv_data + piv_size - 1, v); return *this;} - PIVector & append(const T & v) {return push_back(v);} - PIVector & operator <<(const T & v) {return push_back(v);} - PIVector & operator <<(const PIVector & other) { - size_t ps = piv_size; - alloc(piv_size + other.piv_size); - newT(piv_data + ps, other.piv_data, other.piv_size); - return *this; - } - - PIVector & push_front(const T & v) {insert(0, v); return *this;} - PIVector & prepend(const T & v) {return push_front(v);} - - PIVector & pop_back() {if (piv_size == 0) return *this; resize(piv_size - 1); return *this;} - PIVector & pop_front() {if (piv_size == 0) return *this; remove(0); return *this;} - - T take_back() {T t(back()); pop_back(); return t;} - T take_front() {T t(front()); pop_front(); return t;} - -private: - void _reset() {piv_size = piv_rsize = 0; piv_data = 0;} - size_t asize(size_t s) { - if (s == 0) return 0; - if (piv_rsize + piv_rsize >= s && piv_rsize < s) - return piv_rsize + piv_rsize; - size_t t = 0, s_ = s - 1; - while (s_ >> t) ++t; - return (1 << t); - } - inline void newT(T * dst, const T * src, size_t s) { - for (size_t i = 0; i < s; ++i) - elementNew(dst + i, src[i]); - } - T * newRaw(size_t s) { - //cout << std::dec << " ![("< (new 0x" << (llong)ret << ") ok]!" << endl; - return (T*)ret; - } - /*void reallocRawTemp(size_t s) { - if (piv_tdata == 0) piv_tdata = (T*)(malloc(s * sizeof(T))); - else piv_tdata = (T*)(realloc(piv_tdata, s * sizeof(T))); - }*/ - inline void deleteT(T * d, size_t sz) { - //cout << " ~[("< ok]~" << endl; - } - void deleteRaw(T *& d) { - //cout << " ~[("< ok]~" << endl; - } - void zeroRaw(T * d, size_t s) { - //cout << " ~[("< ok]~" << endl; - } - inline void elementNew(T * to, const T & from) {new(to)T(from);} - inline void elementDelete(T & from) {from.~T();} - void dealloc() {deleteRaw(piv_data);} - inline void alloc(size_t new_size) { - if (new_size <= piv_rsize) { - piv_size = new_size; - return; - } - //int os = piv_size; - piv_size = new_size; - size_t as = asize(new_size); - if (as == piv_rsize) return; - - //cout << std::hex << " ![("< (new 0x" << (llong)piv_data << ") ok]!" << endl; - /*piv_rsize = as; - T * pd = newRaw(piv_rsize); - if (os > 0 && piv_data != 0) { - memcpy(pd, piv_data, os * sizeof(T)); - deleteRaw(piv_data); - } - piv_data = pd;*/ - } - - T * piv_data; - size_t piv_size, piv_rsize; -}; -/* -#define __PIVECTOR_SIMPLE_FUNCTIONS__(T) \ - template<> inline PIVector::~PIVector() {dealloc(); _reset();} \ - template<> inline PIVector & PIVector::push_back(const T & v) {alloc(piv_size + 1); piv_data[piv_size - 1] = v; return *this;} \ - template<> inline PIVector & PIVector::fill(const T & f) { \ - for (size_t i = 0; i < piv_size; ++i) \ - piv_data[i] = f; \ - return *this; \ - } \ - template<> inline PIVector & PIVector::resize(size_t new_size, const T & f) { \ - if (new_size < piv_size) \ - piv_size = new_size; \ - if (new_size > piv_size) { \ - size_t os = piv_size; \ - alloc(new_size); \ - for (size_t i = os; i < new_size; ++i) piv_data[i] = f; \ - } \ - return *this; \ - } \ - template<> inline PIVector & PIVector::insert(size_t index, const T & v) { \ - alloc(piv_size + 1); \ - if (index < piv_size - 1) { \ - size_t os = piv_size - index - 1; \ - memmove(&(piv_data[index + 1]), &(piv_data[index]), os * sizeof(T)); \ - } \ - piv_data[index] = v; \ - return *this; \ - } \ - template<> inline PIVector & PIVector::remove(size_t index, size_t count) { \ - if (count == 0) return *this; \ - if (index + count >= piv_size) { \ - resize(index); \ - return *this; \ - } \ - size_t os = piv_size - index - count; \ - memmove(&(piv_data[index]), &(piv_data[index + count]), os * sizeof(T)); \ - piv_size -= count; \ - return *this; \ - } - -__PIVECTOR_SIMPLE_FUNCTIONS__(char) -__PIVECTOR_SIMPLE_FUNCTIONS__(uchar) -__PIVECTOR_SIMPLE_FUNCTIONS__(short) -__PIVECTOR_SIMPLE_FUNCTIONS__(ushort) -__PIVECTOR_SIMPLE_FUNCTIONS__(int) -__PIVECTOR_SIMPLE_FUNCTIONS__(uint) -__PIVECTOR_SIMPLE_FUNCTIONS__(long) -__PIVECTOR_SIMPLE_FUNCTIONS__(ulong) -__PIVECTOR_SIMPLE_FUNCTIONS__(llong) -__PIVECTOR_SIMPLE_FUNCTIONS__(ullong) -__PIVECTOR_SIMPLE_FUNCTIONS__(float) -__PIVECTOR_SIMPLE_FUNCTIONS__(double) -__PIVECTOR_SIMPLE_FUNCTIONS__(ldouble)*/ -#define __PIVECTOR_SIMPLE_TYPE__(T) \ - template<> inline void PIVector::newT(T * dst, const T * src, size_t s) {memcpy(dst, src, s * sizeof(T));} \ - template<> inline void PIVector::deleteT(T * d, size_t sz) {;} \ - template<> inline void PIVector::elementNew(T * to, const T & from) {(*to) = from;} \ - template<> inline void PIVector::elementDelete(T & from) {;} - -#else - - -template > -class PIP_EXPORT PIVector: public vector { - typedef PIVector _CVector; - typedef vector _stlc; -public: - - PIVector() {piMonitor.containers++;} - PIVector(uint size, const T & value = T()) {piMonitor.containers++; _stlc::resize(size, value);} - ~PIVector() {piMonitor.containers--;} - - const T & at(uint index) const {return (*this)[index];} - T & at(uint index) {return (*this)[index];} - const T * data(uint index = 0) const {return &(*this)[index];} - T * data(uint index = 0) {return &(*this)[index];} - -#ifdef DOXYGEN - uint size() const; -#endif - - int size_s() const {return static_cast(_stlc::size());} - bool isEmpty() const {return _stlc::empty();} - bool has(const T & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;} - int etries(const T & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;} - - typedef int (*CompareFunc)(const T * , const T * ); - - static int compare_func(const T * t0, const T * t1) {return (*t0) == (*t1) ? 0 : ((*t0) < (*t1) ? -1 : 1);} -#ifdef DOXYGEN - - void resize(uint size, const T & new_type = T()); - PIVector & enlarge(uint size); - void clear(); - PIVector & sort(CompareFunc compare = compare_func) {qsort(&at(0), _stlc::size(), sizeof(T), (int(*)(const void * , const void * ))compare); return *this;} - PIVector & fill(const T & t) {_stlc::assign(_stlc::size(), t); return *this;} - T & back(); - const T & back() const; - T & front(); - const T & front() const; - PIVector & push_back(const T & t); - PIVector & push_front(const T & t) {_stlc::insert(_stlc::begin(), t); return *this;} - PIVector & pop_back(); - PIVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;} - T take_back() {T t(_stlc::back()); _stlc::pop_back(); return t;} - T take_front() {T t(_stlc::front()); pop_front(); return t;} - PIVector & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;} - PIVector & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;} - PIVector & removeOne(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;} - PIVector & removeAll(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;} - PIVector & insert(uint pos, const T & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;} - PIVector & insert(uint pos, const PIVector & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;} - T & operator [](uint index); - const T & operator [](uint index) const; - PIVector & operator <<(const T & t) {_stlc::push_back(t); return *this;} - PIVector & operator <<(const PIVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;} - bool operator ==(const PIVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;} - bool operator !=(const PIVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;} - bool contains(const T & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;} - -#else - _CVector & enlarge(int size_) {int ns = size_s() + size_; if (ns <= 0) _stlc::clear(); else _stlc::resize(ns); return *this;} - _CVector & sort(CompareFunc compare = compare_func) {qsort(&at(0), _stlc::size(), sizeof(T), (int(*)(const void * , const void * ))compare); return *this;} - _CVector & fill(const T & t) {_stlc::assign(_stlc::size(), t); return *this;} - _CVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;} - _CVector & push_front(const T & t) {_stlc::insert(_stlc::begin(), t); return *this;} - T take_front() {T t(_stlc::front()); pop_front(); return t;} - T take_back() {T t(_stlc::back()); _stlc::pop_back(); return t;} - _CVector & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;} - _CVector & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;} - _CVector & removeOne(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;} - _CVector & removeAll(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;} - _CVector & insert(uint pos, const T & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;} - _CVector & insert(uint pos, const _CVector & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;} - _CVector & operator <<(const T & t) {_stlc::push_back(t); return *this;} - _CVector & operator <<(const _CVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;} - bool operator ==(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;} - bool operator !=(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;} - bool contains(const T & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;} -#endif -}; - -#define __PIVECTOR_SIMPLE_TYPE__(T) - - -#endif - - -template -inline std::ostream & operator <<(std::ostream & s, const PIVector & v) {s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;} - -template -inline PICout operator <<(PICout s, const PIVector & v) {s.space(); s.setControl(0, true); s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;} - - -#endif // PIVECTOR_H diff --git a/test.txt b/test.txt new file mode 100644 index 00000000..5e9606d8 --- /dev/null +++ b/test.txt @@ -0,0 +1 @@ +1234566789