3.10.2013 - PIPeer release, PIConsole now can work as server and remote client. Remote console test program in directory "remote_console"
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
doc
|
||||
|
||||
@@ -5,6 +5,7 @@ activity=pip
|
||||
activityId=
|
||||
desktop=-1
|
||||
formfactor=0
|
||||
geometry=0,0,1644,997
|
||||
immutability=1
|
||||
lastDesktop=-1
|
||||
lastScreen=0
|
||||
@@ -14,6 +15,7 @@ plugin=newspaper
|
||||
screen=0
|
||||
wallpaperplugin=color
|
||||
wallpaperpluginmode=
|
||||
zvalue=0
|
||||
|
||||
[Containments][1][Wallpaper][color]
|
||||
backgroundMode=0
|
||||
|
||||
@@ -1,29 +1,86 @@
|
||||
project(pip)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} .)
|
||||
set(VERSION "0.0304")
|
||||
include(CheckFunctionExists)
|
||||
set(VERSION "0.0305")
|
||||
set(SOVERSION ${VERSION})
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
set(LIBS)
|
||||
file(GLOB CPPS "pi*.cpp")
|
||||
|
||||
|
||||
# Check Bessel functions
|
||||
set(CMAKE_REQUIRED_INCLUDES math.h)
|
||||
set(CMAKE_REQUIRED_LIBRARIES m)
|
||||
CHECK_FUNCTION_EXISTS(j0 PIP_MATH_J0)
|
||||
CHECK_FUNCTION_EXISTS(j1 PIP_MATH_J1)
|
||||
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")
|
||||
endif ()
|
||||
if (DEFINED PIP_MATH_J1)
|
||||
add_definitions("-DPIP_MATH_J1")
|
||||
endif ()
|
||||
if (DEFINED PIP_MATH_JN)
|
||||
add_definitions("-DPIP_MATH_JN")
|
||||
endif ()
|
||||
if (DEFINED PIP_MATH_Y0)
|
||||
add_definitions("-DPIP_MATH_Y0")
|
||||
endif ()
|
||||
if (DEFINED PIP_MATH_Y1)
|
||||
add_definitions("-DPIP_MATH_Y1")
|
||||
endif ()
|
||||
if (DEFINED PIP_MATH_YN)
|
||||
add_definitions("-DPIP_MATH_YN")
|
||||
endif ()
|
||||
|
||||
|
||||
# Check if USB is on (to enable use "-DUSB=" argument of cmake)
|
||||
if (DEFINED USB)
|
||||
message(STATUS "Building with USB support")
|
||||
unset(USB)
|
||||
add_definitions("-DPIP_USB")
|
||||
list(APPEND LIBS usb)
|
||||
else ()
|
||||
message(STATUS "Building without USB support")
|
||||
endif ()
|
||||
|
||||
|
||||
if (${WIN32})
|
||||
list(APPEND LIBS ws2_32 Iphlpapi)
|
||||
include(GenerateExportHeader)
|
||||
execute_process(COMMAND "make_rc_win.bat")
|
||||
add_definitions("-O2")
|
||||
#add_definitions(-DEF)
|
||||
execute_process(COMMAND "make_rc_win.bat" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
list(APPEND CPPS "pip_resource_win.o")
|
||||
add_library(pip SHARED ${CPPS})
|
||||
generate_export_header(pip)
|
||||
target_link_libraries(pip ws2_32 Iphlpapi)
|
||||
else (${WIN32})
|
||||
if(DEFINED ENV{QNX_HOST})
|
||||
if (${CMAKE_C_COMPILER} STREQUAL "cl")
|
||||
add_definitions("/O2 /Ob2 /Ot")
|
||||
else ()
|
||||
add_definitions("-O2")
|
||||
endif ()
|
||||
else ()
|
||||
add_definitions("-O2")
|
||||
if (DEFINED ENV{QNX_HOST})
|
||||
list(APPEND LIBS socket)
|
||||
add_library(pip STATIC ${CPPS})
|
||||
else()
|
||||
add_definitions("-Wall -O2 -g3")
|
||||
else ()
|
||||
list(APPEND LIBS pthread rt)
|
||||
include(GenerateExportHeader)
|
||||
add_definitions("-Wall -g3")
|
||||
add_library(pip SHARED ${CPPS})
|
||||
endif()
|
||||
target_link_libraries(pip pthread rt)
|
||||
endif (${WIN32})
|
||||
generate_export_header(pip)
|
||||
endif ()
|
||||
endif ()
|
||||
target_link_libraries(pip ${LIBS})
|
||||
|
||||
|
||||
# Test program
|
||||
add_executable(pip_test "main.cpp")
|
||||
target_link_libraries(pip_test pip)
|
||||
|
||||
|
||||
add_subdirectory(system_test)
|
||||
add_subdirectory(remote_console)
|
||||
|
||||
1905
Doxyfile
Normal file
1905
Doxyfile
Normal file
@@ -0,0 +1,1905 @@
|
||||
# Doxyfile 1.8.3.1
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project
|
||||
#
|
||||
# All text after a hash (#) is considered a comment and will be ignored
|
||||
# The format is:
|
||||
# TAG = value [value, ...]
|
||||
# For lists items can also be appended using:
|
||||
# TAG += value [value, ...]
|
||||
# Values that contain spaces should be placed between quotes (" ")
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# This tag specifies the encoding used for all characters in the config file
|
||||
# that follow. The default is UTF-8 which is also the encoding used for all
|
||||
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
|
||||
# iconv built into libc) for the transcoding. See
|
||||
# http://www.gnu.org/software/libiconv for the list of possible encodings.
|
||||
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
|
||||
# The PROJECT_NAME tag is a single word (or sequence of words) that should
|
||||
# identify the project. Note that if you do not use Doxywizard you need
|
||||
# to put quotes around the project name if it contains spaces.
|
||||
|
||||
PROJECT_NAME = PIP
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.3.6
|
||||
|
||||
# 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 quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF = "Platform-Independent Primitives"
|
||||
|
||||
# With the PROJECT_LOGO tag one can specify an logo or icon that is
|
||||
# included in the documentation. The maximum height of the logo should not
|
||||
# exceed 55 pixels and the maximum width should not exceed 200 pixels.
|
||||
# Doxygen will copy the logo to the output directory.
|
||||
|
||||
PROJECT_LOGO =
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
# If a relative path is entered, it will be relative to the location
|
||||
# where doxygen was started. If left blank the current directory will be used.
|
||||
|
||||
OUTPUT_DIRECTORY = doc
|
||||
|
||||
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
|
||||
# 4096 sub-directories (in 2 levels) under the output directory of each output
|
||||
# format and will distribute the generated files over these directories.
|
||||
# Enabling this option can be useful when feeding doxygen a huge amount of
|
||||
# source files, where putting all generated files in the same directory would
|
||||
# otherwise cause performance problems for the file system.
|
||||
|
||||
CREATE_SUBDIRS = 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.
|
||||
# The default language is English, other supported languages are:
|
||||
# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
|
||||
# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
|
||||
# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
|
||||
# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
|
||||
# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
|
||||
# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
|
||||
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
|
||||
# include brief member descriptions after the members that are listed in
|
||||
# the file and class documentation (similar to JavaDoc).
|
||||
# Set to NO to disable this.
|
||||
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
|
||||
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
|
||||
# the brief description of a member or function before the detailed description.
|
||||
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
|
||||
# brief descriptions will be completely suppressed.
|
||||
|
||||
REPEAT_BRIEF = YES
|
||||
|
||||
# This tag implements a quasi-intelligent brief description abbreviator
|
||||
# that is used to form the text in various listings. Each string
|
||||
# in this list, if found as the leading text of the brief description, will be
|
||||
# stripped from the text and the result after processing the whole list, is
|
||||
# used as the annotated text. Otherwise, the brief description is used as-is.
|
||||
# If left blank, the following values are used ("$name" is automatically
|
||||
# replaced with the name of the entity): "The $name class" "The $name widget"
|
||||
# "The $name file" "is" "provides" "specifies" "contains"
|
||||
# "represents" "a" "an" "the"
|
||||
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
"The $name widget" \
|
||||
"The $name file" \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
|
||||
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
|
||||
# Doxygen will generate a detailed section even if there is only a brief
|
||||
# description.
|
||||
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
|
||||
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
|
||||
# inherited members of a class in the documentation of that class as if those
|
||||
# members were ordinary class members. Constructors, destructors and assignment
|
||||
# operators of the base classes will not be shown.
|
||||
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
|
||||
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
|
||||
# path before files name in the file list and in the header files. If set
|
||||
# to NO the shortest path that makes the file name unique will be used.
|
||||
|
||||
FULL_PATH_NAMES = YES
|
||||
|
||||
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
|
||||
# can be used to strip a user-defined part of the path. Stripping is
|
||||
# only done if one of the specified strings matches the left-hand part of
|
||||
# the path. The tag can be used to show relative paths in the file list.
|
||||
# If left blank the directory from which doxygen is run is used as the
|
||||
# path to strip. Note that you specify absolute paths here, but also
|
||||
# relative paths, which will be relative from the directory where doxygen is
|
||||
# started.
|
||||
|
||||
STRIP_FROM_PATH =
|
||||
|
||||
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
|
||||
# the path mentioned in the documentation of a class, which tells
|
||||
# the reader which header file to include in order to use a class.
|
||||
# If left blank only the name of the header file containing the class
|
||||
# definition is used. Otherwise one should specify the include paths that
|
||||
# are normally passed to the compiler using the -I flag.
|
||||
|
||||
STRIP_FROM_INC_PATH =
|
||||
|
||||
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
|
||||
# (but less readable) file names. This can be useful if your file system
|
||||
# doesn't support long names like on DOS, Mac, or CD-ROM.
|
||||
|
||||
SHORT_NAMES = NO
|
||||
|
||||
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
|
||||
# will interpret the first line (until the first dot) of a JavaDoc-style
|
||||
# comment as the brief description. If set to NO, the JavaDoc
|
||||
# comments will behave just like regular Qt-style comments
|
||||
# (thus requiring an explicit @brief command for a brief description.)
|
||||
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
|
||||
# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
|
||||
# interpret the first line (until the first dot) of a Qt-style
|
||||
# comment as the brief description. If set to NO, the comments
|
||||
# will behave just like regular Qt-style comments (thus requiring
|
||||
# an explicit \brief command for a brief description.)
|
||||
|
||||
QT_AUTOBRIEF = NO
|
||||
|
||||
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
|
||||
# treat a multi-line C++ special comment block (i.e. a block of //! or ///
|
||||
# comments) as a brief description. This used to be the default behaviour.
|
||||
# The new default is to treat a multi-line C++ comment block as a detailed
|
||||
# description. Set this tag to YES if you prefer the old behaviour instead.
|
||||
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
|
||||
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
|
||||
# member inherits the documentation from any documented member that it
|
||||
# re-implements.
|
||||
|
||||
INHERIT_DOCS = YES
|
||||
|
||||
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
|
||||
# a new page for each member. If set to NO, the documentation of a member will
|
||||
# be part of the file/class/namespace that contains it.
|
||||
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
|
||||
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
|
||||
# Doxygen uses this value to replace tabs by spaces in code fragments.
|
||||
|
||||
TAB_SIZE = 4
|
||||
|
||||
# This tag can be used to specify a number of aliases that acts
|
||||
# as commands in the documentation. An alias has the form "name=value".
|
||||
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
|
||||
# put the command \sideeffect (or @sideeffect) in the documentation, which
|
||||
# will result in a user-defined paragraph with heading "Side Effects:".
|
||||
# You can put \n's in the value part of an alias to insert newlines.
|
||||
|
||||
ALIASES = "handlers=\name Handlers" \
|
||||
"vhandlers=\name Virtual handlers" \
|
||||
"events=\name Events"
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding
|
||||
# "class=itcl::class" will allow you to use the command class in the
|
||||
# itcl::class meaning.
|
||||
|
||||
TCL_SUBST =
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
|
||||
# sources only. Doxygen will then generate output that is more tailored for C.
|
||||
# For instance, some of the names that are used will be different. The list
|
||||
# of all members will be omitted, etc.
|
||||
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
|
||||
# sources only. Doxygen will then generate output that is more tailored for
|
||||
# Java. For instance, namespaces will be presented as packages, qualified
|
||||
# scopes will look different, etc.
|
||||
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
|
||||
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
|
||||
# sources only. Doxygen will then generate output that is more tailored for
|
||||
# Fortran.
|
||||
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
|
||||
# sources. Doxygen will then generate output that is tailored for
|
||||
# VHDL.
|
||||
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
|
||||
# Doxygen selects the parser to use depending on the extension of the files it
|
||||
# parses. With this tag you can assign which parser to use for a given
|
||||
# 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, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
|
||||
# C++. 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
|
||||
# that for custom extensions you also need to set FILE_PATTERNS otherwise the
|
||||
# files are not read by doxygen.
|
||||
|
||||
EXTENSION_MAPPING =
|
||||
|
||||
# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
|
||||
# comments according to the Markdown format, which allows for more readable
|
||||
# documentation. See http://daringfireball.net/projects/markdown/ for details.
|
||||
# The output of markdown processing is further processed by doxygen, so you
|
||||
# can mix doxygen, HTML, and XML commands with Markdown formatting.
|
||||
# Disable only in case of backward compatibilities issues.
|
||||
|
||||
MARKDOWN_SUPPORT = YES
|
||||
|
||||
# When enabled doxygen tries to link words that correspond to documented classes,
|
||||
# or namespaces to their corresponding documentation. Such a link can be
|
||||
# prevented in individual cases by by putting a % sign in front of the word or
|
||||
# globally by setting AUTOLINK_SUPPORT to NO.
|
||||
|
||||
AUTOLINK_SUPPORT = YES
|
||||
|
||||
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
|
||||
# to include (a tag file for) the STL sources as input, then you should
|
||||
# set this tag to YES in order to let doxygen match functions declarations and
|
||||
# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
|
||||
# func(std::string) {}). This also makes the inheritance and collaboration
|
||||
# diagrams that involve STL classes more complete and accurate.
|
||||
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
|
||||
# If you use Microsoft's C++/CLI language, you should set this option to YES to
|
||||
# enable parsing support.
|
||||
|
||||
CPP_CLI_SUPPORT = NO
|
||||
|
||||
# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
|
||||
# Doxygen will parse them like normal C++ but will assume all classes use public
|
||||
# instead of private inheritance when no explicit protection keyword is present.
|
||||
|
||||
SIP_SUPPORT = NO
|
||||
|
||||
# For Microsoft's IDL there are propget and propput attributes to indicate
|
||||
# getter and setter methods for a property. Setting this option to YES (the
|
||||
# default) will make doxygen replace the get and set methods by a property in
|
||||
# the documentation. This will only work if the methods are indeed getting or
|
||||
# setting a simple type. If this is not the case, or you want to show the
|
||||
# methods anyway, you should set this option to NO.
|
||||
|
||||
IDL_PROPERTY_SUPPORT = NO
|
||||
|
||||
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
|
||||
# tag is set to YES, then doxygen will reuse the documentation of the first
|
||||
# member in the group (if any) for the other members of the group. By default
|
||||
# all members of a group must be documented explicitly.
|
||||
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
|
||||
# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
|
||||
# the same type (for instance a group of public functions) to be put as a
|
||||
# subgroup of that type (e.g. under the Public Functions section). Set it to
|
||||
# NO to prevent subgrouping. Alternatively, this can be done per class using
|
||||
# the \nosubgrouping command.
|
||||
|
||||
SUBGROUPING = NO
|
||||
|
||||
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
|
||||
# unions are shown inside the group in which they are included (e.g. using
|
||||
# @ingroup) instead of on a separate page (for HTML and Man pages) or
|
||||
# section (for LaTeX and RTF).
|
||||
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
|
||||
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
|
||||
# unions with only public data fields will be shown inline in the documentation
|
||||
# of the scope in which they are defined (i.e. file, namespace, or group
|
||||
# documentation), provided this scope is documented. If set to NO (the default),
|
||||
# structs, classes, and unions are shown on a separate page (for HTML and Man
|
||||
# pages) or section (for LaTeX and RTF).
|
||||
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
|
||||
# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
|
||||
# is documented as struct, union, or enum with the name of the typedef. So
|
||||
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
|
||||
# with name TypeT. When disabled the typedef will appear as a member of a file,
|
||||
# namespace, or class. And the struct will be named TypeS. This can typically
|
||||
# be useful for C code in case the coding convention dictates that all compound
|
||||
# types are typedef'ed and only the typedef is referenced, never the tag name.
|
||||
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
|
||||
# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
|
||||
# determine which symbols to keep in memory and which to flush to disk.
|
||||
# When the cache is full, less often used symbols will be written to disk.
|
||||
# For small to medium size projects (<1000 input files) the default value is
|
||||
# probably good enough. For larger projects a too small cache size can cause
|
||||
# doxygen to be busy swapping symbols to and from disk most of the time
|
||||
# causing a significant performance penalty.
|
||||
# If the system has enough physical memory increasing the cache will improve the
|
||||
# performance by keeping more symbols in memory. Note that the value works on
|
||||
# a logarithmic scale so increasing the size by one will roughly double the
|
||||
# memory usage. The cache size is given by this formula:
|
||||
# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
|
||||
# corresponding to a cache size of 2^16 = 65536 symbols.
|
||||
|
||||
SYMBOL_CACHE_SIZE = 0
|
||||
|
||||
# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
|
||||
# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
|
||||
# their name and scope. Since this can be an expensive process and often the
|
||||
# same symbol appear multiple times in the code, doxygen keeps a cache of
|
||||
# pre-resolved symbols. If the cache is too small doxygen will become slower.
|
||||
# If the cache is too large, memory is wasted. The cache size is given by this
|
||||
# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
|
||||
# corresponding to a cache size of 2^16 = 65536 symbols.
|
||||
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
|
||||
# documentation are documented, even if no documentation was available.
|
||||
# Private class members and static file members will be hidden unless
|
||||
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
|
||||
|
||||
EXTRACT_ALL = NO
|
||||
|
||||
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
|
||||
# will be included in the documentation.
|
||||
|
||||
EXTRACT_PRIVATE = NO
|
||||
|
||||
# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
|
||||
# scope will be included in the documentation.
|
||||
|
||||
EXTRACT_PACKAGE = NO
|
||||
|
||||
# If the EXTRACT_STATIC tag is set to YES all static members of a file
|
||||
# will be included in the documentation.
|
||||
|
||||
EXTRACT_STATIC = NO
|
||||
|
||||
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
|
||||
# defined locally in source files will be included in the documentation.
|
||||
# If set to NO only classes defined in header files are included.
|
||||
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
|
||||
# This flag is only useful for Objective-C code. When set to YES local
|
||||
# methods, which are defined in the implementation section but not in
|
||||
# the interface are included in the documentation.
|
||||
# If set to NO (the default) only methods in the interface are included.
|
||||
|
||||
EXTRACT_LOCAL_METHODS = YES
|
||||
|
||||
# If this flag is set to YES, the members of anonymous namespaces will be
|
||||
# extracted and appear in the documentation as a namespace called
|
||||
# 'anonymous_namespace{file}', where file will be replaced with the base
|
||||
# name of the file that contains the anonymous namespace. By default
|
||||
# anonymous namespaces are hidden.
|
||||
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
|
||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
|
||||
# undocumented members of documented classes, files or namespaces.
|
||||
# If set to NO (the default) these members will be included in the
|
||||
# various overviews, but no documentation section is generated.
|
||||
# This option has no effect if EXTRACT_ALL is enabled.
|
||||
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
|
||||
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
|
||||
# undocumented classes that are normally visible in the class hierarchy.
|
||||
# If set to NO (the default) these classes will be included in the various
|
||||
# overviews. This option has no effect if EXTRACT_ALL is enabled.
|
||||
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
|
||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
|
||||
# friend (class|struct|union) declarations.
|
||||
# If set to NO (the default) these declarations will be included in the
|
||||
# documentation.
|
||||
|
||||
HIDE_FRIEND_COMPOUNDS = YES
|
||||
|
||||
# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
|
||||
# documentation blocks found inside the body of a function.
|
||||
# If set to NO (the default) these blocks will be appended to the
|
||||
# function's detailed documentation block.
|
||||
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
|
||||
# The INTERNAL_DOCS tag determines if documentation
|
||||
# that is typed after a \internal command is included. If the tag is set
|
||||
# to NO (the default) then the documentation will be excluded.
|
||||
# Set it to YES to include the internal documentation.
|
||||
|
||||
INTERNAL_DOCS = NO
|
||||
|
||||
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
|
||||
# file names in lower-case letters. If set to YES upper-case letters are also
|
||||
# allowed. This is useful if you have classes or files whose names only differ
|
||||
# in case and if your file system supports case sensitive file names. Windows
|
||||
# and Mac users are advised to set this option to NO.
|
||||
|
||||
CASE_SENSE_NAMES = NO
|
||||
|
||||
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
|
||||
# will show members with their full class and namespace scopes in the
|
||||
# documentation. If set to YES the scope will be hidden.
|
||||
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
|
||||
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
|
||||
# will put a list of the files that are included by a file in the documentation
|
||||
# of that file.
|
||||
|
||||
SHOW_INCLUDE_FILES = NO
|
||||
|
||||
# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
|
||||
# will list include files with double quotes in the documentation
|
||||
# rather than with sharp brackets.
|
||||
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
|
||||
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
|
||||
# is inserted in the documentation for inline members.
|
||||
|
||||
INLINE_INFO = YES
|
||||
|
||||
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
|
||||
# will sort the (detailed) documentation of file and class members
|
||||
# alphabetically by member name. If set to NO the members will appear in
|
||||
# declaration order.
|
||||
|
||||
SORT_MEMBER_DOCS = NO
|
||||
|
||||
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
|
||||
# brief documentation of file, namespace and class members alphabetically
|
||||
# by member name. If set to NO (the default) the members will appear in
|
||||
# declaration order.
|
||||
|
||||
SORT_BRIEF_DOCS = NO
|
||||
|
||||
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
|
||||
# will sort the (brief and detailed) documentation of class members so that
|
||||
# constructors and destructors are listed first. If set to NO (the default)
|
||||
# the constructors will appear in the respective orders defined by
|
||||
# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
|
||||
# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
|
||||
# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
|
||||
|
||||
SORT_MEMBERS_CTORS_1ST = NO
|
||||
|
||||
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
|
||||
# hierarchy of group names into alphabetical order. If set to NO (the default)
|
||||
# the group names will appear in their defined order.
|
||||
|
||||
SORT_GROUP_NAMES = NO
|
||||
|
||||
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
|
||||
# sorted by fully-qualified names, including namespaces. If set to
|
||||
# NO (the default), the class list will be sorted only by class name,
|
||||
# not including the namespace part.
|
||||
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
|
||||
# Note: This option applies only to the class list, not to the
|
||||
# alphabetical list.
|
||||
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
|
||||
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
|
||||
# do proper type resolution of all parameters of a function it will reject a
|
||||
# match between the prototype and the implementation of a member function even
|
||||
# if there is only one candidate or it is obvious which candidate to choose
|
||||
# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
|
||||
# will still accept a match between prototype and implementation in such cases.
|
||||
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
|
||||
# The GENERATE_TODOLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the todo list. This list is created by putting \todo
|
||||
# commands in the documentation.
|
||||
|
||||
GENERATE_TODOLIST = YES
|
||||
|
||||
# The GENERATE_TESTLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the test list. This list is created by putting \test
|
||||
# commands in the documentation.
|
||||
|
||||
GENERATE_TESTLIST = YES
|
||||
|
||||
# The GENERATE_BUGLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the bug list. This list is created by putting \bug
|
||||
# commands in the documentation.
|
||||
|
||||
GENERATE_BUGLIST = YES
|
||||
|
||||
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the deprecated list. This list is created by putting
|
||||
# \deprecated commands in the documentation.
|
||||
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
|
||||
# The ENABLED_SECTIONS tag can be used to enable conditional
|
||||
# documentation sections, marked by \if section-label ... \endif
|
||||
# and \cond section-label ... \endcond blocks.
|
||||
|
||||
ENABLED_SECTIONS =
|
||||
|
||||
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
|
||||
# the initial value of a variable or macro consists of for it to appear in
|
||||
# the documentation. If the initializer consists of more lines than specified
|
||||
# here it will be hidden. Use a value of 0 to hide initializers completely.
|
||||
# The appearance of the initializer of individual variables and macros in the
|
||||
# documentation can be controlled using \showinitializer or \hideinitializer
|
||||
# command in the documentation regardless of this setting.
|
||||
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
|
||||
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
|
||||
# at the bottom of the documentation of classes and structs. If set to YES the
|
||||
# list will mention the files that were used to generate the documentation.
|
||||
|
||||
SHOW_USED_FILES = NO
|
||||
|
||||
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
|
||||
# This will remove the Files entry from the Quick Index and from the
|
||||
# Folder Tree View (if specified). The default is YES.
|
||||
|
||||
SHOW_FILES = YES
|
||||
|
||||
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
|
||||
# Namespaces page. This will remove the Namespaces entry from the Quick Index
|
||||
# and from the Folder Tree View (if specified). The default is YES.
|
||||
|
||||
SHOW_NAMESPACES = YES
|
||||
|
||||
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
|
||||
# doxygen should invoke to get the current version for each file (typically from
|
||||
# the version control system). Doxygen will invoke the program by executing (via
|
||||
# popen()) the command <command> <input-file>, where <command> is the value of
|
||||
# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
|
||||
# provided by doxygen. Whatever the program writes to standard output
|
||||
# is used as the file version. See the manual for examples.
|
||||
|
||||
FILE_VERSION_FILTER =
|
||||
|
||||
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
|
||||
# by doxygen. The layout file controls the global structure of the generated
|
||||
# output files in an output format independent way. To create the layout file
|
||||
# that represents doxygen's defaults, run doxygen with the -l option.
|
||||
# You can optionally specify a file name after the option, if omitted
|
||||
# DoxygenLayout.xml will be used as the name of the layout file.
|
||||
|
||||
LAYOUT_FILE =
|
||||
|
||||
# The CITE_BIB_FILES tag can be used to specify one or more bib files
|
||||
# containing the references data. This must be a list of .bib files. The
|
||||
# .bib extension is automatically appended if omitted. Using this command
|
||||
# requires the bibtex tool 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.
|
||||
|
||||
CITE_BIB_FILES =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The QUIET tag can be used to turn on/off the messages that are generated
|
||||
# by doxygen. Possible values are YES and NO. If left blank NO is used.
|
||||
|
||||
QUIET = NO
|
||||
|
||||
# The WARNINGS tag can be used to turn on/off the warning messages that are
|
||||
# generated by doxygen. Possible values are YES and NO. If left blank
|
||||
# NO is used.
|
||||
|
||||
WARNINGS = YES
|
||||
|
||||
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
|
||||
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
|
||||
# automatically be disabled.
|
||||
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
|
||||
# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
|
||||
# potential errors in the documentation, such as not documenting some
|
||||
# parameters in a documented function, or documenting parameters that
|
||||
# don't exist or using markup commands wrongly.
|
||||
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
|
||||
# The WARN_NO_PARAMDOC option can be enabled to get warnings for
|
||||
# functions that are documented, but have no documentation for their parameters
|
||||
# or return value. If set to NO (the default) doxygen will only warn about
|
||||
# wrong or incomplete parameter documentation, but not about the absence of
|
||||
# documentation.
|
||||
|
||||
WARN_NO_PARAMDOC = NO
|
||||
|
||||
# The WARN_FORMAT tag determines the format of the warning messages that
|
||||
# doxygen can produce. The string should contain the $file, $line, and $text
|
||||
# tags, which will be replaced by the file and line number from which the
|
||||
# warning originated and the warning text. Optionally the format may contain
|
||||
# $version, which will be replaced by the version of the file (if it could
|
||||
# be obtained via FILE_VERSION_FILTER)
|
||||
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
|
||||
# The WARN_LOGFILE tag can be used to specify a file to which warning
|
||||
# and error messages should be written. If left blank the output is written
|
||||
# to stderr.
|
||||
|
||||
WARN_LOGFILE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The INPUT tag can be used to specify the files and/or directories that contain
|
||||
# documented source files. You may enter file names like "myfile.cpp" or
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = .
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||
# also the default input encoding. Doxygen uses libiconv (or the iconv built
|
||||
# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
|
||||
# the list of possible encodings.
|
||||
|
||||
INPUT_ENCODING = UTF-8
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
# and *.h) to filter out the source-files in the directories. If left
|
||||
# blank the following patterns are tested:
|
||||
# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
|
||||
# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
|
||||
# *.f90 *.f *.for *.vhd *.vhdl
|
||||
|
||||
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 turn specify whether or not subdirectories
|
||||
# should be searched for input files as well. Possible values are YES and NO.
|
||||
# If left blank NO is used.
|
||||
|
||||
RECURSIVE = NO
|
||||
|
||||
# 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
|
||||
# subdirectory from a directory tree whose root is specified with the INPUT tag.
|
||||
# Note that relative paths are relative to the directory from which doxygen is
|
||||
# run.
|
||||
|
||||
EXCLUDE =
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
# from the input.
|
||||
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
|
||||
# certain files from those directories. Note that the wildcards are matched
|
||||
# against the file with absolute path, so to exclude all test directories
|
||||
# for example use the pattern */test/*
|
||||
|
||||
EXCLUDE_PATTERNS =
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
# output. The symbol name can be a fully qualified name, a word, or if the
|
||||
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
||||
# AClass::ANamespace, ANamespace::*Test
|
||||
|
||||
EXCLUDE_SYMBOLS =
|
||||
|
||||
# The EXAMPLE_PATH tag can be used to specify one or more files or
|
||||
# directories that contain example code fragments that are included (see
|
||||
# the \include command).
|
||||
|
||||
EXAMPLE_PATH = doc/examples
|
||||
|
||||
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
||||
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
# and *.h) to filter out the source-files in the directories. If left
|
||||
# blank all files are included.
|
||||
|
||||
EXAMPLE_PATTERNS = *
|
||||
|
||||
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
|
||||
# searched for input files to be used with the \include or \dontinclude
|
||||
# commands irrespective of the value of the RECURSIVE tag.
|
||||
# Possible values are YES and NO. If left blank NO is used.
|
||||
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
|
||||
# The IMAGE_PATH tag can be used to specify one or more files or
|
||||
# directories that contain image that are included in the documentation (see
|
||||
# the \image command).
|
||||
|
||||
IMAGE_PATH =
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
# by executing (via popen()) the command <filter> <input-file>, where <filter>
|
||||
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
|
||||
# input file. Doxygen will then use the output that the filter program writes
|
||||
# to standard output. If FILTER_PATTERNS is specified, this tag will be
|
||||
# ignored.
|
||||
|
||||
INPUT_FILTER =
|
||||
|
||||
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
|
||||
# basis. Doxygen will compare the file name with each pattern and apply the
|
||||
# filter if there is a match. The filters are a list of the form:
|
||||
# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
|
||||
# info on how filters are used. If FILTER_PATTERNS is empty or if
|
||||
# non of the patterns match the file name, INPUT_FILTER is applied.
|
||||
|
||||
FILTER_PATTERNS =
|
||||
|
||||
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
|
||||
# INPUT_FILTER) will be used to filter the input files when producing source
|
||||
# files to browse (i.e. when SOURCE_BROWSER is set to YES).
|
||||
|
||||
FILTER_SOURCE_FILES = NO
|
||||
|
||||
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
|
||||
# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
|
||||
# and it is also possible to disable source filtering for a specific pattern
|
||||
# using *.ext= (so without naming a filter). This option only has effect when
|
||||
# FILTER_SOURCE_FILES is enabled.
|
||||
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
|
||||
# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that
|
||||
# is part of the input, its contents will be placed on the main page (index.html).
|
||||
# This can be useful if you have a project on for instance GitHub and want reuse
|
||||
# the introduction page also for the doxygen output.
|
||||
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
|
||||
# be generated. Documented entities will be cross-referenced with these sources.
|
||||
# Note: To get rid of all source code in the generated output, make sure also
|
||||
# VERBATIM_HEADERS is set to NO.
|
||||
|
||||
SOURCE_BROWSER = NO
|
||||
|
||||
# Setting the INLINE_SOURCES tag to YES will include the body
|
||||
# of functions and classes directly in the documentation.
|
||||
|
||||
INLINE_SOURCES = NO
|
||||
|
||||
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
|
||||
# doxygen to hide any special comment blocks from generated source code
|
||||
# fragments. Normal C, C++ and Fortran comments will always remain visible.
|
||||
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
|
||||
# If the REFERENCED_BY_RELATION tag is set to YES
|
||||
# then for each documented function all documented
|
||||
# functions referencing it will be listed.
|
||||
|
||||
REFERENCED_BY_RELATION = NO
|
||||
|
||||
# If the REFERENCES_RELATION tag is set to YES
|
||||
# then for each documented function all documented entities
|
||||
# called/used by that function will be listed.
|
||||
|
||||
REFERENCES_RELATION = NO
|
||||
|
||||
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
|
||||
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
|
||||
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
|
||||
# link to the source code. Otherwise they will link to the documentation.
|
||||
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
|
||||
# If the USE_HTAGS tag is set to YES then the references to source code
|
||||
# will point to the HTML generated by the htags(1) tool instead of doxygen
|
||||
# built-in source browser. The htags tool is part of GNU's global source
|
||||
# tagging system (see http://www.gnu.org/software/global/global.html). You
|
||||
# will need version 4.8.6 or higher.
|
||||
|
||||
USE_HTAGS = NO
|
||||
|
||||
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
|
||||
# will generate a verbatim copy of the header file for each class for
|
||||
# which an include is specified. Set to NO to disable this.
|
||||
|
||||
VERBATIM_HEADERS = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
|
||||
# of all compounds will be generated. Enable this if the project
|
||||
# contains a lot of classes, structs, unions or interfaces.
|
||||
|
||||
ALPHABETICAL_INDEX = YES
|
||||
|
||||
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
|
||||
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
|
||||
# in which this list will be split (can be a number in the range [1..20])
|
||||
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
|
||||
# In case all classes in a project start with a common prefix, all
|
||||
# classes will be put under the same header in the alphabetical index.
|
||||
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
|
||||
# should be ignored while generating the index headers.
|
||||
|
||||
IGNORE_PREFIX =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
|
||||
# generate HTML output.
|
||||
|
||||
GENERATE_HTML = YES
|
||||
|
||||
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `html' will be used as the default path.
|
||||
|
||||
HTML_OUTPUT = html
|
||||
|
||||
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
|
||||
# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
|
||||
# doxygen will generate files with .html extension.
|
||||
|
||||
HTML_FILE_EXTENSION = .html
|
||||
|
||||
# The HTML_HEADER tag can be used to specify a personal HTML header for
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
# standard header. Note that when using a custom header you are responsible
|
||||
# for the proper inclusion of any scripts and style sheets that doxygen
|
||||
# needs, which is dependent on the configuration options used.
|
||||
# It is advised to generate a default header using "doxygen -w html
|
||||
# header.html footer.html stylesheet.css YourConfigFile" and then modify
|
||||
# that header. Note that the header is subject to change so you typically
|
||||
# have to redo this when upgrading to a newer version of doxygen or when
|
||||
# changing the value of configuration settings such as GENERATE_TREEVIEW!
|
||||
|
||||
HTML_HEADER =
|
||||
|
||||
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
# standard footer.
|
||||
|
||||
HTML_FOOTER =
|
||||
|
||||
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
|
||||
# style sheet that is used by each HTML page. It can be used to
|
||||
# fine-tune the look of the HTML output. If left blank doxygen will
|
||||
# generate a default style sheet. Note that it is recommended to use
|
||||
# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
|
||||
# tag will in the future become obsolete.
|
||||
|
||||
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 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.
|
||||
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
|
||||
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||
# other source files which should be copied to the HTML output directory. Note
|
||||
# that these files will be copied to the base HTML output directory. Use the
|
||||
# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
|
||||
# files. In the HTML_STYLESHEET file, use the file name only. Also note that
|
||||
# the files will be copied as-is; there are no commands or markers available.
|
||||
|
||||
HTML_EXTRA_FILES =
|
||||
|
||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
|
||||
# Doxygen will adjust the colors in the style sheet and background images
|
||||
# according to this color. Hue is specified as an angle on a colorwheel,
|
||||
# see http://en.wikipedia.org/wiki/Hue for more information.
|
||||
# For instance the value 0 represents red, 60 is yellow, 120 is green,
|
||||
# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
|
||||
# The allowed range is 0 to 359.
|
||||
|
||||
HTML_COLORSTYLE_HUE = 246
|
||||
|
||||
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
|
||||
# the colors in the HTML output. For a value of 0 the output will use
|
||||
# grayscales only. A value of 255 will produce the most vivid colors.
|
||||
|
||||
HTML_COLORSTYLE_SAT = 79
|
||||
|
||||
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
|
||||
# the luminance component of the colors in the HTML output. Values below
|
||||
# 100 gradually make the output lighter, whereas values above 100 make
|
||||
# the output darker. The value divided by 100 is the actual gamma applied,
|
||||
# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
|
||||
# and 100 does not change the gamma.
|
||||
|
||||
HTML_COLORSTYLE_GAMMA = 75
|
||||
|
||||
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
|
||||
# page will contain the date and time when the page was generated. Setting
|
||||
# this to NO can help when comparing the output of multiple runs.
|
||||
|
||||
HTML_TIMESTAMP = YES
|
||||
|
||||
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
|
||||
# documentation will contain sections that can be hidden and shown after the
|
||||
# page has loaded.
|
||||
|
||||
HTML_DYNAMIC_SECTIONS = YES
|
||||
|
||||
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
|
||||
# entries shown in the various tree structured indices initially; the user
|
||||
# can expand and collapse entries dynamically later on. Doxygen will expand
|
||||
# the tree to such a level that at most the specified number of entries are
|
||||
# visible (unless a fully collapsed tree already exceeds this amount).
|
||||
# So setting the number of entries 1 will produce a full collapsed tree by
|
||||
# default. 0 is a special value representing an infinite number of entries
|
||||
# and will result in a full expanded tree by default.
|
||||
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
|
||||
# If the GENERATE_DOCSET tag is set to YES, additional index files
|
||||
# will be generated that can be used as input for Apple's Xcode 3
|
||||
# integrated development environment, introduced with OSX 10.5 (Leopard).
|
||||
# To create a documentation set, doxygen will generate a Makefile in the
|
||||
# HTML output directory. Running make will produce the docset in that
|
||||
# directory and running "make install" will install the docset in
|
||||
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
|
||||
# it at startup.
|
||||
# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
|
||||
# for more information.
|
||||
|
||||
GENERATE_DOCSET = NO
|
||||
|
||||
# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
|
||||
# feed. A documentation feed provides an umbrella under which multiple
|
||||
# documentation sets from a single provider (such as a company or product suite)
|
||||
# can be grouped.
|
||||
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
|
||||
# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
|
||||
# should uniquely identify the documentation set bundle. This should be a
|
||||
# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
|
||||
# will append .docset to the name.
|
||||
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
|
||||
# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
|
||||
# identify the documentation publisher. This should be a reverse domain-name
|
||||
# style string, e.g. com.mycompany.MyDocSet.documentation.
|
||||
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
|
||||
# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
|
||||
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
|
||||
# will be generated that can be used as input for tools like the
|
||||
# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
|
||||
# of the generated HTML documentation.
|
||||
|
||||
GENERATE_HTMLHELP = NO
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
|
||||
# be used to specify the file name of the resulting .chm file. You
|
||||
# can add a path in front of the file if the result should not be
|
||||
# written to the html output directory.
|
||||
|
||||
CHM_FILE =
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
|
||||
# be used to specify the location (absolute path including file name) of
|
||||
# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
|
||||
# the HTML help compiler on the generated index.hhp.
|
||||
|
||||
HHC_LOCATION =
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
|
||||
# controls if a separate .chi index file is generated (YES) or that
|
||||
# it should be included in the master .chm file (NO).
|
||||
|
||||
GENERATE_CHI = NO
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
|
||||
# is used to encode HtmlHelp index (hhk), content (hhc) and project file
|
||||
# content.
|
||||
|
||||
CHM_INDEX_ENCODING =
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, 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.
|
||||
|
||||
BINARY_TOC = NO
|
||||
|
||||
# The TOC_EXPAND flag can be set to YES to add extra items for group members
|
||||
# to the contents of the HTML help documentation and to the tree view.
|
||||
|
||||
TOC_EXPAND = NO
|
||||
|
||||
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
|
||||
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
|
||||
# that can be used as input for Qt's qhelpgenerator to generate a
|
||||
# Qt Compressed Help (.qch) of the generated HTML documentation.
|
||||
|
||||
GENERATE_QHP = YES
|
||||
|
||||
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
|
||||
# be used to specify the file name of the resulting .qch file.
|
||||
# The path specified is relative to the HTML output folder.
|
||||
|
||||
QCH_FILE = pip.qhp
|
||||
|
||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating
|
||||
# Qt Help Project output. For more information please see
|
||||
# http://doc.trolltech.com/qthelpproject.html#namespace
|
||||
|
||||
QHP_NAMESPACE = PIP
|
||||
|
||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
|
||||
# Qt Help Project output. For more information please see
|
||||
# http://doc.trolltech.com/qthelpproject.html#virtual-folders
|
||||
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
|
||||
# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
|
||||
# add. For more information please see
|
||||
# http://doc.trolltech.com/qthelpproject.html#custom-filters
|
||||
|
||||
QHP_CUST_FILTER_NAME =
|
||||
|
||||
# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
|
||||
# custom filter to add. For more information please see
|
||||
# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
|
||||
# Qt Help Project / Custom Filters</a>.
|
||||
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
|
||||
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
|
||||
# project's
|
||||
# filter section matches.
|
||||
# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
|
||||
# Qt Help Project / Filter Attributes</a>.
|
||||
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
|
||||
# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
|
||||
# be used to specify the location of Qt's qhelpgenerator.
|
||||
# If non-empty doxygen will try to run qhelpgenerator on the generated
|
||||
# .qhp file.
|
||||
|
||||
QHG_LOCATION =
|
||||
|
||||
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
|
||||
# will be generated, which together with the HTML files, form an Eclipse help
|
||||
# plugin. To install this plugin and make it available under the help contents
|
||||
# menu in Eclipse, the contents of the directory containing the HTML and XML
|
||||
# files needs to be copied into the plugins directory of eclipse. The name of
|
||||
# the directory within the plugins directory should be the same as
|
||||
# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
|
||||
# the help appears.
|
||||
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
|
||||
# A unique identifier for the eclipse help plugin. When installing the plugin
|
||||
# the directory name containing the HTML and XML files should also have
|
||||
# this name.
|
||||
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
|
||||
# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
|
||||
# at top of each HTML page. The value NO (the default) enables the index and
|
||||
# the value YES disables it. Since the tabs have the same information as the
|
||||
# navigation tree you can set this option to NO if you already set
|
||||
# GENERATE_TREEVIEW to YES.
|
||||
|
||||
DISABLE_INDEX = NO
|
||||
|
||||
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
|
||||
# structure should be generated to display hierarchical information.
|
||||
# If the tag value is set to YES, a side panel will be generated
|
||||
# containing a tree-like index structure (just like the one that
|
||||
# is generated for HTML Help). For this to work a browser that supports
|
||||
# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
|
||||
# Windows users are probably better off using the HTML help feature.
|
||||
# Since the tree basically has the same information as the tab index you
|
||||
# could consider to set DISABLE_INDEX to NO when enabling this option.
|
||||
|
||||
GENERATE_TREEVIEW = YES
|
||||
|
||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
|
||||
# (range [0,1..20]) that doxygen will group on one line in the generated HTML
|
||||
# documentation. Note that a value of 0 will completely suppress the enum
|
||||
# values from appearing in the overview section.
|
||||
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
|
||||
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
|
||||
# used to set the initial width (in pixels) of the frame in which the tree
|
||||
# is shown.
|
||||
|
||||
TREEVIEW_WIDTH = 250
|
||||
|
||||
# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
|
||||
# links to external symbols imported via tag files in a separate window.
|
||||
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
|
||||
# Use this tag to change the font size of Latex formulas included
|
||||
# as images in the HTML documentation. The default is 10. Note that
|
||||
# when you change the font size after a successful doxygen run you need
|
||||
# to manually remove any form_*.png images from the HTML output directory
|
||||
# to force them to be regenerated.
|
||||
|
||||
FORMULA_FONTSIZE = 10
|
||||
|
||||
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
|
||||
# generated for formulas are transparent PNGs. Transparent PNGs are
|
||||
# not supported properly for IE 6.0, but are supported on all modern browsers.
|
||||
# Note that when changing this option you need to delete any form_*.png files
|
||||
# in the HTML output before the changes have effect.
|
||||
|
||||
FORMULA_TRANSPARENT = YES
|
||||
|
||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
|
||||
# (see http://www.mathjax.org) which uses client side Javascript for the
|
||||
# rendering instead of using prerendered bitmaps. Use this if you do not
|
||||
# have LaTeX installed or if you want to formulas look prettier in the HTML
|
||||
# output. When enabled you may also need to install MathJax separately and
|
||||
# configure the path to it using the MATHJAX_RELPATH option.
|
||||
|
||||
USE_MATHJAX = NO
|
||||
|
||||
# When MathJax is enabled you can set the default output format to be used for
|
||||
# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
|
||||
# SVG. The default value is HTML-CSS, which is slower, but has the best
|
||||
# compatibility.
|
||||
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
|
||||
# When MathJax is enabled you need to specify the location relative to the
|
||||
# HTML output directory using the MATHJAX_RELPATH option. The destination
|
||||
# directory should contain the MathJax.js script. For instance, if the mathjax
|
||||
# directory is located at the same level as the HTML output directory, then
|
||||
# MATHJAX_RELPATH should be ../mathjax. The default value points to
|
||||
# the MathJax Content Delivery Network so you can quickly see the result without
|
||||
# installing MathJax. However, it is strongly recommended to install a local
|
||||
# copy of MathJax from http://www.mathjax.org before deployment.
|
||||
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
|
||||
# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
|
||||
# names that should be enabled during MathJax rendering.
|
||||
|
||||
MATHJAX_EXTENSIONS =
|
||||
|
||||
# When the SEARCHENGINE tag is enabled doxygen will generate a search box
|
||||
# for the HTML output. The underlying search engine uses javascript
|
||||
# and DHTML and should work on any modern browser. Note that when using
|
||||
# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
|
||||
# (GENERATE_DOCSET) there is already a search function so this one should
|
||||
# typically be disabled. For large projects the javascript based search engine
|
||||
# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
|
||||
|
||||
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 search 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 manual for details.
|
||||
|
||||
SERVER_BASED_SEARCH = NO
|
||||
|
||||
# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP
|
||||
# script for searching. Instead the search results are written to an XML file
|
||||
# which needs to be processed by an external indexer. Doxygen will invoke an
|
||||
# external search engine pointed to by the SEARCHENGINE_URL option to obtain
|
||||
# the search results. Doxygen ships with an example indexer (doxyindexer) and
|
||||
# search engine (doxysearch.cgi) which are based on the open source search engine
|
||||
# library Xapian. See the manual for configuration details.
|
||||
|
||||
EXTERNAL_SEARCH = NO
|
||||
|
||||
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
|
||||
# which will returned the search results when EXTERNAL_SEARCH is enabled.
|
||||
# Doxygen ships with an example search engine (doxysearch) which is based on
|
||||
# the open source search engine library Xapian. See the manual for configuration
|
||||
# details.
|
||||
|
||||
SEARCHENGINE_URL =
|
||||
|
||||
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
|
||||
# search data is written to a file for indexing by an external tool. With the
|
||||
# SEARCHDATA_FILE tag the name of this file can be specified.
|
||||
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
|
||||
# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the
|
||||
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
|
||||
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
|
||||
# projects and redirect the results back to the right project.
|
||||
|
||||
EXTERNAL_SEARCH_ID =
|
||||
|
||||
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
|
||||
# projects other than the one defined by this configuration file, but that are
|
||||
# all added to the same external search index. Each project needs to have a
|
||||
# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id
|
||||
# of to a relative location where the documentation can be found.
|
||||
# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ...
|
||||
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
|
||||
# generate Latex output.
|
||||
|
||||
GENERATE_LATEX = NO
|
||||
|
||||
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `latex' will be used as the default path.
|
||||
|
||||
LATEX_OUTPUT = latex
|
||||
|
||||
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
|
||||
# invoked. If left blank `latex' will be used as the default command name.
|
||||
# Note that when enabling USE_PDFLATEX this option is only used for
|
||||
# generating bitmaps for formulas in the HTML output, but not in the
|
||||
# Makefile that is written to the output directory.
|
||||
|
||||
LATEX_CMD_NAME = latex
|
||||
|
||||
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
|
||||
# generate index for LaTeX. If left blank `makeindex' will be used as the
|
||||
# default command name.
|
||||
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
|
||||
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
|
||||
# LaTeX documents. This may be useful for small projects and may help to
|
||||
# save some trees in general.
|
||||
|
||||
COMPACT_LATEX = NO
|
||||
|
||||
# The PAPER_TYPE tag can be used to set the paper type that is used
|
||||
# by the printer. Possible values are: a4, letter, legal and
|
||||
# executive. If left blank a4wide will be used.
|
||||
|
||||
PAPER_TYPE = a4
|
||||
|
||||
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
|
||||
# packages that should be included in the LaTeX output.
|
||||
|
||||
EXTRA_PACKAGES =
|
||||
|
||||
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
|
||||
# the generated latex document. The header should contain everything until
|
||||
# the first chapter. If it is left blank doxygen will generate a
|
||||
# standard header. Notice: only use this tag if you know what you are doing!
|
||||
|
||||
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. Notice: only use this tag if you know what you are doing!
|
||||
|
||||
LATEX_FOOTER =
|
||||
|
||||
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
|
||||
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
|
||||
# contain links (just like the HTML output) instead of page references
|
||||
# This makes the output suitable for online browsing using a pdf viewer.
|
||||
|
||||
PDF_HYPERLINKS = YES
|
||||
|
||||
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
|
||||
# plain latex in the generated Makefile. Set this option to YES to get a
|
||||
# higher quality PDF documentation.
|
||||
|
||||
USE_PDFLATEX = YES
|
||||
|
||||
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
|
||||
# command to the generated LaTeX files. This will instruct LaTeX to keep
|
||||
# running if errors occur, instead of asking the user for help.
|
||||
# This option is also used when generating formulas in HTML.
|
||||
|
||||
LATEX_BATCHMODE = NO
|
||||
|
||||
# If LATEX_HIDE_INDICES is set to YES then doxygen will not
|
||||
# include the index chapters (such as File Index, Compound Index, etc.)
|
||||
# in the output.
|
||||
|
||||
LATEX_HIDE_INDICES = NO
|
||||
|
||||
# If LATEX_SOURCE_CODE is set to YES then doxygen will include
|
||||
# source code with syntax highlighting in the LaTeX output.
|
||||
# Note that which sources are shown also depends on other settings
|
||||
# such as SOURCE_BROWSER.
|
||||
|
||||
LATEX_SOURCE_CODE = NO
|
||||
|
||||
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
|
||||
# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
|
||||
# http://en.wikipedia.org/wiki/BibTeX for more info.
|
||||
|
||||
LATEX_BIB_STYLE = plain
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
|
||||
# The RTF output is optimized for Word 97 and may not look very pretty with
|
||||
# other RTF readers or editors.
|
||||
|
||||
GENERATE_RTF = NO
|
||||
|
||||
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `rtf' will be used as the default path.
|
||||
|
||||
RTF_OUTPUT = rtf
|
||||
|
||||
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
|
||||
# RTF documents. This may be useful for small projects and may help to
|
||||
# save some trees in general.
|
||||
|
||||
COMPACT_RTF = NO
|
||||
|
||||
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
|
||||
# will contain hyperlink fields. The RTF file will
|
||||
# contain links (just like the HTML output) instead of page references.
|
||||
# This makes the output suitable for online browsing using WORD or other
|
||||
# programs which support those fields.
|
||||
# Note: wordpad (write) and others do not support links.
|
||||
|
||||
RTF_HYPERLINKS = NO
|
||||
|
||||
# Load style sheet definitions from file. Syntax is similar to doxygen's
|
||||
# config file, i.e. a series of assignments. You only have to provide
|
||||
# replacements, missing definitions are set to their default value.
|
||||
|
||||
RTF_STYLESHEET_FILE =
|
||||
|
||||
# Set optional variables used in the generation of an rtf document.
|
||||
# Syntax is similar to doxygen's config file.
|
||||
|
||||
RTF_EXTENSIONS_FILE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
|
||||
# generate man pages
|
||||
|
||||
GENERATE_MAN = NO
|
||||
|
||||
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `man' will be used as the default path.
|
||||
|
||||
MAN_OUTPUT = man
|
||||
|
||||
# The MAN_EXTENSION tag determines the extension that is added to
|
||||
# the generated man pages (default is the subroutine's section .3)
|
||||
|
||||
MAN_EXTENSION = .3
|
||||
|
||||
# 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 them the man command
|
||||
# would be unable to find the correct page. The default is NO.
|
||||
|
||||
MAN_LINKS = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_XML tag is set to YES Doxygen will
|
||||
# generate an XML file that captures the structure of
|
||||
# the code including all documentation.
|
||||
|
||||
GENERATE_XML = NO
|
||||
|
||||
# The XML_OUTPUT tag is used to specify where the XML pages will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `xml' will be used as the default path.
|
||||
|
||||
XML_OUTPUT = xml
|
||||
|
||||
# The XML_SCHEMA tag can be used to specify an XML schema,
|
||||
# which can be used by a validating XML parser to check the
|
||||
# syntax of the XML files.
|
||||
|
||||
XML_SCHEMA =
|
||||
|
||||
# The XML_DTD tag can be used to specify an XML DTD,
|
||||
# which can be used by a validating XML parser to check the
|
||||
# syntax of the XML files.
|
||||
|
||||
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 of the XML output.
|
||||
|
||||
XML_PROGRAMLISTING = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
|
||||
# generate an AutoGen Definitions (see autogen.sf.net) file
|
||||
# that captures the structure of the code including all
|
||||
# documentation. Note that this feature is still experimental
|
||||
# and incomplete at the moment.
|
||||
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_PERLMOD tag is set to YES Doxygen will
|
||||
# generate a Perl module file that captures the structure of
|
||||
# the code including all documentation. Note that this
|
||||
# feature is still experimental and incomplete at the
|
||||
# moment.
|
||||
|
||||
GENERATE_PERLMOD = NO
|
||||
|
||||
# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
|
||||
# the necessary Makefile rules, Perl scripts and LaTeX code to be able
|
||||
# to generate PDF and DVI output from the Perl module output.
|
||||
|
||||
PERLMOD_LATEX = NO
|
||||
|
||||
# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
|
||||
# nicely formatted so it can be parsed by a human reader. This is useful
|
||||
# if you want to understand what is going on. On the other hand, if this
|
||||
# tag is set to NO the size of the Perl module output will be much smaller
|
||||
# and Perl will parse it just the same.
|
||||
|
||||
PERLMOD_PRETTY = YES
|
||||
|
||||
# The names of the make variables in the generated doxyrules.make file
|
||||
# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
|
||||
# This is useful so different doxyrules.make files included by the same
|
||||
# Makefile don't overwrite each other's variables.
|
||||
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
|
||||
# evaluate all C-preprocessor directives found in the sources and include
|
||||
# files.
|
||||
|
||||
ENABLE_PREPROCESSING = YES
|
||||
|
||||
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
|
||||
# names in the source code. If set to NO (the default) only conditional
|
||||
# compilation will be performed. Macro expansion can be done in a controlled
|
||||
# way by setting EXPAND_ONLY_PREDEF to YES.
|
||||
|
||||
MACRO_EXPANSION = YES
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
|
||||
# then the macro expansion is limited to the macros specified with the
|
||||
# PREDEFINED and EXPAND_AS_DEFINED tags.
|
||||
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
|
||||
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
|
||||
# pointed to by INCLUDE_PATH will be searched when a #include is found.
|
||||
|
||||
SEARCH_INCLUDES = NO
|
||||
|
||||
# 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.
|
||||
|
||||
INCLUDE_PATH =
|
||||
|
||||
# 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
|
||||
# directories. If left blank, the patterns specified with FILE_PATTERNS will
|
||||
# be used.
|
||||
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
|
||||
# The PREDEFINED tag can be used to specify one or more macro names that
|
||||
# are defined before the preprocessor is started (similar to the -D option of
|
||||
# gcc). The argument of the tag is a list of macros of the form: name
|
||||
# or name=definition (no spaces). If the definition and the = are
|
||||
# omitted =1 is assumed. To prevent a macro definition from being
|
||||
# undefined via #undef or recursively expanded use the := operator
|
||||
# instead of the = operator.
|
||||
|
||||
PREDEFINED = DOXYGEN \
|
||||
PIP_EXPORT
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||
# this tag can be used to specify a list of macro names that should be expanded.
|
||||
# The macro definition that is found in the sources will be used.
|
||||
# Use the PREDEFINED tag if you want to use a different macro definition that
|
||||
# overrules the definition found in the source code.
|
||||
|
||||
EXPAND_AS_DEFINED =
|
||||
|
||||
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
|
||||
# doxygen's preprocessor will 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, because these will confuse the parser if not removed.
|
||||
|
||||
SKIP_FUNCTION_MACROS = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The TAGFILES option can be used to specify one or more tagfiles. For each
|
||||
# tag file the location of the external documentation should be added. The
|
||||
# format of a tag file without this location is as follows:
|
||||
# TAGFILES = file1 file2 ...
|
||||
# Adding location for the tag files is done as follows:
|
||||
# TAGFILES = file1=loc1 "file2 = loc2" ...
|
||||
# where "loc1" and "loc2" can be relative or absolute paths
|
||||
# or URLs. Note that 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.
|
||||
|
||||
TAGFILES =
|
||||
|
||||
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
|
||||
# a tag file that is based on the input files it reads.
|
||||
|
||||
GENERATE_TAGFILE =
|
||||
|
||||
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
|
||||
# in the class index. If set to NO only the inherited external classes
|
||||
# will be listed.
|
||||
|
||||
ALLEXTERNALS = NO
|
||||
|
||||
# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
|
||||
# in the modules index. If set to NO, only the current project's groups will
|
||||
# be listed.
|
||||
|
||||
EXTERNAL_GROUPS = YES
|
||||
|
||||
# The PERL_PATH should be the absolute path and name of the perl script
|
||||
# interpreter (i.e. the result of `which perl').
|
||||
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
|
||||
# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
|
||||
# or super classes. Setting the tag to NO turns the diagrams off. Note that
|
||||
# this option also works with HAVE_DOT disabled, but it is recommended to
|
||||
# install and use dot, since it yields more powerful graphs.
|
||||
|
||||
CLASS_DIAGRAMS = YES
|
||||
|
||||
# You can define message sequence charts within doxygen comments using the \msc
|
||||
# command. Doxygen will then run the mscgen tool (see
|
||||
# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
|
||||
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
|
||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
|
||||
# default search path.
|
||||
|
||||
MSCGEN_PATH =
|
||||
|
||||
# If set to YES, the inheritance and collaboration graphs will hide
|
||||
# inheritance and usage relations if the target is undocumented
|
||||
# or is not a class.
|
||||
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
|
||||
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
|
||||
# available from the path. This tool is part of Graphviz, 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)
|
||||
|
||||
HAVE_DOT = YES
|
||||
|
||||
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
|
||||
# allowed to run in parallel. When set to 0 (the default) doxygen will
|
||||
# base this on the number of processors available in the system. You can set it
|
||||
# explicitly to a value larger than 0 to get control over the balance
|
||||
# between CPU load and processing speed.
|
||||
|
||||
DOT_NUM_THREADS = 8
|
||||
|
||||
# By default doxygen will use the Helvetica font for all dot files that
|
||||
# doxygen generates. When you want a differently looking font 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 setting DOT_FONTPATH to the
|
||||
# directory containing the font.
|
||||
|
||||
DOT_FONTNAME = Helvetica
|
||||
|
||||
# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
|
||||
# The default size is 10pt.
|
||||
|
||||
DOT_FONTSIZE = 10
|
||||
|
||||
# By default doxygen will tell dot to use the Helvetica font.
|
||||
# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
|
||||
# set the path where dot can find it.
|
||||
|
||||
DOT_FONTPATH =
|
||||
|
||||
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
|
||||
# will generate a graph for each documented class showing the direct and
|
||||
# indirect inheritance relations. Setting this tag to YES will force the
|
||||
# CLASS_DIAGRAMS tag to NO.
|
||||
|
||||
CLASS_GRAPH = YES
|
||||
|
||||
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
|
||||
# will generate a graph for each documented class showing the direct and
|
||||
# indirect implementation dependencies (inheritance, containment, and
|
||||
# class references variables) of the class with other documented classes.
|
||||
|
||||
COLLABORATION_GRAPH = NO
|
||||
|
||||
# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
|
||||
# will generate a graph for groups, showing the direct groups dependencies
|
||||
|
||||
GROUP_GRAPHS = NO
|
||||
|
||||
# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
|
||||
# collaboration diagrams in a style similar to the OMG's Unified Modeling
|
||||
# Language.
|
||||
|
||||
UML_LOOK = NO
|
||||
|
||||
# If the UML_LOOK tag is enabled, the fields and methods are shown inside
|
||||
# the class node. If there are many fields or methods and many nodes the
|
||||
# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
|
||||
# threshold limits the number of items for each type to make the size more
|
||||
# managable. Set this to 0 for no limit. Note that the threshold may be
|
||||
# exceeded by 50% before the limit is enforced.
|
||||
|
||||
UML_LIMIT_NUM_FIELDS = 12
|
||||
|
||||
# If set to YES, the inheritance and collaboration graphs will show the
|
||||
# relations between templates and their instances.
|
||||
|
||||
TEMPLATE_RELATIONS = NO
|
||||
|
||||
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
|
||||
# tags are set to YES then doxygen will generate a graph for each documented
|
||||
# file showing the direct and indirect include dependencies of the file with
|
||||
# other documented files.
|
||||
|
||||
INCLUDE_GRAPH = NO
|
||||
|
||||
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
|
||||
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
|
||||
# documented header file showing the documented files that directly or
|
||||
# indirectly include this file.
|
||||
|
||||
INCLUDED_BY_GRAPH = NO
|
||||
|
||||
# If the CALL_GRAPH and HAVE_DOT options are set to YES then
|
||||
# doxygen will generate a call dependency graph for every global function
|
||||
# or class method. Note that enabling this option will significantly increase
|
||||
# the time of a run. So in most cases it will be better to enable call graphs
|
||||
# for selected functions only using the \callgraph command.
|
||||
|
||||
CALL_GRAPH = NO
|
||||
|
||||
# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
|
||||
# doxygen will generate a caller dependency graph for every global function
|
||||
# or class method. Note that enabling this option will significantly increase
|
||||
# the time of a run. So in most cases it will be better to enable caller
|
||||
# graphs for selected functions only using the \callergraph command.
|
||||
|
||||
CALLER_GRAPH = NO
|
||||
|
||||
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
|
||||
# will generate a graphical hierarchy of all classes instead of a textual one.
|
||||
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
|
||||
# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
|
||||
# then doxygen will show the dependencies a directory has on other directories
|
||||
# in a graphical way. The dependency relations are determined by the #include
|
||||
# relations between the files in the directories.
|
||||
|
||||
DIRECTORY_GRAPH = YES
|
||||
|
||||
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
||||
# generated by dot. Possible values are svg, png, jpg, or gif.
|
||||
# If left blank png will be used. 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).
|
||||
|
||||
DOT_IMAGE_FORMAT = svg
|
||||
|
||||
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
|
||||
# enable generation of interactive SVG images that allow zooming and panning.
|
||||
# Note that this requires a modern browser other than Internet Explorer.
|
||||
# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
|
||||
# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
|
||||
# visible. Older versions of IE do not have SVG support.
|
||||
|
||||
INTERACTIVE_SVG = YES
|
||||
|
||||
# The tag DOT_PATH can be used to specify the path where the dot tool can be
|
||||
# found. If left blank, it is assumed the dot tool can be found in the path.
|
||||
|
||||
DOT_PATH =
|
||||
|
||||
# The DOTFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain dot files that are included in the documentation (see the
|
||||
# \dotfile command).
|
||||
|
||||
DOTFILE_DIRS =
|
||||
|
||||
# The MSCFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain msc files that are included in the documentation (see the
|
||||
# \mscfile command).
|
||||
|
||||
MSCFILE_DIRS =
|
||||
|
||||
# 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 by representing a node as a red box. Note that doxygen if the
|
||||
# number of direct children of the root node in a graph is already larger than
|
||||
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
|
||||
# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
|
||||
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
|
||||
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
|
||||
# graphs generated by dot. A depth value of 3 means that only nodes reachable
|
||||
# from the root by following a path via at most 3 edges will be shown. Nodes
|
||||
# that lay further from the root node will be omitted. Note that setting this
|
||||
# option to 1 or 2 may greatly reduce the computation time needed for large
|
||||
# code bases. Also note that the size of a graph can be further restricted by
|
||||
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
|
||||
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
|
||||
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
|
||||
# background. This is disabled by default, because dot on Windows does not
|
||||
# seem to support this out of the box. Warning: Depending on the platform used,
|
||||
# enabling this option may lead to badly anti-aliased labels on the edges of
|
||||
# a graph (i.e. they become hard to read).
|
||||
|
||||
DOT_TRANSPARENT = NO
|
||||
|
||||
# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
|
||||
# files in one run (i.e. multiple -o and -T options on the command line). This
|
||||
# makes dot run faster, but since only newer versions of dot (>1.8.10)
|
||||
# support this, this feature is disabled by default.
|
||||
|
||||
DOT_MULTI_TARGETS = NO
|
||||
|
||||
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
|
||||
# generate a legend page explaining the meaning of the various boxes and
|
||||
# arrows in the dot generated graphs.
|
||||
|
||||
GENERATE_LEGEND = YES
|
||||
|
||||
# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
|
||||
# remove the intermediate dot files that are used to generate
|
||||
# the various graphs.
|
||||
|
||||
DOT_CLEANUP = YES
|
||||
5
clean
5
clean
@@ -5,3 +5,8 @@ rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt
|
||||
cd system_test
|
||||
rm -rvf ./CMakeFiles
|
||||
rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core
|
||||
cd ..
|
||||
cd remote_console
|
||||
rm -rvf ./CMakeFiles
|
||||
rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core
|
||||
cd ..
|
||||
|
||||
14
clean.bat
Executable file
14
clean.bat
Executable file
@@ -0,0 +1,14 @@
|
||||
#make clean
|
||||
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
|
||||
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
|
||||
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 ..
|
||||
117
main.cpp
117
main.cpp
@@ -202,95 +202,68 @@ struct msg2105base {
|
||||
float tangaj_CP;
|
||||
};
|
||||
|
||||
|
||||
struct InpuData {
|
||||
InpuData() {header.msg_id = 2113;}
|
||||
msgHeader header;
|
||||
uint first_number;
|
||||
struct {
|
||||
uchar packet_number: 7;
|
||||
uchar packet_last : 1;
|
||||
};
|
||||
struct {
|
||||
uchar antenna_number : 3;
|
||||
uchar frequency_number: 3;
|
||||
uchar data_type : 2;
|
||||
};
|
||||
uchar data[122];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
class RC: public PIObject {
|
||||
PIOBJECT(RC)
|
||||
public:
|
||||
EVENT_HANDLER2(void, peer, const PIString & , from, const PIByteArray &, data) {piCout << "received from" << from << "\"" << PIString(data) << "\"";}
|
||||
EVENT_HANDLER2(void, slot, void * , data, int, size) {piCout << "read" << PIString((char*)data, size);}
|
||||
EVENT_HANDLER2(void, re, ullong, id, int, size) {piCout << "written id =" << id << "size =" << size;}
|
||||
};
|
||||
|
||||
int main (int argc, char * argv[]) {
|
||||
//PIKbdListener kbd;
|
||||
//kbd.enableExitCapture();
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
InpuData data;
|
||||
PIEthernet eth(PIEthernet::UDP);
|
||||
data.antenna_number = data.frequency_number = data.data_type = 0;
|
||||
float t = 0.f;
|
||||
int pc = 20, cnt = 0;
|
||||
for (int p = 0; p < pc; ++p) {
|
||||
data.packet_number = p;
|
||||
data.packet_last = (p == pc - 1 ? 1 : 0);
|
||||
data.first_number = p * 97;
|
||||
PIBitArray ba_;
|
||||
int ci = 0;
|
||||
for (int i = 0; i < 97; ++i) {
|
||||
t += M_PI/4;
|
||||
ci = sin(t) * 511 + 511;
|
||||
if (cnt % 500 > 80) ci = 512;
|
||||
cnt++;
|
||||
for (int b = 0; b < 10; ++b)
|
||||
ba_.push_back(((ci >> b) & 1) == 1);
|
||||
}
|
||||
//cout << ba_.byteSize() << ", " << ba_.bitSize() << endl;
|
||||
memcpy(data.data, ba_.data(), 122);
|
||||
eth.send("127.0.0.1:5000", &data, sizeof(data));
|
||||
}
|
||||
/*cout << ba_ << endl;
|
||||
for (int i = 0; i < 122; ++i)
|
||||
cout << int(data.data[i]) << ", ";
|
||||
cout << endl;*/
|
||||
/*PIEthernet::InterfaceList il = PIEthernet::interfaces();
|
||||
//const PIEthernet::Interface & i(*(il.getByName("lo")));
|
||||
piForeachC (PIEthernet::Interface & i, il)
|
||||
piCout << NewLine << i.name << NewLine
|
||||
<< "index" << i.index << NewLine
|
||||
<< "address" << i.address << NewLine
|
||||
<< "netmask" << i.netmask << NewLine
|
||||
<< "mac" << i.mac << NewLine
|
||||
<< "broadcast" << i.broadcast << NewLine
|
||||
<< "isActive" << i.isActive() << NewLine
|
||||
<< "isRunning" << i.isRunning() << NewLine
|
||||
<< "isBroadcast" << i.isBroadcast() << NewLine
|
||||
<< "isMulticast" << i.isMulticast() << NewLine
|
||||
<< "isLoopback" << i.isLoopback() << NewLine
|
||||
<< "isPTP" << i.isPTP();*/
|
||||
//return 0;
|
||||
|
||||
/*RC rc__;
|
||||
PIPeer peer(argv[1]);
|
||||
CONNECT2(void, const PIString & , const PIByteArray &, &peer, dataReceivedEvent, &rc__, peer);
|
||||
msleep(1000);
|
||||
peer.send("a", ("hello a from '" + PIString(argv[1]) + "'!").data());
|
||||
peer.send("b", ("hello b from '" + PIString(argv[1]) + "'!").data());
|
||||
peer.send("c", ("hello c from '" + PIString(argv[1]) + "'!").data());*/
|
||||
int a__, b__;
|
||||
PIConsole console(false);
|
||||
console.enableExitCapture();
|
||||
PIProtocol p("/home/peri4/work/ISPUM/nosit_VM6/protocols.conf", "gas", 0, 0, &a__, 4, &b__, 4);
|
||||
p.start();
|
||||
console.addVariable("service", &p);
|
||||
console.start();
|
||||
console.startServer("cons");
|
||||
console.waitForFinish();
|
||||
return 0;
|
||||
|
||||
/*PIKbdListener kbd;
|
||||
kbd.enableExitCapture();
|
||||
PIEthernet * _eth;
|
||||
PIByteArray ba_(16);
|
||||
if (PIString(argv[argc - 1]) == "s") {
|
||||
_eth = new PIEthernet(PIEthernet::TCP_Server);
|
||||
piCout << "listen" << _eth->listen("127.0.0.1:1111");
|
||||
int cc = 0;
|
||||
while (!PIKbdListener::exiting) {
|
||||
if (cc != _eth->clientsCount()) {
|
||||
piCout << "new client";
|
||||
_eth->clients().back()->startThreadedRead();
|
||||
cc++;
|
||||
}
|
||||
msleep(1);
|
||||
}
|
||||
} else {
|
||||
_eth = new PIEthernet(PIEthernet::TCP_Client);
|
||||
piCout << "connection" << _eth->connect("127.0.0.1:1111");
|
||||
_eth->send(PIString("0123456789101112").data(), 16);
|
||||
while (!PIKbdListener::exiting) {
|
||||
msleep(1);
|
||||
}
|
||||
PIFile f("picontainers.h");
|
||||
PIString all = f.readAll();
|
||||
while (!all.isEmpty()) {
|
||||
PIString line = all.takeLine();
|
||||
if (line.takeWord() == "class")
|
||||
piCout << "class" << line.trim();
|
||||
}
|
||||
delete _eth;
|
||||
return 0;
|
||||
|
||||
msg2105base msg;
|
||||
msg.header.size = sizeof(msg);
|
||||
msg.header.msg_id = 2105;
|
||||
msg.msgTime = 1;
|
||||
//PIKbdListener kbd;
|
||||
//kbd.enableExitCapture();
|
||||
RC rc_;
|
||||
PIEthernet eth;
|
||||
CONNECT2(void, ullong, int, ð, threadedWriteEvent, &rc_, re);
|
||||
@@ -313,7 +286,7 @@ int main(int argc, char ** argv) {
|
||||
piMSleep(50);
|
||||
if (PIKbdListener::exiting) break;
|
||||
}
|
||||
return 0;*/
|
||||
return 0;
|
||||
|
||||
PISignals::setSlot(signalFunc);
|
||||
//PISignals::grabSignals(PISignals::Interrupt);
|
||||
|
||||
1
make_rc_win.bat
Executable file
1
make_rc_win.bat
Executable file
@@ -0,0 +1 @@
|
||||
windres -i pip_resource_win.rc -o pip_resource_win.o --include-dir=.
|
||||
@@ -117,19 +117,20 @@ public:
|
||||
|
||||
PIByteArray & compressRLE(uchar threshold = 192);
|
||||
PIByteArray & decompressRLE(uchar threshold = 192);
|
||||
PIByteArray compressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.compressedRLE(threshold); return ba;}
|
||||
PIByteArray decompressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.decompressedRLE(threshold); return ba;}
|
||||
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;}
|
||||
|
||||
PIByteArray & append(void * data, int size) {for (int i = 0; i < size; ++i) push_back(((uchar*)data)[i]); return *this;}
|
||||
PIByteArray & append(const PIByteArray & data) {for (int i = 0; i < data.size_s(); ++i) push_back(data[i]); 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;}
|
||||
//PIByteArray & operator <<(const PIByteArray & v) {for (uint i = 0; i < v.size(); ++i) push_back(v[i]); return *this;}
|
||||
|
||||
uchar checksumPlain8();
|
||||
uint checksumPlain32();
|
||||
@@ -141,6 +142,7 @@ public:
|
||||
|
||||
private:
|
||||
union base64HelpStruct {
|
||||
base64HelpStruct() {memset(this, 0, sizeof(base64HelpStruct));}
|
||||
struct {
|
||||
uchar ascii0: 6;
|
||||
uchar ascii1: 6;
|
||||
@@ -174,15 +176,16 @@ inline PIByteArray & operator <<(PIByteArray & s, const ulong & v) {PBA_OPERATOR
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {PBA_OPERATOR_TO return s;}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const float v) {PBA_OPERATOR_TO return s;}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const double & v) {PBA_OPERATOR_TO return s;}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {int os = s.size_s(); s.enlarge(v.s); memcpy(s.data(os), v.d, v.s); return s;}
|
||||
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;}
|
||||
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;}
|
||||
template <typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;}
|
||||
template <typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIList<T> & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;}
|
||||
template <typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;}
|
||||
template <typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const T & v) {PBA_OPERATOR_TO return s;}
|
||||
//template <typename T>
|
||||
//inline PIByteArray & operator <<(PIByteArray & s, const T & v) {PBA_OPERATOR_TO return s;}
|
||||
|
||||
#undef PBA_OPERATOR_TO
|
||||
#define PBA_OPERATOR_FROM memcpy(&v, s.data(), sizeof(v)); s.remove(0, sizeof(v));
|
||||
@@ -198,16 +201,20 @@ inline PIByteArray & operator >>(PIByteArray & s, ulong & v) {assert(s.size() >=
|
||||
inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, float & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, double & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {assert(s.size_s() >= v.s); memcpy(v.d, s.data(), v.s); s.remove(0, v.s); return s;}
|
||||
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;}
|
||||
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;}
|
||||
template <typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & 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;}
|
||||
template <typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIList<T> & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIList<T> & 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;}
|
||||
template <typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
|
||||
template <typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, T & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & 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;}
|
||||
//template <typename T>
|
||||
//inline PIByteArray & operator >>(PIByteArray & s, T & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
|
||||
#undef PBA_OPERATOR_FROM
|
||||
|
||||
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;}
|
||||
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
|
||||
|
||||
14
picli.cpp
14
picli.cpp
@@ -20,6 +20,18 @@
|
||||
#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 = "-";
|
||||
@@ -69,7 +81,7 @@ void PICLI::parse() {
|
||||
_args_opt << cra;
|
||||
continue;
|
||||
}
|
||||
piCout << "[PICli] Arguments overflow, \"" << cra << "\" ignored";
|
||||
piCoutObj << "[PICli] Arguments overflow, \"" << cra << "\" ignored";
|
||||
}
|
||||
if (last == 0 ? false : last->has_value) {
|
||||
last->value = cra;
|
||||
|
||||
39
picli.h
39
picli.h
@@ -1,3 +1,6 @@
|
||||
/*! \file picli.h
|
||||
* \brief Command-Line parser
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Command-Line Parser
|
||||
@@ -20,26 +23,44 @@
|
||||
#ifndef PICLI_H
|
||||
#define PICLI_H
|
||||
|
||||
#include "pistring.h"
|
||||
#include "piobject.h"
|
||||
|
||||
class PIP_EXPORT PICLI
|
||||
class PIP_EXPORT PICLI: protected 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;}
|
||||
|
||||
PIString rawArgument(int index) {return _args_raw[index];}
|
||||
PIString mandatoryArgument(int index) {return _args_mand[index];}
|
||||
PIString optionalArgument(int index) {return _args_opt[index];}
|
||||
const PIStringList & rawArguments() const {return _args_raw;}
|
||||
const PIStringList & mandatoryArguments() const {return _args_mand;}
|
||||
const PIStringList & optionalArguments() const {return _args_opt;}
|
||||
const PIString programCommand() const {return _args_raw.size() > 0 ? _args_raw.front() : PIString();}
|
||||
|
||||
//! 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
|
||||
const 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();}
|
||||
|
||||
325
piconsole.cpp
325
piconsole.cpp
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "piconsole.h"
|
||||
#include "pipeer.h"
|
||||
|
||||
|
||||
extern PIMutex __PICout_mutex__;
|
||||
@@ -28,6 +29,7 @@ PIConsole::PIConsole(bool startNow, KBFunc slot): PIThread() {
|
||||
needLockRun(true);
|
||||
ret_func = slot;
|
||||
num_format = 0;
|
||||
vid = 0;
|
||||
cur_tab = width = height = pwidth = pheight = max_y = 0;
|
||||
def_align = Nothing;
|
||||
#ifdef WINDOWS
|
||||
@@ -40,13 +42,20 @@ PIConsole::PIConsole(bool startNow, KBFunc slot): PIThread() {
|
||||
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);
|
||||
@@ -227,6 +236,7 @@ PIString PIConsole::fstr(PIFlags<PIConsole::Format> f) {
|
||||
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();
|
||||
@@ -317,6 +327,7 @@ void PIConsole::run() {
|
||||
width = ws.ws_col;
|
||||
height = ws.ws_row;
|
||||
#endif
|
||||
//fflush(0); return;
|
||||
__PICout_mutex__.lock();
|
||||
if (pwidth != width || pheight != height) {
|
||||
clearScreen();
|
||||
@@ -336,27 +347,37 @@ void PIConsole::run() {
|
||||
if (j > height - 3) continue;
|
||||
j++;
|
||||
moveRight(cx);
|
||||
if (tv.type == 0 && tv.s == 0) {
|
||||
if (tv.type == 15) {
|
||||
newLine();
|
||||
continue;
|
||||
}
|
||||
moveRight(tv.offset);
|
||||
PIString rstr;
|
||||
const void * ptr = 0;
|
||||
if (tv.remote) {
|
||||
if (tv.type == 0) {
|
||||
rstr << PIByteArray(tv.rdata);
|
||||
ptr = &rstr;
|
||||
} else
|
||||
ptr = tv.rdata.data();
|
||||
} else
|
||||
ptr = tv.ptr;
|
||||
switch (tv.type) {
|
||||
case 0: clen = printValue(tv.s != 0 ? *tv.s : PIString(), tv.format); break;
|
||||
case 1: clen = printValue(tv.b != 0 ? *tv.b : false, tv.format); break;
|
||||
case 2: clen = printValue(tv.i != 0 ? *tv.i : 0, tv.format); break;
|
||||
case 3: clen = printValue(tv.l != 0 ? *tv.l : 0l, tv.format); break;
|
||||
case 4: clen = printValue(tv.c != 0 ? *tv.c : char(0), tv.format); break;
|
||||
case 5: clen = printValue(tv.f != 0 ? *tv.f : 0.f, tv.format); break;
|
||||
case 6: clen = printValue(tv.d != 0 ? *tv.d : 0., tv.format); break;
|
||||
case 7: clen = printValue(tv.sh != 0 ? *tv.sh : short(0), tv.format); break;
|
||||
case 8: clen = printValue(tv.ui != 0 ? *tv.ui : 0u, tv.format); break;
|
||||
case 9: clen = printValue(tv.ul != 0 ? *tv.ul : 0ul, tv.format); break;
|
||||
case 10: clen = printValue(tv.ush != 0 ? *tv.ush : ushort(0), tv.format); break;
|
||||
case 11: clen = printValue(tv.uc != 0 ? *tv.uc : uchar(0), tv.format); break;
|
||||
case 12: clen = printValue(tv.ll != 0 ? *tv.ll : 0l, tv.format); break;
|
||||
case 13: clen = printValue(tv.ull != 0 ? *tv.ull : 0ull, tv.format); break;
|
||||
case 14: clen = printValue(bitsValue(tv.ptr, tv.bitFrom, tv.bitCount), tv.format); break;
|
||||
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 14: clen = printValue(bitsValue(ptr, tv.bitFrom, tv.bitCount), tv.format); break;
|
||||
}
|
||||
if (clen + tv.offset < (uint)col_wid) {
|
||||
#if defined(QNX) || defined(FREE_BSD)
|
||||
@@ -401,7 +422,7 @@ void PIConsole::fillLabels() {
|
||||
if (ccol.alignment != Nothing) {
|
||||
mx = 0;
|
||||
piForeachC (Variable & j, cvars)
|
||||
if (j.s != 0)
|
||||
if (!j.isEmpty())
|
||||
if (mx < j.name.size())
|
||||
mx = j.name.size();
|
||||
mx += 2;
|
||||
@@ -416,7 +437,7 @@ void PIConsole::fillLabels() {
|
||||
Variable & tv(cvars[j]);
|
||||
cvars[j].nx = cx;
|
||||
cvars[j].ny = cy;
|
||||
if (tv.name.size() == 0) {
|
||||
if (tv.name.isEmpty()) {
|
||||
cvars[j].offset = 0;
|
||||
clearLine();
|
||||
newLine();
|
||||
@@ -424,7 +445,8 @@ void PIConsole::fillLabels() {
|
||||
continue;
|
||||
}
|
||||
clearLine();
|
||||
if (tv.type == 0 && tv.s == 0) {
|
||||
//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);
|
||||
@@ -432,7 +454,7 @@ void PIConsole::fillLabels() {
|
||||
cy++;
|
||||
continue;
|
||||
}
|
||||
if (tv.s != 0) {
|
||||
if (!tv.isEmpty()) {
|
||||
switch (ccol.alignment) {
|
||||
case Nothing:
|
||||
cvars[j].offset = (tv.name + ": ").length();
|
||||
@@ -489,7 +511,7 @@ void PIConsole::status() {
|
||||
}
|
||||
|
||||
|
||||
int PIConsole::bitsValue(const void * src, int offset, int count) {
|
||||
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<const char * >(src)[stbyte];
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -522,38 +544,38 @@ const char * PIConsole::toBin(const void * d, int s) {
|
||||
}
|
||||
|
||||
|
||||
#define ADD_VAR_BODY tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; checkColumn(col);
|
||||
#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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 0; tv.s = 0; column(col).push_back(tv);}
|
||||
void PIConsole::addVariable(const PIString & name, const PIString* ptr, int col, PIFlags<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 0; tv.s = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> 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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 1; tv.b = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 2; tv.i = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 3; tv.l = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 4; tv.c = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 5; tv.f = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 6; tv.d = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 7; tv.sh = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 8; tv.ui = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 9; tv.ul = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 10; tv.ush = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 11; tv.uc = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 12; tv.ll = ptr; column(col).push_back(tv);}
|
||||
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<PIConsole::Format> format) {
|
||||
ADD_VAR_BODY tv.type = 13; tv.ull = ptr; column(col).push_back(tv);}
|
||||
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 PIProtocol * ptr, int col, PIFlags<PIConsole::Format> format) {
|
||||
addString("protocol " + name, col, format | PIConsole::Bold);
|
||||
addVariable("Rec - " + ptr->receiverDeviceName(), ptr->receiverDeviceState_ptr(), col, format);
|
||||
@@ -592,10 +614,10 @@ void PIConsole::addVariable(const PIString & name, const PISystemMonitor * ptr,
|
||||
addVariable("cpu load", &(ptr->statistic().cpu_load_system), col, format);
|
||||
}
|
||||
void PIConsole::addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int col, PIFlags<PIConsole::Format> format) {
|
||||
tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = 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.name = ""; tv.type = 0; tv.d = 0; tv.format = Normal;
|
||||
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);
|
||||
@@ -670,3 +692,226 @@ inline int PIConsole::printValue(const ushort value, PIFlags<PIConsole::Format>
|
||||
inline int PIConsole::printValue(const uint value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
|
||||
inline int PIConsole::printValue(const ulong value, PIFlags<PIConsole::Format> format) {PRINT_VAR_BODY}
|
||||
inline int PIConsole::printValue(const ullong value, PIFlags<PIConsole::Format> 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);
|
||||
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(currentSystemTime().nanoseconds);
|
||||
peer = new PIPeer("_rcc_:" + currentDateTime().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<VariableContent> 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;
|
||||
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<VariableContent> content;
|
||||
PIMap<int, Variable * > 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;
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
144
piconsole.h
144
piconsole.h
@@ -27,8 +27,12 @@
|
||||
#ifndef WINDOWS
|
||||
# include <sys/ioctl.h>
|
||||
# include <fcntl.h>
|
||||
#else
|
||||
# define COMMON_LVB_UNDERSCORE 0x8000
|
||||
#endif
|
||||
|
||||
class PIPeer;
|
||||
|
||||
/// handlers:
|
||||
/// void clearVariables(bool clearScreen = true)
|
||||
/// void start(bool wait = false)
|
||||
@@ -135,14 +139,21 @@ public:
|
||||
bool exitCaptured() const {return listener->exitCaptured();}
|
||||
char exitKey() const {return listener->exitKey();}
|
||||
|
||||
private:
|
||||
void begin();
|
||||
void run();
|
||||
void fillLabels();
|
||||
// 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 getWinCurCoord() {GetConsoleScreenBufferInfo(hOut, &csbi); ccoord = csbi.dwCursorPosition;}
|
||||
COORD & getWinCoord(int dx = 0, int dy = 0) {getWinCurCoord(); ccoord.X += dx; ccoord.Y += dy; return ccoord;}
|
||||
void toUpperLeft() {SetConsoleCursorPosition(hOut, ulcoord);}
|
||||
void moveRight(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(n));}
|
||||
void moveLeft(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(-n));}
|
||||
@@ -168,9 +179,19 @@ private:
|
||||
void hideCursor() {printf("\e[?25l");}
|
||||
void showCursor() {printf("\e[?25h");}
|
||||
#endif
|
||||
|
||||
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);
|
||||
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<PIConsole::Format> format = PIConsole::Normal);
|
||||
inline int printValue(const PIString & str, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
@@ -191,6 +212,16 @@ private:
|
||||
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<PIConsole::Format> format;
|
||||
int nx;
|
||||
@@ -199,31 +230,24 @@ private:
|
||||
int offset;
|
||||
int bitFrom;
|
||||
int bitCount;
|
||||
union {
|
||||
const PIString * s;
|
||||
const bool * b;
|
||||
const short * sh;
|
||||
const int * i;
|
||||
const long * l;
|
||||
const llong * ll;
|
||||
const float * f;
|
||||
const double * d;
|
||||
const char * c;
|
||||
const uchar * uc;
|
||||
const ushort * ush;
|
||||
const uint * ui;
|
||||
const ulong * ul;
|
||||
const ullong * ull;
|
||||
const void * ptr;
|
||||
};
|
||||
void operator =(const Variable & src) {name = src.name; format = src.format; type = src.type; offset = src.offset;
|
||||
bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny;}
|
||||
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;}
|
||||
};
|
||||
|
||||
struct VariableContent {
|
||||
int id;
|
||||
PIByteArray rdata;
|
||||
};
|
||||
|
||||
struct Column {
|
||||
Column(Alignment align = PIConsole::Right) {variables.reserve(16); alignment = align;}
|
||||
PIVector<Variable> variables;
|
||||
Alignment alignment;
|
||||
Column(Alignment align = PIConsole::Right) { alignment = align;}
|
||||
uint size() const {return variables.size();}
|
||||
Variable & operator [](int index) {return variables[index];}
|
||||
const Variable & operator [](int index) const {return variables[index];}
|
||||
@@ -232,15 +256,27 @@ private:
|
||||
};
|
||||
|
||||
struct Tab {
|
||||
Tab(PIString n = "", char k = 0) {columns.reserve(16); name = n; key = k;}
|
||||
PIVector<Column> columns;
|
||||
PIString name;
|
||||
PIString status;
|
||||
char key;
|
||||
Tab() {}
|
||||
Tab(PIString n, char k) {name = n; key = k;}
|
||||
~Tab() {;}
|
||||
};
|
||||
|
||||
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<Column> & columns() {return tabs[cur_tab].columns;}
|
||||
Column & column(int index) {return tabs[cur_tab].columns[index - 1];}
|
||||
inline int couts(const PIString & v);
|
||||
@@ -259,6 +295,14 @@ private:
|
||||
inline int couts(const float v);
|
||||
inline int couts(const double 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);
|
||||
|
||||
#ifdef WINDOWS
|
||||
void * hOut;
|
||||
CONSOLE_SCREEN_BUFFER_INFO sbi, csbi;
|
||||
@@ -277,8 +321,48 @@ private:
|
||||
KBFunc ret_func;
|
||||
int width, height, pwidth, pheight, ret, col_wid, num_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<RemoteClient> 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
|
||||
|
||||
@@ -549,7 +549,7 @@ public:
|
||||
bool contains(const Type & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
|
||||
|
||||
#else
|
||||
_CVector & enlarge(uint size_) {int ns = size_s() + size_; if (ns <= 0) _stlc::clear(); else _stlc::resize(ns); return *this;}
|
||||
_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(Type), (int(*)(const void * , const void * ))compare); return *this;}
|
||||
_CVector & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;}
|
||||
_CVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;}
|
||||
|
||||
99
pidiagnostics.cpp
Normal file
99
pidiagnostics.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Speed and quality in/out diagnostics
|
||||
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pidiagnostics.h"
|
||||
|
||||
|
||||
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();
|
||||
if (el > 0.f) immediate_freq = ifreq = 1.f / el;
|
||||
else immediate_freq = ifreq = 0.f;
|
||||
PITimer::reset();
|
||||
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();
|
||||
}
|
||||
85
pidiagnostics.h
Normal file
85
pidiagnostics.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Speed and quality in/out diagnostics
|
||||
Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIDIAGNOSTICS_H
|
||||
#define PIDIAGNOSTICS_H
|
||||
|
||||
#include "pitimer.h"
|
||||
|
||||
|
||||
class PIP_EXPORT PIDiagnostics: private PITimer
|
||||
{
|
||||
PIOBJECT(PIDiagnostics)
|
||||
public:
|
||||
PIDiagnostics(bool start_ = true);
|
||||
virtual ~PIDiagnostics() {;}
|
||||
|
||||
enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5};
|
||||
|
||||
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);
|
||||
|
||||
float immediateFrequency() const {return immediate_freq;}
|
||||
float integralFrequency() const {return integral_freq;}
|
||||
ullong receiveCountPerSec() const {return packets_in_sec;}
|
||||
ullong sendCountPerSec() const {return packets_out_sec;}
|
||||
ullong receiveBytesPerSec() const {return bytes_in_sec;}
|
||||
ullong sendBytesPerSec() const {return bytes_out_sec;}
|
||||
ullong receiveCount() const {return receive_count;}
|
||||
ullong wrongCount() const {return wrong_count;}
|
||||
ullong sendCount() const {return send_count;}
|
||||
PIDiagnostics::Quality quality() const {return qual;}
|
||||
PIString receiveSpeed() const {return speedIn;}
|
||||
PIString sendSpeed() const {return speedOut;}
|
||||
|
||||
const float * immediateFrequency_ptr() const {return &immediate_freq;}
|
||||
const float * integralFrequency_ptr() const {return &integral_freq;}
|
||||
const ullong * receiveCountPerSec_ptr() const {return &packets_in_sec;}
|
||||
const ullong * sendCountPerSec_ptr() const {return &packets_out_sec;}
|
||||
const ullong * receiveBytesPerSec_ptr() const {return &bytes_in_sec;}
|
||||
const ullong * sendBytesPerSec_ptr() const {return &bytes_out_sec;}
|
||||
const ullong * receiveCount_ptr() const {return &receive_count;}
|
||||
const ullong * wrongCount_ptr() const {return &wrong_count;}
|
||||
const ullong * sendCount_ptr() const {return &send_count;}
|
||||
const int * quality_ptr() const {return (int * )&qual;}
|
||||
const PIString * receiveSpeed_ptr() const {return &speedIn;}
|
||||
const PIString * sendSpeed_ptr() const {return &speedOut;}
|
||||
|
||||
EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_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
|
||||
221
piethernet.cpp
221
piethernet.cpp
@@ -83,7 +83,7 @@ bool PIEthernet::init() {
|
||||
closeSocket(sock);
|
||||
int st = 0, pr = 0;;
|
||||
#ifdef WINDOWS
|
||||
int flags = 0;
|
||||
int flags = WSA_FLAG_OVERLAPPED;
|
||||
#else
|
||||
int so = 1;
|
||||
#endif
|
||||
@@ -96,18 +96,21 @@ bool PIEthernet::init() {
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
if (type_ == UDP) flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF;
|
||||
if (params[ReuseAddress]) flags |= WSA_FLAG_OVERLAPPED;
|
||||
sock = WSASocket(AF_INET, st, pr, NULL, 0, flags);
|
||||
#else
|
||||
sock = socket(AF_INET, st, pr);
|
||||
#endif
|
||||
if (sock == -1) {
|
||||
piCout << "[PIEthernet] Cant`t create socket, " << ethErrorString();
|
||||
piCoutObj << "[PIEthernet] Can`t create socket, " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
#ifndef WINDOWS
|
||||
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));
|
||||
setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (const char * )&bv, sizeof(bv));
|
||||
#endif
|
||||
//cout << "inited " << sock << ": bc = " << params << endl;
|
||||
//fcntl(sock, F_SETFL, 0/*O_NONBLOCK*/);
|
||||
@@ -128,7 +131,7 @@ bool PIEthernet::openDevice() {
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
if (type_ != UDP)
|
||||
return true;
|
||||
//cout << " bind to " << sock << ": " << (params[PIEthernet::Broadcast] ? "0.0.0.0" : path_) << ": " << port_ << " ..." <<endl;
|
||||
//piCout << "bind to" << (params[PIEthernet::Broadcast] ? "bc" : ip_) << ":" << port_ << " ...";
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_family = AF_INET;
|
||||
addr_.sin_port = htons(port_);
|
||||
@@ -143,7 +146,7 @@ bool PIEthernet::openDevice() {
|
||||
tries++;
|
||||
}
|
||||
if (tries == 10) {
|
||||
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
piCoutObj << "[PIEthernet] Can`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
opened_ = true;
|
||||
@@ -156,7 +159,6 @@ bool PIEthernet::openDevice() {
|
||||
|
||||
bool PIEthernet::closeDevice() {
|
||||
//cout << "close\n";
|
||||
if (sock != -1) shutdown(sock, SHUT_RDWR);
|
||||
closeSocket(sock);
|
||||
piForeach (PIEthernet * i, clients_)
|
||||
delete i;
|
||||
@@ -172,7 +174,7 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
|
||||
if (sock == -1) init();
|
||||
if (sock == -1) return false;
|
||||
if (type_ != UDP) {
|
||||
piCout << "[PIEthernet] Only UDP sockets can join multicast groups";
|
||||
piCoutObj << "[PIEthernet] Only UDP sockets can join multicast groups";
|
||||
return false;
|
||||
}
|
||||
if (!opened_) {
|
||||
@@ -185,27 +187,36 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_family = AF_INET;
|
||||
addr_.sin_port = htons(port_);
|
||||
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) {
|
||||
piCout << "[PIEthernet] Cant`t join multicast group " << group << ", " << ethErrorString();
|
||||
piCoutObj << "[PIEthernet] Can`t join multicast group " << group << ", " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
leafs.insert(group, ret);
|
||||
#else
|
||||
# ifndef QNX
|
||||
if (!params[Broadcast])
|
||||
piCout << "[PIEthernet] Warning: \"Broadcast\" parameter not set, \"joinMulticastGroup(\"" << group << "\")\" may be useless!";
|
||||
piCoutObj << "[PIEthernet] Warning: \"Broadcast\" parameter not set, \"joinMulticastGroup(\"" << group << "\")\" may be useless!";
|
||||
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_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
|
||||
piCout << "[PIEthernet] Cant`t join multicast group " << group << ", " << ethErrorString();
|
||||
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 << "[PIEthernet] Can`t join multicast group " << group << ", " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
# endif
|
||||
@@ -218,7 +229,7 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
|
||||
if (sock == -1) init();
|
||||
if (sock == -1) return false;
|
||||
if (type_ != UDP) {
|
||||
piCout << "[PIEthernet] Only UDP sockets can leave multicast groups";
|
||||
piCoutObj << "[PIEthernet] Only UDP sockets can leave multicast groups";
|
||||
return false;
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
@@ -237,7 +248,7 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
|
||||
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) {
|
||||
piCout << "[PIEthernet] Cant`t leave multicast group " << group << ", " << ethErrorString();
|
||||
piCoutObj << "[PIEthernet] Can`t leave multicast group " << group << ", " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -256,10 +267,10 @@ bool PIEthernet::connect() {
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
#endif
|
||||
//piCout << "[PIEthernet] connect to " << ip << ":" << port_;
|
||||
//piCoutObj << "[PIEthernet] connect to " << ip << ":" << port_;
|
||||
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
|
||||
if (!connected_)
|
||||
piCout << "[PIEthernet] Cant`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
piCoutObj << "[PIEthernet] Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
opened_ = connected_;
|
||||
if (connected_) connected();
|
||||
return connected_;
|
||||
@@ -283,14 +294,14 @@ bool PIEthernet::listen() {
|
||||
tries++;
|
||||
}
|
||||
if (tries == 10) {
|
||||
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
piCoutObj << "[PIEthernet] Can`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
if (::listen(sock, 64) == -1) {
|
||||
piCout << "[PIEthernet] Can`t listen on "<< ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
piCoutObj << "[PIEthernet] Can`t listen on "<< ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
//piCout << "[PIEthernet] listen on " << ip_ << ":" << port_;
|
||||
//piCoutObj << "[PIEthernet] listen on " << ip_ << ":" << port_;
|
||||
server_thread_.start(server_func);
|
||||
return true;
|
||||
}
|
||||
@@ -303,13 +314,14 @@ int PIEthernet::read(void * read_to, int max_size) {
|
||||
int rs = 0, s = 0;
|
||||
sockaddr_in client_addr;
|
||||
socklen_t slen = sizeof(client_addr);
|
||||
//piCout << "[PIEthernet] read from " << ip_ << ":" << port_ << endl;
|
||||
//piCoutObj << "[PIEthernet] read from " << ip_ << ":" << port_ << endl;
|
||||
switch (type_) {
|
||||
case TCP_SingleTCP:
|
||||
::listen(sock, 64);
|
||||
s = accept(sock, (sockaddr * )&client_addr, &slen);
|
||||
if (s == -1) {
|
||||
piCout << "[PIEthernet] Cant`t accept new connection, " << ethErrorString();
|
||||
//piCoutObj << "[PIEthernet] Can`t accept new connection, " << ethErrorString();
|
||||
msleep(1);
|
||||
return -1;
|
||||
}
|
||||
rs = recv(s, (char * )read_to, max_size, 0);
|
||||
@@ -323,11 +335,11 @@ int PIEthernet::read(void * read_to, int max_size) {
|
||||
#else
|
||||
rs = recv(sock, read_to, max_size, 0);
|
||||
#endif
|
||||
piCout << "eth" << path_ << "read return" << rs << errno;
|
||||
if (rs <= 0) {
|
||||
//piCout << "eth" << path_ << "read return" << rs << errno;
|
||||
if (rs <= 0 && type_ == TCP_Client) {
|
||||
connected_ = false;
|
||||
disconnected(rs < 0);
|
||||
piCout << "eth" << path_ << "disconnected";
|
||||
//piCoutObj << "eth" << path_ << "disconnected";
|
||||
}
|
||||
if (rs > 0) received(read_to, rs);
|
||||
return rs;
|
||||
@@ -342,10 +354,10 @@ int PIEthernet::read(void * read_to, int max_size) {
|
||||
int PIEthernet::write(const void * data, int max_size) {
|
||||
if (sock == -1) init();
|
||||
if (sock == -1 || !isWriteable()) {
|
||||
//piCout << "[PIEthernet] Can`t send to uninitialized socket";
|
||||
//piCoutObj << "[PIEthernet] Can`t send to uninitialized socket";
|
||||
return -1;
|
||||
}
|
||||
//piCout << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes";
|
||||
//piCoutObj << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes";
|
||||
int ret = 0;
|
||||
switch (type_) {
|
||||
case TCP_SingleTCP:
|
||||
@@ -356,21 +368,22 @@ int PIEthernet::write(const void * data, int max_size) {
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
#endif
|
||||
//piCout << "connect SingleTCP" << ip_s << ":" << port_s << "...";
|
||||
//piCoutObj << "connect SingleTCP" << ip_s << ":" << port_s << "...";
|
||||
if (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) != 0) {
|
||||
piCout << "[PIEthernet] Cant`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString();
|
||||
//piCoutObj << "[PIEthernet] Can`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString();
|
||||
msleep(1);
|
||||
return -1;
|
||||
}
|
||||
//piCout << "ok, write SingleTCP" << int(data) << max_size << "bytes ...";
|
||||
//piCoutObj << "ok, write SingleTCP" << int(data) << max_size << "bytes ...";
|
||||
ret = ::send(sock, (const char *)data, max_size, 0);
|
||||
//piCout << "ok, ret" << ret;
|
||||
//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());
|
||||
/*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;
|
||||
#ifdef WINDOWS
|
||||
return sendto(sock, (const char * )data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
|
||||
@@ -391,7 +404,7 @@ void PIEthernet::server_func(void * eth) {
|
||||
socklen_t slen = sizeof(client_addr);
|
||||
int s = accept(ce->sock, (sockaddr * )&client_addr, &slen);
|
||||
if (s == -1) {
|
||||
piCout << "[PIEthernet] Cant`t accept new connection, " << ethErrorString();
|
||||
if (ce->debug_) piCout << "[PIEthernet] Can`t accept new connection, " << ethErrorString();
|
||||
return;
|
||||
}
|
||||
PIString ip(inet_ntoa(client_addr.sin_addr));
|
||||
@@ -406,19 +419,60 @@ void PIEthernet::server_func(void * eth) {
|
||||
}
|
||||
|
||||
|
||||
PIStringList PIEthernet::interfaces() {
|
||||
PIEthernet::InterfaceList PIEthernet::interfaces() {
|
||||
#ifdef WINDOWS
|
||||
piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead";
|
||||
return PIStringList();
|
||||
#else
|
||||
# ifdef QNX
|
||||
PIStringList il, sl;
|
||||
/*struct if_nameindex * ni = if_nameindex();
|
||||
for (int i = 0; ; ++i) {
|
||||
if (ni[i].if_name == 0 || ni[i].if_index == 0) break;
|
||||
sl << PIString(ni[i].if_name);
|
||||
PIEthernet::InterfaceList il;
|
||||
Interface ci;
|
||||
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_freenameindex(ni);*/
|
||||
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));
|
||||
return il;
|
||||
#else
|
||||
/*# ifdef QNX
|
||||
PIStringList il, sl;
|
||||
PIProcess proc;
|
||||
proc.setGrabOutput(true);
|
||||
proc.exec(ifconfigPath.c_str(), "-l");
|
||||
@@ -436,38 +490,70 @@ PIStringList PIEthernet::interfaces() {
|
||||
for (int j = 0; j < al; ++j)
|
||||
sl << i.trimmed() + ":" + PIString::fromNumber(j);
|
||||
}
|
||||
//cout << out;
|
||||
//cout << sl << endl;
|
||||
return sl;
|
||||
# else
|
||||
PIStringList sl;
|
||||
/*struct if_nameindex * ni = if_nameindex();
|
||||
for (int i = 0; ; ++i) {
|
||||
if (ni[i].if_name == 0 || ni[i].if_index == 0) break;
|
||||
sl << PIString(ni[i].if_name);
|
||||
}
|
||||
if_freenameindex(ni);*/
|
||||
PIProcess proc;
|
||||
proc.setGrabOutput(true);
|
||||
proc.exec(ifconfigPath.c_str(), "-s");
|
||||
if (!proc.waitForFinish(1000)) return sl;
|
||||
PIString out(proc.readOutput());
|
||||
//cout << out << endl;
|
||||
out.cutLeft(out.find('\n') + 1);
|
||||
while (!out.isEmpty()) {
|
||||
sl << out.left(out.find(' '));
|
||||
out.cutLeft(out.find('\n') + 1);
|
||||
}
|
||||
//cout << sl << endl;
|
||||
return sl;
|
||||
# endif
|
||||
# endif*/
|
||||
PIEthernet::InterfaceList il;
|
||||
Interface ci;
|
||||
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();
|
||||
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));
|
||||
}
|
||||
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);
|
||||
return il;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PIString PIEthernet::interfaceAddress(const PIString & interface_) {
|
||||
#ifdef WINDOWS
|
||||
piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead";
|
||||
piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" or \"PIEthernet::interfaces\" instead";
|
||||
return PIString();
|
||||
#else
|
||||
struct ifreq ifr;
|
||||
@@ -484,7 +570,7 @@ PIString PIEthernet::interfaceAddress(const PIString & interface_) {
|
||||
|
||||
|
||||
PIStringList PIEthernet::allAddresses() {
|
||||
#ifdef WINDOWS
|
||||
/*#ifdef WINDOWS
|
||||
PIStringList al;
|
||||
PIString ca;
|
||||
PIP_ADAPTER_INFO pAdapterInfo, pAdapter = 0;
|
||||
@@ -506,10 +592,6 @@ PIStringList PIEthernet::allAddresses() {
|
||||
if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
|
||||
pAdapter = pAdapterInfo;
|
||||
while (pAdapter) {
|
||||
/*if (pAdapter->Type != MIB_IF_TYPE_ETHERNET && pAdapter->Type != MIB_IF_TYPE_LOOPBACK) {
|
||||
pAdapter = pAdapter->Next;
|
||||
continue;
|
||||
}*/
|
||||
ca = PIString(pAdapter->IpAddressList.IpAddress.String);
|
||||
if (ca != "0.0.0.0") al << ca;
|
||||
pAdapter = pAdapter->Next;
|
||||
@@ -519,10 +601,11 @@ PIStringList PIEthernet::allAddresses() {
|
||||
if (pAdapterInfo)
|
||||
HeapFree(GetProcessHeap(), 0, (pAdapterInfo));
|
||||
return al;
|
||||
#else
|
||||
PIStringList il = interfaces(), al;
|
||||
piForeachC (PIString & i, il)
|
||||
al << interfaceAddress(i);
|
||||
#else*/
|
||||
PIEthernet::InterfaceList il = interfaces();
|
||||
PIStringList al;
|
||||
piForeachC (PIEthernet::Interface & i, il)
|
||||
al << i.address;
|
||||
return al.removeStrings("0.0.0.0");
|
||||
#endif
|
||||
//#endif
|
||||
}
|
||||
|
||||
68
piethernet.h
68
piethernet.h
@@ -46,8 +46,10 @@ public:
|
||||
void setSendAddress(const PIString & ip_port) {parseAddress(ip_port, &ip_s, &port_s);}
|
||||
void setSendIP(const PIString & ip) {ip_s = ip;}
|
||||
void setSendPort(int port) {port_s = port;}
|
||||
PIString readAddress() {return path_;}
|
||||
PIString readIP() {parseAddress(path_, &ip_, &port_); return ip_;}
|
||||
int readPort() {parseAddress(path_, &ip_, &port_); return port_;}
|
||||
PIString sendAddress() {return ip_s + ":" + PIString::fromNumber(port_s);}
|
||||
PIString sendIP() {return ip_s;}
|
||||
int sendPort() {return port_s;}
|
||||
|
||||
@@ -84,14 +86,57 @@ public:
|
||||
int write(const void * data, int max_size);
|
||||
int write(const PIByteArray & data) {return write(data.data(), data.size_s());}
|
||||
|
||||
static PIStringList interfaces();
|
||||
static PIString interfaceAddress(const PIString & interface_);
|
||||
static PIStringList allAddresses();
|
||||
|
||||
EVENT1(newConnection, PIEthernet * , client)
|
||||
EVENT0(connected)
|
||||
EVENT1(disconnected, bool, withError)
|
||||
|
||||
enum InterfaceFlag {
|
||||
ifActive = 0x1,
|
||||
ifRunning = 0x2,
|
||||
ifBroadcast = 0x4,
|
||||
ifMulticast = 0x8,
|
||||
ifLoopback = 0x10,
|
||||
ifPTP = 0x20
|
||||
};
|
||||
|
||||
typedef PIFlags<InterfaceFlag> InterfaceFlags;
|
||||
|
||||
struct Interface {
|
||||
int index;
|
||||
PIString name;
|
||||
PIString mac;
|
||||
PIString address;
|
||||
PIString netmask;
|
||||
PIString broadcast;
|
||||
PIString ptp;
|
||||
InterfaceFlags flags;
|
||||
bool isActive() const {return flags[PIEthernet::ifActive];}
|
||||
bool isRunning() const {return flags[PIEthernet::ifRunning];}
|
||||
bool isBroadcast() const {return flags[PIEthernet::ifBroadcast];}
|
||||
bool isMulticast() const {return flags[PIEthernet::ifMulticast];}
|
||||
bool isLoopback() const {return flags[PIEthernet::ifLoopback];}
|
||||
bool isPTP() const {return flags[PIEthernet::ifPTP];}
|
||||
};
|
||||
|
||||
class InterfaceList: public PIVector<PIEthernet::Interface> {
|
||||
public:
|
||||
InterfaceList(): PIVector<PIEthernet::Interface>() {}
|
||||
const Interface * getByIndex(int index) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].index == index) return &((*this)[i]); return 0;}
|
||||
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;}
|
||||
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;}
|
||||
const Interface * getLoopback() const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].isLoopback()) return &((*this)[i]); return 0;}
|
||||
};
|
||||
|
||||
static InterfaceList interfaces();
|
||||
static PIString interfaceAddress(const PIString & interface_);
|
||||
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));}
|
||||
|
||||
protected:
|
||||
PIEthernet(int sock, PIString ip_port);
|
||||
|
||||
@@ -101,11 +146,12 @@ protected:
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
#ifdef WINDOWS
|
||||
void closeSocket(int & sd) {if (sd != -1) closesocket(sd); sd = -1;}
|
||||
void closeSocket(int & sd) {if (sd != -1) {shutdown(sd, SD_BOTH); closesocket(sd);} sd = -1;}
|
||||
#else
|
||||
void closeSocket(int & sd) {if (sd != -1) ::close(sd); sd = -1;}
|
||||
void closeSocket(int & sd) {if (sd != -1) {shutdown(sock, SHUT_RDWR); ::close(sd);} sd = -1;}
|
||||
static PIString getSockAddr(sockaddr * s) {return s == 0 ? PIString() : PIString(inet_ntoa(((sockaddr_in*)s)->sin_addr));}
|
||||
#endif
|
||||
void parseAddress(const PIString & ipp, PIString * ip, int * port);
|
||||
|
||||
|
||||
int sock, sock_s, port_, port_s, port_c, wrote;
|
||||
bool connected_;
|
||||
@@ -125,10 +171,10 @@ private:
|
||||
|
||||
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);
|
||||
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
|
||||
|
||||
@@ -50,6 +50,12 @@ PIEvaluatorContent::PIEvaluatorContent() {
|
||||
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);
|
||||
clearCustomVariables();
|
||||
//addVariable("n", 0.);
|
||||
//addVariable("x1", 123);
|
||||
@@ -126,6 +132,12 @@ PIEvaluatorTypes::BaseFunctions PIEvaluatorContent::getBaseFunction(const PIStri
|
||||
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;
|
||||
return PIEvaluatorTypes::bfUnknown;
|
||||
}
|
||||
|
||||
@@ -957,6 +969,24 @@ inline void PIEvaluator::execFunction(const PIEvaluatorTypes::Instruction & ci)
|
||||
case PIEvaluatorTypes::bfDeg:
|
||||
tmpvars[oi].value = value(ci.operators[0]) * complexd(rad2deg, 0.);
|
||||
break;
|
||||
case PIEvaluatorTypes::bfJ0:
|
||||
tmpvars[oi].value = j0(value(ci.operators[0]).real());
|
||||
break;
|
||||
case PIEvaluatorTypes::bfJ1:
|
||||
tmpvars[oi].value = j1(value(ci.operators[0]).real());
|
||||
break;
|
||||
case PIEvaluatorTypes::bfJN:
|
||||
tmpvars[oi].value = jn(round(value(ci.operators[1]).real()), value(ci.operators[0]).real());
|
||||
break;
|
||||
case PIEvaluatorTypes::bfY0:
|
||||
tmpvars[oi].value = y0(value(ci.operators[0]).real());
|
||||
break;
|
||||
case PIEvaluatorTypes::bfY1:
|
||||
tmpvars[oi].value = y1(value(ci.operators[0]).real());
|
||||
break;
|
||||
case PIEvaluatorTypes::bfYN:
|
||||
tmpvars[oi].value = yn(round(value(ci.operators[1]).real()), value(ci.operators[0]).real());
|
||||
break;
|
||||
case PIEvaluatorTypes::bfRandom:
|
||||
tmp = static_cast<ldouble>(rand()) / RAND_MAX;
|
||||
stmp = value(ci.operators[1]) - value(ci.operators[0]);
|
||||
|
||||
@@ -36,7 +36,8 @@ namespace PIEvaluatorTypes {
|
||||
bfSqrt, bfSqr, bfPow, bfAbs,
|
||||
bfLn, bfLg, bfLog, bfSign,
|
||||
bfIm, bfRe, bfArg, bfLen, bfConj,
|
||||
bfRad, bfDeg};
|
||||
bfRad, bfDeg, bfJ0, bfJ1, bfJN,
|
||||
bfY0, bfY1, bfYN};
|
||||
|
||||
struct Instruction {
|
||||
Instruction() {;}
|
||||
|
||||
@@ -104,7 +104,7 @@ void PIFile::resize(llong new_size, char fill_) {
|
||||
delete[] buff;
|
||||
return;
|
||||
}
|
||||
piCout << "[PIFile] Downsize is not support yet :-(";
|
||||
piCoutObj << "[PIFile] Downsize is not support yet :-(";
|
||||
}
|
||||
|
||||
|
||||
|
||||
54
pifile.h
54
pifile.h
@@ -36,7 +36,7 @@ public:
|
||||
|
||||
//PIFile & operator =(const PIFile & f) {path_ = f.path_; type_ = f.type_; return *this;}
|
||||
|
||||
void flush() {if (!opened_) fflush(fd);}
|
||||
void flush() {if (opened_) fflush(fd);}
|
||||
EVENT_HANDLER(void, clear) {close(); fd = fopen(path_.data(), "w"); if (fd != 0) fclose(fd); fd = 0; opened_ = false; open();}
|
||||
void seek(llong position) {if (!opened_) return; fseek(fd, position, SEEK_SET); clearerr(fd);}
|
||||
void seekToBegin() {if (!opened_) return; fseek(fd, 0, SEEK_SET); clearerr(fd);}
|
||||
@@ -79,34 +79,34 @@ public:
|
||||
|
||||
PIFile & operator =(const PIFile & f) {path_ = f.path_; mode_ = f.mode_; return *this;}
|
||||
|
||||
PIFile & operator <<(const char v) {if (!isWriteable()) return *this; write(&v, 1); return *this;}
|
||||
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;}
|
||||
PIFile & operator <<(const PIString & v) {if (!isWriteable()) return *this; write(v.data(), v.lengthAscii()); return *this;}
|
||||
PIFile & operator <<(const PIByteArray & v) {if (!isWriteable()) return *this; write(v.data(), v.size()); return *this;}
|
||||
PIFile & operator <<(short v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%hd", v); return *this;}
|
||||
PIFile & operator <<(int v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%d", v); return *this;}
|
||||
PIFile & operator <<(long v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%ld", v); return *this;}
|
||||
PIFile & operator <<(llong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%lld", v); return *this;}
|
||||
PIFile & operator <<(uchar v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%u", int(v)); return *this;}
|
||||
PIFile & operator <<(ushort v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%hu", v); return *this;}
|
||||
PIFile & operator <<(uint v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%u", v); return *this;}
|
||||
PIFile & operator <<(ulong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%lu", v); return *this;}
|
||||
PIFile & operator <<(ullong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%llu", v); return *this;}
|
||||
PIFile & operator <<(float v) {if (!isWriteable()) return *this; ret = fprintf(fd, ("%" + prec_str + "f").c_str(), v); return *this;}
|
||||
PIFile & operator <<(double v) {if (!isWriteable()) return *this; ret = fprintf(fd, ("%" + prec_str + "lf").c_str(), v); return *this;}
|
||||
PIFile & operator <<(const PIString & v) {if (canWrite() && fd != 0) write(v.data(), v.lengthAscii()); return *this;}
|
||||
PIFile & operator <<(const PIByteArray & v) {if (canWrite() && fd != 0) write(v.data(), v.size()); return *this;}
|
||||
PIFile & operator <<(short v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%hd", v); return *this;}
|
||||
PIFile & operator <<(int v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%d", v); return *this;}
|
||||
PIFile & operator <<(long v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%ld", v); return *this;}
|
||||
PIFile & operator <<(llong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%lld", v); return *this;}
|
||||
PIFile & operator <<(uchar v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%u", int(v)); return *this;}
|
||||
PIFile & operator <<(ushort v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%hu", v); return *this;}
|
||||
PIFile & operator <<(uint v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%u", v); return *this;}
|
||||
PIFile & operator <<(ulong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%lu", v); return *this;}
|
||||
PIFile & operator <<(ullong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%llu", v); return *this;}
|
||||
PIFile & operator <<(float v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "f").c_str(), v); return *this;}
|
||||
PIFile & operator <<(double v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "lf").c_str(), v); return *this;}
|
||||
|
||||
PIFile & operator >>(char & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%hhn", &v); return *this;}
|
||||
PIFile & operator >>(short & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%hn", &v); return *this;}
|
||||
PIFile & operator >>(int & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%n", &v); return *this;}
|
||||
PIFile & operator >>(long & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%ln", &v); return *this;}
|
||||
PIFile & operator >>(llong & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%lln", &v); return *this;}
|
||||
PIFile & operator >>(uchar & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%hhn", &v); return *this;}
|
||||
PIFile & operator >>(ushort & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%hn", &v); return *this;}
|
||||
PIFile & operator >>(uint & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%n", &v); return *this;}
|
||||
PIFile & operator >>(ulong & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%ln", &v); return *this;}
|
||||
PIFile & operator >>(ullong & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%lln", &v); return *this;}
|
||||
PIFile & operator >>(float & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%f", &v); return *this;}
|
||||
PIFile & operator >>(double & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%lf", &v); return *this;}
|
||||
PIFile & operator >>(char & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hhn", &v); return *this;}
|
||||
PIFile & operator >>(short & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hn", &v); return *this;}
|
||||
PIFile & operator >>(int & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%n", &v); return *this;}
|
||||
PIFile & operator >>(long & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%ln", &v); return *this;}
|
||||
PIFile & operator >>(llong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lln", &v); return *this;}
|
||||
PIFile & operator >>(uchar & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hhn", &v); return *this;}
|
||||
PIFile & operator >>(ushort & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hn", &v); return *this;}
|
||||
PIFile & operator >>(uint & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%n", &v); return *this;}
|
||||
PIFile & operator >>(ulong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%ln", &v); return *this;}
|
||||
PIFile & operator >>(ullong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lln", &v); return *this;}
|
||||
PIFile & operator >>(float & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%f", &v); return *this;}
|
||||
PIFile & operator >>(double & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lf", &v); return *this;}
|
||||
|
||||
static PIFile openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite) {return PIFile(PIString(tmpnam(0)), mode);}
|
||||
static bool isExists(const PIString & path);
|
||||
|
||||
153
piincludes.cpp
153
piincludes.cpp
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "piincludes.h"
|
||||
#include "pimutex.h"
|
||||
#include "piconsole.h"
|
||||
|
||||
bool isPIInit = false;
|
||||
bool piDebug = true;
|
||||
@@ -53,18 +53,167 @@ PIMutex __PICout_mutex__;
|
||||
*/
|
||||
|
||||
|
||||
PICout::PICout(PIFlags<PICoutControl> controls): fo_(true), cc_(false), co_(controls) {
|
||||
#ifdef WINDOWS
|
||||
void * PICout::hOut = 0;
|
||||
WORD PICout::dattr = 0;
|
||||
DWORD PICout::smode = 0;
|
||||
#endif
|
||||
|
||||
|
||||
PICout::PICout(PIFlags<PICoutControl> 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: std::cout << std::flush; break;
|
||||
case PICoutManipulators::Backspace:
|
||||
#ifdef WINDOWS
|
||||
GetConsoleScreenBufferInfo(hOut, &sbi);
|
||||
coord = sbi.dwCursorPosition;
|
||||
coord.X = piMax<int>(0, int(coord.X) - 1);
|
||||
SetConsoleCursorPosition(hOut, coord);
|
||||
printf(" ");
|
||||
SetConsoleCursorPosition(hOut, coord);
|
||||
#else
|
||||
printf("\e[1D \e[1D");
|
||||
#endif
|
||||
break;
|
||||
case PICoutManipulators::ShowCursor:
|
||||
#ifdef WINDOWS
|
||||
GetConsoleCursorInfo(hOut, &curinfo);
|
||||
curinfo.bVisible = true;
|
||||
SetConsoleCursorInfo(hOut, &curinfo);
|
||||
#else
|
||||
printf("\e[?25h");
|
||||
#endif
|
||||
break;
|
||||
case PICoutManipulators::HideCursor:
|
||||
#ifdef WINDOWS
|
||||
CONSOLE_CURSOR_INFO curinfo;
|
||||
GetConsoleCursorInfo(hOut, &curinfo);
|
||||
curinfo.bVisible = false;
|
||||
SetConsoleCursorInfo(hOut, &curinfo);
|
||||
#else
|
||||
printf("\e[?25l");
|
||||
#endif
|
||||
break;
|
||||
default: break;
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#define PINUMERICCOUT if (cnb_ == 10) std::cout << v; else std::cout << PIString::fromNumber(v, cnb_);
|
||||
|
||||
PICout PICout::operator <<(const uchar v) {space(); if (cnb_ == 10) std::cout << ushort(v); else std::cout << 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(); std::cout << v; return *this;}
|
||||
|
||||
PICout PICout::operator <<(const double v) {space(); std::cout << v; return *this;}
|
||||
|
||||
#undef PINUMERICCOUT
|
||||
|
||||
|
||||
void PICout::applyFormat(PICoutFormat f) {
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
/*! \mainpage Title
|
||||
* This is main page
|
||||
*/
|
||||
|
||||
214
piincludes.h
214
piincludes.h
@@ -27,7 +27,7 @@
|
||||
#define PIINCLUDES_H
|
||||
|
||||
//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
|
||||
#define PIP_VERSION 0x000304
|
||||
#define PIP_VERSION 0x000306
|
||||
|
||||
//! Major value of PIP version
|
||||
#define PIP_VERSION_MAJOR (PIP_VERSION & 0xFF0000) >> 16
|
||||
@@ -78,16 +78,16 @@
|
||||
|
||||
#endif
|
||||
|
||||
#if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__
|
||||
#if defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__WIN64__)
|
||||
# define WINDOWS
|
||||
#endif
|
||||
#if __QNX__ || __QNXNTO__
|
||||
#if defined(__QNX__) || defined(__QNXNTO__)
|
||||
# define QNX
|
||||
#endif
|
||||
#if __FreeBSD__
|
||||
#ifdef __FreeBSD__
|
||||
# define FREE_BSD
|
||||
#endif
|
||||
#if __APPLE__ || __MACH__
|
||||
#if defined(__APPLE__) || defined(__MACH__)
|
||||
# define MAC_OS
|
||||
#endif
|
||||
#ifndef WINDOWS
|
||||
@@ -99,7 +99,7 @@
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#if __GNUC__
|
||||
#ifdef __GNUC__
|
||||
# define CC_GCC
|
||||
# define CC_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__)
|
||||
# if CC_GCC_VERSION > 0x025F // > 2.95
|
||||
@@ -107,8 +107,25 @@
|
||||
# define HAS_LOCALE
|
||||
# endif
|
||||
# endif
|
||||
#elif _MSC_VER
|
||||
# pragma GCC diagnostic ignored "-Wformat"
|
||||
# pragma GCC diagnostic ignored "-Wformat-extra-args"
|
||||
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#elif defined(_MSC_VER)
|
||||
# define CC_VC
|
||||
# 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)
|
||||
#else
|
||||
# define CC_OTHER
|
||||
#endif
|
||||
@@ -168,7 +185,7 @@
|
||||
#include <set>
|
||||
#include <map>
|
||||
#ifdef WINDOWS
|
||||
typedef int socklen_t;
|
||||
typedef int socklen_t;
|
||||
# include <conio.h>
|
||||
# include <io.h>
|
||||
# include <winsock2.h>
|
||||
@@ -189,6 +206,7 @@ typedef int socklen_t;
|
||||
# include <fcntl.h>
|
||||
# include <sys/ioctl.h>
|
||||
# include <net/if.h>
|
||||
# include <ifaddrs.h>
|
||||
#endif
|
||||
#ifdef MAC_OS
|
||||
# include <mach/mach_traps.h>
|
||||
@@ -196,8 +214,8 @@ typedef int socklen_t;
|
||||
# include <mach/clock.h>
|
||||
# include <crt_externs.h>
|
||||
# define environ (*_NSGetEnviron())
|
||||
typedef long time_t;
|
||||
extern clock_serv_t __pi_mac_clock;
|
||||
typedef long time_t;
|
||||
extern clock_serv_t __pi_mac_clock;
|
||||
#endif
|
||||
#ifndef QNX
|
||||
# ifndef WINDOWS
|
||||
@@ -212,7 +230,7 @@ extern clock_serv_t __pi_mac_clock;
|
||||
# define PIP_TIMER_RT
|
||||
#endif
|
||||
#ifdef FREE_BSD
|
||||
extern char ** environ;
|
||||
extern char ** environ;
|
||||
#endif
|
||||
#include "pimonitor.h"
|
||||
|
||||
@@ -405,7 +423,7 @@ template<typename T> inline T piClamp(const T & v, const T & min, const T & max)
|
||||
extern bool isPIInit;
|
||||
|
||||
//! global variable enabling output to piCout
|
||||
extern bool piDebug;
|
||||
extern PIP_EXPORT bool piDebug;
|
||||
|
||||
extern string ifconfigPath;
|
||||
|
||||
@@ -656,6 +674,9 @@ private:
|
||||
//! Macro used for conditional (piDebug) output to PICout
|
||||
#define piCout if (piDebug) PICout()
|
||||
|
||||
//! Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject
|
||||
#define piCoutObj if (piDebug && debug_) PICout()
|
||||
|
||||
class PIMutex;
|
||||
extern PIMutex __PICout_mutex__;
|
||||
|
||||
@@ -664,25 +685,58 @@ 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, '"' */
|
||||
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 */
|
||||
Flush /*! Flush the output */,
|
||||
Backspace /*! Remove last symbol */,
|
||||
ShowCursor /*! Show cursor */,
|
||||
HideCursor /*! Hide cursor */
|
||||
};
|
||||
|
||||
//! \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
|
||||
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,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -695,7 +749,7 @@ public:
|
||||
//! Default constructor with default features
|
||||
PICout(PIFlags<PICoutControl> controls = AddSpaces | AddNewLine);
|
||||
|
||||
PICout(const PICout & other): fo_(other.fo_), cc_(true), co_(other.co_) {;}
|
||||
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 <tt>"const char * "</tt> type
|
||||
@@ -711,89 +765,141 @@ public:
|
||||
PICout operator <<(const char v) {space(); std::cout << v; return *this;}
|
||||
|
||||
//! Output operator for <tt>"unsigned char"</tt> values
|
||||
PICout operator <<(const uchar v) {space(); std::cout << ushort(v); return *this;}
|
||||
PICout operator <<(const uchar v);
|
||||
|
||||
//! Output operator for <tt>"short"</tt> values
|
||||
PICout operator <<(const short v) {space(); std::cout << v; return *this;}
|
||||
PICout operator <<(const short v);
|
||||
|
||||
//! Output operator for <tt>"unsigned short"</tt> values
|
||||
PICout operator <<(const ushort v) {space(); std::cout << v; return *this;}
|
||||
PICout operator <<(const ushort v);
|
||||
|
||||
//! Output operator for <tt>"int"</tt> values
|
||||
PICout operator <<(const int v) {space(); std::cout << v; return *this;}
|
||||
PICout operator <<(const int v);
|
||||
|
||||
//! Output operator for <tt>"unsigned int"</tt> values
|
||||
PICout operator <<(const uint v) {space(); std::cout << v; return *this;}
|
||||
PICout operator <<(const uint v);
|
||||
|
||||
//! Output operator for <tt>"long"</tt> values
|
||||
PICout operator <<(const long v) {space(); std::cout << v; return *this;}
|
||||
PICout operator <<(const long v);
|
||||
|
||||
//! Output operator for <tt>"unsigned long"</tt> values
|
||||
PICout operator <<(const ulong v) {space(); std::cout << v; return *this;}
|
||||
PICout operator <<(const ulong v);
|
||||
|
||||
//! Output operator for <tt>"long long"</tt> values
|
||||
PICout operator <<(const llong v) {space(); std::cout << v; return *this;}
|
||||
PICout operator <<(const llong v);
|
||||
|
||||
//! Output operator for <tt>"unsigned long long"</tt> values
|
||||
PICout operator <<(const ullong v) {space(); std::cout << v; return *this;}
|
||||
PICout operator <<(const ullong v);
|
||||
|
||||
//! Output operator for <tt>"float"</tt> values
|
||||
PICout operator <<(const float v) {space(); std::cout << v; return *this;}
|
||||
PICout operator <<(const float v);
|
||||
|
||||
//! Output operator for <tt>"double"</tt> values
|
||||
PICout operator <<(const double v) {space(); std::cout << v; return *this;}
|
||||
PICout operator <<(const double v);
|
||||
|
||||
//! Output operator for \a PICoutSpecialChar values
|
||||
PICout operator <<(const PICoutSpecialChar v) {
|
||||
switch (v) {
|
||||
case Null: std::cout << char(0);
|
||||
case NewLine: std::cout << '\n';
|
||||
case Tab: std::cout << '\t';
|
||||
case Esc: std::cout << '\e';
|
||||
case Quote: std::cout << '"';
|
||||
case Null: std::cout << char(0); break;
|
||||
case NewLine: std::cout << '\n'; fo_ = true; break;
|
||||
case Tab: std::cout << '\t'; break;
|
||||
case Esc:
|
||||
#ifdef CC_VC
|
||||
std::cout << char(27);
|
||||
#else
|
||||
std::cout << '\e';
|
||||
#endif
|
||||
break;
|
||||
case Quote: std::cout << '"'; break;
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Output operator for \a PIFlags<PICoutFormat> values
|
||||
PICout operator <<(const PIFlags<PICoutFormat> 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) {
|
||||
switch (v) {
|
||||
case Flush: std::cout << std::flush;
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
PICout operator <<(const PICoutAction v);
|
||||
|
||||
//! Set control flag "c" is "on" state
|
||||
void setControl(PICoutControl c, bool on = true) {co_.setFlag(c, on);}
|
||||
PICout & setControl(PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;}
|
||||
|
||||
//! Set control flags "c" and if "save" exec \a saveControl()
|
||||
void setControl(PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c;}
|
||||
PICout & setControl(PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c; return *this;}
|
||||
|
||||
//! Save control flags to internal stack \sa \a restoreControl()
|
||||
void saveControl() {cos_.push(co_);}
|
||||
PICout & saveControl() {cos_.push(co_); return *this;}
|
||||
|
||||
//! Restore control flags from internal stack \sa \a saveControl()
|
||||
void restoreControl() {if (!cos_.empty()) {co_ = cos_.top(); cos_.pop();}}
|
||||
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() */
|
||||
inline void space() {if (!fo_ && co_[AddSpaces]) std::cout << ' '; fo_ = false;}
|
||||
inline PICout & space() {if (!fo_ && co_[AddSpaces]) std::cout << ' '; fo_ = false; return *this;}
|
||||
|
||||
/*! \brief Conditional put quote character to output
|
||||
* \details If control \a AddQuotes is set
|
||||
* quote character is put \sa \a space(), \a newLine() */
|
||||
inline void quote() {if (co_[AddQuotes]) std::cout << '"'; fo_ = false;}
|
||||
inline PICout & quote() {if (co_[AddQuotes]) std::cout << '"'; fo_ = false; return *this;}
|
||||
|
||||
/*! \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() */
|
||||
inline void newLine() {if (co_[AddNewLine]) std::cout << std::endl; fo_ = false;}
|
||||
inline PICout & newLine() {if (co_[AddNewLine]) std::cout << std::endl; fo_ = false; return *this;}
|
||||
|
||||
private:
|
||||
bool fo_, cc_;
|
||||
void applyFormat(PICoutFormat f);
|
||||
|
||||
bool fo_, cc_, fc_;
|
||||
int cnb_, attr_;
|
||||
PICoutControls co_;
|
||||
std::stack<PICoutControls> cos_;
|
||||
#ifdef WINDOWS
|
||||
static void * hOut;
|
||||
static WORD dattr;
|
||||
static DWORD smode;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // PIINCLUDES_H
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* \brief Base class for input/output classes
|
||||
*
|
||||
* \section PIIODevice_sec0 Synopsis
|
||||
* This class provide open/close logic, threaded read and virtual input/output
|
||||
* 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.
|
||||
*
|
||||
@@ -41,13 +41,20 @@
|
||||
* bool func_name(void * Threaded_read_data, uchar * readed_data, int readed_size)\n
|
||||
* Threaded read starts with function \a startThreadedRead().
|
||||
*
|
||||
* \section PIIODevice_sec3 Internal buffer
|
||||
* \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_sec4 Reopen
|
||||
* \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(),
|
||||
@@ -58,11 +65,10 @@
|
||||
*/
|
||||
|
||||
|
||||
//! Constructs a empty PIIODevice
|
||||
PIIODevice::PIIODevice(): PIThread() {
|
||||
mode_ = ReadOnly;
|
||||
opened_ = init_ = thread_started_ = false;
|
||||
reopen_enabled_ = true;
|
||||
reopen_enabled_ = raise_threaded_read_ = true;
|
||||
reopen_timeout_ = 1000;
|
||||
ret_func_ = 0;
|
||||
ret_data_ = 0;
|
||||
@@ -82,7 +88,7 @@ PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode type, bool
|
||||
path_ = path;
|
||||
mode_ = type;
|
||||
opened_ = init_ = thread_started_ = false;
|
||||
reopen_enabled_ = true;
|
||||
reopen_enabled_ = raise_threaded_read_ = true;
|
||||
reopen_timeout_ = 1000;
|
||||
ret_func_ = 0;
|
||||
ret_data_ = 0;
|
||||
@@ -150,7 +156,7 @@ void PIIODevice::begin() {
|
||||
void PIIODevice::run() {
|
||||
if (!isReadable()) {
|
||||
//cout << "not readable\n";
|
||||
stop();
|
||||
PIThread::stop();
|
||||
return;
|
||||
}
|
||||
if (!thread_started_) {
|
||||
@@ -165,7 +171,7 @@ void PIIODevice::run() {
|
||||
return;
|
||||
}
|
||||
threadedRead(buffer_tr.data(), readed_);
|
||||
threadedReadEvent(buffer_tr.data(), readed_);
|
||||
if (raise_threaded_read_) threadedReadEvent(buffer_tr.data(), readed_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
117
piiodevice.h
117
piiodevice.h
@@ -28,23 +28,13 @@
|
||||
// function executed from threaded read, pass ThreadedReadData, readedData, sizeOfData
|
||||
typedef bool (*ReadRetFunc)(void * , uchar * , int );
|
||||
|
||||
// events:
|
||||
// void opened()
|
||||
// void closed()
|
||||
//
|
||||
// handlers:
|
||||
// bool open()
|
||||
// bool open(const PIString & path)
|
||||
// bool open(const DeviceMode & type)
|
||||
// bool open(const PIString & path, const DeviceMode & type)
|
||||
// bool close()
|
||||
// bool initialize()
|
||||
// void flush()
|
||||
|
||||
class PIP_EXPORT PIIODevice: public PIThread
|
||||
{
|
||||
PIOBJECT(PIIODevice)
|
||||
public:
|
||||
|
||||
//! Constructs a empty PIIODevice
|
||||
PIIODevice();
|
||||
|
||||
//! \brief Open modes for PIIODevice
|
||||
@@ -55,7 +45,7 @@ public:
|
||||
};
|
||||
|
||||
PIIODevice(const PIString & path, DeviceMode type = ReadWrite, bool initNow = true);
|
||||
virtual ~PIIODevice() {stop(); write_thread.stop(); if (opened_) {closeDevice(); if (!opened_) closed();}}
|
||||
virtual ~PIIODevice() {stop(); if (opened_) {closeDevice(); if (!opened_) closed();}}
|
||||
|
||||
//! Current open mode of device
|
||||
DeviceMode mode() const {return mode_;}
|
||||
@@ -63,67 +53,119 @@ public:
|
||||
//! Current path of device
|
||||
PIString path() const {return path_;}
|
||||
|
||||
//! return \b true if mode is ReadOnly or ReadWrite
|
||||
//! Set path of device
|
||||
void setPath(const PIString & path) {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
|
||||
//! 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
|
||||
//! Return \b true if device is successfully opened
|
||||
bool isOpened() const {return opened_;}
|
||||
|
||||
//! return \b true if device is closed
|
||||
//! Return \b true if device is closed
|
||||
bool isClosed() const {return !opened_;}
|
||||
|
||||
//! return \b true if device can read \b now
|
||||
//! 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
|
||||
//! Return \b true if device can write \b now
|
||||
bool canWrite() const {return opened_ && (mode_ & WriteOnly);}
|
||||
|
||||
|
||||
// Enable timer to periodically open device until it will be opened
|
||||
//! Set execution of \a open enabled while threaded read on closed device
|
||||
void setReopenEnabled(bool yes = true) {reopen_enabled_ = yes;}
|
||||
|
||||
//! Set timeout in milliseconds between \a open tryings if reopen is enabled
|
||||
void setReopenTimeout(int msecs = 1000) {reopen_timeout_ = msecs;}
|
||||
|
||||
|
||||
//! Return reopen enable
|
||||
bool isReopenEnabled() const {return reopen_enabled_;}
|
||||
|
||||
//! Return reopen timeout
|
||||
int reopenTimeout() {return reopen_timeout_;}
|
||||
|
||||
|
||||
// set return function executed when successful read in thread
|
||||
/** \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 \b true if threaded read is started
|
||||
bool isThreadedRead() const {return isRunning();}
|
||||
void startThreadedRead() {if (!isRunning()) start();}
|
||||
void startThreadedRead(ReadRetFunc func) {ret_func_ = func; if (!isRunning()) start();}
|
||||
|
||||
//! 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::stop();}
|
||||
|
||||
|
||||
//! 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.stop();}
|
||||
|
||||
//! Clear threaded write task queue
|
||||
void clearThreadedWriteQueue() {write_thread.lock(); write_queue.clear(); write_thread.unlock();}
|
||||
|
||||
|
||||
// Read from device to "read_to" maximum "max_size" bytes, return readed bytes count
|
||||
virtual int read(void * read_to, int max_size) {piCout << "[PIIODevice] \"read\" not implemented!"; return -2;}
|
||||
//! Start both threaded read and threaded write
|
||||
void start() {startThreadedRead(); startThreadedWrite();}
|
||||
|
||||
// Write to device "data" maximum "max_size" bytes, return written bytes count
|
||||
virtual int write(const void * data, int max_size) {piCout << "[PIIODevice] \"write\" not implemented!"; return -2;}
|
||||
//! 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);}
|
||||
|
||||
// Read from device maximum "max_size" bytes and return them as PIByteArray
|
||||
|
||||
//! Reimplement this function to read from your device
|
||||
virtual int read(void * read_to, int max_size) {piCoutObj << "[PIIODevice] \"read\" not implemented!"; return -2;}
|
||||
|
||||
//! Reimplement this function to write to your device
|
||||
virtual int write(const void * data, int max_size) {piCoutObj << "[PIIODevice] \"write\" 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);}
|
||||
|
||||
//! Write to device "data"
|
||||
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);
|
||||
|
||||
|
||||
EVENT_HANDLER(bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
|
||||
EVENT_HANDLER1(bool, open, const PIString &, _path) {path_ = _path; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
|
||||
EVENT_HANDLER1(bool, open, const DeviceMode &, _type) {mode_ = _type; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
|
||||
@@ -153,6 +195,12 @@ public:
|
||||
//! \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
|
||||
//! \{
|
||||
@@ -174,19 +222,22 @@ public:
|
||||
//! \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 queue item with id "id"
|
||||
//! \brief Raise if write thread succesfull write some data of task with ID "id"
|
||||
|
||||
//! \}
|
||||
|
||||
protected:
|
||||
// Function executed before first openDevice() or from constructor
|
||||
|
||||
//! Function executed before first \a openDevice() or from constructor
|
||||
virtual bool init() {return true;}
|
||||
|
||||
// Functions to open and close device, return value will set to "opened_" variable
|
||||
//! 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_"
|
||||
//! 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;}
|
||||
|
||||
void terminate();
|
||||
@@ -194,7 +245,7 @@ protected:
|
||||
PIString path_;
|
||||
DeviceMode mode_;
|
||||
ReadRetFunc ret_func_;
|
||||
bool init_, opened_, thread_started_, reopen_enabled_;
|
||||
bool init_, opened_, thread_started_, reopen_enabled_, raise_threaded_read_;
|
||||
int reopen_timeout_;
|
||||
void * ret_data_;
|
||||
|
||||
|
||||
@@ -64,13 +64,15 @@ void PIKbdListener::run() {
|
||||
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 = ker.uChar.AsciiChar; break;
|
||||
default: ret = 1; lc = (shift ? char(toupper(ker.uChar.AsciiChar)) : ker.uChar.AsciiChar); break;
|
||||
}
|
||||
if (lc == 0) return;
|
||||
} else return;
|
||||
|
||||
596
pimath.cpp
596
pimath.cpp
@@ -20,6 +20,443 @@
|
||||
#include "pimath.h"
|
||||
|
||||
|
||||
#ifndef PIP_MATH_J0
|
||||
double j0(const double & v) {
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef PIP_MATH_J1
|
||||
double j1(const double & v) {
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef PIP_MATH_JN
|
||||
double jn(const int & n, const double & v) {
|
||||
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 * j0(x);
|
||||
return result;
|
||||
}
|
||||
if (n == 1) {
|
||||
result = sg * j1(x);
|
||||
return result;
|
||||
}
|
||||
if (n == 2) {
|
||||
if (x == 0)
|
||||
result = 0;
|
||||
else
|
||||
result = sg * (2.0 * j1(x) / x - j0(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 = j1(x) / pk;
|
||||
else
|
||||
ans = j0(x) / pkm1;
|
||||
result = sg * ans;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef PIP_MATH_Y0
|
||||
double y0(const double & v) {
|
||||
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 * j0(x) * log(x);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef PIP_MATH_Y1
|
||||
double y1(const double & v) {
|
||||
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 * (j1(x) * log(x) - 1 / x);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef PIP_MATH_YN
|
||||
double yn(const int & n, const double & v) {
|
||||
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 = y0(x);
|
||||
return result;
|
||||
}
|
||||
if (n == 1) {
|
||||
result = s * y1(x);
|
||||
return result;
|
||||
}
|
||||
a = y0(x);
|
||||
b = y1(x);
|
||||
for (i = 1; i <= n - 1; i++) {
|
||||
tmp = b;
|
||||
b = 2 * i / x * b - a;
|
||||
a = tmp;
|
||||
}
|
||||
result = s * b;
|
||||
return result;
|
||||
}
|
||||
#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\
|
||||
@@ -70,7 +507,7 @@ void Solver::fromTF(const TransferFunction & TF) {
|
||||
if (TF.vector_An.size() >= TF.vector_Bm.size())
|
||||
size = TF.vector_An.size()-1;
|
||||
else {
|
||||
cout << "Solver error: {A} should be greater than {B}" << endl;
|
||||
piCout << "Solver error: {A} should be greater than {B}";
|
||||
return;
|
||||
}
|
||||
if (size == 0) return;
|
||||
@@ -327,7 +764,7 @@ void PIFFT::fftc1d(const PIVector<complexd> &a, uint n) {
|
||||
|
||||
void PIFFT::fftc1r(const PIVector<double> & a, uint n) {
|
||||
uint i;
|
||||
if( n%2==0 ) {
|
||||
if( n%2==0) {
|
||||
PIVector<double> buf;
|
||||
uint n2 = n/2;
|
||||
//buf.resize(n);
|
||||
@@ -455,14 +892,14 @@ void PIFFT::ftbase_ftbasegenerateplanrec(
|
||||
int ftbase_fftcodeletplan = 2;
|
||||
int ftbase_fftrealcooleytukeyplan = 5;
|
||||
int ftbase_fftemptyplan = 6;
|
||||
if( *plansize+ftbase_ftbaseplanentrysize>(*planarraysize) ) {
|
||||
if( *plansize+ftbase_ftbaseplanentrysize>(*planarraysize)) {
|
||||
curplan.plan.resize(8*(*planarraysize));
|
||||
*planarraysize = 8*(*planarraysize);
|
||||
}
|
||||
entryoffset = *plansize;
|
||||
esize = ftbase_ftbaseplanentrysize;
|
||||
*plansize = *plansize+esize;
|
||||
if( n==1 ) {
|
||||
if( n==1) {
|
||||
curplan.plan[entryoffset+0] = esize;
|
||||
curplan.plan[entryoffset+1] = -1;
|
||||
curplan.plan[entryoffset+2] = -1;
|
||||
@@ -474,12 +911,12 @@ void PIFFT::ftbase_ftbasegenerateplanrec(
|
||||
return;
|
||||
}
|
||||
ftbasefactorize(n, &n1, &n2);
|
||||
if( n1!=1 ) {
|
||||
if( n1!=1) {
|
||||
*tmpmemsize = piMax<int>(*tmpmemsize, 2*n1*n2);
|
||||
curplan.plan[entryoffset+0] = esize;
|
||||
curplan.plan[entryoffset+1] = n1;
|
||||
curplan.plan[entryoffset+2] = n2;
|
||||
if( tasktype==ftbase_ftbasecffttask )
|
||||
if( tasktype==ftbase_ftbasecffttask)
|
||||
curplan.plan[entryoffset+3] = ftbase_fftcooleytukeyplan;
|
||||
else
|
||||
curplan.plan[entryoffset+3] = ftbase_fftrealcooleytukeyplan;
|
||||
@@ -501,9 +938,9 @@ void PIFFT::ftbase_ftbasegenerateplanrec(
|
||||
curplan.plan[entryoffset+5] = -1;
|
||||
curplan.plan[entryoffset+6] = -1;
|
||||
curplan.plan[entryoffset+7] = *precomputedsize;
|
||||
if( n==3 )
|
||||
if( n==3)
|
||||
*precomputedsize = *precomputedsize+2;
|
||||
if( n==5 )
|
||||
if( n==5)
|
||||
*precomputedsize = *precomputedsize+5;
|
||||
return;
|
||||
} else {
|
||||
@@ -547,22 +984,22 @@ void PIFFT::ftbase_ftbaseprecomputeplanrec(ftplan* plan,
|
||||
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 ) {
|
||||
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 ) {
|
||||
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 ) {
|
||||
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 ) {
|
||||
if( n==5) {
|
||||
offs = curplan.plan[entryoffset+7];
|
||||
v = 2*M_PI/5;
|
||||
curplan.precomputed[offs+0] = (cos(v)+cos(2*v))/2-1;
|
||||
@@ -573,7 +1010,7 @@ void PIFFT::ftbase_ftbaseprecomputeplanrec(ftplan* plan,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fftbluesteinplan ) {
|
||||
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];
|
||||
@@ -587,7 +1024,7 @@ void PIFFT::ftbase_ftbaseprecomputeplanrec(ftplan* plan,
|
||||
curplan.precomputed[offs+2*i+1] = by;
|
||||
curplan.precomputed[offs+2*m+2*i+0] = bx;
|
||||
curplan.precomputed[offs+2*m+2*i+1] = by;
|
||||
if( i>0 ) {
|
||||
if( i>0) {
|
||||
curplan.precomputed[offs+2*(m-i)+0] = bx;
|
||||
curplan.precomputed[offs+2*(m-i)+1] = by;
|
||||
}
|
||||
@@ -601,29 +1038,29 @@ void PIFFT::ftbase_ftbaseprecomputeplanrec(ftplan* plan,
|
||||
void PIFFT::ftbasefactorize(int n, int* n1, int* n2) {
|
||||
*n1 = *n2 = 0;
|
||||
int ftbase_ftbasecodeletrecommended = 5;
|
||||
if( (*n1)*(*n2)!=n ) {
|
||||
if( (*n1)*(*n2)!=n) {
|
||||
for(int j=ftbase_ftbasecodeletrecommended; j>=2; j--) {
|
||||
if( n%j==0 ) {
|
||||
if( n%j==0) {
|
||||
*n1 = j;
|
||||
*n2 = n/j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( (*n1)*(*n2)!=n ) {
|
||||
if( (*n1)*(*n2)!=n) {
|
||||
for(int j=ftbase_ftbasecodeletrecommended+1; j<=n-1; j++) {
|
||||
if( n%j==0 ) {
|
||||
if( n%j==0) {
|
||||
*n1 = j;
|
||||
*n2 = n/j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( (*n1)*(*n2)!=n ) {
|
||||
if( (*n1)*(*n2)!=n) {
|
||||
*n1 = 1;
|
||||
*n2 = n;
|
||||
}
|
||||
if( (*n2)==1 && (*n1)!=1 ) {
|
||||
if( (*n2)==1 && (*n1)!=1) {
|
||||
*n2 = *n1;
|
||||
*n1 = 1;
|
||||
}
|
||||
@@ -637,15 +1074,15 @@ Is number smooth?
|
||||
Copyright 01.05.2009 by Bochkanov Sergey
|
||||
*************************************************************************/
|
||||
void PIFFT::ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int* best) {
|
||||
if( seed>=n ) {
|
||||
if( seed>=n) {
|
||||
*best = piMin<int>(*best, seed);
|
||||
return;
|
||||
}
|
||||
if( leastfactor<=2 )
|
||||
if( leastfactor<=2)
|
||||
ftbase_ftbasefindsmoothrec(n, seed*2, 2, best);
|
||||
if( leastfactor<=3 )
|
||||
if( leastfactor<=3)
|
||||
ftbase_ftbasefindsmoothrec(n, seed*3, 3, best);
|
||||
if( leastfactor<=5 )
|
||||
if( leastfactor<=5)
|
||||
ftbase_ftbasefindsmoothrec(n, seed*5, 5, best);
|
||||
}
|
||||
|
||||
@@ -670,9 +1107,9 @@ void PIFFT::ftbase_internalreallintranspose(PIVector<double>* a, int m, int n, i
|
||||
void PIFFT::ftbase_fftirltrec(PIVector<double>* a, int astart, int astride, PIVector<double>* b, int bstart, int bstride, int m, int n) {
|
||||
int idx1, idx2;
|
||||
int m1, n1;
|
||||
if( m==0||n==0 )
|
||||
if( m==0||n==0)
|
||||
return;
|
||||
if( piMax<int>(m, n)<=8 ) {
|
||||
if( piMax<int>(m, n)<=8) {
|
||||
for(int i=0; i<=m-1; i++) {
|
||||
idx1 = bstart+i;
|
||||
idx2 = astart+i*astride;
|
||||
@@ -684,15 +1121,15 @@ void PIFFT::ftbase_fftirltrec(PIVector<double>* a, int astart, int astride, PIVe
|
||||
}
|
||||
return;
|
||||
}
|
||||
if( n>m ) {
|
||||
if( n>m) {
|
||||
n1 = n/2;
|
||||
if( n-n1>=8&&n1%8!=0 )
|
||||
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 )
|
||||
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);
|
||||
@@ -709,9 +1146,9 @@ void PIFFT::ftbase_internalcomplexlintranspose(PIVector<double>* a, int m, int n
|
||||
|
||||
void PIFFT::ftbase_ffticltrec(PIVector<double>* a, int astart, int astride, PIVector<double>* b, int bstart, int bstride, int m, int n) {
|
||||
int idx1, idx2, m2, m1, n1;
|
||||
if( m==0||n==0 )
|
||||
if( m==0||n==0)
|
||||
return;
|
||||
if( piMax<int>(m, n)<=8 ) {
|
||||
if( piMax<int>(m, n)<=8) {
|
||||
m2 = 2*bstride;
|
||||
for(int i=0; i<=m-1; i++) {
|
||||
idx1 = bstart+2*i;
|
||||
@@ -725,15 +1162,15 @@ void PIFFT::ftbase_ffticltrec(PIVector<double>* a, int astart, int astride, PIVe
|
||||
}
|
||||
return;
|
||||
}
|
||||
if( n>m ) {
|
||||
if( n>m) {
|
||||
n1 = n/2;
|
||||
if( n-n1>=8&&n1%8!=0 )
|
||||
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 )
|
||||
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);
|
||||
@@ -775,9 +1212,9 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
int ftbase_fftemptyplan = 6;
|
||||
PIVector<double> & tmpb(curplan.tmpbuf);
|
||||
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fftemptyplan )
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fftemptyplan)
|
||||
return;
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fftcooleytukeyplan ) {
|
||||
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));
|
||||
@@ -790,7 +1227,7 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf));
|
||||
return;
|
||||
}
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fftrealcooleytukeyplan ) {
|
||||
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));
|
||||
@@ -817,7 +1254,7 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
}
|
||||
for (int i=0; i<2*n2*2; i++) (*a)[offs+i] = tmpb[i];
|
||||
}
|
||||
if( n1%2!=0 )
|
||||
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));
|
||||
@@ -826,7 +1263,7 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf));
|
||||
return;
|
||||
}
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fhtcooleytukeyplan ) {
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fhtcooleytukeyplan) {
|
||||
n1 = curplan.plan[entryoffset+1];
|
||||
n2 = curplan.plan[entryoffset+2];
|
||||
n = n1*n2;
|
||||
@@ -846,7 +1283,7 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
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 ) {
|
||||
if( n2%2==0) {
|
||||
offs = 2*(n2/2)*n1;
|
||||
offsa = aoffset+n2/2*n1;
|
||||
for(int j=0; j<=n1-1; j++)
|
||||
@@ -868,11 +1305,11 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
ftbase_internalreallintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf));
|
||||
return;
|
||||
}
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fftcodeletplan ) {
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fftcodeletplan) {
|
||||
n1 = curplan.plan[entryoffset+1];
|
||||
n2 = curplan.plan[entryoffset+2];
|
||||
n = n1*n2;
|
||||
if( n==2 ) {
|
||||
if( n==2) {
|
||||
a0x = (*a)[aoffset+0];
|
||||
a0y = (*a)[aoffset+1];
|
||||
a1x = (*a)[aoffset+2];
|
||||
@@ -887,7 +1324,7 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
(*a)[aoffset+3] = v3;
|
||||
return;
|
||||
}
|
||||
if( n==3 ) {
|
||||
if( n==3) {
|
||||
offs = curplan.plan[entryoffset+7];
|
||||
c1 = curplan.precomputed[offs+0];
|
||||
c2 = curplan.precomputed[offs+1];
|
||||
@@ -919,7 +1356,7 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
(*a)[aoffset+5] = a2y;
|
||||
return;
|
||||
}
|
||||
if( n==4 ) {
|
||||
if( n==4) {
|
||||
a0x = (*a)[aoffset+0];
|
||||
a0y = (*a)[aoffset+1];
|
||||
a1x = (*a)[aoffset+2];
|
||||
@@ -946,7 +1383,7 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
(*a)[aoffset+7] = m2y-m3y;
|
||||
return;
|
||||
}
|
||||
if( n==5 ) {
|
||||
if( n==5) {
|
||||
offs = curplan.plan[entryoffset+7];
|
||||
c1 = curplan.precomputed[offs+0];
|
||||
c2 = curplan.precomputed[offs+1];
|
||||
@@ -996,18 +1433,18 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fhtcodeletplan ) {
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fhtcodeletplan) {
|
||||
n1 = curplan.plan[entryoffset+1];
|
||||
n2 = curplan.plan[entryoffset+2];
|
||||
n = n1*n2;
|
||||
if( n==2 ) {
|
||||
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 ) {
|
||||
if( n==3) {
|
||||
offs = curplan.plan[entryoffset+7];
|
||||
c1 = curplan.precomputed[offs+0];
|
||||
c2 = curplan.precomputed[offs+1];
|
||||
@@ -1024,7 +1461,7 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
(*a)[aoffset+2] = s1x+m2y;
|
||||
return;
|
||||
}
|
||||
if( n==4 ) {
|
||||
if( n==4) {
|
||||
a0x = (*a)[aoffset+0];
|
||||
a1x = (*a)[aoffset+1];
|
||||
a2x = (*a)[aoffset+2];
|
||||
@@ -1039,7 +1476,7 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
(*a)[aoffset+3] = m2x+m3y;
|
||||
return;
|
||||
}
|
||||
if( n==5 ) {
|
||||
if( n==5) {
|
||||
offs = curplan.plan[entryoffset+7];
|
||||
c1 = curplan.precomputed[offs+0];
|
||||
c2 = curplan.precomputed[offs+1];
|
||||
@@ -1067,7 +1504,7 @@ void PIFFT::ftbaseexecuteplanrec(PIVector<double>* a, int aoffset, ftplan* plan,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fftbluesteinplan ) {
|
||||
if( curplan.plan[entryoffset+3]==ftbase_fftbluesteinplan) {
|
||||
n = curplan.plan[entryoffset+1];
|
||||
m = curplan.plan[entryoffset+4];
|
||||
offs = curplan.plan[entryoffset+7];
|
||||
@@ -1148,8 +1585,8 @@ void PIFFT::ftbase_ffttwcalc(PIVector<double> * a, int aoffset, int n1, int n2)
|
||||
tmpy = x*twy+y*twxm1;
|
||||
(*a)[offs+0] = x+tmpx;
|
||||
(*a)[offs+1] = y+tmpy;
|
||||
if( j<n1-1 ) {
|
||||
if( j%ftbase_ftbaseupdatetw==0 ) {
|
||||
if( j<n1-1) {
|
||||
if( j%ftbase_ftbaseupdatetw==0) {
|
||||
v = -2*M_PI*i*(j+1)/n;
|
||||
twxm1 = -2*sqr(sin(0.5*v));
|
||||
twy = sin(v);
|
||||
@@ -1162,8 +1599,8 @@ void PIFFT::ftbase_ffttwcalc(PIVector<double> * a, int aoffset, int n1, int n2)
|
||||
}
|
||||
}
|
||||
|
||||
if( i<n2-1 ) {
|
||||
if( j%ftbase_ftbaseupdatetw==0 ) {
|
||||
if( i<n2-1) {
|
||||
if( j%ftbase_ftbaseupdatetw==0) {
|
||||
v = -2*M_PI*(i+1)/n;
|
||||
twrowxm1 = -2*sqr(sin(0.5*v));
|
||||
twrowy = sin(v);
|
||||
@@ -1176,52 +1613,3 @@ void PIFFT::ftbase_ffttwcalc(PIVector<double> * a, int aoffset, int n1, int n2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PIStatistic::PIStatistic() {
|
||||
mean = 0.;
|
||||
variance = 0.;
|
||||
skewness = 0.;
|
||||
kurtosis = 0.;
|
||||
}
|
||||
|
||||
|
||||
bool PIStatistic::calculate(const PIVector<double> & val) {
|
||||
double v = 0., v1 = 0., v2 = 0., stddev = 0.;
|
||||
int i, n = val.size();
|
||||
if (n < 2)
|
||||
return false;
|
||||
/*
|
||||
* Mean
|
||||
*/
|
||||
for (i = 0; i < n; i++)
|
||||
mean += val[i];
|
||||
mean /= n;
|
||||
/*
|
||||
* 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 - v2) / (n - 1);
|
||||
if(variance < 0)
|
||||
variance = 0.;
|
||||
stddev = sqrt(variance);
|
||||
/*
|
||||
* Skewness and kurtosis
|
||||
*/
|
||||
if (stddev != 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
195
pimath.h
195
pimath.h
@@ -35,6 +35,18 @@
|
||||
#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
|
||||
@@ -53,6 +65,12 @@
|
||||
#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;
|
||||
|
||||
@@ -70,7 +88,12 @@ const complexd complexd_1(1.);
|
||||
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<double>(c.real()), piRound<double>(c.imag()));}
|
||||
@@ -79,23 +102,42 @@ inline complexd ceil(const complexd & c) {return complexd(ceil(c.real()), ceil(c
|
||||
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));}
|
||||
#if CC_GCC_VERSION <= 0x025F
|
||||
#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;}
|
||||
inline double j0(const double & v) {return v;}
|
||||
inline double j1(const double & v) {v;}
|
||||
inline double jn(const int & n, const double & v) {return v;}
|
||||
inline double y0(const double & v) {return v;}
|
||||
inline double y1(const double & v) {return v;}
|
||||
inline double yn(const int & n, const double & v) {return v;}
|
||||
# endif
|
||||
#endif
|
||||
#ifndef PIP_MATH_J0
|
||||
__attribute__ ((unused)) static double j0(const double & v);
|
||||
#endif
|
||||
#ifndef PIP_MATH_J1
|
||||
__attribute__ ((unused)) static double j1(const double & v);
|
||||
#endif
|
||||
#ifndef PIP_MATH_JN
|
||||
__attribute__ ((unused)) static double jn(const int & n, const double & v);
|
||||
#endif
|
||||
#ifndef PIP_MATH_Y0
|
||||
__attribute__ ((unused)) static double y0(const double & v);
|
||||
#endif
|
||||
#ifndef PIP_MATH_Y1
|
||||
__attribute__ ((unused)) static double y1(const double & v);
|
||||
#endif
|
||||
#ifndef PIP_MATH_YN
|
||||
__attribute__ ((unused)) static double yn(const int & n, const double & v);
|
||||
#endif
|
||||
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;}
|
||||
|
||||
// [-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<double> abs(const PIVector<complexd> & v) {
|
||||
PIVector<double> result;
|
||||
result.resize(v.size());
|
||||
@@ -152,7 +194,7 @@ public:
|
||||
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;}
|
||||
_CVector & operator =(const _CVector & v) {c = v.c; 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];}
|
||||
@@ -166,6 +208,7 @@ public:
|
||||
_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;}
|
||||
|
||||
@@ -187,7 +230,13 @@ private:
|
||||
template<uint Size, typename Type>
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIMathVectorT<Size, Type> & v) {s << '{'; PIMV_FOR(i, 0) {s << v[i]; if (i < Size - 1) s << ", ";} s << '}'; return s;}
|
||||
template<uint Size, typename Type>
|
||||
inline PICout operator <<(PICout s, const PIMathVectorT<Size, Type> & v) {s << '{'; PIMV_FOR(i, 0) {s << v[i]; if (i < Size - 1) s << ", ";} s << '}'; return s;}
|
||||
template<uint Size, typename Type>
|
||||
inline bool operator ||(const PIMathVectorT<Size, Type> & f, const PIMathVectorT<Size, Type> & s) {return (f * s).isNull();}
|
||||
template<uint Size, typename Type>
|
||||
inline PIMathVectorT<Size, Type> sqrt(const PIMathVectorT<Size, Type> & v) {PIMathVectorT<Size, Type> ret; PIMV_FOR(i, 0) {ret[i] = sqrt(v[i]);} return ret;}
|
||||
template<uint Size, typename Type>
|
||||
inline PIMathVectorT<Size, Type> sqr(const PIMathVectorT<Size, Type> & v) {PIMathVectorT<Size, Type> ret; PIMV_FOR(i, 0) {ret[i] = sqr(v[i]);} return ret;}
|
||||
|
||||
//template<uint Size0, typename Type0 = double, uint Size1 = Size0, typename Type1 = Type0> /// vector {Size0, Type0} to vector {Size1, Type1}
|
||||
//inline operator PIMathVectorT<Size1, Type1>(const PIMathVectorT<Size0, Type0> & v) {PIMathVectorT<Size1, Type1> tv; uint sz = piMin<uint>(Size0, Size1); for (uint i = 0; i < sz; ++i) tv[i] = v[i]; return tv;}
|
||||
@@ -220,6 +269,10 @@ public:
|
||||
PIMathMatrixT(const PIVector<Type> & 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;}
|
||||
@@ -360,8 +413,16 @@ private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
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<uint Cols, uint Rows, typename Type>
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIMathMatrixT<Cols, Rows, Type> & 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<uint Cols, uint Rows, typename Type>
|
||||
inline PICout operator <<(PICout s, const PIMathMatrixT<Cols, Rows, Type> & 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<uint CR, uint Rows0, uint Cols1, typename Type>
|
||||
@@ -487,6 +548,8 @@ private:
|
||||
|
||||
template<typename Type>
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIMathVector<Type> & v) {s << '{'; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << '}'; return s;}
|
||||
template<typename Type>
|
||||
inline PICout operator <<(PICout s, const PIMathVector<Type> & v) {s << '{'; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << '}'; return s;}
|
||||
|
||||
typedef PIMathVector<int> PIMathVectori;
|
||||
typedef PIMathVector<double> PIMathVectord;
|
||||
@@ -658,6 +721,8 @@ private:
|
||||
|
||||
template<typename Type>
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIMathMatrix<Type> & 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<typename Type>
|
||||
inline PICout operator <<(PICout s, const PIMathMatrix<Type> & 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<typename Type>
|
||||
@@ -829,14 +894,116 @@ private:
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class PIP_EXPORT PIStatistic {
|
||||
public:
|
||||
PIStatistic();
|
||||
bool calculate(const PIVector<double> &val);
|
||||
double mean;
|
||||
double variance;
|
||||
double skewness;
|
||||
double kurtosis;
|
||||
PIStatistic() {
|
||||
mean = T();
|
||||
variance = T();
|
||||
skewness = T();
|
||||
kurtosis = T();
|
||||
}
|
||||
bool calculate(const PIVector<T> &val) {
|
||||
T v = T(), v1 = T(), v2 = T(), stddev = T();
|
||||
int i, n = val.size();
|
||||
mean = T();
|
||||
variance = T();
|
||||
skewness = T();
|
||||
kurtosis = T();
|
||||
if (n < 2)
|
||||
return false;
|
||||
/*
|
||||
* Mean
|
||||
*/
|
||||
for (i = 0; i < n; i++)
|
||||
mean += val[i];
|
||||
mean /= n;
|
||||
/*
|
||||
* 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 - v2) / (n - 1);
|
||||
if (variance < T())
|
||||
variance = T();
|
||||
stddev = sqrt(variance);
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
T mean;
|
||||
T variance;
|
||||
T skewness;
|
||||
T kurtosis;
|
||||
};
|
||||
|
||||
typedef PIStatistic<int> PIStatistici;
|
||||
typedef PIStatistic<float> PIStatisticf;
|
||||
typedef PIStatistic<double> PIStatisticd;
|
||||
|
||||
|
||||
template <typename T>
|
||||
bool OLS_Linear(const PIVector<PIPair<T, T> > & 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<T, T> & 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 <typename T>
|
||||
bool WLS_Linear(const PIVector<PIPair<T, T> > & input, const PIVector<T> & 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<T, T> & 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
|
||||
|
||||
@@ -64,12 +64,12 @@ public:
|
||||
PIRepeater(const PIString & config, const PIString & name) {
|
||||
PIConfig conf(config, PIIODevice::ReadOnly);
|
||||
if (!conf.isOpened()) {
|
||||
piCout << "[PIRepeater \"" << name << "\"] Can`t open \"" << config << "\"!";
|
||||
piCoutObj << "[PIRepeater \"" << name << "\"] Can`t open \"" << config << "\"!";
|
||||
return;
|
||||
}
|
||||
PIConfig::Entry & b(conf.getValue(name));
|
||||
if (b.childCount() != 2) {
|
||||
piCout << "[PIRepeater \"" << name << "\"] \"" << config << "\" should consist 2 nodes!";
|
||||
piCoutObj << "[PIRepeater \"" << name << "\"] \"" << config << "\" should consist 2 nodes!";
|
||||
return;
|
||||
}
|
||||
addProtocol(config, b.child(0)->fullName());
|
||||
|
||||
35
piobject.cpp
35
piobject.cpp
@@ -21,6 +21,41 @@
|
||||
|
||||
PIVector<PIObject * > PIObject::objects;
|
||||
|
||||
|
||||
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;
|
||||
|
||||
23
piobject.h
23
piobject.h
@@ -253,11 +253,22 @@ class PIP_EXPORT PIObject
|
||||
{
|
||||
friend class PIObjectManager;
|
||||
public:
|
||||
PIObject(const PIString & name = PIString()) {piMonitor.objects++; setName(name); objects << this;}
|
||||
|
||||
//! Contructs PIObject with name "name"
|
||||
PIObject(const PIString & name = PIString()) {piMonitor.objects++; setName(name); objects << this; debug_ = true;}
|
||||
~PIObject() {piMonitor.objects--; objects.removeAll(this);}
|
||||
|
||||
//! Returns object name
|
||||
const PIString & name() const {return name_;}
|
||||
|
||||
//! Set object name
|
||||
void setName(const PIString & name) {name_ = name;}
|
||||
|
||||
//! Return if debug of this object is active
|
||||
bool debug() const {return debug_;}
|
||||
|
||||
//! Set object debug active
|
||||
void setDebug(bool debug) {debug_ = debug;}
|
||||
/*
|
||||
PIStringList events();
|
||||
PIStringList eventHandlers();
|
||||
@@ -307,6 +318,11 @@ public:
|
||||
// / 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]);
|
||||
@@ -325,6 +341,8 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! 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]);
|
||||
@@ -334,6 +352,8 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! 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);}
|
||||
@@ -464,6 +484,7 @@ public:
|
||||
|
||||
protected:
|
||||
PIString name_;
|
||||
bool debug_;
|
||||
|
||||
private:
|
||||
struct Connection {
|
||||
|
||||
333
pip.cbp
Normal file
333
pip.cbp
Normal file
@@ -0,0 +1,333 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="pip" />
|
||||
<Option makefile_is_custom="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Option virtualFolders="CMake Files\;CMake Files\arm_core\;CMake Files\arm_gui\;CMake Files\peri4_widgets\;CMake Files\pip\;CMake Files\pip\system_test\;CMake Files\RLSysteModel\;" />
|
||||
<Build>
|
||||
<Target title="all">
|
||||
<Option working_dir="C:/Qt/synchro-a/src/pip" />
|
||||
<Option type="4" />
|
||||
<MakeCommands>
|
||||
<Build command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 all" />
|
||||
<CompileFile command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 "$file"" />
|
||||
<Clean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 clean" />
|
||||
<DistClean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 clean" />
|
||||
</MakeCommands>
|
||||
</Target>
|
||||
<Target title="pip">
|
||||
<Option output="C:/Qt/synchro-a/src/pip/libpip.dll" prefix_auto="0" extension_auto="0" />
|
||||
<Option working_dir="C:/Qt/synchro-a/src/pip" />
|
||||
<Option object_output="./" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add directory="C:/Qt/synchro-a/src" />
|
||||
<Add directory="C:/Qt/synchro-a/src/peri4_widgets" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/." />
|
||||
</Compiler>
|
||||
<MakeCommands>
|
||||
<Build command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 pip" />
|
||||
<CompileFile command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 "$file"" />
|
||||
<Clean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 clean" />
|
||||
<DistClean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 clean" />
|
||||
</MakeCommands>
|
||||
</Target>
|
||||
<Target title="pip/fast">
|
||||
<Option output="C:/Qt/synchro-a/src/pip/libpip.dll" prefix_auto="0" extension_auto="0" />
|
||||
<Option working_dir="C:/Qt/synchro-a/src/pip" />
|
||||
<Option object_output="./" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add directory="C:/Qt/synchro-a/src" />
|
||||
<Add directory="C:/Qt/synchro-a/src/peri4_widgets" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/." />
|
||||
</Compiler>
|
||||
<MakeCommands>
|
||||
<Build command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 pip/fast" />
|
||||
<CompileFile command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 "$file"" />
|
||||
<Clean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 clean" />
|
||||
<DistClean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 clean" />
|
||||
</MakeCommands>
|
||||
</Target>
|
||||
<Target title="pip_test">
|
||||
<Option output="C:/Qt/synchro-a/src/pip/pip_test.exe" prefix_auto="0" extension_auto="0" />
|
||||
<Option working_dir="C:/Qt/synchro-a/src/pip" />
|
||||
<Option object_output="./" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add directory="C:/Qt/synchro-a/src" />
|
||||
<Add directory="C:/Qt/synchro-a/src/peri4_widgets" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/." />
|
||||
</Compiler>
|
||||
<MakeCommands>
|
||||
<Build command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 pip_test" />
|
||||
<CompileFile command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 "$file"" />
|
||||
<Clean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 clean" />
|
||||
<DistClean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 clean" />
|
||||
</MakeCommands>
|
||||
</Target>
|
||||
<Target title="pip_test/fast">
|
||||
<Option output="C:/Qt/synchro-a/src/pip/pip_test.exe" prefix_auto="0" extension_auto="0" />
|
||||
<Option working_dir="C:/Qt/synchro-a/src/pip" />
|
||||
<Option object_output="./" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add directory="C:/Qt/synchro-a/src" />
|
||||
<Add directory="C:/Qt/synchro-a/src/peri4_widgets" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/." />
|
||||
</Compiler>
|
||||
<MakeCommands>
|
||||
<Build command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 pip_test/fast" />
|
||||
<CompileFile command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 "$file"" />
|
||||
<Clean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 clean" />
|
||||
<DistClean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/Makefile" VERBOSE=1 clean" />
|
||||
</MakeCommands>
|
||||
</Target>
|
||||
<Target title="pip_sys_test">
|
||||
<Option output="C:/Qt/synchro-a/src/pip/system_test/pip_sys_test.exe" prefix_auto="0" extension_auto="0" />
|
||||
<Option working_dir="C:/Qt/synchro-a/src/pip/system_test" />
|
||||
<Option object_output="./" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add directory="C:/Qt/synchro-a/src" />
|
||||
<Add directory="C:/Qt/synchro-a/src/peri4_widgets" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/." />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/system_test" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/system_test/." />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/system_test/.." />
|
||||
</Compiler>
|
||||
<MakeCommands>
|
||||
<Build command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/system_test/Makefile" VERBOSE=1 pip_sys_test" />
|
||||
<CompileFile command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/system_test/Makefile" VERBOSE=1 "$file"" />
|
||||
<Clean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/system_test/Makefile" VERBOSE=1 clean" />
|
||||
<DistClean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/system_test/Makefile" VERBOSE=1 clean" />
|
||||
</MakeCommands>
|
||||
</Target>
|
||||
<Target title="pip_sys_test/fast">
|
||||
<Option output="C:/Qt/synchro-a/src/pip/system_test/pip_sys_test.exe" prefix_auto="0" extension_auto="0" />
|
||||
<Option working_dir="C:/Qt/synchro-a/src/pip/system_test" />
|
||||
<Option object_output="./" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add option="-DPIP_USB" />
|
||||
<Add directory="C:/Qt/synchro-a/src" />
|
||||
<Add directory="C:/Qt/synchro-a/src/peri4_widgets" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/." />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/system_test" />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/system_test/." />
|
||||
<Add directory="C:/Qt/synchro-a/src/pip/system_test/.." />
|
||||
</Compiler>
|
||||
<MakeCommands>
|
||||
<Build command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/system_test/Makefile" VERBOSE=1 pip_sys_test/fast" />
|
||||
<CompileFile command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/system_test/Makefile" VERBOSE=1 "$file"" />
|
||||
<Clean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/system_test/Makefile" VERBOSE=1 clean" />
|
||||
<DistClean command="C:/MinGW/bin/mingw32-make.exe -f "C:/Qt/synchro-a/src/pip/system_test/Makefile" VERBOSE=1 clean" />
|
||||
</MakeCommands>
|
||||
</Target>
|
||||
</Build>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/main.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pibytearray.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/picli.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/picodec.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piconfig.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piconsole.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pidiagnostics.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pidir.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piethernet.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pievaluator.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pifile.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piincludes.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piiodevice.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pikbdlistener.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pimath.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pimonitor.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piobject.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pipacketextractor.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pipeer.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piprocess.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piprotocol.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piserial.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pisignals.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pistring.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pisystemmonitor.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pisystemtests.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pithread.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pitimer.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piusb.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pivariable.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/system_test/main.cpp">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pibytearray.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/picli.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/picodec.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piconfig.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piconsole.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pidiagnostics.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pidir.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piethernet.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pievaluator.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pifile.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piincludes.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piiodevice.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pikbdlistener.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pimath.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pimonitor.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piobject.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pip_resource_win.o">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pipacketextractor.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pipeer.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piprocess.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piprotocol.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piserial.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pisignals.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pistring.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pisystemmonitor.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pisystemtests.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pithread.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pitimer.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/piusb.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/pivariable.h">
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/arm_core/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\arm_core\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/arm_core/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\arm_core\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/arm_gui/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\arm_gui\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/arm_gui/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\arm_gui\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/peri4_widgets/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\peri4_widgets\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/peri4_widgets/peri4_widgets.qrc">
|
||||
<Option virtualFolder="CMake Files\peri4_widgets\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/peri4_widgets/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\peri4_widgets\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/peri4_widgets/peri4_widgets.qrc">
|
||||
<Option virtualFolder="CMake Files\peri4_widgets\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\pip\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\pip\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/system_test/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\pip\system_test\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/pip/system_test/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\pip\system_test\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/RLSysteModel/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\RLSysteModel\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/RLSysteModel/icons.qrc">
|
||||
<Option virtualFolder="CMake Files\RLSysteModel\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/RLSysteModel/pcollection.qrc">
|
||||
<Option virtualFolder="CMake Files\RLSysteModel\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/RLSysteModel/CMakeLists.txt">
|
||||
<Option virtualFolder="CMake Files\RLSysteModel\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/RLSysteModel/icons.qrc">
|
||||
<Option virtualFolder="CMake Files\RLSysteModel\" />
|
||||
</Unit>
|
||||
<Unit filename="C:/Qt/synchro-a/src/RLSysteModel/pcollection.qrc">
|
||||
<Option virtualFolder="CMake Files\RLSysteModel\" />
|
||||
</Unit>
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
||||
2
pip.pro
2
pip.pro
@@ -9,7 +9,7 @@ INCLUDEPATH += .
|
||||
QT -= core gui
|
||||
CONFIG -= qt
|
||||
CONFIG += dll
|
||||
VERSION = 0.3.4
|
||||
VERSION = 0.3.6
|
||||
|
||||
# Input
|
||||
HEADERS += \
|
||||
|
||||
215
pip.pro.user
Normal file
215
pip.pro.user
Normal file
@@ -0,0 +1,215 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by Qt Creator 2.4.1, 2013-04-09T20:11:21. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QString" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QString" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap"/>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Target.DesktopTarget</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildCOnfiguration.ToolChain">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</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Qt 4.8.0 (4.8.0) Релиз</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory">E:/pprojects/pip</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId">6</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">false</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Установка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Без установки</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Project.UseGlobal">true</value>
|
||||
<value type="bool" key="Analyzer.Project.UseGlobal">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">pip</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase">2</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">pip.pro</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">false</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
|
||||
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">false</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
|
||||
<value type="QString">{e0680b61-7ce7-4775-a872-e83c6b7b3dfe}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">10</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
35
pip_export.h
Normal file
35
pip_export.h
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
#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
|
||||
38
pip_resource.rc
Normal file
38
pip_resource.rc
Normal file
@@ -0,0 +1,38 @@
|
||||
# if defined(UNDER_CE)
|
||||
# include <winbase.h>
|
||||
# else
|
||||
# include <winver.h>
|
||||
# endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,3,6,0
|
||||
PRODUCTVERSION 0,3,6,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "\0"
|
||||
VALUE "FileDescription", "\0"
|
||||
VALUE "FileVersion", "0.3.6.0\0"
|
||||
VALUE "LegalCopyright", "\0"
|
||||
VALUE "OriginalFilename", "pip0.dll\0"
|
||||
VALUE "ProductName", "pip\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
/* End of Version info */
|
||||
|
||||
34
pip_resource_win.rc
Normal file
34
pip_resource_win.rc
Normal file
@@ -0,0 +1,34 @@
|
||||
# if defined(UNDER_CE)
|
||||
# include <winbase.h>
|
||||
# else
|
||||
# include <winver.h>
|
||||
# endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,3,6,0
|
||||
PRODUCTVERSION 0,3,6,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
FILEFLAGS 0x0L
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Peri4\0"
|
||||
VALUE "FileDescription", "Platform-Independent Primitives\0"
|
||||
VALUE "FileVersion", "0.3.6.0\0"
|
||||
VALUE "LegalCopyright", "\0"
|
||||
VALUE "OriginalFilename", "libpip.dll\0"
|
||||
VALUE "ProductName", "PIP\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
/* End of Version info */
|
||||
|
||||
38
pip_test_resource.rc
Normal file
38
pip_test_resource.rc
Normal file
@@ -0,0 +1,38 @@
|
||||
# if defined(UNDER_CE)
|
||||
# include <winbase.h>
|
||||
# else
|
||||
# include <winver.h>
|
||||
# endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,3,2,0
|
||||
PRODUCTVERSION 0,3,2,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "\0"
|
||||
VALUE "FileDescription", "\0"
|
||||
VALUE "FileVersion", "0.3.2.0\0"
|
||||
VALUE "LegalCopyright", "\0"
|
||||
VALUE "OriginalFilename", "pip_test.exe\0"
|
||||
VALUE "ProductName", "pip_test\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
/* End of Version info */
|
||||
|
||||
411
pipeer.cpp
411
pipeer.cpp
@@ -19,45 +19,36 @@
|
||||
|
||||
#include "pipeer.h"
|
||||
|
||||
#define _PIPEER_PORT_SYNC_START 13313
|
||||
#define _PIPEER_PORT_SYNC_END 13353
|
||||
#define _PIPEER_IP_MULTICAST "239.13.3.12"
|
||||
#define _PIPEER_MSG_SIZE 8192
|
||||
|
||||
PIPeer::PIPeer(const PIString & name): PIEthernet() {
|
||||
PIPeer::PIPeer(const PIString & name): PIObject() {
|
||||
rec_mc = rec_bc = false;
|
||||
setName(name);
|
||||
setParameter(PIEthernet::Broadcast);
|
||||
setReadPort(13312);
|
||||
setSendPort(13312);
|
||||
self_info.name = name_;
|
||||
self_info.dist = 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);
|
||||
|
||||
PIEthernet * ce;
|
||||
PIStringList sl = PIEthernet::allAddresses();
|
||||
PIString ta;
|
||||
self_info.name = name_;
|
||||
self_info.dist = 0;
|
||||
piForeachC (PIString & i, sl) {
|
||||
ce = new PIEthernet(this, func_readed);
|
||||
ce->setReadAddress(i, 13313);
|
||||
eths << ce;
|
||||
ce->startThreadedRead();
|
||||
self_info.addresses << i;
|
||||
//cout << i << ": " << ta << endl;
|
||||
}
|
||||
eth_send = new PIEthernet();
|
||||
eth_send->initialize();
|
||||
|
||||
startThreadedRead();
|
||||
//joinMulticastGroup("239.13.3.12");
|
||||
//timer.addDelimiter(5);
|
||||
sl.removeAll("127.0.0.1"); sl << "127.0.0.1";
|
||||
initMulticasts(sl);
|
||||
initEths(sl);
|
||||
//piCout << "Peer" << name_;
|
||||
timer.addDelimiter(5);
|
||||
timer.start(1000);
|
||||
sendSelfInfo();
|
||||
}
|
||||
|
||||
|
||||
PIPeer::~PIPeer() {
|
||||
terminate();
|
||||
piForeach (PIEthernet * i, mc_eths)
|
||||
i->stopThreadedRead();
|
||||
sendSelfRemove();
|
||||
//leaveMulticastGroup("239.13.3.12");
|
||||
delete eth_send;
|
||||
destroyMulticasts();
|
||||
piForeach (PIEthernet * i, eths)
|
||||
delete i;
|
||||
eths.clear();
|
||||
@@ -66,7 +57,7 @@ PIPeer::~PIPeer() {
|
||||
|
||||
void PIPeer::timerEvent(void * data, int delim) {
|
||||
switch (delim) {
|
||||
case 1: // 5 s
|
||||
case 5: // 5 s
|
||||
syncPeers();
|
||||
break;
|
||||
}
|
||||
@@ -74,46 +65,260 @@ void PIPeer::timerEvent(void * data, int delim) {
|
||||
}
|
||||
|
||||
|
||||
bool PIPeer::threadedRead(uchar * data, int size) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
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 << "[PIPeer \"" + name_ + "\"] Can`t find suitable network interface for multicast receive, check for exists at least one interface with multicasting enabled!";
|
||||
if (!rec_bc) piCoutObj << "[PIPeer \"" + name_ + "\"] 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<PeerInfo * > 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::sendToNeighbour(PIPeer::PeerInfo * peer, const PIByteArray & ba) {
|
||||
if (peer->_neth == 0) return false;
|
||||
//piCout << "send to" << peer->name << peer->_naddress << ba.size_s() << "bytes";
|
||||
diag_d.sended(ba.size_s());
|
||||
return peer->_neth->send(peer->_naddress, ba.data(), ba.size_s());
|
||||
}
|
||||
|
||||
|
||||
bool PIPeer::send(const PIString & to, const void * data, int size) {
|
||||
PeerInfo * dp = quickestPeer(to);
|
||||
if (dp == 0) {
|
||||
//piCoutObj << "[PIPeer \"" + name_ + "\"] 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;
|
||||
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;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PIPeer::dataRead(uchar * readed, int size) {
|
||||
diag_d.received(size);
|
||||
PIByteArray ba(readed, size), sba;
|
||||
int type, cnt, rec_size;
|
||||
PIString from, to;
|
||||
ba >> type >> 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<PeerInfo * >(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 << "[PIPeer \"" + name_ + "\"] 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 << "[PIPeer \"" + name_ + "\"] Translate data packet" << type << from << to << cnt << rec_size;
|
||||
sendToNeighbour(dp, sba);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PIPeer::multicastRead(uchar * data, int size) {
|
||||
PIMutexLocker locker(mc_mutex);
|
||||
diag_s.received(size);
|
||||
int header;
|
||||
PeerInfo pi;
|
||||
PIByteArray ba(data, size);
|
||||
PIVector<PeerInfo> rpeers;
|
||||
ba >> header >> pi.name;
|
||||
//piCout << "read type" << header << "from" << pi.name;
|
||||
if (pi.name == name_) return true;
|
||||
//piCout << "analyz ...";
|
||||
switch (header) {
|
||||
case 1: // new peer accepted
|
||||
//piCout << "new peer packet ...";
|
||||
if (hasPeer(pi.name)) break;
|
||||
ba >> pi.dist >> pi.addresses;
|
||||
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;
|
||||
cout << "[PIPeer \"" + name_ + "\"] new peer \"" << pi.name << "\"" << " dist " << pi.dist << endl;
|
||||
//piCoutObj << "[PIPeer \"" + name_ + "\"] 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)) {
|
||||
cout << "[PIPeer \"" + name_ + "\"] remove peer \"" << pi.name << "\"" << endl;
|
||||
//piCoutObj << "[PIPeer \"" + name_ + "\"] 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
|
||||
ba >> pi.addresses >> rpeers;
|
||||
//piCout << "sync packet ...";
|
||||
ba >> pi.addresses >> pi.netmasks >> pi.neighbours >> rpeers;
|
||||
rpeers << pi;
|
||||
//cout << "[PIPeer \"" + name_ + "\"] rec sync " << rpeers.size_s() << " peers" << endl;
|
||||
//piCout << "[PIPeer \"" + name_ + "\"] rec sync " << rpeers.size_s() << " peers";
|
||||
for (uint i = 0; i < rpeers.size(); ++i) {
|
||||
PeerInfo & rpeer(rpeers[i]);
|
||||
//cout << " to sync " << rpeer.name << endl;
|
||||
//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) {
|
||||
//cout << "synced " << peer.name << endl;
|
||||
//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;
|
||||
@@ -123,6 +328,17 @@ bool PIPeer::threadedRead(uchar * data, int size) {
|
||||
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;
|
||||
}
|
||||
@@ -130,57 +346,146 @@ bool PIPeer::threadedRead(uchar * data, int size) {
|
||||
}
|
||||
|
||||
|
||||
bool PIPeer::func_readed(void * peer, uchar * data, int size) {
|
||||
PIPeer * p = (PIPeer * )peer;
|
||||
cout << "[PIPeer \"" + p->name_ + "\"] received " << data << endl;
|
||||
return true;
|
||||
void PIPeer::sendMulticast(const PIByteArray & ba) {
|
||||
piForeach (PIEthernet * e, mc_eths) {
|
||||
for (int p = _PIPEER_PORT_SYNC_START; p < _PIPEER_PORT_SYNC_END; ++p) {
|
||||
e->setSendPort(p);
|
||||
//errorClear();
|
||||
//piCout << "send to" << e->sendAddress() << e->send(ba);
|
||||
//piCout << PIEthernet::ethErrorString();
|
||||
e->send(ba);
|
||||
diag_s.sended(ba.size_s());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIPeer::sendPeerInfo(const PeerInfo & info) {
|
||||
PIByteArray ba;
|
||||
ba << int(1) << info.name << info.dist << info.addresses;
|
||||
write(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;
|
||||
write(ba);
|
||||
sendMulticast(ba);
|
||||
}
|
||||
|
||||
|
||||
void PIPeer::syncPeers() {
|
||||
//cout << "[PIPeer \"" + name_ + "\"] sync " << peers.size_s() << " peers" << endl;
|
||||
//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 > 1 && cp.dist == 0) {
|
||||
if (cp.sync > 3 && cp.dist == 0) {
|
||||
pn = cp.name;
|
||||
cout << "[PIPeer \"" + name_ + "\"] sync: remove " << pn << endl;
|
||||
//piCoutObj << "[PIPeer \"" + name_ + "\"] sync: remove " << pn;
|
||||
peers.remove(i);
|
||||
sendPeerRemove(pn);
|
||||
--i;
|
||||
findNearestAddresses();
|
||||
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 << peers;
|
||||
write(ba);
|
||||
ba << int(3) << self_info.name << self_info.addresses << self_info.netmasks << self_info.neighbours << peers;
|
||||
sendMulticast(ba);
|
||||
}
|
||||
|
||||
|
||||
void PIPeer::findNearestAddresses() {
|
||||
cout << "[PIPeer \"" + name_ + "\"] findNearestAddresses" << endl;
|
||||
//piCout << "[PIPeer \"" + name_ + "\"] findNearestAddresses";
|
||||
addresses_map.clear();
|
||||
int max_dist = -1;
|
||||
piForeach (PeerInfo & i, peers)
|
||||
static PIMap<PIString, PeerInfo * > 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;
|
||||
PIVector<PeerInfo * > cwave;
|
||||
for (int d = 0; d <= max_dist; ++d) {
|
||||
//if ()
|
||||
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<PeerInfo * > 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<PeerInfo * > & 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 **";*/
|
||||
}
|
||||
|
||||
131
pipeer.h
131
pipeer.h
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Peer - named I/O ethernet node
|
||||
Peer - named I/O ethernet node, forming self-organized peering network
|
||||
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -21,35 +21,103 @@
|
||||
#define PIPEER_H
|
||||
|
||||
#include "piethernet.h"
|
||||
#include "pidiagnostics.h"
|
||||
|
||||
class PIP_EXPORT PIPeer: public PIEthernet
|
||||
class PIP_EXPORT PIPeer: public PIObject
|
||||
{
|
||||
PIOBJECT(PIPeer)
|
||||
struct PeerInfo;
|
||||
friend PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v);
|
||||
friend PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v);
|
||||
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);
|
||||
~PIPeer();
|
||||
virtual ~PIPeer();
|
||||
|
||||
//const PIString & id() const {return id_;}
|
||||
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<uchar> _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<PeerInfo> & allPeers() const {return peers;}
|
||||
bool isPeerExists(const PIString & name) const {return getPeerByName(name) != 0;}
|
||||
|
||||
const PeerInfo * getPeerByName(const PIString & name) const {piForeachC (PeerInfo & i, peers) if (i.name == name) return &i; return 0;}
|
||||
|
||||
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:
|
||||
bool threadedRead(uchar * readed, int size);
|
||||
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);
|
||||
static bool func_readed(void * peer, uchar * data, int size);
|
||||
|
||||
struct PeerInfo {
|
||||
PIString name;
|
||||
PIString nearest_address;
|
||||
PIStringList addresses;
|
||||
int dist;
|
||||
int sync;
|
||||
int _wave;
|
||||
};
|
||||
|
||||
|
||||
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;}
|
||||
@@ -60,23 +128,36 @@ private:
|
||||
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
|
||||
|
||||
int header; // 1 - new peer, 2 - remove peer, 3 - sync peers, 4 - data
|
||||
// Data packet: 4, from, to, ticks, data_size, data
|
||||
};
|
||||
|
||||
PIList<PIEthernet * > eths;
|
||||
PIEthernet * eth_send;
|
||||
typedef std::pair<PIString, PIVector<PeerInfo * > > napair;
|
||||
|
||||
PIVector<PIEthernet * > eths;
|
||||
PIVector<PIEthernet * > mc_eths;
|
||||
PITimer timer;
|
||||
PIMutex mc_mutex;
|
||||
bool rec_mc, rec_bc;
|
||||
|
||||
PeerInfo self_info;
|
||||
PIVector<PeerInfo> peers;
|
||||
PIMap<PIString, PIVector<PeerInfo * > > 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.dist; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v) {s >> v.name >> v.addresses >> v.dist; return s;}
|
||||
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
|
||||
|
||||
@@ -141,12 +141,12 @@ void PIProcess::run() {
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
CloseHandle(pi.hProcess);
|
||||
} else
|
||||
piCout << "[PIProcess] \"CreateProcess\" error, " << errorString();
|
||||
piCoutObj << "[PIProcess] \"CreateProcess\" error, " << errorString();
|
||||
#else
|
||||
|
||||
//cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
|
||||
if (execve(str.c_str(), a, e) < 0)
|
||||
piCout << "[PIProcess] \"execve\" error, " << errorString();
|
||||
piCoutObj << "[PIProcess] \"execve\" error, " << errorString();
|
||||
} else {
|
||||
msleep(1);
|
||||
//cout << "wait" << endl;
|
||||
|
||||
@@ -26,7 +26,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
PIObject::setName(name);
|
||||
PIConfig conf(config, PIIODevice::ReadOnly);
|
||||
if (!conf.isOpened()) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Can`t open \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Can`t open \"" << config << "\"!";
|
||||
devReceiverState = devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
|
||||
/// receiver section
|
||||
if (rb.isEntryExists("ip") && rb.isEntryExists("device")) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) dev = gdev;
|
||||
if (gok && ok && (dev != gdev)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -59,7 +59,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) ps = gps;
|
||||
if (gok && ok && (ps != gps)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive port in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receive port in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -74,7 +74,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -85,18 +85,18 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) freq = gfreq;
|
||||
if (gok && ok && (freq != gfreq)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
eth->setReopenTimeout(freq * 1000);
|
||||
}
|
||||
if (recDataPtr == 0)
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!";
|
||||
if (recDataSize == 0)
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null receive data size!";
|
||||
} else {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.port\" or \"" << name << ".port\" in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.port\" or \"" << name << ".port\" in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -106,7 +106,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) dev = gdev;
|
||||
if (gok && ok && (dev != gdev)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -115,7 +115,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) ps = gps;
|
||||
if (gok && ok && (ps != gps)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"speed\" in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receive \"speed\" in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -124,7 +124,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"parity\" in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receive \"parity\" in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -135,7 +135,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) ps = gps;
|
||||
if (gok && ok && (ps != gps)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"vtime\" in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receive \"vtime\" in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -162,11 +162,11 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
}
|
||||
has_dev = true;
|
||||
if (recDataPtr == 0)
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!";
|
||||
if (recDataSize == 0)
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null receive data size!";
|
||||
} else {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.speed\" or \"" << name << ".speed\" in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.speed\" or \"" << name << ".speed\" in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -176,7 +176,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) history_write_rec = ghist;
|
||||
if (gok && ok && (history_write_rec != ghist)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver history in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receiver history in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -187,7 +187,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
history_id_rec = rb.getValue("historyID", 0, &ok);
|
||||
if (!ok) {
|
||||
history_id_rec = protName.toByteArray().checksumCRC16();
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: no receiver history ID defined, write with ID = " << history_id_rec;
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: no receiver history ID defined, write with ID = " << history_id_rec;
|
||||
}
|
||||
history_file_rec.open(history_path_rec, PIIODevice::WriteOnly);
|
||||
}
|
||||
@@ -196,21 +196,21 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
gfreq = b.getValue("frequency", -1.f, &gok);
|
||||
if (gok && !ok) freq = gfreq;
|
||||
if (gok && ok && (freq != gfreq)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous expected frequency in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous expected frequency in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
if (freq > 0.f && !has_dev)
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: no receiver device and not null expected frequency!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: no receiver device and not null expected frequency!";
|
||||
float tm = b.getValue("disconnectTimeout", 3.f);
|
||||
if (tm <= 0.f)
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: diconnect timeout <= 0 s!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: diconnect timeout <= 0 s!";
|
||||
timeout_ = (tm < 0.f) ? 0.f : tm;
|
||||
setExpectedFrequency(freq);
|
||||
|
||||
/// sender section
|
||||
if (sb.isEntryExists("ip") && sb.isEntryExists("device")) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -220,7 +220,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) dev = gdev;
|
||||
if (gok && ok && (dev != gdev)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -229,7 +229,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) ps = gps;
|
||||
if (gok && ok && (ps != gps)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send port in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous send port in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -243,7 +243,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -254,18 +254,18 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) freq = gfreq;
|
||||
if (gok && ok && (freq != gfreq)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
eth->setReopenTimeout(freq * 1000);
|
||||
}
|
||||
if (sendDataPtr_ == 0)
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!";
|
||||
if (sendDataSize_ == 0)
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null send data size!";
|
||||
} else {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.port\" or \"" << name << ".port\" in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.port\" or \"" << name << ".port\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -275,7 +275,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) dev = gdev;
|
||||
if (gok && ok && (dev != gdev)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -284,7 +284,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) ps = gps;
|
||||
if (gok && ok && (ps != gps)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"speed\" in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous send \"speed\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -293,7 +293,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"parity\" in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous send \"parity\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -304,14 +304,14 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
pp.setFlag(PISerial::TwoStopBits, flag);
|
||||
}
|
||||
} else {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -322,16 +322,16 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
ser->setParameters(pp);
|
||||
has_dev = true;
|
||||
if (sendDataPtr_ == 0)
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!";
|
||||
if (sendDataSize_ == 0)
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null send data size!";
|
||||
}
|
||||
history_write_send = sb.getValue("writeHistory", false, &ok);
|
||||
ghist = b.getValue("writeHistory", false, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) history_write_send = ghist;
|
||||
if (gok && ok && (history_write_send != ghist)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender history in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous sender history in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
@@ -342,7 +342,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
history_id_send = sb.getValue("historyID", 0, &ok);
|
||||
if (!ok) {
|
||||
history_id_send = protName.toByteArray().checksumCRC16() + 1;
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: no sender history ID defined, write with ID = " << history_id_send;
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: no sender history ID defined, write with ID = " << history_id_send;
|
||||
}
|
||||
history_file_send.open(history_path_send, PIIODevice::WriteOnly);
|
||||
}
|
||||
@@ -351,12 +351,12 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
|
||||
gfreq = b.getValue("frequency", -1.f, &gok);
|
||||
if (gok && !ok) freq = gfreq;
|
||||
if (gok && ok && (freq != gfreq)) {
|
||||
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender frequency in \"" << config << "\"!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous sender frequency in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
if (freq > 0.f && !has_dev)
|
||||
piCout << "[PIProtocol \"" << name << "\"] Warning: no sender device and not null send frequency!";
|
||||
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: no sender device and not null send frequency!";
|
||||
setSenderFrequency(freq);
|
||||
|
||||
headerPtr = (uchar * )recHeaderPtr;
|
||||
|
||||
@@ -29,8 +29,9 @@
|
||||
|
||||
class PIProtocol;
|
||||
|
||||
class PIP_EXPORT PIMultiProtocolBase
|
||||
class PIP_EXPORT PIMultiProtocolBase: protected PIObject
|
||||
{
|
||||
PIOBJECT(PIMultiProtocolBase)
|
||||
friend class PIProtocol;
|
||||
public:
|
||||
PIMultiProtocolBase() {;}
|
||||
|
||||
38
piserial.cpp
38
piserial.cpp
@@ -67,14 +67,14 @@ bool PISerial::setPin(int number, bool on) {
|
||||
case 3: return setST(on); break;
|
||||
case 4: return setDTR(on); break;
|
||||
case 5:
|
||||
piCout << "[PISerial] Pin number 5 is ground";
|
||||
piCoutObj << "[PISerial] 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:
|
||||
piCout << "[PISerial] Pin number " << number << " doesn`t exists!";
|
||||
piCoutObj << "[PISerial] Pin number " << number << " doesn`t exists!";
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@@ -93,7 +93,7 @@ bool PISerial::isPin(int number) const {
|
||||
case 8: return isCTS(); break;
|
||||
case 9: return isRNG(); break;
|
||||
default:
|
||||
piCout << "[PISerial] Pin number " << number << " doesn`t exists!";
|
||||
piCoutObj << "[PISerial] Pin number " << number << " doesn`t exists!";
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@@ -103,16 +103,16 @@ bool PISerial::isPin(int number) const {
|
||||
bool PISerial::setBit(int bit, bool on, const PIString & bname) {
|
||||
#ifndef WINDOWS
|
||||
if (fd < 0) {
|
||||
piCout << "[PISerial] set" << bname << " error: \"" << path_ << "\" is not opened!";
|
||||
piCoutObj << "[PISerial] set" << bname << " error: \"" << path_ << "\" is not opened!";
|
||||
return false;
|
||||
}
|
||||
if (ioctl(fd, on ? TIOCMBIS : TIOCMBIC, &bit) < 0) {
|
||||
piCout << "[PISerial] set" << bname << " error: " << errorString();
|
||||
piCoutObj << "[PISerial] set" << bname << " error: " << errorString();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(";
|
||||
piCoutObj << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(";
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -121,15 +121,15 @@ bool PISerial::setBit(int bit, bool on, const PIString & bname) {
|
||||
bool PISerial::isBit(int bit, const PIString & bname) const {
|
||||
#ifndef WINDOWS
|
||||
if (fd < 0) {
|
||||
piCout << "[PISerial] is" << bname << " error: \"" << path_ << "\" is not opened!";
|
||||
piCoutObj << "[PISerial] is" << bname << " error: \"" << path_ << "\" is not opened!";
|
||||
return false;
|
||||
}
|
||||
int ret = 0;
|
||||
if (ioctl(fd, TIOCMGET, &ret) < 0)
|
||||
piCout << "[PISerial] is" << bname << " error: " << errorString();
|
||||
piCoutObj << "[PISerial] is" << bname << " error: " << errorString();
|
||||
return ret & bit;
|
||||
#else
|
||||
piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(";
|
||||
piCoutObj << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(";
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -301,7 +301,7 @@ bool PISerial::openDevice() {
|
||||
if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;}
|
||||
hCom = CreateFileA(path_.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
|
||||
if(hCom == INVALID_HANDLE_VALUE) {
|
||||
piCout << "[PISerial] Unable to open \"" << path_ << "\"";
|
||||
piCoutObj << "[PISerial] Unable to open \"" << path_ << "\"";
|
||||
return false;
|
||||
}
|
||||
fd = 0;
|
||||
@@ -312,7 +312,7 @@ bool PISerial::openDevice() {
|
||||
times.WriteTotalTimeoutConstant = 1;
|
||||
times.WriteTotalTimeoutMultiplier = 0;
|
||||
if (SetCommTimeouts(hCom, ×) == -1) {
|
||||
piCout << "[PISerial] Unable to set timeouts for \"" << path_ << "\"";
|
||||
piCoutObj << "[PISerial] Unable to set timeouts for \"" << path_ << "\"";
|
||||
CloseHandle(hCom);
|
||||
fd = -1;
|
||||
return false;
|
||||
@@ -330,7 +330,7 @@ bool PISerial::openDevice() {
|
||||
}
|
||||
desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT;
|
||||
if (SetCommState(hCom, &desc) == -1) {
|
||||
piCout << "[PISerial] Unable to set comm state for \"" << path_ << "\"";
|
||||
piCoutObj << "[PISerial] Unable to set comm state for \"" << path_ << "\"";
|
||||
CloseHandle(hCom);
|
||||
fd = -1;
|
||||
return false;
|
||||
@@ -345,7 +345,7 @@ bool PISerial::openDevice() {
|
||||
//cout << "init ser " << path_ << " mode " << om << " param " << params << endl;
|
||||
fd = ::open(path_.data(), O_NOCTTY | om);
|
||||
if(fd == -1) {
|
||||
piCout << "[PISerial] Unable to open \"" << path_ << "\"";
|
||||
piCoutObj << "[PISerial] Unable to open \"" << path_ << "\"";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -371,20 +371,20 @@ bool PISerial::openDevice() {
|
||||
fcntl(fd, F_SETFL, 0);
|
||||
|
||||
if(tcsetattr(fd, TCSANOW, &desc) < 0) {
|
||||
piCout << "[PISerial] Can`t set attributes for \"" << path_ << "\"";
|
||||
piCoutObj << "[PISerial] Can`t set attributes for \"" << path_ << "\"";
|
||||
::close(fd);
|
||||
return false;
|
||||
}
|
||||
//piCout << "[PISerial] Initialized " << path_;
|
||||
//piCoutObj << "[PISerial] Initialized " << path_;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int PISerial::write(const void * data, int max_size, bool wait) {
|
||||
//piCout << "[PISerial] send " << max_size << ": " << PIString((char*)data, max_size);
|
||||
//piCoutObj << "[PISerial] send " << max_size << ": " << PIString((char*)data, max_size);
|
||||
if (fd == -1 || !canWrite()) {
|
||||
//piCout << "[PISerial] Can`t write to uninitialized COM";
|
||||
//piCoutObj << "[PISerial] Can`t write to uninitialized COM";
|
||||
return -1;
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
@@ -402,6 +402,6 @@ int PISerial::write(const void * data, int max_size, bool wait) {
|
||||
if (wait) tcdrain(fd);
|
||||
#endif
|
||||
return (int)wrote;
|
||||
//piCout << "[PISerial] Error while sending";
|
||||
//piCout << "[PISerial] Wrote " << wrote << " bytes in " << path_;
|
||||
//piCoutObj << "[PISerial] Error while sending";
|
||||
//piCoutObj << "[PISerial] Wrote " << wrote << " bytes in " << path_;
|
||||
}
|
||||
|
||||
318
pistatemachine.h
Normal file
318
pistatemachine.h
Normal file
@@ -0,0 +1,318 @@
|
||||
/*! \file pistatemachine.h
|
||||
* \brief Base class for custom state machine
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
State machine
|
||||
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef 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 <typename Type = int>
|
||||
class PIP_EXPORT PIStateMachine: public PIObject
|
||||
{
|
||||
PIOBJECT(PIStateMachine)
|
||||
public:
|
||||
//! Constructs an empty state machine
|
||||
PIStateMachine() {resetConditions();}
|
||||
~PIStateMachine() {;}
|
||||
|
||||
//! %Condition is a pair (string, number)
|
||||
typedef PIPair<PIString, int> Condition;
|
||||
|
||||
//! %Rule of transition between states of machine
|
||||
struct Rule {
|
||||
//! Constuctor
|
||||
Rule() {;}
|
||||
//! Constuctor
|
||||
Rule(Type f, Type t, const PIStringList & c = PIStringList(), Handler h = 0, bool rac = false) {
|
||||
from = f;
|
||||
to = t;
|
||||
for (int i = 0; i < c.size_s(); ++i)
|
||||
conditions << Condition(c[i], 1);
|
||||
resetAllConditions = rac;
|
||||
handler = h;
|
||||
}
|
||||
//! Source state
|
||||
Type from;
|
||||
//! Destination state
|
||||
Type to;
|
||||
//! %Conditions of transition
|
||||
PIVector<Condition> conditions;
|
||||
//! 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() {;}
|
||||
//! 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;}
|
||||
};
|
||||
|
||||
|
||||
//! Add state of machine
|
||||
void addState(Type value, const PIString & name = "", Handler handler = 0) {if (states_.contain(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 resetAllConditions = false) {if (rules_.contain(Rule(from, to))) return; rules_ << Rule(from, to, PIStringList(condition), handler, resetAllConditions);}
|
||||
|
||||
//! Add rule of transition
|
||||
void addRule(Type from, Type to, Handler handler, bool resetAllConditions = false) {if (rules_.contain(Rule(from, to))) return; rules_ << Rule(from, to, PIStringList(), handler, resetAllConditions);}
|
||||
|
||||
//! Add rule of transition
|
||||
void addRule(Type from, Type to, const PIStringList & conditions = PIStringList(), Handler handler = 0, bool resetAllConditions = false) {if (rules_.contain(Rule(from, to))) return; rules_ << Rule(from, to, conditions, handler, resetAllConditions);}
|
||||
|
||||
//! Add rule of transition
|
||||
void addRule(const Rule & rule) {if (rules_.contain(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) r.handler(this);
|
||||
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<Condition> & 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) {
|
||||
if (switch_to != state_.value) switchToState(switch_to);
|
||||
execution(state_);
|
||||
if (state_.handler != 0) state_.handler(this);
|
||||
}
|
||||
|
||||
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<State> states_;
|
||||
PIVector<Rule> rules_;
|
||||
State init_, state_;
|
||||
Type switch_to;
|
||||
PIVector<Condition> cond;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // PISTATEMACHINE_H
|
||||
156
pistring.cpp
156
pistring.cpp
@@ -249,10 +249,10 @@ PIString & PIString::cutMid(const int start, const int len) {
|
||||
PIString & PIString::trim() {
|
||||
int st = 0, fn = 0;
|
||||
for (int i = 0; i < length(); ++i)
|
||||
if (at(i) != ' ' && at(i) != '\t')
|
||||
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r')
|
||||
{st = i; break;}
|
||||
for (int i = length() - 1; i >= 0; --i)
|
||||
if (at(i) != ' ' && at(i) != '\t')
|
||||
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r')
|
||||
{fn = i; break;}
|
||||
*this = mid(st, fn - st + 1);
|
||||
return *this;
|
||||
@@ -262,10 +262,10 @@ PIString & PIString::trim() {
|
||||
PIString PIString::trimmed() const {
|
||||
int st = 0, fn = 0;
|
||||
for (int i = 0; i < length(); ++i)
|
||||
if (at(i) != ' ' && at(i) != '\t')
|
||||
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r')
|
||||
{st = i; break;}
|
||||
for (int i = length() - 1; i >= 0; --i)
|
||||
if (at(i) != ' ' && at(i) != '\t')
|
||||
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r')
|
||||
{fn = i; break;}
|
||||
return mid(st, fn - st + 1);
|
||||
}
|
||||
@@ -293,7 +293,7 @@ PIString & PIString::replace(const PIString & what, const PIString & with, bool
|
||||
|
||||
|
||||
PIString & PIString::replaceAll(const PIString & what, const PIString & with) {
|
||||
if (what.isEmpty()) return *this;
|
||||
if (what.isEmpty() || what == with) return *this;
|
||||
bool ok = true;
|
||||
while (ok) replace(what, with, &ok);
|
||||
return *this;
|
||||
@@ -356,6 +356,152 @@ int PIString::findLast(const PIString str, const int start) const {
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
} 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::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();
|
||||
|
||||
44
pistring.h
44
pistring.h
@@ -86,7 +86,7 @@ public:
|
||||
PIString(const int len, const PIChar & c) {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
|
||||
|
||||
//! Contructs string from other string "str"
|
||||
PIString(const PIString & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
|
||||
PIString(const PIString & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; uint len = str.size(); for (uint i = 0; i < len; ++i) push_back(str[i]);}
|
||||
|
||||
~PIString() {piMonitor.strings--; piMonitor.containers++;}
|
||||
|
||||
@@ -341,11 +341,39 @@ public:
|
||||
* \sa \a reverse() */
|
||||
PIString reversed() const {PIString str(*this); str.reverse(); return str;}
|
||||
|
||||
|
||||
/*! \brief Take a symbol from the begin of this string and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::takeSymbol
|
||||
* \sa \a \a takeWord(), 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 takeLine(), \a takeNumber(), \a takeRange() */
|
||||
PIString takeWord();
|
||||
|
||||
/*! \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 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 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 os char sequence
|
||||
* \details It`s equivalent length of char sequence
|
||||
* returned by function \a data() \n
|
||||
* Example: \snippet pistring.cpp PIString::lengthAscii
|
||||
* \sa \a data() */
|
||||
@@ -645,10 +673,10 @@ inline PICout operator <<(PICout s, const PIString & v) {s.space(); s.quote(); s
|
||||
|
||||
|
||||
//! \relatesalso PIString \relatesalso PIByteArray \brief Output operator to PIByteArray
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << v.size_s(); for (int i = 0; i < v.length(); ++i) s << v[i]; return s;}
|
||||
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) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {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
|
||||
@@ -728,6 +756,14 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! \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;}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ bool PISystemMonitor::startOnProcess(int pID) {
|
||||
file.open("/proc/" + PIString::fromNumber(pID_) + "/stat", PIIODevice::ReadOnly);
|
||||
filem.open("/proc/" + PIString::fromNumber(pID_) + "/statm", PIIODevice::ReadOnly);
|
||||
if (!file.isOpened()) {
|
||||
piCout << "[PISystemMonitor] Can`t find process with ID = " << pID_ << "!";
|
||||
piCoutObj << "[PISystemMonitor] Can`t find process with ID = " << pID_ << "!";
|
||||
return false;
|
||||
}
|
||||
cycle = -1;
|
||||
|
||||
21
pitimer.cpp
21
pitimer.cpp
@@ -174,7 +174,7 @@ void PITimer::start(double msecs) {
|
||||
ti = timer_create(CLOCK_REALTIME, &se, &timer);
|
||||
//cout << "***create timer " << msecs << " msecs\n";
|
||||
if (ti == -1) {
|
||||
piCout << "[PITimer] Can`t create timer for " << msecs << " msecs: " << errorString();
|
||||
piCoutObj << "[PITimer] Can`t create timer for " << msecs << " msecs: " << errorString();
|
||||
return;
|
||||
}
|
||||
timer_settime(timer, 0, &spec, 0);
|
||||
@@ -192,7 +192,7 @@ void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
|
||||
ti = timer_create(CLOCK_REALTIME, &se, &timer);
|
||||
//cout << "***create timer\n";
|
||||
if (ti == -1) {
|
||||
piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString();
|
||||
piCoutObj << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString();
|
||||
return;
|
||||
}
|
||||
timer_settime(timer, 0, &spec, 0);
|
||||
@@ -218,7 +218,7 @@ void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_date
|
||||
ti = timer_create(CLOCK_REALTIME, &se, &timer);
|
||||
//cout << "***create timer\n";
|
||||
if (ti == -1) {
|
||||
piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString();
|
||||
piCoutObj << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString();
|
||||
return;
|
||||
}
|
||||
timer_settime(timer, TIMER_ABSTIME, &spec, 0);
|
||||
@@ -246,7 +246,7 @@ void PITimer::TimerPool::begin() {
|
||||
sa.sa_handler = empty_handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
if (sigaction(SIGALRM, &sa, 0) == -1) {
|
||||
piCout << "[PITimer] sigaction error: " << errorString();
|
||||
piCoutObj << "[PITimer] sigaction error: " << errorString();
|
||||
stop();
|
||||
return;
|
||||
}*/
|
||||
@@ -260,12 +260,12 @@ void PITimer::TimerPool::begin() {
|
||||
spec.it_value = spec.it_interval;
|
||||
//cout << "***create pool timer\n";
|
||||
if (timer_create(CLOCK_REALTIME, &se, &timer) == -1) {
|
||||
piCout << "[PITimer] Can`t create timer for pool: " << errorString();
|
||||
piCoutObj << "[PITimer] Can`t create timer for pool: " << errorString();
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
if (timer_settime(timer, 0, &spec, 0) == -1) {
|
||||
piCout << "[PITimer] Can`t set timer for pool: " << errorString();
|
||||
piCoutObj << "[PITimer] Can`t set timer for pool: " << errorString();
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
@@ -358,7 +358,7 @@ void PITimer::start(double msecs) {
|
||||
|
||||
|
||||
void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
|
||||
//piCout << "defStart exec with" << delay_msecs << interval_msecs;
|
||||
//piCoutObj << "defStart exec with" << delay_msecs << interval_msecs;
|
||||
if (interval_msecs < 0 || running_) return;
|
||||
interval_ = interval_msecs;
|
||||
PISystemTime cst = currentSystemTime();
|
||||
@@ -367,12 +367,12 @@ void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
|
||||
if (st_time < cst) st_time = cst;
|
||||
running_ = deferred_ = true;
|
||||
PIThread::start();
|
||||
//piCout << "timer start def";
|
||||
//piCoutObj << "timer start def";
|
||||
}
|
||||
|
||||
|
||||
void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_datetime) {
|
||||
//piCout << "defStart exec to" << start_datetime.toString() << interval_msecs;
|
||||
//piCoutObj << "defStart exec to" << start_datetime.toString() << interval_msecs;
|
||||
if (interval_msecs < 0 || running_) return;
|
||||
interval_ = interval_msecs;
|
||||
PISystemTime cst = currentSystemTime();
|
||||
@@ -381,7 +381,7 @@ void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_date
|
||||
if (st_time < cst) st_time = cst;
|
||||
running_ = deferred_ = true;
|
||||
PIThread::start();
|
||||
//piCout << "timer start def";
|
||||
//piCoutObj << "timer start def";
|
||||
}
|
||||
|
||||
|
||||
@@ -621,6 +621,7 @@ PIDateTime currentDateTime() {
|
||||
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;
|
||||
|
||||
@@ -190,6 +190,11 @@ public:
|
||||
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--;}}
|
||||
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--;}}
|
||||
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();}
|
||||
|
||||
double elapsed_n(); // nanoseconds
|
||||
|
||||
357
piusb.cpp
Normal file
357
piusb.cpp
Normal file
@@ -0,0 +1,357 @@
|
||||
#include "piusb.h"
|
||||
|
||||
#ifdef PIP_USB
|
||||
# ifdef WINDOWS
|
||||
# include <lusb0_usb.h>
|
||||
# else
|
||||
# include <usb.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
PIUSB::PIUSB(ushort vid, ushort pid): PIIODevice("", ReadWrite, false) {
|
||||
vid_ = vid;
|
||||
pid_ = pid;
|
||||
path_ = PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0");
|
||||
dev_num = 1;
|
||||
intefrace_ = 0;
|
||||
hdev = 0;
|
||||
interface_claimed = -1;
|
||||
timeout_r = timeout_w = 1000;
|
||||
}
|
||||
|
||||
|
||||
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::Endpoint> PIUSB::endpointsRead() {
|
||||
PIVector<Endpoint> ret;
|
||||
piForeachC (Endpoint & i, eps)
|
||||
if (i.direction == Endpoint::Read)
|
||||
ret << i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIVector<PIUSB::Endpoint> PIUSB::endpointsWrite() {
|
||||
PIVector<Endpoint> 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 << "[PIUSB] 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 << "[PIUSB] 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 << "[PIUSB] 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::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 << "[PIUSB] Error: Cant`t find busses!";
|
||||
return false;
|
||||
}
|
||||
if (usb_find_devices() < 0) {
|
||||
piCoutObj << "[PIUSB] Error: Cant`t find devices!";
|
||||
return false;
|
||||
}
|
||||
|
||||
//piCoutObj << "[PIUSB] 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 == dev_num) {
|
||||
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 && ep_write.address == 0) ep_write = eps.back();
|
||||
if (eps.back().direction == Endpoint::Read && ep_read.address == 0) ep_read = eps.back();
|
||||
}
|
||||
|
||||
//piCoutObj << "[PIUSB] Device found at address:" << "Bus: " << dev->bus->dirname << ", Device: " << dev->filename;
|
||||
found = true;
|
||||
break;
|
||||
} else cur_num++;
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
if (!found) {
|
||||
piCoutObj << "[PIUSB] Error: Cant`t find device!";
|
||||
return false;
|
||||
}
|
||||
//piCoutObj << "[PIUSB] Open ... " << flush;
|
||||
hdev = usb_open(dev);
|
||||
if (hdev == 0) {
|
||||
piCoutObj << "[PIUSB] Error: Cant`t open device:" << usb_strerror();
|
||||
return false;
|
||||
}// else piCoutObj << "[PIUSB] ok";
|
||||
//usb_reset(hdev);
|
||||
|
||||
//usb_set_configuration(hdev, 1);
|
||||
//usb_set_altinterface(hdev, 0);
|
||||
|
||||
# ifndef WINDOWS
|
||||
char tbuff[256];
|
||||
//piCoutObj << "[PIUSB] Check for bounded driver ... " << flush;
|
||||
if (usb_get_driver_np(hdev, intefrace_, tbuff, sizeof(tbuff) - 1) >= 0) {
|
||||
//piCoutObj << "[PIUSB] yes" << "Found driver: " << tbuff;
|
||||
//piCoutObj << "[PIUSB] Detach driver ... " << flush;
|
||||
if (usb_detach_kernel_driver_np(hdev, intefrace_)< 0) {
|
||||
piCoutObj << "[PIUSB] Error: Cant`t detach bounded driver!";
|
||||
return false;
|
||||
}// else piCoutObj << "[PIUSB] ok";
|
||||
}// else piCoutObj << "[PIUSB] no";
|
||||
# endif
|
||||
|
||||
//piCoutObj << "[PIUSB] Claim interface ... " << flush;
|
||||
if (usb_claim_interface(hdev, intefrace_) < 0) {
|
||||
piCoutObj << "[PIUSB] Error: Cant`t claim interface:" << usb_strerror();
|
||||
return false;
|
||||
} // else piCoutObj << "[PIUSB] 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<void * >(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;
|
||||
}
|
||||
137
piusb.h
Normal file
137
piusb.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
USB, based on libusb
|
||||
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIUSB_H
|
||||
#define PIUSB_H
|
||||
|
||||
#include "piiodevice.h"
|
||||
|
||||
struct usb_dev_handle;
|
||||
|
||||
class PIP_EXPORT PIUSB: public PIIODevice {
|
||||
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<Endpoint> 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<Interface> 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<Configuration> configurations;
|
||||
};
|
||||
|
||||
const Descriptor & currentDescriptor() const {return desc_;}
|
||||
const Configuration & currentConfiguration() const {return conf_;}
|
||||
const Interface & currentInterface() const {return iface_;}
|
||||
|
||||
ushort vendorID() const {return vid_;}
|
||||
ushort productID() const {return pid_;}
|
||||
|
||||
const PIVector<Endpoint> & endpoints() const {return eps;}
|
||||
PIVector<Endpoint> endpointsRead();
|
||||
PIVector<Endpoint> endpointsWrite();
|
||||
Endpoint getEndpointByAddress(uchar address);
|
||||
|
||||
const Endpoint & endpointRead() {return ep_read;}
|
||||
const Endpoint & endpointWrite() {return ep_write;}
|
||||
|
||||
bool setConfiguration(uchar value);
|
||||
bool setInterface(uchar value);
|
||||
|
||||
void setEndpointRead(const Endpoint & ep) {ep_read = ep;}
|
||||
void setEndpointWrite(const Endpoint & ep) {ep_write = ep;}
|
||||
void setDeviceNumber(int dn) {dev_num = dn;}
|
||||
void setTimeoutRead(int t) {timeout_r = t;}
|
||||
void setTimeoutWrite(int t) {timeout_w = t;}
|
||||
|
||||
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();
|
||||
|
||||
protected:
|
||||
//bool init();
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
|
||||
PIVector<Endpoint> eps;
|
||||
ushort vid_, pid_;
|
||||
int dev_num, intefrace_, timeout_r, timeout_w;
|
||||
int interface_claimed;
|
||||
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
|
||||
6
remote_console/CMakeLists.txt
Normal file
6
remote_console/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} . ../)
|
||||
file(GLOB CPPS "*.cpp")
|
||||
add_definitions(-Wall -O2)
|
||||
add_executable(pip_remote_console "main.cpp")
|
||||
target_link_libraries(pip_remote_console pip)
|
||||
66
remote_console/main.cpp
Normal file
66
remote_console/main.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Remote console viewer
|
||||
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pip.h"
|
||||
|
||||
void key_event(char key, void * );
|
||||
|
||||
PIConsole console(false, key_event);
|
||||
PIStringList as;
|
||||
bool selected = false;
|
||||
|
||||
void key_event(char key, void * ) {
|
||||
if (key < '1' || key > '9') return;
|
||||
int ind = key - '1';
|
||||
if (ind < 0 || ind >= as.size_s()) return;
|
||||
selected = true;
|
||||
console.connectToServer(as[ind]);
|
||||
console.clearScreen();
|
||||
piCout << "Connecting to" << console.selectedServer() << "...";
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
console.enableExitCapture();
|
||||
console.listenServers();
|
||||
while (!PIKbdListener::exiting) {
|
||||
msleep(200);
|
||||
if (selected) break;
|
||||
console.clearScreen();
|
||||
as = console.availableServers();
|
||||
if (as.isEmpty()) {
|
||||
piCout << "No servers are available!";
|
||||
} else {
|
||||
piCout << "Select one with numeric key:";
|
||||
for (int i = 0; i < as.size_s(); ++i)
|
||||
piCout << (i + 1) << as[i];
|
||||
}
|
||||
}
|
||||
if (!selected) return 0;
|
||||
console.clearScreen();
|
||||
piCout << "Connecting to" << console.selectedServer() << "...";
|
||||
while (!PIKbdListener::exiting) {
|
||||
msleep(20);
|
||||
if (console.isConnected())
|
||||
break;
|
||||
}
|
||||
if (PIKbdListener::exiting)
|
||||
return 0;
|
||||
console.start();
|
||||
console.waitForFinish();
|
||||
};
|
||||
Reference in New Issue
Block a user