30.11.2013 - New PICollection namespace, Android support, my own PIVector implementation
This commit is contained in:
@@ -5,7 +5,7 @@ activity=pip
|
||||
activityId=
|
||||
desktop=-1
|
||||
formfactor=0
|
||||
geometry=0,0,1644,997
|
||||
geometry=0,0,1607,862
|
||||
immutability=1
|
||||
lastDesktop=-1
|
||||
lastScreen=0
|
||||
|
||||
@@ -2,11 +2,11 @@ project(pip)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} .)
|
||||
include(CheckFunctionExists)
|
||||
set(VERSION "0.0306")
|
||||
set(VERSION "0.0307")
|
||||
set(SOVERSION ${VERSION})
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
set(LIBS)
|
||||
file(GLOB CPPS "pi*.cpp")
|
||||
file(GLOB CPPS "pi*.cpp" "ifaddrs_3rd.c")
|
||||
|
||||
|
||||
# Check Bessel functions
|
||||
@@ -49,6 +49,16 @@ else ()
|
||||
endif ()
|
||||
|
||||
|
||||
# Check if STL containers is on (to enable use "-DPIP_CONTAINERS_STL=" argument of cmake)
|
||||
if (DEFINED PIP_CONTAINERS_STL)
|
||||
message(STATUS "Building with STL containers")
|
||||
unset(PIP_CONTAINERS_STL)
|
||||
add_definitions("-DPIP_CONTAINERS_STL")
|
||||
else ()
|
||||
message(STATUS "Building with PIP containers")
|
||||
endif ()
|
||||
|
||||
|
||||
if (${WIN32})
|
||||
list(APPEND LIBS ws2_32 Iphlpapi)
|
||||
execute_process(COMMAND "make_rc_win.bat" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
@@ -77,11 +87,14 @@ else ()
|
||||
endif ()
|
||||
endif ()
|
||||
target_link_libraries(pip ${LIBS})
|
||||
install(TARGETS pip DESTINATION bin)
|
||||
|
||||
|
||||
# Test program
|
||||
find_package(Qt4 REQUIRED)
|
||||
include_directories(${QT_INCLUDES})
|
||||
add_executable(pip_test "main.cpp")
|
||||
target_link_libraries(pip_test pip)
|
||||
target_link_libraries(pip_test pip ${QT_QTCORE_LIBRARY})
|
||||
|
||||
|
||||
add_subdirectory(system_test)
|
||||
|
||||
2282
Doxyfile
2282
Doxyfile
@@ -1,112 +1,104 @@
|
||||
# Doxyfile 1.8.5
|
||||
# Doxyfile 1.8.4
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
# doxygen (www.doxygen.org) for a project
|
||||
#
|
||||
# All text after a double hash (##) is considered a comment and is placed in
|
||||
# front of the TAG it is preceding.
|
||||
#
|
||||
# All text after a single hash (#) is considered a comment and will be ignored.
|
||||
# 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 (\" \").
|
||||
# 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.
|
||||
# The default value is: UTF-8.
|
||||
# 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 a sequence of words surrounded by
|
||||
# double-quotes, unless you are using Doxywizard) that should identify the
|
||||
# project for which the documentation is generated. This name is used in the
|
||||
# title of most generated pages and in a few other places.
|
||||
# The default value is: My Project.
|
||||
# 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.
|
||||
# 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
|
||||
PROJECT_NUMBER = 0.3.7
|
||||
|
||||
# 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.
|
||||
# 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.
|
||||
# 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) path
|
||||
# into which the generated documentation will be written. 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.
|
||||
# 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 causes
|
||||
# performance problems for the file system.
|
||||
# The default value is: NO.
|
||||
# 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.
|
||||
# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-
|
||||
# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi,
|
||||
# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en,
|
||||
# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish,
|
||||
# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
|
||||
# Turkish, Ukrainian and Vietnamese.
|
||||
# The default value is: English.
|
||||
# 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, Latvian, 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 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.
|
||||
# The default value is: YES.
|
||||
# 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 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
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
|
||||
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 and the.
|
||||
# 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" \
|
||||
@@ -121,9 +113,8 @@ ABBREVIATE_BRIEF = "The $name class" \
|
||||
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
|
||||
# Doxygen will generate a detailed section even if there is only a brief
|
||||
# description.
|
||||
# The default value is: NO.
|
||||
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
|
||||
@@ -131,164 +122,146 @@ ALWAYS_DETAILED_SEC = NO
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
|
||||
# If the FULL_PATH_NAMES tag is set to YES 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
|
||||
# The default value is: YES.
|
||||
# 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
|
||||
|
||||
# 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 can specify absolute paths here, but also relative paths, which
|
||||
# will be relative from the directory where doxygen is started.
|
||||
# This tag requires that the tag FULL_PATH_NAMES is set to 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 list of include paths that are normally passed to the compiler
|
||||
# using the -I flag.
|
||||
# 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 is your file systems doesn't
|
||||
# support long names like on DOS, Mac, or CD-ROM.
|
||||
# The default value is: NO.
|
||||
# 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-style will behave just like regular Qt-
|
||||
# style comments (thus requiring an explicit @brief command for a brief
|
||||
# description.)
|
||||
# The default value is: 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 Qt-style will behave just like regular Qt-style comments (thus
|
||||
# requiring an explicit \brief command for a brief description.)
|
||||
# The default value is: 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 behavior. 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 behavior instead.
|
||||
#
|
||||
# Note that setting this tag to YES also means that rational rose comments are
|
||||
# not recognized any more.
|
||||
# The default value is: 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 then an undocumented member inherits the
|
||||
# documentation from any documented member that it re-implements.
|
||||
# The default value is: YES.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# 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.
|
||||
# Minimum value: 1, maximum value: 16, default value: 4.
|
||||
# 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 act 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.
|
||||
# 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"
|
||||
"events=\name Events" \
|
||||
"ioparams=\name Configurable parameters"
|
||||
|
||||
# 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.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# 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 or
|
||||
# Python sources only. Doxygen will then generate output that is more tailored
|
||||
# for that language. For instance, namespaces will be presented as packages,
|
||||
# qualified scopes will look different, etc.
|
||||
# The default value is: 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. Doxygen will then generate output that is tailored for Fortran.
|
||||
# The default value is: NO.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# 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,
|
||||
# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
|
||||
# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
|
||||
# (default is Fortran), use: inc=Fortran f=C.
|
||||
#
|
||||
# Note For files without extension you can use no_extension as a placeholder.
|
||||
#
|
||||
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
||||
# the files are not read by doxygen.
|
||||
# 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 the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
|
||||
# according to the Markdown format, which allows for more readable
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
# 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
|
||||
|
||||
@@ -296,41 +269,35 @@ MARKDOWN_SUPPORT = YES
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
|
||||
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);
|
||||
# versus func(std::string) {}). This also make the inheritance and collaboration
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
|
||||
# If you use Microsoft's C++/CLI language, you should set this option to YES to
|
||||
# enable parsing support.
|
||||
# The default value is: NO.
|
||||
|
||||
CPP_CLI_SUPPORT = NO
|
||||
|
||||
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
|
||||
# http://www.riverbankcomputing.co.uk/software/sip/intro) 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.
|
||||
# The default value is: 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 will make
|
||||
# doxygen to 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.
|
||||
# The default value is: YES.
|
||||
# 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
|
||||
|
||||
@@ -338,61 +305,51 @@ IDL_PROPERTY_SUPPORT = NO
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
|
||||
# Set the SUBGROUPING tag to YES 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.
|
||||
# The default value is: YES.
|
||||
# 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).
|
||||
#
|
||||
# Note that this feature does not work in combination with
|
||||
# SEPARATE_MEMBER_PAGES.
|
||||
# The default value is: 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 or simple typedef fields will be shown inline in
|
||||
# the documentation of the scope in which they are defined (i.e. file,
|
||||
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
|
||||
# unions with only public data fields or simple typedef 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, structs, classes, and unions are shown on a separate page (for HTML and
|
||||
# Man pages) or section (for LaTeX and RTF).
|
||||
# The default value is: NO.
|
||||
# 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 tag is enabled, a typedef of a struct, union, or
|
||||
# enum is documented as struct, union, or enum with the name of the typedef. So
|
||||
# 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
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
|
||||
# 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 appears 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. At the end of a run doxygen will report the cache usage and suggest
|
||||
# the optimal cache size from a speed point of view.
|
||||
# Minimum value: 0, maximum value: 9, default value: 0.
|
||||
# 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
|
||||
|
||||
@@ -401,369 +358,329 @@ LOOKUP_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# 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 respectively EXTRACT_STATIC tags are set to YES.
|
||||
# Note: This will also disable the warnings about undocumented members that are
|
||||
# normally produced when WARNINGS is set to YES.
|
||||
# The default value is: NO.
|
||||
# documentation are documented, even if no documentation was available.
|
||||
# Private class members and static file members will be hidden unless
|
||||
# the EXTRACT_PRIVATE respectively 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.
|
||||
# The default value is: 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.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_PACKAGE = NO
|
||||
|
||||
# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
|
||||
# included in the documentation.
|
||||
# The default value is: 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. Does not have any effect
|
||||
# for Java sources.
|
||||
# The default value is: YES.
|
||||
# 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 only methods in the interface are
|
||||
# included.
|
||||
# The default value is: NO.
|
||||
# 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 namespace
|
||||
# are hidden.
|
||||
# The default value is: NO.
|
||||
# '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 inside documented classes or files. If set to NO 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.
|
||||
# The default value is: 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 these classes will be included in the various overviews. This option has
|
||||
# no effect if EXTRACT_ALL is enabled.
|
||||
# The default value is: NO.
|
||||
# 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 these declarations will be
|
||||
# included in the documentation.
|
||||
# The default value is: NO.
|
||||
# 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 these
|
||||
# blocks will be appended to the function's detailed documentation block.
|
||||
# The default value is: NO.
|
||||
# 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 then the documentation
|
||||
# will be excluded. Set it to YES to include the internal documentation.
|
||||
# The default value is: 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
|
||||
# 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.
|
||||
# The default value is: system dependent.
|
||||
|
||||
CASE_SENSE_NAMES = NO
|
||||
|
||||
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
|
||||
# their full class and namespace scopes in the documentation. If set to YES the
|
||||
# scope will be hidden.
|
||||
# The default value is: 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 then doxygen will put a list of
|
||||
# the files that are included by a file in the documentation of that file.
|
||||
# The default value is: YES.
|
||||
# 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.
|
||||
# The default value is: 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 then a tag [inline] is inserted in the
|
||||
# documentation for inline members.
|
||||
# The default value is: YES.
|
||||
# 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 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.
|
||||
# The default value is: 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
|
||||
# descriptions of file, namespace and class members alphabetically by member
|
||||
# name. If set to NO the members will appear in declaration order.
|
||||
# The default value is: 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 constructors will appear in the
|
||||
# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
|
||||
# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
|
||||
# member documentation.
|
||||
# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
|
||||
# detailed member documentation.
|
||||
# The default value is: 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 group names will
|
||||
# appear in their defined order.
|
||||
# The default value is: 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 class list will
|
||||
# be sorted only by class name, not including the namespace part.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# 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.
|
||||
# The default value is: 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.
|
||||
# The default value is: YES.
|
||||
# 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.
|
||||
# The default value is: 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.
|
||||
# The default value is: 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.
|
||||
# The default value is: 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.
|
||||
# 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 that the
|
||||
# initial value of a variable or macro / define can have 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 value of individual variables and macros / defines can be
|
||||
# controlled using \showinitializer or \hideinitializer command in the
|
||||
# documentation regardless of this setting.
|
||||
# Minimum value: 0, maximum value: 10000, default value: 30.
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
# 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 value is: YES.
|
||||
# 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 value is: 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. For an example see the documentation.
|
||||
# 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.
|
||||
#
|
||||
# Note that if you run doxygen from a directory containing a file called
|
||||
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
|
||||
# tag is left empty.
|
||||
# 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 reference definitions. This must be a list of .bib files. The .bib
|
||||
# extension is automatically appended if omitted. This 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. See
|
||||
# also \cite for info how to create references.
|
||||
# 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
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The QUIET tag can be used to turn on/off the messages that are generated to
|
||||
# standard output by doxygen. If QUIET is set to YES this implies that the
|
||||
# messages are off.
|
||||
# The default value is: NO.
|
||||
# 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 to standard error ( stderr) by doxygen. If WARNINGS is set to YES
|
||||
# this implies that the warnings are on.
|
||||
#
|
||||
# Tip: Turn warnings on while writing the documentation.
|
||||
# The default value is: YES.
|
||||
# generated by doxygen. Possible values are YES and NO. If left blank
|
||||
# NO is used.
|
||||
|
||||
WARNINGS = YES
|
||||
|
||||
# If the WARN_IF_UNDOCUMENTED tag 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.
|
||||
# The default value is: 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 the WARN_IF_DOC_ERROR tag 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.
|
||||
# The default value is: 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
|
||||
|
||||
# This 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 doxygen will only warn about wrong or incomplete parameter
|
||||
# documentation, but not about the absence of documentation.
|
||||
# The default value is: NO.
|
||||
# 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)
|
||||
# The default value is: $file:$line: $text.
|
||||
# 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 standard
|
||||
# error (stderr).
|
||||
# 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
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The INPUT tag is 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.
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
# 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. Doxygen uses
|
||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||
# documentation (see: http://www.gnu.org/software/libiconv) for the list of
|
||||
# possible encodings.
|
||||
# The default value is: UTF-8.
|
||||
# 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 patterns (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++, *.java, *.ii,
|
||||
# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
|
||||
# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
|
||||
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
|
||||
# *.qsf, *.as and *.js.
|
||||
# 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 \
|
||||
@@ -800,16 +717,15 @@ FILE_PATTERNS = *.c \
|
||||
*.vhd \
|
||||
*.vhdl
|
||||
|
||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||
# be searched for input files as well.
|
||||
# The default value is: NO.
|
||||
# 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.
|
||||
|
||||
@@ -818,16 +734,14 @@ 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.
|
||||
# The default value is: NO.
|
||||
|
||||
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/*
|
||||
# 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 =
|
||||
|
||||
@@ -836,49 +750,41 @@ EXCLUDE_PATTERNS =
|
||||
# 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
|
||||
#
|
||||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories use the pattern */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).
|
||||
# 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 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.
|
||||
# The default value is: NO.
|
||||
# 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 images that are to be included in the documentation (see the
|
||||
# \image command).
|
||||
# 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 = doc/images
|
||||
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
# Note that the filter must not add or remove lines; it is applied before the
|
||||
# code is scanned, but not when the output code is generated. If lines are added
|
||||
# or removed, the anchors will not be placed correctly.
|
||||
@@ -886,241 +792,169 @@ IMAGE_PATH = doc/images
|
||||
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 information on how
|
||||
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
|
||||
# patterns match the file name, INPUT_FILTER is applied.
|
||||
# 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 also be used to filter the input files that are used for
|
||||
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
|
||||
# The default value is: NO.
|
||||
# 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 tag requires that the tag FILTER_SOURCE_FILES is set to YES.
|
||||
# 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_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
|
||||
# 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 to reuse the introduction page also for the doxygen output.
|
||||
# and want reuse the introduction page also for the doxygen output.
|
||||
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
# 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 that
|
||||
# also VERBATIM_HEADERS is set to NO.
|
||||
# The default value is: NO.
|
||||
# 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,
|
||||
# classes and enums directly into the documentation.
|
||||
# The default value is: 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 will instruct doxygen to hide any
|
||||
# special comment blocks from generated source code fragments. Normal C, C++ and
|
||||
# Fortran comments will always remain visible.
|
||||
# The default value is: YES.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# 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.
|
||||
# The default value is: 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 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.
|
||||
# The default value is: YES.
|
||||
# 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 SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
|
||||
# source code will show a tooltip with additional information such as prototype,
|
||||
# brief description and links to the definition and documentation. Since this
|
||||
# will make the HTML file larger and loading of large files a bit slower, you
|
||||
# can opt to disable this feature.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag SOURCE_BROWSER is set to YES.
|
||||
|
||||
SOURCE_TOOLTIPS = 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.
|
||||
#
|
||||
# To use it do the following:
|
||||
# - Install the latest version of global
|
||||
# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
|
||||
# - Make sure the INPUT points to the root of the source tree
|
||||
# - Run doxygen as normal
|
||||
#
|
||||
# Doxygen will invoke htags (and that will in turn invoke gtags), so these
|
||||
# tools must be available from the command line (i.e. in the search path).
|
||||
#
|
||||
# The result: instead of the source browser generated by doxygen, the links to
|
||||
# source code will now point to the output of htags.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag SOURCE_BROWSER is set to 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 the YES 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.
|
||||
# See also: Section \class.
|
||||
# The default value is: YES.
|
||||
# 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
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
|
||||
# clang parser (see: http://clang.llvm.org/) for more acurate parsing at the
|
||||
# cost of reduced performance. This can be particularly helpful with template
|
||||
# rich C++ code for which doxygen's built-in parser lacks the necessary type
|
||||
# information.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# compiled with the --with-libclang option.
|
||||
# The default value is: NO.
|
||||
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||
# line options that you would normally use when invoking the compiler. Note that
|
||||
# the include paths will already be set by doxygen for the files and directories
|
||||
# specified with INPUT and INCLUDE_PATH.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_OPTIONS =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
# 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
|
||||
|
||||
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
|
||||
# which the alphabetical index list will be split.
|
||||
# Minimum value: 1, maximum value: 20, default value: 5.
|
||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to 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 a prefix (or a list of prefixes) that should be ignored
|
||||
# while generating the index headers.
|
||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
|
||||
# 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
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
|
||||
# The default value is: YES.
|
||||
# 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.
|
||||
# The default directory is: html.
|
||||
# This tag requires that the tag GENERATE_HTML is set to 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).
|
||||
# The default value is: .html.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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 user-defined HTML header file for
|
||||
# each generated HTML page. If the tag is left blank doxygen will generate a
|
||||
# standard header.
|
||||
#
|
||||
# To get valid HTML the header file that includes any scripts and style sheets
|
||||
# that doxygen needs, which is dependent on the configuration options used (e.g.
|
||||
# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
|
||||
# default header using
|
||||
# doxygen -w html new_header.html new_footer.html new_stylesheet.css
|
||||
# YourConfigFile
|
||||
# and then modify the file new_header.html. See also section "Doxygen usage"
|
||||
# for information on how to generate the default header that doxygen normally
|
||||
# uses.
|
||||
# Note: The header is subject to change so you typically have to regenerate the
|
||||
# default header when upgrading to a newer version of doxygen. For a description
|
||||
# of the possible markers and block names see the documentation.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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 user-defined HTML footer for each
|
||||
# generated HTML page. If the tag is left blank doxygen will generate a standard
|
||||
# footer. See HTML_HEADER for more information on how to generate a default
|
||||
# footer and what special commands can be used inside the footer. See also
|
||||
# section "Doxygen usage" for information on how to generate the default footer
|
||||
# that doxygen normally uses.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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.
|
||||
# See also section "Doxygen usage" for information on how to generate the style
|
||||
# sheet that doxygen normally uses.
|
||||
# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
|
||||
# it is more robust and this tag (HTML_STYLESHEET) will in the future become
|
||||
# obsolete.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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. For an example
|
||||
# see the documentation.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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 =
|
||||
|
||||
@@ -1128,807 +962,629 @@ HTML_EXTRA_STYLESHEET =
|
||||
# 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.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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 stylesheet 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.
|
||||
# Minimum value: 0, maximum value: 359, default value: 220.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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.
|
||||
# Minimum value: 0, maximum value: 255, default value: 100.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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.
|
||||
# Minimum value: 40, maximum value: 240, default value: 80.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
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.
|
||||
# Minimum value: 0, maximum value: 9999, default value: 100.
|
||||
# This tag requires that the tag GENERATE_HTML is set to 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 (see: http://developer.apple.com/tools/xcode/), 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
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
GENERATE_DOCSET = NO
|
||||
|
||||
# This tag determines the name of the docset 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.
|
||||
# The default value is: Doxygen generated docs.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
# 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"
|
||||
|
||||
# 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.
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
# 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
|
||||
|
||||
# The DOCSET_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.
|
||||
# The default value is: org.doxygen.Publisher.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
# 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 DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
|
||||
# The default value is: Publisher.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
|
||||
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
||||
# Windows.
|
||||
#
|
||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
||||
# files are now used as the Windows 98 help format, and will replace the old
|
||||
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
|
||||
# HTML files also contain an index, a table of contents, and you can search for
|
||||
# words in the documentation. The HTML workshop also contains a viewer for
|
||||
# compressed HTML files.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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
|
||||
|
||||
# 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
|
||||
# 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.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
CHM_FILE =
|
||||
|
||||
# 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.
|
||||
# The file has to be specified with full path.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
# 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 =
|
||||
|
||||
# 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).
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
# 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
|
||||
|
||||
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
|
||||
# and project file content.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
# 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 =
|
||||
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
# 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 table of contents of the HTML help documentation and to the tree view.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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.
|
||||
# This tag requires that the tag GENERATE_QHP is set to 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 Qt Help Project / Namespace
|
||||
# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
# 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 Qt Help Project / Virtual
|
||||
# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
|
||||
# folders).
|
||||
# The default value is: doc.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
# 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 the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
||||
# filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
# 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_FILTER_ATTRS tag specifies the list of the attributes of the
|
||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
# 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. Qt Help Project / Filter Attributes (see:
|
||||
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
# 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 =
|
||||
|
||||
# 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.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
# 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 =
|
||||
QHG_LOCATION = qhelpgenerator
|
||||
|
||||
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
|
||||
# generated, together with the HTML files, they 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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. Each documentation set should have its own identifier.
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
|
||||
# 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
|
||||
|
||||
# If you want full control over the layout of the generated HTML pages it might
|
||||
# be necessary to disable the index and replace it with your own. The
|
||||
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
|
||||
# of each HTML page. A value of NO enables the index and the value YES disables
|
||||
# it. Since the tabs in the index contain the same information as the navigation
|
||||
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
|
||||
# further fine-tune the look of the index. As an example, the default style
|
||||
# sheet generated by doxygen has an example that shows how to put an image at
|
||||
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
|
||||
# the same information as the tab index, you could consider setting
|
||||
# DISABLE_INDEX to YES when enabling this option.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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 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.
|
||||
# Minimum value: 0, maximum value: 20, default value: 4.
|
||||
# This tag requires that the tag GENERATE_HTML is set to 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.
|
||||
# Minimum value: 0, maximum value: 1500, default value: 250.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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. 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.
|
||||
# Minimum value: 8, maximum value: 50, default value: 10.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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 directory before the changes have effect.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to 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
|
||||
# the MathJax output. See the MathJax site (see:
|
||||
# http://docs.mathjax.org/en/latest/output.html) for more details.
|
||||
# Possible values are: HTML-CSS (which is slower, but has the best
|
||||
# compatibility), NativeMML (i.e. MathML) and SVG.
|
||||
# The default value is: HTML-CSS.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
# the 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.
|
||||
# The default value is: http://cdn.mathjax.org/mathjax/latest.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
# 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 more MathJax
|
||||
# extension names that should be enabled during MathJax rendering. For example
|
||||
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
|
||||
# names that should be enabled during MathJax rendering.
|
||||
|
||||
MATHJAX_EXTENSIONS =
|
||||
|
||||
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
||||
# of code that will be used on startup of the MathJax code. See the MathJax site
|
||||
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
|
||||
# example see the documentation.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript
|
||||
# pieces of code that will be used on startup of the MathJax code.
|
||||
|
||||
MATHJAX_CODEFILE =
|
||||
|
||||
# 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. It is possible to
|
||||
# search using the keyboard; to jump to the search box use <access key> + S
|
||||
# (what the <access key> is depends on the OS and browser, but it is typically
|
||||
# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
|
||||
# key> to jump into the search results window, the results can be navigated
|
||||
# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
|
||||
# the search. The filter options can be selected when the cursor is inside the
|
||||
# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
|
||||
# to select a filter and <Enter> or <escape> to activate or cancel the filter
|
||||
# option.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
# 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 searching depending on the
|
||||
# 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 section "External Indexing and Searching" for details.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
# enabled the indexing and searching needs to be provided by external tools.
|
||||
# See the manual for details.
|
||||
|
||||
SERVER_BASED_SEARCH = NO
|
||||
|
||||
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
|
||||
# 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: http://xapian.org/).
|
||||
#
|
||||
# See the section "External Indexing and Searching" for details.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
# 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 return the search results when EXTERNAL_SEARCH is enabled.
|
||||
#
|
||||
# Doxygen ships with an example indexer ( doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see: http://xapian.org/). See the section "External Indexing and
|
||||
# Searching" for details.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
# 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.
|
||||
# The default file is: searchdata.xml.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
|
||||
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
|
||||
# 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.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
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 = tagname1=loc1 tagname2=loc2 ...
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
# 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
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
|
||||
# The default value is: YES.
|
||||
# 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.
|
||||
# The default directory is: latex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
# The default file is: latex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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.
|
||||
# The default file is: makeindex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
|
||||
# 14 inches) and executive (7.25 x 10.5 inches).
|
||||
# The default value is: a4.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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 a4 will be used.
|
||||
|
||||
PAPER_TYPE = a4
|
||||
|
||||
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
|
||||
# that should be included in the LaTeX output. To get the times font for
|
||||
# instance you can specify
|
||||
# EXTRA_PACKAGES=times
|
||||
# If left blank no extra packages will be included.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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. See
|
||||
# section "Doxygen usage" for information on how to let doxygen write the
|
||||
# default header to a separate file.
|
||||
#
|
||||
# Note: Only use a user-defined header if you know what you are doing! The
|
||||
# following commands have a special meaning inside the header: $title,
|
||||
# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
|
||||
# replace them by respectively the title of the page, the current date and time,
|
||||
# only the current date, the version number of doxygen, the project name (see
|
||||
# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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.
|
||||
#
|
||||
# Note: Only use a user-defined footer if you know what you are doing!
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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 =
|
||||
|
||||
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||
# other source files which should be copied to the LATEX_OUTPUT output
|
||||
# directory. Note that the files will be copied as-is; there are no commands or
|
||||
# markers available.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images
|
||||
# or other source files which should be copied to the LaTeX output directory.
|
||||
# Note that the files will be copied as-is; there are no commands or markers
|
||||
# available.
|
||||
|
||||
LATEX_EXTRA_FILES =
|
||||
|
||||
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
|
||||
# prepared for conversion to PDF (using ps2pdf or pdflatex). 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.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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 LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
||||
# the PDF file directly from the LaTeX files. Set this option to YES to get a
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to 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 the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
|
||||
# index chapters (such as File Index, Compound Index, etc.) in the output.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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 the LATEX_SOURCE_CODE tag 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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. See
|
||||
# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
||||
# The default value is: plain.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
# 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
|
||||
# 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 too pretty with other RTF
|
||||
# readers/editors.
|
||||
# The default value is: NO.
|
||||
# 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.
|
||||
# The default directory is: rtf.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
# 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 some other Word compatible readers that support those
|
||||
# fields.
|
||||
#
|
||||
# Note: WordPad (write) and others do not support links.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
# 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 stylesheet 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.
|
||||
#
|
||||
# See also section "Doxygen usage" for information on how to generate the
|
||||
# default style sheet that doxygen normally uses.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
# 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. A template extensions file can be generated
|
||||
# using doxygen -e rtf extensionFile.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
# 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
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
|
||||
# classes and files.
|
||||
# The default value is: NO.
|
||||
# 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. A directory man3 will be created inside the directory specified by
|
||||
# MAN_OUTPUT.
|
||||
# The default directory is: man.
|
||||
# This tag requires that the tag GENERATE_MAN is set to YES.
|
||||
# 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. In case the manual section does not start with a number, the number
|
||||
# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
|
||||
# optional.
|
||||
# The default value is: .3.
|
||||
# This tag requires that the tag GENERATE_MAN is set to YES.
|
||||
# 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 value is: NO.
|
||||
# This tag requires that the tag GENERATE_MAN is set to YES.
|
||||
# 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
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# 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.
|
||||
# The default directory is: xml.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
# 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 a XML schema, which can be used by a
|
||||
# validating XML parser to check the syntax of the XML files.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
# 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 a XML DTD, which can be used by a
|
||||
# validating XML parser to check the syntax of the XML files.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
# 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 related to the DOCBOOK output
|
||||
# configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
|
||||
# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files
|
||||
# that can be used to generate PDF.
|
||||
# The default value is: NO.
|
||||
|
||||
GENERATE_DOCBOOK = NO
|
||||
|
||||
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
|
||||
# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
|
||||
# front of it.
|
||||
# The default directory is: docbook.
|
||||
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
|
||||
# front of it. If left blank docbook will be used as the default path.
|
||||
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
|
||||
# Definitions (see http://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.
|
||||
# The default value is: NO.
|
||||
# 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
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
|
||||
# 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.
|
||||
# This tag requires that the tag GENERATE_PERLMOD is set to 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 =
|
||||
|
||||
@@ -1936,129 +1592,111 @@ PERLMOD_MAKEVAR_PREFIX =
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
|
||||
# C-preprocessor directives found in the sources and include files.
|
||||
# The default value is: YES.
|
||||
# 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 only conditional compilation will be
|
||||
# performed. Macro expansion can be done in a controlled way by setting
|
||||
# EXPAND_ONLY_PREDEF to YES.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to 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 includes files in the
|
||||
# INCLUDE_PATH will be searched if a #include is found.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
# 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.
|
||||
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
|
||||
# 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.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
# 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 e.g.
|
||||
# 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.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
# 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.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
# 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 then doxygen's preprocessor will
|
||||
# remove all refrences to function-like macros that are alone on a line, have an
|
||||
# all uppercase name, and do not end with a semicolon. Such function macros are
|
||||
# typically used for boiler-plate code, and will confuse the parser if not
|
||||
# removed.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
# 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 options related to external references
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The TAGFILES tag can be used to specify one or more tag files. 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 ...
|
||||
# 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. See the
|
||||
# section "Linking to external documentation" for more information about the use
|
||||
# of tag files.
|
||||
# Note: Each tag file must have an unique name (where the name does NOT include
|
||||
# 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 = 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. See section "Linking to
|
||||
# external documentation" for more information about the usage of tag files.
|
||||
# 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 class will be listed in the
|
||||
# class index. If set to NO only the inherited external classes will be listed.
|
||||
# The default value is: NO.
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
# 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
|
||||
|
||||
# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
|
||||
# the related pages index. If set to NO, only the current project's pages will
|
||||
# be listed.
|
||||
# The default value is: YES.
|
||||
# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed
|
||||
# in the related pages index. If set to NO, only the current project's
|
||||
# pages will be listed.
|
||||
|
||||
EXTERNAL_PAGES = YES
|
||||
|
||||
# The PERL_PATH should be the absolute path and name of the perl script
|
||||
# interpreter (i.e. the result of 'which perl').
|
||||
# The default file (with absolute path) is: /usr/bin/perl.
|
||||
# interpreter (i.e. the result of `which perl').
|
||||
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
@@ -2066,280 +1704,222 @@ PERL_PATH = /usr/bin/perl
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
|
||||
# (in HTML 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.
|
||||
# The default value is: YES.
|
||||
# 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
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
# 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 (see:
|
||||
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
|
||||
# Bell Labs. The other options in this section have no effect if this option is
|
||||
# set to NO
|
||||
# The default value is: NO.
|
||||
# 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 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.
|
||||
# Minimum value: 0, maximum value: 32, default value: 0.
|
||||
# This tag requires that the tag HAVE_DOT is set to 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
|
||||
|
||||
# When you want a differently looking font n the dot files that doxygen
|
||||
# generates you can specify the font name using DOT_FONTNAME. You need to make
|
||||
# sure dot is able to find the font, which can be done by putting it in a
|
||||
# standard location or by setting the DOTFONTPATH environment variable or by
|
||||
# setting DOT_FONTPATH to the directory containing the font.
|
||||
# The default value is: Helvetica.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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
|
||||
DOT_FONTNAME = "DejaVu Sans Mono"
|
||||
|
||||
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
|
||||
# dot graphs.
|
||||
# Minimum value: 4, maximum value: 24, default value: 10.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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 default font as specified with
|
||||
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
|
||||
# the path where dot can find it using this tag.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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 tag is 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.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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 tag is 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.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to 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 tag is set to YES then doxygen will generate a graph for
|
||||
# groups, showing the direct groups dependencies.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
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 manageable. Set this to 0
|
||||
# for no limit. Note that the threshold may be exceeded by 50% before the limit
|
||||
# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
|
||||
# but if the number exceeds 15, the total amount of fields shown is limited to
|
||||
# 10.
|
||||
# Minimum value: 0, maximum value: 100, default value: 10.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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
|
||||
# manageable. 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 the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
||||
# collaboration graphs will show the relations between templates and their
|
||||
# instances.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# If set to YES, the inheritance and collaboration graphs will show the
|
||||
# relations between templates and their instances.
|
||||
|
||||
TEMPLATE_RELATIONS = NO
|
||||
|
||||
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES 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.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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 INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES 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.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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 tag is 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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 tag is 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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 tag is set to YES then doxygen will graphical
|
||||
# hierarchy of all classes instead of a textual one.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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 tag is 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.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to 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.
|
||||
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
|
||||
# to make the SVG files visible in IE 9+ (other browsers do not have this
|
||||
# requirement).
|
||||
# Possible values are: png, jpg, gif and svg.
|
||||
# The default value is: png.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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.
|
||||
# Note: 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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 DOT_PATH tag can be used to specify the path where the dot tool can be
|
||||
# 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.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
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).
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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).
|
||||
# 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.
|
||||
# Minimum value: 0, maximum value: 10000, default value: 50.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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
|
||||
# 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.
|
||||
# Minimum value: 0, maximum value: 1000, default value: 0.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
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).
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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 doxygen will generate a legend page
|
||||
# explaining the meaning of the various boxes and arrows in the dot generated
|
||||
# graphs.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# 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 doxygen will remove the intermediate dot
|
||||
# files that are used to generate the various graphs.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to 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
|
||||
|
||||
519
ifaddrs_3rd.c
Normal file
519
ifaddrs_3rd.c
Normal file
@@ -0,0 +1,519 @@
|
||||
/*
|
||||
Copyright (c) 2013, Kenneth MacKay
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(__ANDROID__) || defined(_ANDROID_) || defined(ANDROID)
|
||||
|
||||
#include "ifaddrs_3rd.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
typedef struct NetlinkList {
|
||||
struct NetlinkList * m_next;
|
||||
struct nlmsghdr * m_data;
|
||||
unsigned int m_size;
|
||||
} NetlinkList;
|
||||
|
||||
static int netlink_socket(void) {
|
||||
int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (l_socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_nl l_addr;
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
if (bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) {
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return l_socket;
|
||||
}
|
||||
|
||||
static int netlink_send(int p_socket, int p_request) {
|
||||
char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
|
||||
memset(l_buffer, 0, sizeof(l_buffer));
|
||||
struct nlmsghdr * l_hdr = (struct nlmsghdr *)l_buffer;
|
||||
struct rtgenmsg * l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr);
|
||||
|
||||
l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg));
|
||||
l_hdr->nlmsg_type = p_request;
|
||||
l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||
l_hdr->nlmsg_pid = 0;
|
||||
l_hdr->nlmsg_seq = p_socket;
|
||||
l_msg->rtgen_family = AF_UNSPEC;
|
||||
|
||||
struct sockaddr_nl l_addr;
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
|
||||
}
|
||||
|
||||
static int netlink_recv(int p_socket, void * p_buffer, size_t p_len) {
|
||||
struct msghdr l_msg;
|
||||
struct iovec l_iov = { p_buffer, p_len };
|
||||
struct sockaddr_nl l_addr;
|
||||
int l_result;
|
||||
|
||||
for (;;) {
|
||||
l_msg.msg_name = (void *)&l_addr;
|
||||
l_msg.msg_namelen = sizeof(l_addr);
|
||||
l_msg.msg_iov = &l_iov;
|
||||
l_msg.msg_iovlen = 1;
|
||||
l_msg.msg_control = NULL;
|
||||
l_msg.msg_controllen = 0;
|
||||
l_msg.msg_flags = 0;
|
||||
int l_result = recvmsg(p_socket, &l_msg, 0);
|
||||
|
||||
if (l_result < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (l_msg.msg_flags & MSG_TRUNC) {
|
||||
// buffer was too small
|
||||
return -1;
|
||||
}
|
||||
return l_result;
|
||||
}
|
||||
}
|
||||
|
||||
static struct nlmsghdr * getNetlinkResponse(int p_socket, int * p_size, int * p_done) {
|
||||
size_t l_size = 4096;
|
||||
void * l_buffer = NULL;
|
||||
|
||||
for (;;) {
|
||||
free(l_buffer);
|
||||
l_buffer = malloc(l_size);
|
||||
|
||||
int l_read = netlink_recv(p_socket, l_buffer, l_size);
|
||||
*p_size = l_read;
|
||||
if (l_read == -2) {
|
||||
free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
if (l_read >= 0) {
|
||||
pid_t l_pid = getpid();
|
||||
struct nlmsghdr * l_hdr;
|
||||
for (l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) {
|
||||
if ((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (l_hdr->nlmsg_type == NLMSG_DONE) {
|
||||
*p_done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (l_hdr->nlmsg_type == NLMSG_ERROR) {
|
||||
free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return l_buffer;
|
||||
}
|
||||
|
||||
l_size *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList * newListItem(struct nlmsghdr * p_data, unsigned int p_size) {
|
||||
NetlinkList * l_item = malloc(sizeof(NetlinkList));
|
||||
l_item->m_next = NULL;
|
||||
l_item->m_data = p_data;
|
||||
l_item->m_size = p_size;
|
||||
return l_item;
|
||||
}
|
||||
|
||||
static void freeResultList(NetlinkList * p_list) {
|
||||
NetlinkList * l_cur;
|
||||
while (p_list) {
|
||||
l_cur = p_list;
|
||||
p_list = p_list->m_next;
|
||||
free(l_cur->m_data);
|
||||
free(l_cur);
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList * getResultList(int p_socket, int p_request) {
|
||||
if (netlink_send(p_socket, p_request) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetlinkList * l_list = NULL;
|
||||
NetlinkList * l_end = NULL;
|
||||
int l_size;
|
||||
int l_done = 0;
|
||||
while (!l_done) {
|
||||
struct nlmsghdr * l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
|
||||
if (!l_hdr) {
|
||||
// error
|
||||
freeResultList(l_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetlinkList * l_item = newListItem(l_hdr, l_size);
|
||||
if (!l_list) {
|
||||
l_list = l_item;
|
||||
} else {
|
||||
l_end->m_next = l_item;
|
||||
}
|
||||
l_end = l_item;
|
||||
}
|
||||
return l_list;
|
||||
}
|
||||
|
||||
static size_t maxSize(size_t a, size_t b) {
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) {
|
||||
switch (p_family) {
|
||||
case AF_INET:
|
||||
return sizeof(struct sockaddr_in);
|
||||
case AF_INET6:
|
||||
return sizeof(struct sockaddr_in6);
|
||||
case AF_PACKET:
|
||||
return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
|
||||
default:
|
||||
return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
static void makeSockaddr(sa_family_t p_family, struct sockaddr * p_dest, void * p_data, size_t p_size) {
|
||||
switch (p_family) {
|
||||
case AF_INET:
|
||||
memcpy(&((struct sockaddr_in *)p_dest)->sin_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&((struct sockaddr_in6 *)p_dest)->sin6_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_PACKET:
|
||||
memcpy(((struct sockaddr_ll *)p_dest)->sll_addr, p_data, p_size);
|
||||
((struct sockaddr_ll *)p_dest)->sll_halen = p_size;
|
||||
break;
|
||||
default:
|
||||
memcpy(p_dest->sa_data, p_data, p_size);
|
||||
break;
|
||||
}
|
||||
p_dest->sa_family = p_family;
|
||||
}
|
||||
|
||||
static void addToEnd(struct ifaddrs ** p_resultList, struct ifaddrs * p_entry) {
|
||||
if (!*p_resultList) {
|
||||
*p_resultList = p_entry;
|
||||
} else {
|
||||
struct ifaddrs * l_cur = *p_resultList;
|
||||
while (l_cur->ifa_next) {
|
||||
l_cur = l_cur->ifa_next;
|
||||
}
|
||||
l_cur->ifa_next = p_entry;
|
||||
}
|
||||
}
|
||||
|
||||
static void interpretLink(struct nlmsghdr * p_hdr, struct ifaddrs ** p_links, struct ifaddrs ** p_resultList) {
|
||||
struct ifinfomsg * l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
size_t l_dataSize = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
struct rtattr * l_rta;
|
||||
for (l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) {
|
||||
void * l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch (l_rta->rta_type) {
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
|
||||
break;
|
||||
case IFLA_IFNAME:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
l_dataSize += NLMSG_ALIGN(l_rtaSize);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ifaddrs * l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize + l_dataSize);
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = "";
|
||||
|
||||
char * l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
char * l_addr = l_name + l_nameSize;
|
||||
char * l_data = l_addr + l_addrSize;
|
||||
|
||||
l_entry->ifa_flags = l_info->ifi_flags;
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
for (l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) {
|
||||
void * l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch (l_rta->rta_type) {
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST: {
|
||||
size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
|
||||
makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
|
||||
((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
|
||||
if (l_rta->rta_type == IFLA_ADDRESS) {
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
} else {
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFLA_IFNAME:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
memcpy(l_data, l_rtaData, l_rtaDataSize);
|
||||
l_entry->ifa_data = l_data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
p_links[l_info->ifi_index - 1] = l_entry;
|
||||
}
|
||||
|
||||
static void interpretAddr(struct nlmsghdr * p_hdr, struct ifaddrs ** p_links, struct ifaddrs ** p_resultList) {
|
||||
struct ifaddrmsg * l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
|
||||
int l_addedNetmask = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
struct rtattr * l_rta;
|
||||
for (l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) {
|
||||
void * l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
if (l_info->ifa_family == AF_PACKET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (l_rta->rta_type) {
|
||||
case IFA_ADDRESS:
|
||||
case IFA_LOCAL:
|
||||
if ((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) {
|
||||
// make room for netmask
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
l_addedNetmask = 1;
|
||||
}
|
||||
case IFA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
break;
|
||||
case IFA_LABEL:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ifaddrs * l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name;
|
||||
|
||||
char * l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
char * l_addr = l_name + l_nameSize;
|
||||
|
||||
l_entry->ifa_flags = l_info->ifa_flags | p_links[l_info->ifa_index - 1]->ifa_flags;
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
for (l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) {
|
||||
void * l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch (l_rta->rta_type) {
|
||||
case IFA_ADDRESS:
|
||||
case IFA_BROADCAST:
|
||||
case IFA_LOCAL: {
|
||||
size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
|
||||
makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
if (l_info->ifa_family == AF_INET6) {
|
||||
if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) {
|
||||
((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
|
||||
}
|
||||
}
|
||||
|
||||
if (l_rta->rta_type == IFA_ADDRESS) {
|
||||
// apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
|
||||
if (l_entry->ifa_addr) {
|
||||
l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
|
||||
} else {
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
} else if (l_rta->rta_type == IFA_LOCAL) {
|
||||
if (l_entry->ifa_addr) {
|
||||
l_entry->ifa_dstaddr = l_entry->ifa_addr;
|
||||
}
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
} else {
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFA_LABEL:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6)) {
|
||||
unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
|
||||
unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
|
||||
char l_mask[16] = {0};
|
||||
unsigned i;
|
||||
for (i = 0; i < (l_prefix / 8); ++i) {
|
||||
l_mask[i] = 0xff;
|
||||
}
|
||||
l_mask[i] = 0xff << (8 - (l_prefix % 8));
|
||||
|
||||
makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
|
||||
l_entry->ifa_netmask = (struct sockaddr *)l_addr;
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
}
|
||||
|
||||
static void interpret(int p_socket, NetlinkList * p_netlinkList, struct ifaddrs ** p_links, struct ifaddrs ** p_resultList) {
|
||||
pid_t l_pid = getpid();
|
||||
for (; p_netlinkList; p_netlinkList = p_netlinkList->m_next) {
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr * l_hdr;
|
||||
for (l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) {
|
||||
if ((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (l_hdr->nlmsg_type == NLMSG_DONE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (l_hdr->nlmsg_type == RTM_NEWLINK) {
|
||||
interpretLink(l_hdr, p_links, p_resultList);
|
||||
} else if (l_hdr->nlmsg_type == RTM_NEWADDR) {
|
||||
interpretAddr(l_hdr, p_links, p_resultList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned countLinks(int p_socket, NetlinkList * p_netlinkList) {
|
||||
unsigned l_links = 0;
|
||||
pid_t l_pid = getpid();
|
||||
for (; p_netlinkList; p_netlinkList = p_netlinkList->m_next) {
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr * l_hdr;
|
||||
for (l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) {
|
||||
if ((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (l_hdr->nlmsg_type == NLMSG_DONE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (l_hdr->nlmsg_type == RTM_NEWLINK) {
|
||||
++l_links;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return l_links;
|
||||
}
|
||||
|
||||
int getifaddrs(struct ifaddrs ** ifap) {
|
||||
if (!ifap) {
|
||||
return -1;
|
||||
}
|
||||
*ifap = NULL;
|
||||
|
||||
int l_socket = netlink_socket();
|
||||
if (l_socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
NetlinkList * l_linkResults = getResultList(l_socket, RTM_GETLINK);
|
||||
if (!l_linkResults) {
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
NetlinkList * l_addrResults = getResultList(l_socket, RTM_GETADDR);
|
||||
if (!l_addrResults) {
|
||||
close(l_socket);
|
||||
freeResultList(l_linkResults);
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults);
|
||||
struct ifaddrs * l_links[l_numLinks];
|
||||
memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *));
|
||||
|
||||
interpret(l_socket, l_linkResults, l_links, ifap);
|
||||
interpret(l_socket, l_addrResults, l_links, ifap);
|
||||
|
||||
freeResultList(l_linkResults);
|
||||
freeResultList(l_addrResults);
|
||||
close(l_socket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void freeifaddrs(struct ifaddrs * ifa) {
|
||||
struct ifaddrs * l_cur;
|
||||
while (ifa) {
|
||||
l_cur = ifa;
|
||||
ifa = ifa->ifa_next;
|
||||
free(l_cur);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
58
ifaddrs_3rd.h
Normal file
58
ifaddrs_3rd.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1999
|
||||
* Berkeley Software Design, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
|
||||
*/
|
||||
|
||||
#if defined(__ANDROID__) || defined(_ANDROID_) || defined(ANDROID)
|
||||
|
||||
#ifndef _IFADDRS_H_
|
||||
#define _IFADDRS_H_
|
||||
|
||||
struct ifaddrs {
|
||||
struct ifaddrs *ifa_next;
|
||||
char *ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
struct sockaddr *ifa_addr;
|
||||
struct sockaddr *ifa_netmask;
|
||||
struct sockaddr *ifa_dstaddr;
|
||||
void *ifa_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* This may have been defined in <net/if.h>. Note that if <net/if.h> is
|
||||
* to be included it must be included before this header file.
|
||||
*/
|
||||
#ifndef ifa_broadaddr
|
||||
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern int getifaddrs(struct ifaddrs **ifap);
|
||||
extern void freeifaddrs(struct ifaddrs *ifa);
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
455
main.cpp
455
main.cpp
@@ -17,410 +17,63 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
//#define PIP_DEBUG
|
||||
/*#include "pip.h"
|
||||
|
||||
|
||||
class ElementA: public PIObject {
|
||||
PIOBJECT(ElementA)
|
||||
// ...
|
||||
};
|
||||
ADD_NEW_TO_COLLECTION(ab_group, ElementA)
|
||||
|
||||
class ElementB: public PIObject {
|
||||
PIOBJECT(ElementB)
|
||||
// ...
|
||||
};
|
||||
ADD_NEW_TO_COLLECTION(ab_group, ElementB)
|
||||
|
||||
class ElementC: public PIObject {
|
||||
PIOBJECT(ElementC)
|
||||
// ...
|
||||
};
|
||||
ADD_NEW_TO_COLLECTION(c_group, ElementC)
|
||||
|
||||
class ElementD: public PIObject {
|
||||
PIOBJECT(ElementD)
|
||||
// ...
|
||||
};
|
||||
*/
|
||||
#include "pip.h"
|
||||
#include <QVector>
|
||||
|
||||
|
||||
class ThreadTest: public PIThread {
|
||||
public:
|
||||
ThreadTest(): PIThread() {cnt = 0; b = r = e = false;}
|
||||
int cnt;
|
||||
bool b, r, e;
|
||||
private:
|
||||
void begin() {b = true; cout << " thread begin\n";}
|
||||
void run() {r = true; cout << " thread run " << cnt++ << endl; if (cnt == 10) stop();}
|
||||
void end() {e = true; cout << " thread end\n";}
|
||||
};
|
||||
|
||||
PIMutex mutex_;
|
||||
bool m = false;
|
||||
int cnt = 0, gm = 0;
|
||||
|
||||
class MutexTest: public PIThread {
|
||||
public:
|
||||
MutexTest(): PIThread() {;}
|
||||
private:
|
||||
void run() {mutex_.lock(); if (m && cnt > 1) gm++; m = true; cout << " " << flush; if (cnt++ >= 128) stop(); msleep(1); mutex_.unlock();}
|
||||
};
|
||||
|
||||
class MutexTest2: public PIThread {
|
||||
public:
|
||||
MutexTest2(): PIThread() {;}
|
||||
private:
|
||||
void run() {mutex_.lock(); if (!m && cnt > 1) gm++; m = false; cout << "|" << flush; if (cnt++ >= 128) stop(); msleep(1); mutex_.unlock();}
|
||||
};
|
||||
|
||||
|
||||
void signalFunc(PISignals::Signal signal) {
|
||||
if (signal != PISignals::Interrupt) return;
|
||||
cout << endl << "Ctrl+C pressed, exiting ..." << endl;
|
||||
exit(0);
|
||||
};
|
||||
|
||||
|
||||
bool t = false;
|
||||
void timerEvent(void * data, int delim) {
|
||||
t = true;
|
||||
cout << " tick from constuctor, delimiter = " << delim << ", data = " << data << endl;
|
||||
};
|
||||
|
||||
bool t2 = false;
|
||||
void timerEvent2(void * data, int delim) {
|
||||
t2 = true;
|
||||
cout << " tick from delimiter " << delim << ", data = " << data << endl;
|
||||
};
|
||||
|
||||
|
||||
class ObjectTest: public PIObject {
|
||||
PIOBJECT(ObjectTest)
|
||||
public:
|
||||
ObjectTest(const PIString & name = PIString()): PIObject(name) {h = hi = ht = false;}
|
||||
EVENT_HANDLER(void, handler) {h = true; cout << " handler in \"" << name() << "\"" << endl;}
|
||||
EVENT_HANDLER2(void, handler_i_s, int, i, PIString, s) {hi = true; cout << " handler_i_s in \"" << name() << "\", i = " << i << ", s = \"" << s << "\"" << endl;}
|
||||
EVENT_HANDLER2(void, handler_timeout, void * , data, int, delim) {ht = true; cout << " handler_timeout in \"" << name() << "\", data = " << data << ", delim = " << delim << endl;}
|
||||
bool h, hi, ht;
|
||||
};
|
||||
|
||||
|
||||
class ObjectTest2: public PIObject {
|
||||
PIOBJECT(ObjectTest2)
|
||||
public:
|
||||
ObjectTest2(const PIString & name = PIString()): PIObject(name) {;}
|
||||
void raise0(const PIString & e) {cout << " event \"" << e << "\" from \"" << name() << "\"" << endl; raiseEvent(this, e);}
|
||||
void raise2(const PIString & e, int i, const PIString & s) {cout << " event \"" << e << "\" from \"" << name() << "\"" << endl; raiseEvent<int, PIString>(this, e, i, s);}
|
||||
EVENT(event0)
|
||||
EVENT(event2)
|
||||
|
||||
};
|
||||
|
||||
class CA: public PIObject {
|
||||
PIOBJECT(CA)
|
||||
public:
|
||||
CA(const PIString & n): PIObject(n) {;}
|
||||
EVENT_HANDLER(void, handler_ca) {a = true; cout << " handler CA" << endl;}
|
||||
EVENT(event_ca)
|
||||
bool a;
|
||||
};
|
||||
|
||||
class CB: public CA {
|
||||
PIOBJECT(CB)
|
||||
public:
|
||||
CB(const PIString & n): CA(n) {;}
|
||||
EVENT_HANDLER(void, handler_cb) {b = true; cout << " handler CB" << endl;}
|
||||
bool b;
|
||||
};
|
||||
|
||||
class CC: public CB {
|
||||
PIOBJECT(CC)
|
||||
public:
|
||||
CC(const PIString & n): CB(n) {;}
|
||||
EVENT_HANDLER(void, handler_cc) {c = true; cout << " handler CC" << endl;}
|
||||
bool c;
|
||||
};
|
||||
|
||||
class CD: public CC {
|
||||
PIOBJECT(CD)
|
||||
public:
|
||||
CD(const PIString & n): CC(n) {;}
|
||||
EVENT_HANDLER(void, handler_cd) {d = true; cout << " handler CD" << endl;}
|
||||
bool d;
|
||||
};
|
||||
|
||||
/*
|
||||
PIDiagnostics diag;
|
||||
bool corr = true;
|
||||
void te(void * , int) {
|
||||
diag.received(256, corr);
|
||||
diag.sended(512);
|
||||
}*/
|
||||
|
||||
class ObjectA: public PIObject {
|
||||
PIOBJECT(ObjectA)
|
||||
public:
|
||||
EVENT_HANDLER1(void, handlerA, const PIString & , str) {piCout << "handler A:" << str;}
|
||||
EVENT2(eventA2, int, i, float, f);
|
||||
EVENT1(eventA1, const PIString & , str);
|
||||
};
|
||||
|
||||
class ObjectB: public PIObject {
|
||||
PIOBJECT(ObjectB)
|
||||
public:
|
||||
EVENT_HANDLER2(void, handlerB, int, i, float, f) {piCout << "handler B:" << i << "," << f;}
|
||||
EVENT1(eventB, PIString, str);
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct msgHeader {
|
||||
msgHeader(ushort msg_id_ = 0) {
|
||||
sign[0] = 'B';
|
||||
sign[1] = 'R';
|
||||
sign[2] = 'K';
|
||||
sign[3] = 'D';
|
||||
msg_id = msg_id_;
|
||||
sys_id = 2;
|
||||
subsys_id = 1;
|
||||
fragment = security = cnt = 0;
|
||||
size = sizeof(msgHeader);
|
||||
}
|
||||
char sign[4];
|
||||
ushort size;
|
||||
ushort cnt;
|
||||
uchar fragment;
|
||||
ushort msg_id;
|
||||
uchar sys_id;
|
||||
uchar subsys_id;
|
||||
uchar security;
|
||||
bool verify_sign() {return (sign[0] == 'B' && sign[1] == 'R' && sign[2] == 'K' && sign[3] == 'D');}
|
||||
};
|
||||
|
||||
|
||||
struct msg2105base {
|
||||
msgHeader header;
|
||||
union {
|
||||
ullong msgTime;
|
||||
struct {
|
||||
uint time_ns;
|
||||
uint time_s;
|
||||
};
|
||||
};
|
||||
uint id;
|
||||
ushort type1kod;
|
||||
float type1ver;
|
||||
ushort type2kod;
|
||||
float type2ver;
|
||||
ushort type3kod;
|
||||
float type3ver;
|
||||
double azimut;
|
||||
ullong imp_recv_time;
|
||||
double geo_width_PEC;
|
||||
double geo_length_PEC;
|
||||
double geo_width_CP;
|
||||
double geo_length_CP;
|
||||
float height;
|
||||
float kurs_CP;
|
||||
float kren_CP;
|
||||
float tangaj_CP;
|
||||
};
|
||||
|
||||
#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;}
|
||||
};
|
||||
|
||||
void tfunc(void*,int);
|
||||
PITimer tm_(tfunc);
|
||||
void tfunc(void*,int) {piCout << tm_.elapsed_m();}
|
||||
int main (int argc, char * argv[]) {
|
||||
/*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.addTab("ftab", 'f');
|
||||
console.addVariable("service", &p);
|
||||
console.addTab("stab", 's');
|
||||
//console.start();
|
||||
console.startServer("cons");
|
||||
console.waitForFinish();
|
||||
return 0;
|
||||
|
||||
PIFile f("picontainers.h");
|
||||
PIString all = f.readAll();
|
||||
while (!all.isEmpty()) {
|
||||
PIString line = all.takeLine();
|
||||
if (line.takeWord() == "class")
|
||||
piCout << "class" << line.trim();
|
||||
PITimer tm;
|
||||
std::vector<int> sv;
|
||||
PIVector<int> pv;
|
||||
QVector<int> qv;
|
||||
pv.reserve(256);
|
||||
for (int s = 1; s <= 20; ++s) {
|
||||
int cnt = s * 1000000;
|
||||
piCout << "********";
|
||||
piCout << cnt << "insertion:";
|
||||
sv.clear();
|
||||
pv.clear();
|
||||
qv.clear();
|
||||
tm.reset();
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
sv.push_back(i);
|
||||
}
|
||||
piCout << "stl:" << tm.elapsed_m();
|
||||
tm.reset();
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
pv.push_back(i);
|
||||
}
|
||||
piCout << "pip:" << tm.elapsed_m();
|
||||
tm.reset();
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
qv.append(i);
|
||||
}
|
||||
piCout << " qt:" << tm.elapsed_m();
|
||||
}
|
||||
return 0;
|
||||
|
||||
msg2105base msg;
|
||||
msg.header.size = sizeof(msg);
|
||||
msg.header.msg_id = 2105;
|
||||
msg.msgTime = 1;
|
||||
RC rc_;
|
||||
PIEthernet eth;
|
||||
CONNECT2(void, ullong, int, ð, threadedWriteEvent, &rc_, re);
|
||||
eth.setParameter(PIEthernet::Broadcast);
|
||||
eth.open("127.0.0.1:10211");
|
||||
eth.setSendAddress("234.0.2.1:10211");
|
||||
eth.joinMulticastGroup("234.0.2.1");
|
||||
eth.startThreadedWrite();
|
||||
for (int i = 0; i < 100000; ++i) {
|
||||
PISystemTime tm = currentSystemTime();
|
||||
msg.type1kod = (i + 1) % 34;
|
||||
msg.id = piRoundd(double(i) / 5. + 50);
|
||||
if (i % 15 >= 10) msg.id += 10000;
|
||||
msg.time_ns = tm.seconds;
|
||||
msg.time_s = tm.nanoseconds;
|
||||
msg.azimut = sin(float(i) / 20.) * 90;
|
||||
msg.geo_width_PEC = sin(float(i) / 50.) * 90;
|
||||
msg.geo_length_PEC = cos(float(i) / 50.) * 90;
|
||||
piCout << "push to queue with id =" << eth.writeThreaded(&msg, sizeof(msg));
|
||||
piMSleep(50);
|
||||
if (PIKbdListener::exiting) break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
PISignals::setSlot(signalFunc);
|
||||
//PISignals::grabSignals(PISignals::Interrupt);
|
||||
bool r_string = true, r_thread = true, r_mutex = true, r_timer = true, r_file = true, r_eval = true, r_event = true;
|
||||
bool succ = true;
|
||||
cout << "== PIP test program ==" << endl;
|
||||
cout << "== Built with PIP " << PIPVersion() << " ==" << endl << endl;
|
||||
cout << "== String test ==" << endl;
|
||||
PIString string("test string");
|
||||
cout << " \"test string\" -> \"" << string << "\"" << endl;
|
||||
if (string.length() != 11) succ = r_string = false;
|
||||
cout << " to char * = \"" << string.data() << "\"" << endl;
|
||||
cout << " to std::string = \"" << string.stdString() << "\"" << endl;
|
||||
if (string.stdString().length() != 11) succ = r_string = false;
|
||||
#ifdef HAS_LOCALE
|
||||
cout << " to std::wstring = \"" << string.stdWString() << "\"" << endl;
|
||||
if (string.stdWString().length() != 11) succ = r_string = false;
|
||||
#endif
|
||||
if (succ) cout << " convertions success" << endl;
|
||||
else cout << " convertions fail" << endl;
|
||||
succ = true;
|
||||
string = PIString("αβγ°℃");
|
||||
cout << " \"αβγ°℃\" -> \"" << string << "\"" << endl;
|
||||
if (string.length() != 5) succ = r_string = false;
|
||||
cout << " to char * = \"" << string.data() << "\"" << endl;
|
||||
cout << " to std::string = \"" << string.stdString() << "\"" << endl;
|
||||
if (string.stdString().length() != 11) succ = r_string = false;
|
||||
#ifdef HAS_LOCALE
|
||||
cout << " to std::wstring = \"" << string.stdWString() << "\"" << endl;
|
||||
if (string.stdWString().length() != 5) succ = r_string = false;
|
||||
#endif
|
||||
if (succ) cout << " complex convertions success" << endl;
|
||||
else cout << " complex convertions fail" << endl;
|
||||
if (r_string) cout << "== Success ==" << endl;
|
||||
else cout << "== Fail ==" << endl;
|
||||
|
||||
cout << endl << "== Thread test ==" << endl;
|
||||
ThreadTest thread;
|
||||
thread.start(100);
|
||||
msleep(10);
|
||||
thread.waitForFinish();
|
||||
r_thread = thread.b && thread.r && thread.e && thread.cnt == 10;
|
||||
if (r_thread) cout << "== Success ==" << endl;
|
||||
else cout << "== Fail ==" << endl;
|
||||
|
||||
cout << endl << "== Mutex test ==" << endl << " ";
|
||||
MutexTest thread_m;
|
||||
MutexTest2 thread_m2;
|
||||
thread_m.start();
|
||||
thread_m2.start();
|
||||
thread_m.waitForFinish();
|
||||
thread_m2.waitForFinish();
|
||||
cout << endl;
|
||||
r_mutex = gm < 5;
|
||||
if (r_mutex) cout << "== Success ==" << endl;
|
||||
else cout << "== Fail ==" << endl;
|
||||
|
||||
cout << endl << "== Timer test ==" << endl;
|
||||
PITimer timer(timerEvent, (void*)255);
|
||||
timer.addDelimiter(2);
|
||||
timer.addDelimiter(5, timerEvent2);
|
||||
timer.start(100.f);
|
||||
msleep(1005);
|
||||
timer.stop();
|
||||
r_timer = t && t2;
|
||||
if (r_timer) cout << "== Success ==" << endl;
|
||||
else cout << "== Fail ==" << endl;
|
||||
|
||||
cout << endl << "== File test ==" << endl;
|
||||
PIFile file(" file_test", PIIODevice::ReadWrite);
|
||||
cout << " file \"" << file.path() << "\" is ";
|
||||
if (!file.isOpened()) cout << "not ";
|
||||
cout << "opened" << endl;
|
||||
file.clear();
|
||||
file << "test string";
|
||||
cout << " write " << file.pos() << " bytes" << endl;
|
||||
if (file.pos() != 11) r_file = false;
|
||||
PIByteArray ba = file.readAll();
|
||||
if (ba.size() != 11) r_file = false;
|
||||
cout << " read " << ba.size() << " bytes: \"" << PIString(ba) << '\"' << endl;
|
||||
file.remove();
|
||||
if (r_file) cout << "== Success ==" << endl;
|
||||
else cout << "== Fail ==" << endl;
|
||||
|
||||
cout << endl << "== Evaluator test ==" << endl;
|
||||
PIEvaluator evaluator;
|
||||
evaluator.setVariable("x", complexd(2., 1.));
|
||||
PIString expression("2x^2 + i");
|
||||
evaluator.check(expression);
|
||||
cout << " expression = \"" << expression << '\"' << endl;
|
||||
cout << " recognized = \"" << evaluator.expression() << '\"' << endl;
|
||||
cout << " error = \"" << evaluator.error() << '\"' << endl;
|
||||
cout << " \"x\" = " << evaluator.content.variable("x").value << endl;
|
||||
cout << " result = " << evaluator.evaluate() << endl;
|
||||
r_eval = round(evaluator.lastResult()) == complexd(6., 9.);
|
||||
if (r_eval) cout << "== Success ==" << endl;
|
||||
else cout << "== Fail ==" << endl;
|
||||
|
||||
cout << endl << "== Event test ==" << endl;
|
||||
ObjectTest object("obj");
|
||||
ObjectTest2 object2("obj2");
|
||||
PITimer timer2;
|
||||
timer2.setData((void * )128);
|
||||
timer2.addDelimiter(2);
|
||||
timer2.addDelimiter(5);
|
||||
CONNECT0(void, &object2, event0, &object, handler);
|
||||
CONNECT2(void, int, PIString, &object2, event2, &object, handler_i_s);
|
||||
CONNECT2(void, void * , int, &timer2, timeout, &object, handler_timeout);
|
||||
object2.raise0("event0");
|
||||
object2.raise2("event2", 123, "string");
|
||||
timer2.start(100.f);
|
||||
msleep(505);
|
||||
timer2.stop();
|
||||
CA ca("cd");
|
||||
CD cd("cd");
|
||||
CONNECT(void, &ca, event_ca, &cd, handler_cd);
|
||||
CONNECT(void, &ca, event_ca, &cd, handler_cc);
|
||||
CONNECT(void, &ca, event_ca, &cd, handler_cb);
|
||||
CONNECT(void, &ca, event_ca, &cd, handler_ca);
|
||||
PIObject::raiseEvent(&ca, "event_ca");
|
||||
r_event = object.h && object.hi && object.ht && cd.a && cd.b && cd.c && cd.d;
|
||||
if (r_event) cout << "== Success ==" << endl;
|
||||
else cout << "== Fail ==" << endl;
|
||||
|
||||
cout << endl << "== Results ==" << endl;
|
||||
cout << "= String " << r_string << " =" << endl;
|
||||
cout << "= Thread " << r_thread << " =" << endl;
|
||||
cout << "= Mutex " << r_mutex << " =" << endl;
|
||||
cout << "= Timer " << r_timer << " =" << endl;
|
||||
cout << "= File " << r_file << " =" << endl;
|
||||
cout << "= Evaluator " << r_eval << " =" << endl;
|
||||
cout << "= Event " << r_event << " =" << endl;
|
||||
if (r_string && r_thread && r_mutex && r_timer && r_file && r_eval && r_event)
|
||||
cout << "== All tests successful ==" << endl;
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
* to manipulate it.
|
||||
*
|
||||
* \section PIByteArray_sec0 Usage
|
||||
* PIByteArray can be used to store custom data and manipulate it. There are many
|
||||
* %PIByteArray can be used to store custom data and manipulate it. There are many
|
||||
* stream operators to store/restore common types to byte array. Store operators
|
||||
* places data at the end of arraym restore operators takes data from the beginning
|
||||
* of array.
|
||||
@@ -36,6 +36,26 @@
|
||||
* * CRC 16-bit
|
||||
* * CRC 32-bit
|
||||
*
|
||||
* One of the major usage of %PIByteArray is stream functions. You can form binary
|
||||
* packet from many types (also dynamic types, e.g. PIVector) with one line:
|
||||
* \snippet pibytearray.cpp 0
|
||||
*
|
||||
* Or you can descibe stream operator of your own type and store/restore vectors of
|
||||
* your type:
|
||||
* \snippet pibytearray.cpp 1
|
||||
*
|
||||
* For store/restore custom data blocks there is PIByteArray::RawData class. Stream
|
||||
* operators of this class simply store/restore data block to/from byte array.
|
||||
* \snippet pibytearray.cpp 2
|
||||
*
|
||||
* \section PIByteArray_sec1 Attention
|
||||
* Stream operator of %PIByteArray store byte array as vector, not simply append
|
||||
* content of byte array. This operators useful to transmit custom data as %PIByteArray
|
||||
* packed into parent byte array, e.g. to form packet from %PIByteArray.
|
||||
* To append one byte array to another use funtion \a append().
|
||||
* \snippet pibytearray.cpp 3
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -54,13 +54,13 @@ class PIP_EXPORT PIByteArray: public PIVector<uchar>
|
||||
{
|
||||
public:
|
||||
|
||||
//! Contructs an empty byte array
|
||||
//! Constructs an empty byte array
|
||||
PIByteArray() {;}
|
||||
|
||||
//! Contructs 0-filled byte array size "size"
|
||||
//! Constructs 0-filled byte array with size "size"
|
||||
PIByteArray(const uint size) {resize(size);}
|
||||
|
||||
//! Contructs byte array from data "data" and size "size"
|
||||
//! Constructs byte array from data "data" and size "size"
|
||||
PIByteArray(const void * data, const uint size) {for (uint i = 0; i < size; ++i) push_back(((uchar * )data)[i]);}
|
||||
|
||||
|
||||
@@ -69,9 +69,9 @@ public:
|
||||
friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v);
|
||||
friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v);
|
||||
public:
|
||||
//! Contructs data block
|
||||
//! Constructs data block
|
||||
RawData(void * data, int size) {d = data; s = size;}
|
||||
//! Contructs data block
|
||||
//! Constructs data block
|
||||
RawData(const void * data, const int size) {d = const_cast<void * >(data); s = size;}
|
||||
RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;}
|
||||
private:
|
||||
@@ -102,10 +102,10 @@ public:
|
||||
PIByteArray & compressHuffman() {*this = huffman.compress(*this); return *this;}
|
||||
|
||||
//! Add to the end data "data" with size "size"
|
||||
PIByteArray & append(void * data, int size) {for (int i = 0; i < size; ++i) push_back(((uchar*)data)[i]); return *this;}
|
||||
PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;}
|
||||
|
||||
//! Add to the end byte array "data"
|
||||
PIByteArray & append(const PIByteArray & data) {for (int i = 0; i < data.size_s(); ++i) push_back(data[i]); return *this;}
|
||||
PIByteArray & append(const PIByteArray & data_) {uint ps = size(); enlarge(data_.size_s()); memcpy(data(ps), data_.data(), data_.size()); return *this;}
|
||||
/*PIByteArray & operator <<(short v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}
|
||||
PIByteArray & operator <<(ushort v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}
|
||||
PIByteArray & operator <<(int v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}
|
||||
@@ -183,9 +183,9 @@ inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {PBA_OPERATO
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const float v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const double & v) {PBA_OPERATOR_TO return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {s << v.size_s(); int os = s.size_s(); s.enlarge(v.size_s()); if (v.size_s() > 0) memcpy(s.data(os), v.data(), v.size()); return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {int os = s.size_s(); s.enlarge(v.s); if (v.s > 0) memcpy(s.data(os), v.d, v.s); return s;}
|
||||
//! \relatesalso PIByteArray \brief Store operator
|
||||
template <typename T>
|
||||
@@ -226,9 +226,9 @@ inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {assert(s.size() >
|
||||
inline PIByteArray & operator >>(PIByteArray & s, float & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
inline PIByteArray & operator >>(PIByteArray & s, double & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); if (sz > 0) memcpy(v.data(), s.data(), v.size()); s.remove(0, v.size()); return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {assert(s.size_s() >= v.s); if (v.s > 0) memcpy(v.d, s.data(), v.s); s.remove(0, v.s); return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator
|
||||
template <typename T>
|
||||
|
||||
2
pichar.h
2
pichar.h
@@ -26,7 +26,7 @@
|
||||
#include "pibytearray.h"
|
||||
/*! \brief Unicode char
|
||||
* \details This class is wrapper around \c "uint".
|
||||
* There are many contructors and information functions;
|
||||
* There are many contructors and information functions
|
||||
*/
|
||||
class PIP_EXPORT PIChar
|
||||
{
|
||||
|
||||
3
picli.h
3
picli.h
@@ -25,10 +25,11 @@
|
||||
|
||||
#include "piobject.h"
|
||||
|
||||
class PIP_EXPORT PICLI: protected PIObject
|
||||
class PIP_EXPORT PICLI: public PIObject
|
||||
{
|
||||
PIOBJECT(PICLI)
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
PICLI(int argc, char * argv[]);
|
||||
|
||||
|
||||
46
picollection.cpp
Normal file
46
picollection.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "picollection.h"
|
||||
|
||||
|
||||
/** \class PICollection
|
||||
* \brief Interface to discover element groups
|
||||
* \details
|
||||
* \section PICollection_sec0 Synopsis
|
||||
* This class has only static functions so no need to create instance of the
|
||||
* %PICollection. This class provide macros to add some classes or existing
|
||||
* objects to global collection and access to them from any place of the code.
|
||||
* \snippet picollection.cpp main
|
||||
* */
|
||||
|
||||
|
||||
PIStringList PICollection::groups() {
|
||||
PIStringList sl;
|
||||
piForeachC (Group & g, _groups)
|
||||
sl << g.name;
|
||||
return sl;
|
||||
}
|
||||
|
||||
|
||||
PIVector<const PIObject * > PICollection::groupElements(const PIString & group) {
|
||||
piForeachC (Group & g, _groups)
|
||||
if (g.name == group)
|
||||
return g.elements;
|
||||
return PIVector<const PIObject * >();
|
||||
}
|
||||
|
||||
|
||||
void PICollection::addToGroup(const PIString & group, const PIObject * element) {
|
||||
PIString n = element->className();
|
||||
piForeach (Group & g, _groups)
|
||||
if (g.name == group) {
|
||||
for (int i = 0; i < g.elements.size_s(); ++i)
|
||||
if (PIString(g.elements[i]->className()) == n)
|
||||
return;
|
||||
g.elements << element;
|
||||
return;
|
||||
}
|
||||
_groups << Group(group);
|
||||
_groups.back().elements << element;
|
||||
}
|
||||
|
||||
|
||||
PIVector<PICollection::Group> PICollection::_groups;
|
||||
81
picollection.h
Normal file
81
picollection.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*! \file picollection.h
|
||||
* \brief Custom elements collection
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
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
|
||||
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 PICOLLECTION_H
|
||||
#define PICOLLECTION_H
|
||||
|
||||
#include "piobject.h"
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
/** \brief Add existing element "object" in group with name "group"
|
||||
* \relatesalso PICollection
|
||||
* \details If there is no group with name "group" it will be created.
|
||||
* Only one element of the class "object" can be in group "group". If
|
||||
* this is already exists nothing be happens. \n "object" should to
|
||||
* be pointer to object based on PIObject. */
|
||||
# define ADD_TO_COLLECTION(group, object)
|
||||
|
||||
/** \brief Add new element of class "class" in group with name "group"
|
||||
* \relatesalso PICollection
|
||||
* \details If there is no group with name "group" it will be created.
|
||||
* Only one element of the class "class" can be in group "group". If
|
||||
* this is already exists nothing be happens. \n "class" should to
|
||||
* be name of the any class based on PIObject. */
|
||||
# define ADD_NEW_TO_COLLECTION(group, class)
|
||||
|
||||
#else
|
||||
# define ADD_TO_COLLECTION(group, object) static PICollection::CollectionAdder __##group##_##__LINE__##_##adder##__(#group, object);
|
||||
# define ADD_NEW_TO_COLLECTION(group, class) static PICollection::CollectionAdder __##group##_##class##_##adder##__(#group, new class());
|
||||
#endif
|
||||
|
||||
class PICollection
|
||||
{
|
||||
public:
|
||||
PICollection() {;}
|
||||
|
||||
//! \brief Returns all existing groups by their names
|
||||
static PIStringList groups();
|
||||
|
||||
//! \brief Returns all elements of group "group"
|
||||
static PIVector<const PIObject * > groupElements(const PIString & group);
|
||||
|
||||
static void addToGroup(const PIString & group, const PIObject * element);
|
||||
|
||||
class CollectionAdder {
|
||||
public:
|
||||
CollectionAdder(const PIString & group, const PIObject * element) {PICollection::addToGroup(group, element);}
|
||||
};
|
||||
|
||||
protected:
|
||||
struct Group {
|
||||
Group(const PIString & name_ = PIString()) {name = name_;}
|
||||
//~Group() {piCout << "delete group" << name << this; piForeach (const PIObject * o, elements) delete o; elements.clear();}
|
||||
PIString name;
|
||||
PIVector<const PIObject * > elements;
|
||||
};
|
||||
|
||||
static PIVector<Group> _groups;
|
||||
|
||||
};
|
||||
|
||||
#endif // PICOLLECTION_H
|
||||
39
piconfig.cpp
39
piconfig.cpp
@@ -30,17 +30,42 @@
|
||||
* \image html piconfig.png
|
||||
*
|
||||
* \section PIConfig_sec1 Concepts
|
||||
* Each entry of internal tree has type PIConfig::Entry. This class
|
||||
* has next properties:
|
||||
* Each node of internal tree has type PIConfig::Entry. %PIConfig
|
||||
* has one root element \a rootEntry(). Any entry of configuration file is a
|
||||
* child of this element.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \class PIConfig::Entry
|
||||
* \brief %Entry of configuration file
|
||||
* \details This class is node of internal PIConfig tree.
|
||||
* %Entry provide access to elements of PIConfig. Each entry has
|
||||
* children or next properties:
|
||||
* * name
|
||||
* * value
|
||||
* * type
|
||||
* * comment
|
||||
* Entry class has many implicit convertions to common types: bolean,
|
||||
* integers, float, double, PIString, PIStringList.
|
||||
*
|
||||
*/
|
||||
* Each property is a PIString. These properties forms from text line with
|
||||
* format: \code{.cpp} <name> = <value> #<type> <comment> \endcode
|
||||
* Type and comment are optional fields. Type is a single letter immediately
|
||||
* after comment symbol "#". \n \n
|
||||
* %Entry has many implicit convertions to common types: boolean, integers,
|
||||
* float, double, PIString, PIStringList. \n \n
|
||||
* Generally there is no need to create instance of %PIConfig::Entry manually,
|
||||
* it returns by functions \a getValue() of \a PIConfig, \a PIConfig::Entry or
|
||||
* \a PIConfig::Branch. If there is no suitable entry to return, reference to
|
||||
* internal instance of %PIConfig::Entry with "default" value will be returned.
|
||||
* \snippet piconfig.cpp PIConfig::Entry
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \class PIConfig::Branch
|
||||
* \brief %Branch is a list of entries of configuration file
|
||||
* \details %Branch provides some features to get entries lists.
|
||||
* \snippet piconfig.cpp PIConfig::Branch
|
||||
*
|
||||
*/
|
||||
|
||||
PIConfig::Entry PIConfig::Branch::_empty;
|
||||
PIConfig::Entry PIConfig::Entry::_empty;
|
||||
@@ -184,7 +209,7 @@ PIConfig::Branch PIConfig::Entry::getValues(const PIString & vname) {
|
||||
|
||||
bool PIConfig::Entry::entryExists(const Entry * e, const PIString & name) const {
|
||||
if (e->_children.isEmpty()) {
|
||||
if (e->_name == name) return true;
|
||||
if (e->_name == name) return true;
|
||||
else return false;
|
||||
}
|
||||
piForeachC (Entry * i, e->_children)
|
||||
@@ -484,7 +509,7 @@ void PIConfig::parse() {
|
||||
name = tree.back();
|
||||
tree.pop_back();
|
||||
entry = &root;
|
||||
piForeach (PIString & i, tree) {
|
||||
piForeachC (PIString & i, tree) {
|
||||
te = entry->findChild(i);
|
||||
if (te == 0) {
|
||||
ce = new Entry();
|
||||
|
||||
273
piconfig.h
273
piconfig.h
@@ -26,37 +26,38 @@
|
||||
#include "pifile.h"
|
||||
|
||||
#define PICONFIG_GET_VALUE \
|
||||
Entry & getValue(const PIString & vname, const char * def, bool * exist = 0) {return getValue(vname, PIString(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const PIStringList & def, bool * exist = 0) {return getValue(vname, def.join("%|%"), exist);} \
|
||||
Entry & getValue(const PIString & vname, const bool def, bool * exist = 0) {return getValue(vname, PIString::fromBool(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const short def, bool * exist = 0) {return getValue(vname, itos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const int def, bool * exist = 0) {return getValue(vname, itos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const long def, bool * exist = 0) {return getValue(vname, ltos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const uchar def, bool * exist = 0) {return getValue(vname, uitos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const ushort def, bool * exist = 0) {return getValue(vname, uitos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const uint def, bool * exist = 0) {return getValue(vname, uitos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const ulong def, bool * exist = 0) {return getValue(vname, ultos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const float def, bool * exist = 0) {return getValue(vname, ftos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const double def, bool * exist = 0) {return getValue(vname, dtos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) {return getValue(vname, PIString(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) {return getValue(vname, def.join("%|%"), exists);} \
|
||||
Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) {return getValue(vname, PIString::fromBool(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const short def, bool * exists = 0) {return getValue(vname, itos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const int def, bool * exists = 0) {return getValue(vname, itos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const long def, bool * exists = 0) {return getValue(vname, ltos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) {return getValue(vname, ultos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const float def, bool * exists = 0) {return getValue(vname, ftos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const double def, bool * exists = 0) {return getValue(vname, dtos(def), exists);} \
|
||||
\
|
||||
Entry & getValue(const PIString & vname, const char * def, bool * exist = 0) const {return getValue(vname, PIString(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const PIStringList & def, bool * exist = 0) const {return getValue(vname, def.join("%|%"), exist);} \
|
||||
Entry & getValue(const PIString & vname, const bool def, bool * exist = 0) const {return getValue(vname, PIString::fromBool(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const short def, bool * exist = 0) const {return getValue(vname, itos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const int def, bool * exist = 0) const {return getValue(vname, itos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const long def, bool * exist = 0) const {return getValue(vname, ltos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const uchar def, bool * exist = 0) const {return getValue(vname, uitos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const ushort def, bool * exist = 0) const {return getValue(vname, uitos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const uint def, bool * exist = 0) const {return getValue(vname, uitos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const ulong def, bool * exist = 0) const {return getValue(vname, ultos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const float def, bool * exist = 0) const {return getValue(vname, ftos(def), exist);} \
|
||||
Entry & getValue(const PIString & vname, const double def, bool * exist = 0) const {return getValue(vname, dtos(def), exist);}
|
||||
Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) const {return getValue(vname, PIString(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) const {return getValue(vname, def.join("%|%"), exists);} \
|
||||
Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) const {return getValue(vname, PIString::fromBool(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const short def, bool * exists = 0) const {return getValue(vname, itos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const int def, bool * exists = 0) const {return getValue(vname, itos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const long def, bool * exists = 0) const {return getValue(vname, ltos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) const {return getValue(vname, ultos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const float def, bool * exists = 0) const {return getValue(vname, ftos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const double def, bool * exists = 0) const {return getValue(vname, dtos(def), exists);}
|
||||
|
||||
class PIP_EXPORT PIConfig: public PIFile
|
||||
{
|
||||
friend class Entry;
|
||||
friend class Branch;
|
||||
public:
|
||||
|
||||
//! Contructs and read configuration file at path "path" in mode "mode"
|
||||
PIConfig(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
|
||||
|
||||
@@ -64,6 +65,7 @@ public:
|
||||
|
||||
class Entry;
|
||||
|
||||
|
||||
class PIP_EXPORT Branch: public PIVector<Entry * > {
|
||||
friend class PIConfig;
|
||||
friend class Entry;
|
||||
@@ -71,8 +73,8 @@ public:
|
||||
public:
|
||||
Branch() {;}
|
||||
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0);
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0) const {return const_cast<Branch * >(this)->getValue(vname, def, exist);}
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0);
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {return const_cast<Branch * >(this)->getValue(vname, def, exists);}
|
||||
PICONFIG_GET_VALUE
|
||||
|
||||
Branch allLeaves();
|
||||
@@ -95,64 +97,196 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
class PIP_EXPORT Entry {
|
||||
friend class PIConfig;
|
||||
friend class Branch;
|
||||
public:
|
||||
Entry() {_parent = 0;}
|
||||
|
||||
//! Returns parent entry, or 0 if there is no parent (root of default value)
|
||||
Entry * parent() const {return _parent;}
|
||||
|
||||
//! Returns children count
|
||||
int childCount() {return _children.size_s();}
|
||||
|
||||
//! Returns children as \a PIConfig::Branch
|
||||
Branch & children() {_children.delim = delim; return _children;}
|
||||
|
||||
//! Returns child at index "index"
|
||||
Entry * child(const int index) const {return _children[index];}
|
||||
|
||||
//! Returns first child with name "name"
|
||||
Entry * findChild(const PIString & name) {piForeach (Entry * i, _children) if (i->_name == name) return i; return 0;}
|
||||
|
||||
//! Returns first child with name "name"
|
||||
const Entry * findChild(const PIString & name) const {piForeachC (Entry * i, _children) if (i->_name == name) return i; return 0;}
|
||||
|
||||
//! Returns \b true if there is no children
|
||||
bool isLeaf() const {return _children.isEmpty();}
|
||||
|
||||
|
||||
//! Returns name
|
||||
const PIString & name() const {return _name;}
|
||||
|
||||
//! Returns value
|
||||
const PIString & value() const {return _value;}
|
||||
|
||||
//! Returns type
|
||||
const PIString & type() const {return _type;}
|
||||
|
||||
//! Returns comment
|
||||
const PIString & comment() const {return _comment;}
|
||||
|
||||
/** \brief Returns full name, i.e. name as it looks in file
|
||||
* \details In case of default entry full name always is empty
|
||||
* \snippet piconfig.cpp fullName */
|
||||
const PIString & fullName() const {return _full_name;}
|
||||
|
||||
//! Set name to "value" and returns this
|
||||
Entry & setName(const PIString & value) {_name = value; return *this;}
|
||||
|
||||
//! Set type to "value" and returns this
|
||||
Entry & setType(const PIString & value) {_type = value; return *this;}
|
||||
|
||||
//! Set comment to "value" and returns this
|
||||
Entry & setComment(const PIString & value) {_comment = value; return *this;}
|
||||
|
||||
//! Set value to "value" and returns this
|
||||
Entry & setValue(const PIString & value) {_value = value; return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "l"
|
||||
Entry & setValue(const PIStringList & value) {setValue(value.join("%|%")); setType("l"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "s"
|
||||
Entry & setValue(const char * value) {setValue(PIString(value)); setType("s"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "b"
|
||||
Entry & setValue(const bool value) {setValue(btos(value)); setType("b"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "s"
|
||||
Entry & setValue(const char value) {setValue(PIString(1, value)); setType("s"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const short value) {setValue(itos(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const int value) {setValue(itos(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const long value) {setValue(ltos(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const uchar value) {setValue(uitos(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const ushort value) {setValue(uitos(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const uint value) {setValue(uitos(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const ulong value) {setValue(ultos(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "f"
|
||||
Entry & setValue(const float value) {setValue(ftos(value)); setType("f"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "f"
|
||||
Entry & setValue(const double value) {setValue(dtos(value)); setType("f"); return *this;}
|
||||
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0);
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0) const {return const_cast<Entry * >(this)->getValue(vname, def, exist);}
|
||||
|
||||
/** \brief Returns entry with name "vname" and default value "def"
|
||||
* \details If there is no suitable entry found, reference to default internal entry with
|
||||
* value = "def" will be returned, and if "exists" not null it will be set to \b false */
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0);
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {return const_cast<Entry * >(this)->getValue(vname, def, exists);}
|
||||
PICONFIG_GET_VALUE
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const bool def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const short def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const int def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const long def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const uint def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const float def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const double def, bool * exists = 0)
|
||||
//! \brief Returns entry with name "vname" and default value "def"
|
||||
|
||||
|
||||
//! Find all entries with names with substrings "vname" and returns them as \a PIConfig::Branch
|
||||
Branch getValues(const PIString & vname);
|
||||
|
||||
|
||||
//! If there is no children returns if name == "name". Else returns if any child has name == "name"
|
||||
bool isEntryExists(const PIString & name) const {return entryExists(this, name);}
|
||||
|
||||
|
||||
//! Convertion to boolean
|
||||
operator bool() {return _value.toBool();}
|
||||
|
||||
//! Convertion to char
|
||||
operator char() {return (_value.isEmpty() ? 0 : _value[0].toAscii());}
|
||||
|
||||
//! Convertion to short
|
||||
operator short() {return _value.toShort();}
|
||||
|
||||
//! Convertion to int
|
||||
operator int() {return _value.toInt();}
|
||||
|
||||
//! Convertion to long
|
||||
operator long() {return _value.toLong();}
|
||||
|
||||
//! Convertion to uchar
|
||||
operator uchar() {return _value.toInt();}
|
||||
|
||||
//! Convertion to ushort
|
||||
operator ushort() {return _value.toShort();}
|
||||
|
||||
//! Convertion to uint
|
||||
operator uint() {return _value.toInt();}
|
||||
|
||||
//! Convertion to ulong
|
||||
operator ulong() {return _value.toLong();}
|
||||
|
||||
//! Convertion to float
|
||||
operator float() {return _value.toFloat();}
|
||||
|
||||
//! Convertion to double
|
||||
operator double() {return _value.toDouble();}
|
||||
|
||||
//! Convertion to PIString
|
||||
operator PIString() {return _value;}
|
||||
|
||||
//! Convertion to PIStringList
|
||||
operator PIStringList() {return _value.split("%|%");}
|
||||
|
||||
private:
|
||||
@@ -177,27 +311,94 @@ public:
|
||||
int _line;
|
||||
};
|
||||
|
||||
|
||||
//! Returns top-level entry with name "vname", if doesn`t exists return entry with value "def" and set *exist to false
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0);
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0) const {return const_cast<PIConfig * >(this)->getValue(vname, def, exist);}
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0);
|
||||
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {return const_cast<PIConfig * >(this)->getValue(vname, def, exists);}
|
||||
|
||||
PICONFIG_GET_VALUE
|
||||
|
||||
//! Returns top-level entries with names matches "vname"
|
||||
//! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const bool def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const short def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const int def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const long def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const uint def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const float def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
//! \fn Entry & getValue(const PIString & vname, const double def, bool * exists = 0)
|
||||
//! \brief Returns top-level entry with name "vname" and default value "def"
|
||||
|
||||
|
||||
//! Returns top-level entries with names with substrings "vname"
|
||||
Branch getValues(const PIString & vname);
|
||||
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "type" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true);
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "l" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const PIStringList & value, bool write = true) {setValue(name, value.join("%|%"), "l", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "s" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const char * value, bool write = true) {setValue(name, PIString(value), "s", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "b" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const bool value, bool write = true) {setValue(name, btos(value), "b", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const short value, bool write = true) {setValue(name, itos(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const int value, bool write = true) {setValue(name, itos(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const long value, bool write = true) {setValue(name, ltos(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const uchar value, bool write = true) {setValue(name, uitos(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const ushort value, bool write = true) {setValue(name, uitos(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const uint value, bool write = true) {setValue(name, uitos(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const ulong value, bool write = true) {setValue(name, ultos(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "f" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const float value, bool write = true) {setValue(name, ftos(value), "f", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "f" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const double value, bool write = true) {setValue(name, dtos(value), "f", write);}
|
||||
|
||||
//! Returns root entry
|
||||
@@ -210,10 +411,10 @@ public:
|
||||
bool isEntryExists(const PIString & name) const {return entryExists(&root, name);}
|
||||
|
||||
//! Returns all top-level entries
|
||||
Branch allTree() {Branch b; piForeach (Entry * i, root._children) b << i; return b;}
|
||||
Branch allTree() {Branch b; piForeach (Entry * i, root._children) b << i; b.delim = delim; return b;}
|
||||
|
||||
//! Returns all entries without children
|
||||
Branch allLeaves() {Branch b; allLeaves(b, &root); b.sort(Entry::compare); return b;}
|
||||
Branch allLeaves() {Branch b; allLeaves(b, &root); b.sort(Entry::compare); b.delim = delim; return b;}
|
||||
|
||||
int entryIndex(const PIString & name);
|
||||
|
||||
@@ -231,10 +432,14 @@ public:
|
||||
void removeEntry(const PIString & name, bool write = true);
|
||||
void removeEntry(uint number, bool write = true);
|
||||
|
||||
|
||||
//! Parse file and build internal tree
|
||||
void readAll();
|
||||
|
||||
//! Write all internal tree to file
|
||||
void writeAll();
|
||||
|
||||
//! Returns current tree delimiter
|
||||
//! Returns current tree delimiter, default "."
|
||||
const PIString & delimiter() const {return delim;}
|
||||
|
||||
//! Set current tree delimiter
|
||||
|
||||
@@ -21,6 +21,31 @@
|
||||
#include "pipeer.h"
|
||||
|
||||
|
||||
/** \class PIConsole
|
||||
* \brief Console output class
|
||||
* \details
|
||||
* \section PIConsole_sec0 Synopsis
|
||||
* This class provides output to console with automatic alignment and update.
|
||||
* It supports tabs, keyboard listening, formats and colors.
|
||||
*
|
||||
* \section PIConsole_sec1 Layout
|
||||
* %PIConsole works with variable pointers. You should add your variables with
|
||||
* functions \a addVariable() which receives label name, pointer to variable
|
||||
* and optional column and format. Columns count is dynamically increased if
|
||||
* new column used. E.g. if you add variable to empty tab to column 3, columns
|
||||
* count will be increased to 3, but two firsts columns will be empty. Each column
|
||||
* filled from top to bottom, but you can add just string with function
|
||||
* \a addString() or add empty line with function \a addEmptyLine(). Layout scheme:
|
||||
* \image html piconsole_layout.png
|
||||
*
|
||||
* \section PIConsole_sec2 Keyboard usage
|
||||
* %PIConsole should to be single in application. %PIConsole aggregate PIKbdListener
|
||||
* which grab keyboard and automatic switch tabs by theirs bind keys. If there is no
|
||||
* tab binded to pressed key external function "slot" will be called
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
extern PIMutex __PICout_mutex__;
|
||||
|
||||
|
||||
@@ -173,6 +198,7 @@ void PIConsole::key_event(char key, void * t) {
|
||||
}
|
||||
}
|
||||
if (p->ret_func != 0) p->ret_func(key, t);
|
||||
p->keyPressed(key, t);
|
||||
}
|
||||
|
||||
|
||||
@@ -352,13 +378,12 @@ void PIConsole::run() {
|
||||
continue;
|
||||
}
|
||||
moveRight(tv.offset);
|
||||
PIString rstr;
|
||||
const void * ptr = 0;
|
||||
if (tv.remote) {
|
||||
if (tv.type == 0) {
|
||||
rstr.clear();
|
||||
PIByteArray tba(tv.rdata);
|
||||
tba >> rstr;
|
||||
rba = tv.rdata;
|
||||
rba >> rstr;
|
||||
rstr.trim();
|
||||
ptr = &rstr;
|
||||
} else
|
||||
@@ -580,6 +605,24 @@ void PIConsole::addVariable(const PIString & name, const llong * ptr, int col, P
|
||||
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.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);}
|
||||
/** \brief Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
* \details This function add to column "column" next lines:
|
||||
* * "protocol <name>"
|
||||
* * "Rec - receiverDeviceName": \a PIProtocol::receiverDeviceState
|
||||
* * "Send - senderDeviceName": \a PIProtocol::senderDeviceState
|
||||
* * "Received count": \a PIProtocol::receiveCount
|
||||
* * "Invalid count": \a PIProtocol::wrongCount
|
||||
* * "Missed count": \a PIProtocol::missedCount
|
||||
* * "Sended count": \a PIProtocol::sendCount
|
||||
* * "Immediate Frequency, Hz": \a PIProtocol::immediateFrequency
|
||||
* * "Integral Frequency, Hz": \a PIProtocol::integralFrequency
|
||||
* * "Receive speed": \a PIProtocol::receiveSpeed
|
||||
* * "Send speed": \a PIProtocol::sendSpeed
|
||||
* * "Receiver history size": \a PIProtocol::receiverHistorySize
|
||||
* * "Sender history size": \a PIProtocol::senderHistorySize
|
||||
* * "Disconnect Timeout, s": \a PIProtocol::disconnectTimeout
|
||||
* * "Quality": \a PIProtocol::quality
|
||||
* */
|
||||
void PIConsole::addVariable(const PIString & name, const PIProtocol * ptr, int col, PIFlags<PIConsole::Format> format) {
|
||||
addString("protocol " + name, col, format | PIConsole::Bold);
|
||||
addVariable("Rec - " + ptr->receiverDeviceName(), ptr->receiverDeviceState_ptr(), col, format);
|
||||
@@ -597,6 +640,18 @@ void PIConsole::addVariable(const PIString & name, const PIProtocol * ptr, int c
|
||||
addVariable("Disconnect Timeout, s", ptr->disconnectTimeout_ptr(), col, format);
|
||||
addVariable("Quality", ptr->quality_ptr(), col, format);
|
||||
}
|
||||
/** \brief Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
* \details This function add to column "column" next lines:
|
||||
* * "<name> diagnostics"
|
||||
* * "Received count": \a PIDiagnostics::receiveCount
|
||||
* * "Invalid count": \a PIDiagnostics::wrongCount
|
||||
* * "Sended count": \a PIDiagnostics::sendCount
|
||||
* * "Immediate Frequency, Hz": \a PIDiagnostics::immediateFrequency
|
||||
* * "Integral Frequency, Hz": \a PIDiagnostics::integralFrequency
|
||||
* * "Receive speed": \a PIDiagnostics::receiveSpeed
|
||||
* * "Send speed": \a PIDiagnostics::sendSpeed
|
||||
* * "Quality": \a PIDiagnostics::quality
|
||||
* */
|
||||
void PIConsole::addVariable(const PIString & name, const PIDiagnostics * ptr, int col, PIFlags<PIConsole::Format> format) {
|
||||
addString(name + " diagnostics", col, format | PIConsole::Bold);
|
||||
addVariable("Received count", ptr->receiveCount_ptr(), col, format);
|
||||
@@ -704,6 +759,7 @@ void PIConsole::startServer(const PIString & name) {
|
||||
server_mode = true;
|
||||
peer = new PIPeer("_rcs_:" + name);
|
||||
CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived);
|
||||
CONNECT1(void, const PIString & , peer, peerDisconnectedEvent, this, peerDisconnectedEvent);
|
||||
peer_timer.start(50.);
|
||||
serverSendInfo();
|
||||
}
|
||||
@@ -795,6 +851,7 @@ void PIConsole::serverSendData() {
|
||||
break;
|
||||
case Connected:
|
||||
ba << int(0xEE) << content;
|
||||
//piCout << "send data" << ba.size();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
@@ -920,3 +977,12 @@ void PIConsole::peerTimer(void * data, int delim) {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIConsole::peerDisconnectedEvent(const PIString & name) {
|
||||
for (int i = 0; i < remote_clients.size_s(); ++i)
|
||||
if (remote_clients[i].name == name) {
|
||||
remote_clients.remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
201
piconsole.h
201
piconsole.h
@@ -36,66 +36,109 @@
|
||||
|
||||
class PIPeer;
|
||||
|
||||
/// handlers:
|
||||
/// void clearVariables(bool clearScreen = true)
|
||||
/// void start(bool wait = false)
|
||||
/// void stop(bool clear = false)
|
||||
class PIP_EXPORT PIConsole: public PIThread
|
||||
{
|
||||
PIOBJECT(PIConsole)
|
||||
public:
|
||||
|
||||
//! Constructs %PIConsole with key handler "slot" and if "startNow" start it
|
||||
PIConsole(bool startNow = true, KBFunc slot = 0);
|
||||
|
||||
~PIConsole();
|
||||
|
||||
enum Format {Normal = 0x01,
|
||||
Bold = 0x02,
|
||||
Faint = 0x04,
|
||||
Italic = 0x08,
|
||||
Underline = 0x10,
|
||||
Blink = 0x20,
|
||||
Inverse = 0x40,
|
||||
Black = 0x100,
|
||||
Red = 0x200,
|
||||
Green = 0x400,
|
||||
Yellow = 0x800,
|
||||
Blue = 0x1000,
|
||||
Magenta = 0x2000,
|
||||
Cyan = 0x4000,
|
||||
White = 0x8000,
|
||||
BackBlack = 0x10000,
|
||||
BackRed = 0x20000,
|
||||
BackGreen = 0x40000,
|
||||
BackYellow = 0x80000,
|
||||
BackBlue = 0x100000,
|
||||
BackMagenta = 0x200000,
|
||||
BackCyan = 0x400000,
|
||||
BackWhite = 0x800000,
|
||||
Dec = 0x1000000,
|
||||
Hex = 0x2000000,
|
||||
Oct = 0x4000000,
|
||||
Bin = 0x8000000,
|
||||
Scientific = 0x10000000};
|
||||
enum Alignment {Nothing, Left, Right};
|
||||
|
||||
//! Variables output format
|
||||
enum Format {
|
||||
Normal /** Default console format */ = 0x01,
|
||||
Bold /** Bold text */ = 0x02,
|
||||
Faint = 0x04,
|
||||
Italic = 0x08,
|
||||
Underline /** Underlined text */ = 0x10,
|
||||
Blink /** Blinked text */ = 0x20,
|
||||
Inverse /** Swap text and background colors */ = 0x40,
|
||||
Black /** Black text */ = 0x100,
|
||||
Red /** Red text */ = 0x200,
|
||||
Green /** Green text */ = 0x400,
|
||||
Yellow /** Yellow text */ = 0x800,
|
||||
Blue /** Blue text */ = 0x1000,
|
||||
Magenta /** Magenta text */ = 0x2000,
|
||||
Cyan /** Cyan text */ = 0x4000,
|
||||
White /** White text */ = 0x8000,
|
||||
BackBlack /** Black background */ = 0x10000,
|
||||
BackRed /** Red background */ = 0x20000,
|
||||
BackGreen /** Green background */ = 0x40000,
|
||||
BackYellow /** Yellow background */ = 0x80000,
|
||||
BackBlue /** Blue background */ = 0x100000,
|
||||
BackMagenta /** Magenta background */ = 0x200000,
|
||||
BackCyan /** Cyan background */ = 0x400000,
|
||||
BackWhite /** White background */ = 0x800000,
|
||||
Dec /** Decimal base for integers */ = 0x1000000,
|
||||
Hex /** Hexadecimal base for integers */ = 0x2000000,
|
||||
Oct /** Octal base for integers */ = 0x4000000,
|
||||
Bin /** Binary base for integers */ = 0x8000000,
|
||||
Scientific /** Scientific representation of floats */ = 0x10000000
|
||||
};
|
||||
|
||||
//! Column labels alignment
|
||||
enum Alignment {
|
||||
Nothing /** No alignment */ ,
|
||||
Left /** Labels align left and variables align left */ ,
|
||||
Right /** Labels align right and variables align left */
|
||||
};
|
||||
|
||||
//! Add to current tab to column "column" string "name" with format "format"
|
||||
void addString(const PIString & name, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const PIString * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const char * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const bool * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const short * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const int * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const long * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const llong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const uchar * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const ushort * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const uint * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const ulong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const ullong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const float * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format"
|
||||
void addVariable(const PIString & name, const double * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
void addVariable(const PIString & name, const PIProtocol * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
void addVariable(const PIString & name, const PIDiagnostics * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
void addVariable(const PIString & name, const PISystemMonitor * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
void addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" bits field with label "name", pointer "ptr" and format "format"
|
||||
void addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitsCount, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
|
||||
|
||||
//! Add to current tab to column "column" "count" empty lines
|
||||
void addEmptyLine(int column = 1, uint count = 1);
|
||||
|
||||
PIString getString(int x, int y);
|
||||
@@ -109,37 +152,68 @@ public:
|
||||
float getFloat(const PIString & name) {return getString(name).toFloat();}
|
||||
double getDouble(const PIString & name) {return getString(name).toDouble();}
|
||||
|
||||
|
||||
//! Returns tabs count
|
||||
uint tabsCount() const {return tabs.size();}
|
||||
|
||||
//! Returns current tab name
|
||||
PIString currentTab() const {return tabs[cur_tab].name;}
|
||||
|
||||
//! Add new tab with name "name", bind key "bind_key" and returns this tab index
|
||||
int addTab(const PIString & name, char bind_key = 0);
|
||||
|
||||
//! Remove tab with index "index"
|
||||
void removeTab(uint index);
|
||||
|
||||
//! Remove tab with name "name"
|
||||
void removeTab(const PIString & name);
|
||||
|
||||
//! Set current tab to tab with index "index", returns if tab exists
|
||||
bool setTab(uint index);
|
||||
|
||||
//! Set current tab to tab with name "name", returns if tab exists
|
||||
bool setTab(const PIString & name);
|
||||
|
||||
//! Set tab with index "index" bind key to "bind_key", returns if tab exists
|
||||
bool setTabBindKey(uint index, char bind_key);
|
||||
|
||||
//! Set tab with name "name" bind key to "bind_key", returns if tab exists
|
||||
bool setTabBindKey(const PIString & name, char bind_key);
|
||||
|
||||
//! Remove all tabs and if "clearScreen" clear the screen
|
||||
void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();}
|
||||
|
||||
|
||||
//! Set custom status text of current tab to "str"
|
||||
void addCustomStatus(const PIString & str) {tabs[cur_tab].status = str;}
|
||||
|
||||
//! Clear custom status text of current tab
|
||||
void clearCustomStatus() {tabs[cur_tab].status.clear();}
|
||||
|
||||
//! Returns default alignment
|
||||
Alignment defaultAlignment() const {return def_align;}
|
||||
|
||||
//! Set default alignment to "align"
|
||||
void setDefaultAlignment(Alignment align) {def_align = align;}
|
||||
|
||||
//! Set column "col" alignment to "align"
|
||||
void setColumnAlignment(int col, Alignment align) {if (col < 0 || col >= columns().size_s()) return; column(col).alignment = align;}
|
||||
|
||||
//! Set all columns of all tabs alignment to "align"
|
||||
void setColumnAlignmentToAll(Alignment align) {piForeach (Tab & i, tabs) piForeach (Column & j, i.columns) j.alignment = align; fillLabels();}
|
||||
|
||||
EVENT_HANDLER0(void, clearVariables) {clearVariables(true);}
|
||||
EVENT_HANDLER1(void, clearVariables, bool, clearScreen) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} columns().clear();}
|
||||
|
||||
EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT}
|
||||
EVENT_HANDLER0(void, start) {start(false);}
|
||||
EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
|
||||
EVENT_HANDLER0(void, stop) {stop(false);}
|
||||
EVENT_HANDLER1(void, stop, bool, clear);
|
||||
PIString fstr(PIFlags<PIConsole::Format> f);
|
||||
|
||||
|
||||
//! Directly call function from \a PIKbdListener
|
||||
void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);}
|
||||
|
||||
//! Directly call function from \a PIKbdListener
|
||||
void disableExitCapture() {listener->disableExitCapture();}
|
||||
|
||||
//! Directly call function from \a PIKbdListener
|
||||
bool exitCaptured() const {return listener->exitCaptured();}
|
||||
|
||||
//! Directly call function from \a PIKbdListener
|
||||
char exitKey() const {return listener->exitKey();}
|
||||
|
||||
// Server functions
|
||||
@@ -183,6 +257,41 @@ public:
|
||||
void showCursor() {printf("\e[?25h");}
|
||||
#endif
|
||||
|
||||
EVENT_HANDLER0(void, clearVariables) {clearVariables(true);}
|
||||
EVENT_HANDLER1(void, clearVariables, bool, clearScreen) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} columns().clear();}
|
||||
|
||||
EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT}
|
||||
EVENT_HANDLER0(void, start) {start(false);}
|
||||
EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
|
||||
EVENT_HANDLER0(void, stop) {stop(false);}
|
||||
EVENT_HANDLER1(void, stop, bool, clear);
|
||||
|
||||
EVENT2(keyPressed, char, key, void * , data)
|
||||
|
||||
//! \handlers
|
||||
//! \{
|
||||
|
||||
//! \fn void waitForFinish()
|
||||
//! \brief block until finished (exit key will be pressed)
|
||||
|
||||
//! \fn void clearVariables(bool clearScreen = true)
|
||||
//! \brief Remove all columns at current tab and if "clearScreen" clear the screen
|
||||
|
||||
//! \fn void start(bool wait = false)
|
||||
//! \brief Start console output and if "wait" block until finished (exit key will be pressed)
|
||||
|
||||
//! \fn void stop(bool clear = false)
|
||||
//! \brief Stop console output and if "clear" clear the screen
|
||||
|
||||
//! \}
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
//! \fn void keyPressed(char key, void * data)
|
||||
//! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object
|
||||
|
||||
//! \}
|
||||
|
||||
private:
|
||||
#ifdef WINDOWS
|
||||
void getWinCurCoord() {GetConsoleScreenBufferInfo(hOut, &csbi); ccoord = csbi.dwCursorPosition;}
|
||||
@@ -239,7 +348,7 @@ private:
|
||||
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;}
|
||||
bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny; rdata = src.rdata; id = src.id;}
|
||||
};
|
||||
|
||||
struct VariableContent {
|
||||
@@ -305,6 +414,7 @@ private:
|
||||
RemoteClient & remoteClient(const PIString & fname);
|
||||
EVENT_HANDLER2(void, peerReceived, const PIString &, from, const PIByteArray &, data);
|
||||
EVENT_HANDLER2(void, peerTimer, void * , data, int, delim);
|
||||
EVENT_HANDLER1(void, peerDisconnectedEvent, const PIString &, name);
|
||||
|
||||
#ifdef WINDOWS
|
||||
void * hOut;
|
||||
@@ -317,7 +427,8 @@ private:
|
||||
struct termios sterm, vterm;
|
||||
#endif
|
||||
PIVector<Tab> tabs;
|
||||
PIString binstr;
|
||||
PIString binstr, rstr;
|
||||
PIByteArray rba;
|
||||
Variable tv;
|
||||
PIKbdListener * listener;
|
||||
Alignment def_align;
|
||||
|
||||
177
picontainers.cpp
Normal file
177
picontainers.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Generic containers
|
||||
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/>.
|
||||
*/
|
||||
|
||||
// * This class based on std::vector, expanding his functionality
|
||||
|
||||
#include "pivector.h"
|
||||
|
||||
/** \class PIVector
|
||||
* \brief Dynamic array of any type
|
||||
* \details This class used to store dynamic array of any
|
||||
* type of data. In memory data stored linear. You can insert
|
||||
* item in any place of remove some items from any place.
|
||||
* For quick add elements this is stream operator <<.
|
||||
|
||||
* \fn PIVector::PIVector();
|
||||
* Contructs an empty vector
|
||||
|
||||
* \fn PIVector::PIVector(ullong size, const Type & value = Type());
|
||||
* \brief Contructs vector with size "size" filled elements "value"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::PIVector
|
||||
|
||||
* \fn const Type & PIVector::at(ullong index) const;
|
||||
* \brief Read-only access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::at_c
|
||||
* \sa \a operator[]
|
||||
|
||||
* \fn Type & PIVector::at(ullong index);
|
||||
* \brief Full access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::at
|
||||
* \sa \a operator[]
|
||||
|
||||
* \fn const Type * PIVector::data(ullong index = 0) const;
|
||||
* \brief Read-only pointer to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::data_c
|
||||
|
||||
* \fn Type * PIVector::data(ullong index = 0);
|
||||
* \brief Pointer to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::data
|
||||
|
||||
* \fn ullong PIVector::size() const;
|
||||
* \brief Elements count
|
||||
|
||||
* \fn int PIVector::size_s() const;
|
||||
* \brief Elements count
|
||||
|
||||
* \fn bool PIVector::isEmpty() const;
|
||||
* \brief Return \c "true" if vector is empty, i.e. size = 0
|
||||
|
||||
* \fn bool PIVector::has(const Type & t) const;
|
||||
|
||||
* \fn bool PIVector::contains(const Type & v) const;
|
||||
* \brief Return \c "true" if vector has at least one element equal "t"
|
||||
|
||||
* \fn int PIVector::etries(const Type & t) const;
|
||||
* \brief Return how many times element "t" appears in vector
|
||||
|
||||
* \fn static int PIVector::compare_func(const Type * t0, const Type * t1);
|
||||
* \brief Standard compare function for type "Type". Return 0 if t0 = t1, -1 if t0 < t1 and 1 if t0 > t1.
|
||||
|
||||
* \fn void PIVector::resize(ullong size, const Type & new_type = Type());
|
||||
* \brief Resize vector to size "size"
|
||||
* \details Elements removed from end of vector if new size < old size, or added new elements = "new_type" if new size > old size.\n
|
||||
* Example: \snippet picontainers.cpp PIVector::resize
|
||||
* \sa \a size(), \a clear()
|
||||
|
||||
* \fn PIVector<T> & PIVector::enlarge(ullong size);
|
||||
* \brief Increase vector size with "size" elements
|
||||
|
||||
* \fn void PIVector::clear();
|
||||
* \brief Clear vector. Equivalent to call <tt>"resize(0)"</tt>
|
||||
|
||||
* \fn PIVector<T> & PIVector::sort(CompareFunc compare = compare_func);
|
||||
* \brief Sort vector using quick sort algorithm and standard compare function
|
||||
* \details Example: \snippet picontainers.cpp PIVector::sort_0
|
||||
* With custom compare function: \snippet picontainers.cpp PIVector::sort_1
|
||||
|
||||
* \fn PIVector<T> & PIVector::fill(const Type & t);
|
||||
* \brief Fill vector with elements "t" leave size is unchanged and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::fill
|
||||
|
||||
* \fn Type & PIVector::back();
|
||||
* \brief Last element of the vector
|
||||
|
||||
* \fn const Type & PIVector::back() const;
|
||||
* \brief Last element of the vector
|
||||
|
||||
* \fn Type & PIVector::front();
|
||||
* \brief First element of the vector
|
||||
|
||||
* \fn const Type & PIVector::front() const;
|
||||
* \brief First element of the vector
|
||||
|
||||
* \fn PIVector<T> & PIVector::push_back(const Type & t);
|
||||
* \brief Add new element "t" at the end of vector and return reference to vector
|
||||
|
||||
* \fn PIVector<T> & PIVector::push_front(const Type & t);
|
||||
* \brief Add new element "t" at the beginning of vector and return reference to vector
|
||||
|
||||
* \fn PIVector<T> & PIVector::pop_back();
|
||||
* \brief Remove one element from the end of vector and return reference to vector
|
||||
|
||||
* \fn PIVector<T> & PIVector::pop_front();
|
||||
* \brief Remove one element from the beginning of vector and return reference to vector
|
||||
|
||||
* \fn Type PIVector::take_back();
|
||||
* \brief Remove one element from the end of vector and return it
|
||||
|
||||
* \fn Type PIVector::take_front();
|
||||
* \brief Remove one element from the beginning of vector and return it
|
||||
|
||||
* \fn PIVector<T> & PIVector::remove(uint index);
|
||||
* \brief Remove one element by index "index" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::remove_0
|
||||
* \sa \a removeOne(), \a removeAll()
|
||||
|
||||
* \fn PIVector<T> & PIVector::remove(uint index, uint count);
|
||||
* \brief Remove "count" elements by first index "index" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::remove_1
|
||||
* \sa \a removeOne(), \a removeAll()
|
||||
|
||||
* \fn PIVector<T> & PIVector::removeOne(const Type & v);
|
||||
* \brief Remove no more than one element equal "v" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::removeOne
|
||||
* \sa \a remove(), \a removeAll()
|
||||
|
||||
* \fn PIVector<T> & PIVector::removeAll(const Type & v);
|
||||
* \brief Remove all elements equal "v" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::removeAll
|
||||
* \sa \a remove(), \a removeOne()
|
||||
|
||||
* \fn PIVector<T> & PIVector::insert(uint pos, const Type & t);
|
||||
* \brief Insert element "t" after index "pos" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::insert_0
|
||||
|
||||
* \fn PIVector<T> & PIVector::insert(uint pos, const PIVector<T> & t);
|
||||
* \brief Insert other vector "t" after index "pos" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::insert_1
|
||||
|
||||
* \fn Type & PIVector::operator [](uint index);
|
||||
* \brief Full access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::()
|
||||
* \sa \a at()
|
||||
|
||||
* \fn const Type & PIVector::operator [](uint index) const;
|
||||
* \brief Read-only access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::()_c
|
||||
* \sa \a at()
|
||||
|
||||
* \fn PIVector<T> & PIVector::operator <<(const Type & t);
|
||||
* \brief Add new element "t" at the end of vector and return reference to vector
|
||||
|
||||
* \fn PIVector<T> & PIVector::operator <<(const PIVector<T> & t);
|
||||
* \brief Add vector "t" at the end of vector and return reference to vector
|
||||
|
||||
* \fn bool PIVector::operator ==(const PIVector<T> & t);
|
||||
* \brief Compare with vector "t"
|
||||
|
||||
* \fn bool PIVector::operator !=(const PIVector<T> & t);
|
||||
* \brief Compare with vector "t"
|
||||
|
||||
* */
|
||||
563
picontainers.h
563
picontainers.h
@@ -1,12 +1,12 @@
|
||||
/*! \file picontainers.h
|
||||
* \brief Generic containers based on STL
|
||||
* \brief Generic containers
|
||||
*
|
||||
* This file declare all containers and useful macroses
|
||||
* This file declare all containers and useful macros
|
||||
* to use them
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Generic containers based on STL
|
||||
Generic containers
|
||||
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -26,7 +26,9 @@
|
||||
#ifndef PICONTAINERS_H
|
||||
#define PICONTAINERS_H
|
||||
|
||||
#include "piincludes.h"
|
||||
#include "pivector.h"
|
||||
#include "pistack.h"
|
||||
#include "piqueue.h"
|
||||
|
||||
#ifdef DOXYGEN
|
||||
/*! \def piForeach(i,c)
|
||||
@@ -62,46 +64,68 @@
|
||||
#ifdef CC_GCC
|
||||
|
||||
template<typename Type>
|
||||
class _PIForeachC {
|
||||
class _PIForeach {
|
||||
public:
|
||||
_PIForeachC(const Type & t, bool i = false): _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin(); _break = false;}
|
||||
_PIForeach(Type & t): _t(t) {_it = _t.begin(); _break = false;}
|
||||
typename Type::value_type _var;
|
||||
typename Type::const_iterator _it;
|
||||
typename Type::const_reverse_iterator _rit;
|
||||
const Type & _t;
|
||||
bool _break, _inv;
|
||||
inline bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();}
|
||||
inline void operator ++() {if (_inv) _rit++; else _it++; _break = false;}
|
||||
typename Type::iterator _it;
|
||||
Type & _t;
|
||||
bool _break;
|
||||
inline bool isEnd() {return _it == _t.end();}
|
||||
inline void operator ++() {_it++; _break = false;}
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
class _PIForeach {
|
||||
class _PIForeachR {
|
||||
public:
|
||||
_PIForeach(Type & t, bool i = false): _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin(); _break = false;}
|
||||
_PIForeachR(Type & t): _t(t) {_rit = _t.rbegin(); _break = false;}
|
||||
typename Type::value_type _var;
|
||||
typename Type::iterator _it;
|
||||
typename Type::reverse_iterator _rit;
|
||||
Type & _t;
|
||||
bool _break, _inv;
|
||||
inline bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();}
|
||||
inline void operator ++() {if (_inv) _rit++; else _it++; _break = false;}
|
||||
bool _break;
|
||||
inline bool isEnd() {return _rit == _t.rend();}
|
||||
inline void operator ++() {_rit++; _break = false;}
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
class _PIForeachC {
|
||||
public:
|
||||
_PIForeachC(const Type & t): _t(t) {_it = _t.begin(); _break = false;}
|
||||
typename Type::value_type _var;
|
||||
typename Type::const_iterator _it;
|
||||
const Type & _t;
|
||||
bool _break;
|
||||
inline bool isEnd() {return _it == _t.end();}
|
||||
inline void operator ++() {_it++; _break = false;}
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
class _PIForeachCR {
|
||||
public:
|
||||
_PIForeachCR(const Type & t): _t(t) {_rit = _t.rbegin(); _break = false;}
|
||||
typename Type::value_type _var;
|
||||
typename Type::const_reverse_iterator _rit;
|
||||
const Type & _t;
|
||||
bool _break;
|
||||
inline bool isEnd() {return _rit == _t.rend();}
|
||||
inline void operator ++() {_rit++; _break = false;}
|
||||
};
|
||||
|
||||
#define piForeach(i,c) for(_PIForeach<typeof(c)> _for(c); !_for.isEnd(); ++_for) \
|
||||
for(i = *_for._it; !_for._break; _for._break = true)
|
||||
#define piForeachR(i,c) for(_PIForeach<typeof(c)> _for(c, true); !_for.isEnd(); ++_for) \
|
||||
for(i = *_for._rit; !_for._break; _for._break = true)
|
||||
for(i(*_for._it); !_for._break; _for._break = true)
|
||||
#define piForeachR(i,c) for(_PIForeachR<typeof(c)> _for(c); !_for.isEnd(); ++_for) \
|
||||
for(i(*_for._rit); !_for._break; _for._break = true)
|
||||
#define piForeachA(i,c) for(_PIForeach<typeof(c)> _for(c); !_for.isEnd(); ++_for) \
|
||||
for(typeof(_for._var) & i(*_for._it); !_for._break; _for._break = true)
|
||||
#define piForeachAR(i,c) for(_PIForeach<typeof(c)> _for(c, true); !_for.isEnd(); ++_for) \
|
||||
#define piForeachAR(i,c) for(_PIForeachR<typeof(c)> _for(c); !_for.isEnd(); ++_for) \
|
||||
for(typeof(_for._var) & i(*_for._rit); !_for._break; _for._break = true)
|
||||
#define piForeachC(i,c) for(_PIForeachC<typeof(c)> _for(c); !_for.isEnd(); ++_for) \
|
||||
for(const i = *_for._it; !_for._break; _for._break = true)
|
||||
#define piForeachCR(i,c) for(_PIForeachC<typeof(c)> _for(c, true); !_for.isEnd(); ++_for) \
|
||||
for(const i = *_for._rit; !_for._break; _for._break = true)
|
||||
for(const i(*_for._it); !_for._break; _for._break = true)
|
||||
#define piForeachCR(i,c) for(_PIForeachCR<typeof(c)> _for(c); !_for.isEnd(); ++_for) \
|
||||
for(const i(*_for._rit); !_for._break; _for._break = true)
|
||||
#define piForeachCA(i,c) for(_PIForeachC<typeof(c)> _for(c); !_for.isEnd(); ++_for) \
|
||||
for(const typeof(_for._var) & i(*_for._it); !_for._break; _for._break = true)
|
||||
#define piForeachCAR(i,c) for(_PIForeachC<typeof(c)> _for(c, true); !_for.isEnd(); ++_for) \
|
||||
#define piForeachCAR(i,c) for(_PIForeachCR<typeof(c)> _for(c); !_for.isEnd(); ++_for) \
|
||||
for(const typeof(_for._var) & i(*_for._rit); !_for._break; _for._break = true)
|
||||
|
||||
#define piForeachRA piForeachAR
|
||||
@@ -163,424 +187,6 @@ template <typename T> inline _PIForeachC<T> * _PIForeachCastC(_PIForeachBase & c
|
||||
|
||||
#define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c)
|
||||
|
||||
/*
|
||||
template <typename T>
|
||||
class PIVector {
|
||||
public:
|
||||
PIVector(uint size = 0, const T & f = T()): data_(0), size_(0), rsize_(0) {resize(size, f);}
|
||||
PIVector(T * d, uint size): data_(0), size_(0), rsize_(0) {alloc(size); for (uint i = 0; i < size; ++i) data_[i] = d[i];}
|
||||
~PIVector() {dealloc();}
|
||||
|
||||
typedef T value_type;
|
||||
|
||||
class iterator {
|
||||
friend class PIVector<T>;
|
||||
private:
|
||||
iterator(PIVector<T> * v, int p): parent(v), pos(p) {}
|
||||
PIVector<T> * parent;
|
||||
int pos;
|
||||
public:
|
||||
iterator(): parent(0) {}
|
||||
T & operator *() {return (*parent)[pos];}
|
||||
const T & operator *() const {return (*parent)[pos];}
|
||||
void operator ++() {++pos;}
|
||||
void operator ++(int) {++pos;}
|
||||
void operator --() {--pos;}
|
||||
void operator --(int) {--pos;}
|
||||
bool operator ==(const iterator & it) const {return (pos == it.pos);}
|
||||
bool operator !=(const iterator & it) const {return (pos != it.pos);}
|
||||
};
|
||||
|
||||
class const_iterator {
|
||||
friend class PIVector<T>;
|
||||
private:
|
||||
const_iterator(const PIVector<T> * v, int p): parent(v), pos(p) {}
|
||||
const PIVector<T> * parent;
|
||||
int pos;
|
||||
public:
|
||||
const_iterator(): parent(0) {}
|
||||
//T & operator *() {return (*parent)[pos];}
|
||||
const T & operator *() const {return (*parent)[pos];}
|
||||
void operator ++() {++pos;}
|
||||
void operator ++(int) {++pos;}
|
||||
void operator --() {--pos;}
|
||||
void operator --(int) {--pos;}
|
||||
bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
|
||||
bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
|
||||
};
|
||||
|
||||
class reverse_iterator {
|
||||
friend class PIVector<T>;
|
||||
private:
|
||||
reverse_iterator(PIVector<T> * v, int p): parent(v), pos(p) {}
|
||||
PIVector<T> * parent;
|
||||
int pos;
|
||||
public:
|
||||
reverse_iterator(): parent(0) {}
|
||||
T & operator *() {return (*parent)[pos];}
|
||||
const T & operator *() const {return (*parent)[pos];}
|
||||
void operator ++() {--pos;}
|
||||
void operator ++(int) {--pos;}
|
||||
void operator --() {++pos;}
|
||||
void operator --(int) {++pos;}
|
||||
bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);}
|
||||
bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);}
|
||||
};
|
||||
|
||||
class const_reverse_iterator {
|
||||
friend class PIVector<T>;
|
||||
private:
|
||||
const_reverse_iterator(const PIVector<T> * v, int p): parent(v), pos(p) {}
|
||||
const PIVector<T> * parent;
|
||||
int pos;
|
||||
public:
|
||||
const_reverse_iterator(): parent(0) {}
|
||||
//T & operator *() {return (*parent)[pos];}
|
||||
const T & operator *() const {return (*parent)[pos];}
|
||||
void operator ++() {--pos;}
|
||||
void operator ++(int) {--pos;}
|
||||
void operator --() {++pos;}
|
||||
void operator --(int) {++pos;}
|
||||
bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
|
||||
bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
|
||||
};
|
||||
|
||||
iterator begin() {return iterator(this, 0);}
|
||||
iterator end() {return iterator(this, size_);}
|
||||
const_iterator begin() const {return const_iterator(this, 0);}
|
||||
const_iterator end() const {return const_iterator(this, size_);}
|
||||
reverse_iterator rbegin() {return reverse_iterator(this, size_ - 1);}
|
||||
reverse_iterator rend() {return reverse_iterator(this, -1);}
|
||||
const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size_ - 1);}
|
||||
const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
|
||||
|
||||
uint size() const {return size_;}
|
||||
int size_s() const {return size_;}
|
||||
int length() const {return size_;}
|
||||
bool isEmpty() const {return (size_ == 0);}
|
||||
|
||||
T & operator [](int index) {return data_[index];}
|
||||
T & at(uint index) {return data_[index];}
|
||||
const T & operator [](int index) const {return data_[index];}
|
||||
const T & at(uint index) const {return data_[index];}
|
||||
T & back() {return data_[size_ - 1];}
|
||||
const T & back() const {return data_[size_ - 1];}
|
||||
T & front() {return data_[0];}
|
||||
const T & front() const {return data_[0];}
|
||||
|
||||
bool operator ==(const PIVector<T> & t) const {if (size_ != t.size_) return false; for (uint i = 0; i < size_; ++i) if (t[i] != data_[i]) return false; return true;}
|
||||
bool operator !=(const PIVector<T> & t) const {if (size_ != t.size_) return true; for (uint i = 0; i < size_; ++i) if (t[i] != data_[i]) return true; return false;}
|
||||
bool contains(const T & v) const {for (uint i = 0; i < size_; ++i) if (v == data_[i]) return true; return false;}
|
||||
|
||||
T * data(int index = 0) {return &(data_[index]);}
|
||||
const T * data(int index = 0) const {return &(data_[index]);}
|
||||
PIVector<T> & clear() {resize(0); return *this;}
|
||||
PIVector<T> & fill(const T & f = T()) {
|
||||
if (sizeof(T) == 1) memset(data_, f, size_);
|
||||
else for (uint i = 0; i < size_; ++i) memcpy(&(data_[i]), &f, sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
PIVector<T> & assign(const T & f = T()) {return fill(f);}
|
||||
PIVector<T> & resize(uint new_size, const T & f = T()) {
|
||||
if (new_size < size_) {
|
||||
size_ = new_size;
|
||||
return *this;
|
||||
}
|
||||
if (new_size > size_) {
|
||||
os = size_;
|
||||
alloc(new_size);
|
||||
uint ds = size_ - os;
|
||||
//if (sizeof(T) == 1) memset(&(data_[os]), f, ds);
|
||||
for (uint i = 0; i < ds; ++i) data_[os + i] = f;
|
||||
return *this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
PIVector<T> & insert(int index, const T & v = T()) {
|
||||
push_back(v);
|
||||
if (index >= int(size_ - 1)) return *this;
|
||||
os = size_ - index;
|
||||
T * pd = new T[os * sizeof(T)];
|
||||
memcpy(pd, &(data_[index]), os * sizeof(T));
|
||||
memcpy(&(data_[index + 1]), pd, os * sizeof(T));
|
||||
delete[] pd;
|
||||
data_[index] = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PIVector<T> & remove(int index, int count = 1) {
|
||||
if (index + count >= int(size_)) {
|
||||
resize(index);
|
||||
return *this;
|
||||
}
|
||||
os = size_ - index - count;
|
||||
T * pd = new T[os * sizeof(T)];
|
||||
memcpy(pd, &(data_[index + count]), os * sizeof(T));
|
||||
memcpy(&(data_[index]), pd, os * sizeof(T));
|
||||
delete[] pd;
|
||||
resize(size_ - count);
|
||||
return *this;
|
||||
}
|
||||
|
||||
typedef int (*CompareFunc)(const T * , const T * );
|
||||
static int compare_func(const T * t0, const T * t1) {return (*t0) == (*t1) ? 0 : ((*t0) < (*t1) ? -1 : 1);}
|
||||
PIVector<T> & sort(CompareFunc compare = compare_func) {qsort(data_, size_, sizeof(T), (int(*)(const void * , const void * ))compare); return *this;}
|
||||
|
||||
PIVector<T> & removeOne(const T & v) {for (uint i = 0; i < size_; ++i) if (data_[i] == v) {remove(i); return *this;} return *this;}
|
||||
PIVector<T> & removeAll(const T & v) {for (uint i = 0; i < size_; ++i) if (data_[i] == v) {remove(i); --i;} return *this;}
|
||||
|
||||
PIVector<T> & push_back(const T & v) {alloc(size_ + 1); data_[size_ - 1] = v; return *this;}
|
||||
PIVector<T> & append(const T & v) {return push_back(v);}
|
||||
PIVector<T> & operator <<(const T & v) {return push_back(v);}
|
||||
|
||||
PIVector<T> & push_front(const T & v) {insert(0, v); return *this;}
|
||||
PIVector<T> & prepend(const T & v) {return push_front(v);}
|
||||
//PIVector<T> & operator <<(const T & v) {return push_back(v);}
|
||||
|
||||
PIVector<T> & pop_back() {if (size_ == 0) return *this; resize(size_ - 1); return *this;}
|
||||
PIVector<T> & pop_front() {if (size_ == 0) return *this; remove(0); return *this;}
|
||||
|
||||
private:
|
||||
uint asize(uint s) {if (s == 0) return 0; if (rsize_ + rsize_ >= s && rsize_ < s) return rsize_ + rsize_; uint t = 0, s_ = s - 1; while (s_ >> t) ++t; return (1 << t);}
|
||||
void dealloc() {if (data_ != 0) delete[] data_; data_ = 0;}
|
||||
void alloc(uint new_size) {
|
||||
if (new_size <= rsize_) {
|
||||
size_ = new_size;
|
||||
return;
|
||||
}
|
||||
os = size_;
|
||||
size_ = new_size;
|
||||
uint as = asize(new_size);
|
||||
if (as == rsize_) return;
|
||||
T * pd = 0;
|
||||
if (os > 0) {
|
||||
pd = new T[os * sizeof(T)];
|
||||
memcpy(pd, data_, os * sizeof(T));
|
||||
}
|
||||
rsize_ = as;
|
||||
dealloc();
|
||||
data_ = new T[rsize_ * sizeof(T)];
|
||||
if (os > 0) {
|
||||
memcpy(data_, pd, size_ * sizeof(T));
|
||||
delete[] pd;
|
||||
}
|
||||
}
|
||||
|
||||
T * data_;
|
||||
uint size_, rsize_, os;
|
||||
};
|
||||
*/
|
||||
|
||||
/*! \brief Dynamic array for any type
|
||||
* \details This class used to store dynamic array of any
|
||||
* type of data. In memory data stored linear. You can insert
|
||||
* item in any place of remove some items from any place.
|
||||
* For quick add elements there is stream operator <<.
|
||||
* This class based on std::vector, expanding his
|
||||
* functionality.
|
||||
*/
|
||||
template<typename Type, typename Allocator = std::allocator<Type> >
|
||||
class PIP_EXPORT PIVector: public vector<Type, Allocator> {
|
||||
typedef PIVector<Type, Allocator> _CVector;
|
||||
typedef vector<Type, Allocator> _stlc;
|
||||
public:
|
||||
//! Contructs an empty vector
|
||||
PIVector() {piMonitor.containers++;}
|
||||
|
||||
//! Contructs vector with single element "value"
|
||||
PIVector(const Type & value) {piMonitor.containers++; _stlc::push_back(value);}
|
||||
|
||||
//! Contructs vector with two elements "v0" and "v1"
|
||||
PIVector(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);}
|
||||
|
||||
//! Contructs vector with three elements "v0", "v1" and "v2"
|
||||
PIVector(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);}
|
||||
|
||||
//! Contructs vector with four elements "v0", "v1", "v2" and "v3"
|
||||
PIVector(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);}
|
||||
|
||||
/*! \brief Contructs vector with size "size" filled elements "value"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::PIVector */
|
||||
PIVector(uint size, const Type & value = Type()) {piMonitor.containers++; _stlc::resize(size, value);}
|
||||
~PIVector() {piMonitor.containers--;}
|
||||
|
||||
/*! \brief Read-only access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::at_c
|
||||
* \sa \a operator[] */
|
||||
const Type & at(uint index) const {return (*this)[index];}
|
||||
|
||||
/*! \brief Full access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::at
|
||||
* \sa \a operator[] */
|
||||
Type & at(uint index) {return (*this)[index];}
|
||||
|
||||
/*! \brief Read-only pointer to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::data_c */
|
||||
const Type * data(uint index = 0) const {return &(*this)[index];}
|
||||
|
||||
/*! \brief Pointer to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::data */
|
||||
Type * data(uint index = 0) {return &(*this)[index];}
|
||||
|
||||
#ifdef DOXYGEN
|
||||
//! Elements count
|
||||
uint size() const;
|
||||
#endif
|
||||
|
||||
//! Elements count
|
||||
int size_s() const {return static_cast<int>(_stlc::size());}
|
||||
|
||||
//! Return \c "true" if vector is empty, i.e. size = 0
|
||||
bool isEmpty() const {return _stlc::empty();}
|
||||
|
||||
//! Return \c "true" if vector has at least one element equal "t"
|
||||
bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;}
|
||||
|
||||
//! Return how many times element "t" appears in vector
|
||||
int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;}
|
||||
typedef int (*CompareFunc)(const Type * , const Type * );
|
||||
|
||||
//! Standard compare function for type "Type". Return 0 if t0 = t1, -1 if t0 < t1 and 1 if t0 > t1.
|
||||
static int compare_func(const Type * t0, const Type * t1) {return (*t0) == (*t1) ? 0 : ((*t0) < (*t1) ? -1 : 1);}
|
||||
#ifdef DOXYGEN
|
||||
|
||||
/*! \brief Resize vector to size "size"
|
||||
* \details Elements removed from end of vector if new size < old size, or added new elements = "new_type" if new size > old size.\n
|
||||
* Example: \snippet picontainers.cpp PIVector::resize
|
||||
* \sa \a size(), \a clear() */
|
||||
void resize(uint size, const Type & new_type = Type());
|
||||
|
||||
//! Increase vector size with "size" elements
|
||||
PIVector<Type, Allocator> & enlarge(uint size);
|
||||
|
||||
//! Clear vector. Equivalent to call <tt>"resize(0)"</tt>
|
||||
void clear();
|
||||
|
||||
/*! \brief Sort vector using quick sort algorithm and standard compare function
|
||||
* \details Example: \snippet picontainers.cpp PIVector::sort_0
|
||||
* With custom compare function: \snippet picontainers.cpp PIVector::sort_1 */
|
||||
PIVector<Type, Allocator> & sort(CompareFunc compare = compare_func) {qsort(&at(0), _stlc::size(), sizeof(Type), (int(*)(const void * , const void * ))compare); return *this;}
|
||||
|
||||
/*! \brief Fill vector with elements "t" leave size is unchanged and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::fill */
|
||||
PIVector<Type, Allocator> & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;}
|
||||
|
||||
//! Last element of vector
|
||||
Type & back();
|
||||
|
||||
//! Last element of vector
|
||||
const Type & back() const;
|
||||
|
||||
//! First element of vector
|
||||
Type & front();
|
||||
|
||||
//! First element of vector
|
||||
const Type & front() const;
|
||||
|
||||
//! Add new element "t" at the end of vector and return reference to vector
|
||||
PIVector<Type, Allocator> & push_back(const Type & t);
|
||||
|
||||
//! Add new element "t" at the beginning of vector and return reference to vector
|
||||
PIVector<Type, Allocator> & push_front(const Type & t) {_stlc::insert(_stlc::begin(), t); return *this;}
|
||||
|
||||
//! Remove one element from the end of vector and return reference to vector
|
||||
PIVector<Type, Allocator> & pop_back();
|
||||
|
||||
//! Remove one element from the beginning of vector and return reference to vector
|
||||
PIVector<Type, Allocator> & pop_front() {_stlc::erase(_stlc::begin()); return *this;}
|
||||
|
||||
//! Remove one element from the end of vector and return it
|
||||
Type take_back() {Type t(_stlc::back()); _stlc::pop_back(); return t;}
|
||||
|
||||
//! Remove one element from the beginning of vector and return it
|
||||
Type take_front() {Type t(_stlc::front()); pop_front(); return t;}
|
||||
|
||||
/*! \brief Remove one element by index "index" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::remove_0
|
||||
* \sa \a removeOne(), \a removeAll() */
|
||||
PIVector<Type, Allocator> & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
|
||||
|
||||
/*! \brief Remove "count" elements by first index "index" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::remove_1
|
||||
* \sa \a removeOne(), \a removeAll() */
|
||||
PIVector<Type, Allocator> & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
|
||||
|
||||
/*! \brief Remove no more than one element equal "v" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::removeOne
|
||||
* \sa \a remove(), \a removeAll() */
|
||||
PIVector<Type, Allocator> & removeOne(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;}
|
||||
|
||||
/*! \brief Remove all elements equal "v" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::removeAll
|
||||
* \sa \a remove(), \a removeOne() */ */
|
||||
PIVector<Type, Allocator> & removeAll(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;}
|
||||
|
||||
/*! \brief Insert element "t" after index "pos" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::insert_0 */
|
||||
PIVector<Type, Allocator> & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
|
||||
|
||||
/*! \brief Insert other vector "t" after index "pos" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::insert_1 */
|
||||
PIVector<Type, Allocator> & insert(uint pos, const PIVector<Type, Allocator> & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;}
|
||||
|
||||
/*! \brief Full access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::()
|
||||
* \sa \a at() */
|
||||
Type & operator [](uint index);
|
||||
|
||||
/*! \brief Read-only access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::()_c
|
||||
* \sa \a at() */
|
||||
const Type & operator [](uint index) const;
|
||||
|
||||
//! Add new element "t" at the end of vector and return reference to vector
|
||||
PIVector<Type, Allocator> & operator <<(const Type & t) {_stlc::push_back(t); return *this;}
|
||||
|
||||
//! Add vector "t" at the end of vector and return reference to vector
|
||||
PIVector<Type, Allocator> & operator <<(const PIVector<Type, Allocator> & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
|
||||
|
||||
//! Compare with vector "t"
|
||||
bool operator ==(const PIVector<Type, Allocator> & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;}
|
||||
|
||||
//! Compare with vector "t"
|
||||
bool operator !=(const PIVector<Type, Allocator> & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;}
|
||||
|
||||
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(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;}
|
||||
_CVector & push_front(const Type & t) {_stlc::insert(_stlc::begin(), t); return *this;}
|
||||
Type take_front() {Type t(_stlc::front()); pop_front(); return t;}
|
||||
Type take_back() {Type t(_stlc::back()); _stlc::pop_back(); return t;}
|
||||
_CVector & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
|
||||
_CVector & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
|
||||
_CVector & removeOne(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;}
|
||||
_CVector & removeAll(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;}
|
||||
_CVector & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
|
||||
_CVector & insert(uint pos, const _CVector & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;}
|
||||
_CVector & operator <<(const Type & t) {_stlc::push_back(t); return *this;}
|
||||
_CVector & operator <<(const _CVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
|
||||
bool operator ==(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;}
|
||||
bool operator !=(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;}
|
||||
bool contains(const Type & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
|
||||
#endif
|
||||
};
|
||||
|
||||
/*! \brief Output operator for std::ostream
|
||||
* \relates PIVector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::ostream<< */
|
||||
template<typename Type>
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIVector<Type> & v) {s << "{"; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;}
|
||||
|
||||
/*! \brief Output operator for PICout
|
||||
* \relates PIVector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::PICout<< */
|
||||
template<typename Type>
|
||||
inline PICout operator <<(PICout s, const PIVector<Type> & v) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;}
|
||||
|
||||
template<typename Type, typename Allocator = std::allocator<Type> >
|
||||
class PIP_EXPORT PIList: public list<Type, Allocator> {
|
||||
@@ -610,41 +216,64 @@ public:
|
||||
PIVector<Type> toVector() {PIVector<Type> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
|
||||
};
|
||||
|
||||
/*! \brief Set of any type
|
||||
* \details This class used to store collection of unique elements
|
||||
* of any type. You can only add values to set with \a operator<< or
|
||||
* with function \a insert(). You can discover if value already in
|
||||
* set with \a operator[] or with function \a find(). These function
|
||||
* has logarithmic complexity.
|
||||
*/
|
||||
template<typename Type, typename Compare = std::less<Type>, typename Allocator = std::allocator<Type> >
|
||||
class PIP_EXPORT PISet: public set<Type, Compare, Allocator> {
|
||||
typedef PISet<Type, Compare, Allocator> _CSet;
|
||||
typedef set<Type, Compare, Allocator> _stlc;
|
||||
public:
|
||||
|
||||
//! Contructs an empty set
|
||||
PISet() {piMonitor.containers++;}
|
||||
|
||||
//! Contructs set with one element "value"
|
||||
PISet(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);}
|
||||
|
||||
//! Contructs set with elements "v0" and "v1"
|
||||
PISet(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::insert(v0); _stlc::insert(v1);}
|
||||
|
||||
//! Contructs set with elements "v0", "v1" and "v2"
|
||||
PISet(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::insert(v0); _stlc::insert(v1); _stlc::insert(v2);}
|
||||
|
||||
//! Contructs set with elements "v0", "v1", "v2" and "v3"
|
||||
PISet(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::insert(v0); _stlc::insert(v1); _stlc::insert(v2); _stlc::insert(v3);}
|
||||
|
||||
~PISet() {piMonitor.containers--;}
|
||||
|
||||
//! Returns elements count
|
||||
int size_s() const {return static_cast<int>(_stlc::size());}
|
||||
|
||||
//! Returns if set is empty
|
||||
bool isEmpty() const {return _stlc::empty();}
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
//! Clear th set
|
||||
void clear();
|
||||
|
||||
//! Insert element "t" if it doesn`t exists in this set
|
||||
void insert(const Type & t);
|
||||
|
||||
#endif
|
||||
|
||||
_CSet & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
|
||||
_CSet & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
|
||||
_CSet & operator <<(const Type & t) {_stlc::insert(t); return *this;}
|
||||
|
||||
//! Returns if element "t" exists in this set
|
||||
bool operator [](const Type & t) {return _stlc::find(t);}
|
||||
|
||||
//! Returns content of set as PIVector
|
||||
PIVector<Type> toVector() {PIVector<Type> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
class PIP_EXPORT PIStack: public PIVector<Type> {
|
||||
typedef PIStack<Type> _CStack;
|
||||
public:
|
||||
PIStack() {;}
|
||||
PIStack(const Type & value) {_CStack::resize(1, value);}
|
||||
PIStack(const Type & v0, const Type & v1) {_CStack::push_back(v0); _CStack::push_back(v1);}
|
||||
PIStack(const Type & v0, const Type & v1, const Type & v2) {_CStack::push_back(v0); _CStack::push_back(v1); _CStack::push_back(v2);}
|
||||
PIStack(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {_CStack::push_back(v0); _CStack::push_back(v1); _CStack::push_back(v2); _CStack::push_back(v3);}
|
||||
_CStack & push(const Type & v) {_CStack::push_back(v); return *this;}
|
||||
Type pop() {Type t = Type(); if (_CStack::size() == 0) return t; t = _CStack::back(); _CStack::pop_back(); return t;}
|
||||
Type & top() {return _CStack::back();}
|
||||
const Type & top() const {return _CStack::back();}
|
||||
PIVector<Type> toVector() {PIVector<Type> v; for (typename _CStack::const_iterator i = _CStack::begin(); i != _CStack::end(); ++i) v << *i; return v;}
|
||||
};
|
||||
|
||||
|
||||
template<typename Type, typename Allocator = std::allocator<Type> >
|
||||
class PIP_EXPORT PIDeque: public deque<Type, Allocator> {
|
||||
@@ -665,22 +294,6 @@ public:
|
||||
PIVector<Type> toVector() {PIVector<Type> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
class PIP_EXPORT PIQueue: public PIDeque<Type> {
|
||||
typedef PIQueue<Type> _CQueue;
|
||||
public:
|
||||
PIQueue() {;}
|
||||
PIQueue(const Type & value) {_CQueue::resize(1, value);}
|
||||
PIQueue(const Type & v0, const Type & v1) {_CQueue::push_front(v0); _CQueue::push_front(v1);}
|
||||
PIQueue(const Type & v0, const Type & v1, const Type & v2) {_CQueue::push_front(v0); _CQueue::push_front(v1); _CQueue::push_front(v2);}
|
||||
PIQueue(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {_CQueue::push_front(v0); _CQueue::push_front(v1); _CQueue::push_front(v2); _CQueue::push_front(v3);}
|
||||
_CQueue & enqueue(const Type & v) {_CQueue::push_front(v); return *this;}
|
||||
Type dequeue() {Type t = Type(); if (_CQueue::size() == 0) return t; t = _CQueue::back(); _CQueue::pop_back(); return t;}
|
||||
Type & head() {return _CQueue::back();}
|
||||
const Type & head() const {return _CQueue::back();}
|
||||
PIVector<Type> toVector() {PIVector<Type> v; for (typename _CQueue::const_iterator i = _CQueue::begin(); i != _CQueue::end(); ++i) v << *i; return v;}
|
||||
};
|
||||
|
||||
|
||||
template<typename Type0, typename Type1>
|
||||
class PIP_EXPORT PIPair {
|
||||
|
||||
25
picrc.h
25
picrc.h
@@ -165,12 +165,14 @@ inline std::ostream & operator <<(std::ostream & s, const uint_cl<L> & v) {std::
|
||||
template <uint L>
|
||||
class PIP_EXPORT PICRC {
|
||||
public:
|
||||
PICRC(const uint_cl<L> & poly) {poly_ = poly; reverse_poly = true; init_ = uint_cl<L>(0).inversed(); out_ = uint_cl<L>(0).inversed(); initTable();}
|
||||
PICRC(const uint_cl<L> & poly, bool reverse, const uint_cl<L> & initial, const uint_cl<L> & out_xor) {poly_ = poly; reverse_poly = reverse; init_ = initial; out_ = out_xor; initTable();}
|
||||
PICRC(const uint_cl<L> & poly) {poly_ = poly; reverse_poly = true; init_ = uint_cl<L>(0).inversed(); out_ = uint_cl<L>(0).inversed(); reverse_before_xor = reverse_data = false; initTable();}
|
||||
PICRC(const uint_cl<L> & poly, bool reverse_poly_, const uint_cl<L> & initial, const uint_cl<L> & out_xor) {poly_ = poly; reverse_poly = reverse_poly_; init_ = initial; out_ = out_xor; reverse_before_xor = reverse_data = false; initTable();}
|
||||
|
||||
void setInitial(const uint_cl<L> & v) {init_ = v;}
|
||||
void setOutXor(const uint_cl<L> & v) {out_ = v;}
|
||||
void setReversePolynome(bool yes) {reverse_poly = yes; initTable();}
|
||||
void setReverseOutBeforeXOR(bool yes) {reverse_before_xor = yes;}
|
||||
void setReverseDataBytes(bool yes) {reverse_data = yes;}
|
||||
|
||||
void initTable() {
|
||||
uint_cl<L> tmp, pol = reverse_poly ? poly_.reversed() : poly_;
|
||||
@@ -186,14 +188,17 @@ public:
|
||||
|
||||
uint_cl<L> calculate(const void * data, int size) {
|
||||
uint_cl<L> crc = init_;
|
||||
uchar * data_ = (uchar * )data;
|
||||
uchar * data_ = (uchar * )data, cb;
|
||||
//cout << "process " << size << endl;
|
||||
uchar nTemp;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
nTemp = data_[i] ^ uchar(crc);
|
||||
cb = data_[i];
|
||||
if (reverse_data) cb = reverseByte(cb);
|
||||
nTemp = cb ^ uchar(crc);
|
||||
crc = crc >> 8;
|
||||
crc = crc ^ table[nTemp];
|
||||
}
|
||||
if (reverse_before_xor) crc = crc.reversed();
|
||||
return crc ^ out_;
|
||||
|
||||
}
|
||||
@@ -201,9 +206,19 @@ public:
|
||||
uint_cl<L> calculate(const char * str) {string s(str); return calculate((void * )s.data(), s.size());}
|
||||
|
||||
private:
|
||||
uchar reverseByte(uchar b) {
|
||||
uchar ret = 0;
|
||||
bool bit;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
bit = 1 & (b >> (7 - i));
|
||||
if (bit) ret |= (1 << i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint_cl<L> table[256];
|
||||
uint_cl<L> poly_, init_, out_;
|
||||
bool reverse_poly;
|
||||
bool reverse_poly, reverse_before_xor, reverse_data;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -20,6 +20,23 @@
|
||||
#include "pidiagnostics.h"
|
||||
|
||||
|
||||
/** \class PIDiagnostics
|
||||
* \brief Connection quality diagnostics
|
||||
* \details
|
||||
* \section PIDiagnostics_sec0 Synopsis
|
||||
* This class provide abstract connection quality diagnostics and
|
||||
* counting. You should create instance of %PIDiagnostics and on
|
||||
* packet receive call function \a received(), on packet send call
|
||||
* function \a sended(). %PIDiagnostics calculates correct, wrong
|
||||
* and sended counters, packets per second, bytes per seconds,
|
||||
* immediate and integral receive frequencies and receive/send speeds
|
||||
* in human readable representation. There statistics are calculates
|
||||
* one time per period, by default 1 second. To calculate them you
|
||||
* should start %PIDiagnostics with function \a start() or pass \b true
|
||||
* to constructor.
|
||||
* */
|
||||
|
||||
|
||||
PIDiagnostics::PIDiagnostics(bool start_): PITimer() {
|
||||
PITimer::reset();
|
||||
reset();
|
||||
@@ -46,9 +63,9 @@ void PIDiagnostics::received(int size, bool correct) {
|
||||
rec_once = 1;
|
||||
if (correct) {
|
||||
float el = elapsed_s();
|
||||
PITimer::reset();
|
||||
if (el > 0.f) immediate_freq = ifreq = 1.f / el;
|
||||
else immediate_freq = ifreq = 0.f;
|
||||
PITimer::reset();
|
||||
receive_count++;
|
||||
packets_in_sec++;
|
||||
bytes_in_sec += size;
|
||||
|
||||
136
pidiagnostics.h
136
pidiagnostics.h
@@ -30,10 +30,94 @@ class PIP_EXPORT PIDiagnostics: private PITimer
|
||||
{
|
||||
PIOBJECT(PIDiagnostics)
|
||||
public:
|
||||
|
||||
//! Constructs an empty diagnostics and if "strat_" start it
|
||||
PIDiagnostics(bool start_ = true);
|
||||
|
||||
virtual ~PIDiagnostics() {;}
|
||||
|
||||
enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5};
|
||||
//! Connection quality
|
||||
enum Quality {
|
||||
Unknown /** Unknown, no one packet received yet */ = 1,
|
||||
Failure /** No connection, no one correct packet received for last period */ = 2,
|
||||
Bad /** Bad connection, correct packets received <= 20% */ = 3,
|
||||
Average /** Average connection, correct packets received > 20% and <= 80% */ = 4,
|
||||
Good /** Good connection, correct packets received > 80% */ = 5
|
||||
};
|
||||
|
||||
|
||||
//! Returns immediate receive frequency, packets/s
|
||||
float immediateFrequency() const {return immediate_freq;}
|
||||
|
||||
//! Returns integral receive frequency for period, packets/s
|
||||
float integralFrequency() const {return integral_freq;}
|
||||
|
||||
//! Returns correct received packets per second
|
||||
ullong receiveCountPerSec() const {return packets_in_sec;}
|
||||
|
||||
//! Returns sended packets per second
|
||||
ullong sendCountPerSec() const {return packets_out_sec;}
|
||||
|
||||
//! Returns correct received bytes per second
|
||||
ullong receiveBytesPerSec() const {return bytes_in_sec;}
|
||||
|
||||
//! Returns sended bytes per second
|
||||
ullong sendBytesPerSec() const {return bytes_out_sec;}
|
||||
|
||||
//! Returns overall correct received packets count
|
||||
ullong receiveCount() const {return receive_count;}
|
||||
|
||||
//! Returns overall wrong received packets count
|
||||
ullong wrongCount() const {return wrong_count;}
|
||||
|
||||
//! Returns overall sended packets count
|
||||
ullong sendCount() const {return send_count;}
|
||||
|
||||
//! Returns connection quality
|
||||
PIDiagnostics::Quality quality() const {return qual;}
|
||||
|
||||
//! Returns receive speed in format "n {B|kB|MB|GB|TB}/s"
|
||||
PIString receiveSpeed() const {return speedIn;}
|
||||
|
||||
//! Returns send speed in format "n {B|kB|MB|GB|TB}/s"
|
||||
PIString sendSpeed() const {return speedOut;}
|
||||
|
||||
|
||||
//! Returns immediate receive frequency pointer, packets/s. Useful for output to PIConsole
|
||||
const float * immediateFrequency_ptr() const {return &immediate_freq;}
|
||||
|
||||
//! Returns integral receive frequency pointer for period, packets/s. Useful for output to PIConsole
|
||||
const float * integralFrequency_ptr() const {return &integral_freq;}
|
||||
|
||||
//! Returns correct received packets per second pointer. Useful for output to PIConsole
|
||||
const ullong * receiveCountPerSec_ptr() const {return &packets_in_sec;}
|
||||
|
||||
//! Returns sended packets per second pointer. Useful for output to PIConsole
|
||||
const ullong * sendCountPerSec_ptr() const {return &packets_out_sec;}
|
||||
|
||||
//! Returns correct received bytes per second pointer. Useful for output to PIConsole
|
||||
const ullong * receiveBytesPerSec_ptr() const {return &bytes_in_sec;}
|
||||
|
||||
//! Returns sended bytes per second pointer. Useful for output to PIConsole
|
||||
const ullong * sendBytesPerSec_ptr() const {return &bytes_out_sec;}
|
||||
|
||||
//! Returns overall correct received packets count pointer. Useful for output to PIConsole
|
||||
const ullong * receiveCount_ptr() const {return &receive_count;}
|
||||
|
||||
//! Returns overall wrong received packets count pointer. Useful for output to PIConsole
|
||||
const ullong * wrongCount_ptr() const {return &wrong_count;}
|
||||
|
||||
//! Returns overall sended packets count pointer. Useful for output to PIConsole
|
||||
const ullong * sendCount_ptr() const {return &send_count;}
|
||||
|
||||
//! Returns connection quality pointer. Useful for output to PIConsole
|
||||
const int * quality_ptr() const {return (int * )&qual;}
|
||||
|
||||
//! Returns receive speed pointer in format "n {B|kB|MB|GB|TB}/s". Useful for output to PIConsole
|
||||
const PIString * receiveSpeed_ptr() const {return &speedIn;}
|
||||
|
||||
//! Returns send speed pointer in format "n {B|kB|MB|GB|TB}/s". Useful for output to PIConsole
|
||||
const PIString * sendSpeed_ptr() const {return &speedOut;}
|
||||
|
||||
EVENT_HANDLER0(void, start) {start(1000.);}
|
||||
EVENT_HANDLER1(void, start, double, msecs) {if (msecs > 0.) PITimer::start(msecs);}
|
||||
@@ -43,34 +127,32 @@ public:
|
||||
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)
|
||||
|
||||
//! \handlers
|
||||
//! \{
|
||||
|
||||
//! \fn void start(double msecs = 1000.)
|
||||
//! \brief Start diagnostics evaluations with period "msecs" milliseconds
|
||||
|
||||
//! \fn void reset()
|
||||
//! \brief Reset diagnostics counters
|
||||
|
||||
//! \fn void received(int size, bool correct = true)
|
||||
//! \brief Notify diagnostics about "correct" corected received packet
|
||||
|
||||
//! \fn void sended(int size)
|
||||
//! \brief Notify diagnostics about sended packet
|
||||
|
||||
//! \}
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
//! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality)
|
||||
//! \brief Raise on change receive quality from "old_quality" to "new_quality"
|
||||
|
||||
//! \}
|
||||
|
||||
private:
|
||||
void tick(void * data, int delimiter);
|
||||
void changeDisconnectTimeout();
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "pidir.h"
|
||||
|
||||
#ifndef WINDOWS
|
||||
#if !defined(WINDOWS) && !defined(ANDROID)
|
||||
#ifdef WINDOWS
|
||||
const PIChar PIDir::separator = '\\';
|
||||
#else
|
||||
|
||||
8
pidir.h
8
pidir.h
@@ -22,8 +22,12 @@
|
||||
|
||||
#include "pifile.h"
|
||||
#include "pistring.h"
|
||||
#ifndef WINDOWS
|
||||
#include <sys/dir.h>
|
||||
#if !defined(WINDOWS) && !defined(ANDROID)
|
||||
#ifdef ANDROID
|
||||
# include <sys/dirent.h>
|
||||
#else
|
||||
# include <sys/dir.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
class PIP_EXPORT PIDir
|
||||
|
||||
@@ -19,17 +19,40 @@
|
||||
|
||||
#include "piethernet.h"
|
||||
#include "piconfig.h"
|
||||
#ifdef QNX
|
||||
# include <net/if_dl.h>
|
||||
# include <hw/nicinfo.h>
|
||||
# include <sys/dcmd_io-net.h>
|
||||
#endif
|
||||
|
||||
|
||||
PIEthernet::PIEthernet(void * data, ReadRetFunc slot): PIIODevice("", ReadWrite) {
|
||||
/** \class PIEthernet
|
||||
* \brief Ethernet device
|
||||
* \details
|
||||
* \section PIEthernet_sec0 Synopsis
|
||||
* %PIEthernet designed to work with IPv4 network by two protocols:
|
||||
* UDP and TCP. This class allow you send and receive packets to/from
|
||||
* another computer through network.
|
||||
*
|
||||
* \section PIEthernet_sec1 IPv4
|
||||
*
|
||||
*
|
||||
* \section PIEthernet_sec2 UDP
|
||||
* User Datagram Protocol
|
||||
*
|
||||
* \section PIEthernet_sec3 TCP
|
||||
* Transmission Control Protocol
|
||||
*
|
||||
* */
|
||||
|
||||
|
||||
PIEthernet::PIEthernet(): PIIODevice("", ReadWrite) {
|
||||
piMonitor.ethernets++;
|
||||
setPriority(piHigh);
|
||||
type_ = UDP;
|
||||
ret_data_ = data;
|
||||
ip_ = ip_s = "";
|
||||
port_ = port_s = 0;
|
||||
sock = sock_s = -1;
|
||||
ret_func_ = slot;
|
||||
connected_ = false;
|
||||
params = PIEthernet::ReuseAddress;
|
||||
server_thread_.setData(this);
|
||||
@@ -38,17 +61,16 @@ PIEthernet::PIEthernet(void * data, ReadRetFunc slot): PIIODevice("", ReadWrite)
|
||||
}
|
||||
|
||||
|
||||
PIEthernet::PIEthernet(PIEthernet::Type type, void * data, ReadRetFunc slot): PIIODevice("", ReadWrite) {
|
||||
PIEthernet::PIEthernet(PIEthernet::Type type, const PIString & ip_port, const PIFlags<PIEthernet::Parameters> params_): PIIODevice(ip_port, ReadWrite) {
|
||||
piMonitor.ethernets++;
|
||||
setPriority(piHigh);
|
||||
type_ = type;
|
||||
ret_data_ = data;
|
||||
ip_ = ip_s = "";
|
||||
port_ = port_s = 0;
|
||||
parseAddress(ip_port, &ip_, &port_);
|
||||
ip_s = "";
|
||||
port_s = 0;
|
||||
sock = sock_s = -1;
|
||||
ret_func_ = slot;
|
||||
connected_ = false;
|
||||
params = (type == UDP ? PIEthernet::ReuseAddress : 0);
|
||||
params = params_;
|
||||
server_thread_.setData(this);
|
||||
setThreadedReadBufferSize(65536);
|
||||
if (type_ != UDP) init();
|
||||
@@ -75,6 +97,7 @@ PIEthernet::~PIEthernet() {
|
||||
if (server_thread_.isRunning()) server_thread_.terminate();
|
||||
stop();
|
||||
closeSocket(sock);
|
||||
closeSocket(sock_s);
|
||||
//if (buffer_ != 0) delete buffer_;
|
||||
//buffer_ = 0;
|
||||
}
|
||||
@@ -83,7 +106,8 @@ PIEthernet::~PIEthernet() {
|
||||
bool PIEthernet::init() {
|
||||
//cout << "init " << type_ << endl;
|
||||
closeSocket(sock);
|
||||
int st = 0, pr = 0;;
|
||||
closeSocket(sock_s);
|
||||
int st = 0, pr = 0;
|
||||
#ifdef WINDOWS
|
||||
int flags = WSA_FLAG_OVERLAPPED;
|
||||
#else
|
||||
@@ -99,10 +123,12 @@ bool PIEthernet::init() {
|
||||
#ifdef WINDOWS
|
||||
if (type_ == UDP) flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF;
|
||||
sock = WSASocket(AF_INET, st, pr, NULL, 0, flags);
|
||||
sock_s = WSASocket(AF_INET, st, pr, NULL, 0, WSA_FLAG_OVERLAPPED);
|
||||
#else
|
||||
sock = socket(AF_INET, st, pr);
|
||||
sock_s = socket(AF_INET, st, pr);
|
||||
#endif
|
||||
if (sock == -1) {
|
||||
if (sock == -1 || sock_s == -1) {
|
||||
piCoutObj << "Can`t create socket, " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
@@ -161,6 +187,7 @@ bool PIEthernet::openDevice() {
|
||||
bool PIEthernet::closeDevice() {
|
||||
//cout << "close\n";
|
||||
closeSocket(sock);
|
||||
closeSocket(sock_s);
|
||||
piForeach (PIEthernet * i, clients_)
|
||||
delete i;
|
||||
clients_.clear();
|
||||
@@ -177,7 +204,7 @@ void PIEthernet::closeSocket(int & sd) {
|
||||
shutdown(sd, SD_BOTH);
|
||||
closesocket(sd);
|
||||
#else
|
||||
shutdown(sock, SHUT_RDWR);
|
||||
shutdown(sd, SHUT_RDWR);
|
||||
::close(sd);
|
||||
#endif
|
||||
}
|
||||
@@ -193,7 +220,7 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
|
||||
return false;
|
||||
}
|
||||
if (!opened_) {
|
||||
if (mcast_queue.has(group))
|
||||
if (mcast_queue.contains(group))
|
||||
return false;
|
||||
mcast_queue.enqueue(group);
|
||||
return true;
|
||||
@@ -353,7 +380,7 @@ int PIEthernet::read(void * read_to, int max_size) {
|
||||
//piCout << "eth" << path_ << "read return" << rs << errno;
|
||||
if (rs <= 0 && type_ == TCP_Client) {
|
||||
connected_ = false;
|
||||
disconnected(rs < 0);
|
||||
if (connected_) disconnected(rs < 0);
|
||||
//piCoutObj << "eth" << path_ << "disconnected";
|
||||
}
|
||||
if (rs > 0) received(read_to, rs);
|
||||
@@ -402,9 +429,9 @@ int PIEthernet::write(const void * data, int max_size) {
|
||||
saddr_.sin_family = AF_INET;
|
||||
//piCout << "[PIEth] write to" << ip_s << ":" << port_s << max_size << "bytes ...";
|
||||
#ifdef WINDOWS
|
||||
return sendto(sock, (const char * )data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
|
||||
return sendto(sock_s, (const char * )data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
|
||||
#else
|
||||
return sendto(sock, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
|
||||
return sendto(sock_s, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
|
||||
#endif
|
||||
//piCout << "[PIEth] write to" << ip_s << ":" << port_s << "ok";
|
||||
case TCP_Client:
|
||||
|
||||
199
piethernet.h
199
piethernet.h
@@ -32,106 +32,241 @@ class PIP_EXPORT PIEthernet: public PIIODevice
|
||||
PIOBJECT(PIEthernet)
|
||||
friend class PIPeer;
|
||||
public:
|
||||
// slot is any function format "bool <func>(void*, uchar*, int)"
|
||||
PIEthernet(void * data, ReadRetFunc slot);
|
||||
|
||||
enum Type {UDP, TCP_Client, TCP_Server, TCP_SingleTCP};
|
||||
enum Parameters {ReuseAddress = 0x1, Broadcast = 0x2};
|
||||
//! Contructs UDP %PIEthernet with empty read address
|
||||
PIEthernet();
|
||||
|
||||
//! \brief Type of %PIEthernet
|
||||
enum Type {
|
||||
UDP /** UDP - User Datagram Protocol */ ,
|
||||
TCP_Client /** TCP client - allow connection to TCP server */ ,
|
||||
TCP_Server /** TCP server - receive connections from TCP clients */ ,
|
||||
TCP_SingleTCP
|
||||
};
|
||||
|
||||
//! \brief Parameters of %PIEthernet
|
||||
enum Parameters {
|
||||
ReuseAddress /** Rebind address if there is already binded */ = 0x1,
|
||||
Broadcast /** Broadcast send */ = 0x2
|
||||
};
|
||||
|
||||
//! Contructs %PIEthernet with type "type", read address "ip_port" and parameters "params"
|
||||
PIEthernet(Type type, const PIString & ip_port = PIString(), const PIFlags<Parameters> params = 0);
|
||||
|
||||
PIEthernet(Type type = UDP, void * data = 0, ReadRetFunc slot = 0);
|
||||
virtual ~PIEthernet();
|
||||
|
||||
|
||||
//! Set read address
|
||||
void setReadAddress(const PIString & ip, int port) {path_ = ip + ":" + PIString::fromNumber(port);}
|
||||
|
||||
//! Set read address in format "i.i.i.i:p"
|
||||
void setReadAddress(const PIString & ip_port) {path_ = ip_port;}
|
||||
|
||||
//! Set read IP
|
||||
void setReadIP(const PIString & ip) {parseAddress(path_, &ip_, &port_); path_ = ip + ":" + PIString::fromNumber(port_);}
|
||||
|
||||
//! Set read port
|
||||
void setReadPort(int port) {parseAddress(path_, &ip_, &port_); path_ = ip_ + ":" + PIString::fromNumber(port);}
|
||||
|
||||
|
||||
//! Set send address
|
||||
void setSendAddress(const PIString & ip, int port) {ip_s = ip; port_s = port;}
|
||||
|
||||
//! Set send address in format "i.i.i.i:p"
|
||||
void setSendAddress(const PIString & ip_port) {parseAddress(ip_port, &ip_s, &port_s);}
|
||||
|
||||
//! Set send IP
|
||||
void setSendIP(const PIString & ip) {ip_s = ip;}
|
||||
|
||||
//! Set send port
|
||||
void setSendPort(int port) {port_s = port;}
|
||||
|
||||
|
||||
//! Returns read address in format "i.i.i.i:p"
|
||||
PIString readAddress() {return path_;}
|
||||
|
||||
//! Returns read IP
|
||||
PIString readIP() {parseAddress(path_, &ip_, &port_); return ip_;}
|
||||
|
||||
//! Returns read port
|
||||
int readPort() {parseAddress(path_, &ip_, &port_); return port_;}
|
||||
|
||||
|
||||
//! Returns send address in format "i.i.i.i:p"
|
||||
PIString sendAddress() {return ip_s + ":" + PIString::fromNumber(port_s);}
|
||||
|
||||
//! Returns send IP
|
||||
PIString sendIP() {return ip_s;}
|
||||
|
||||
//! Returns send port
|
||||
int sendPort() {return port_s;}
|
||||
|
||||
|
||||
//! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them
|
||||
void setParameters(PIFlags<PIEthernet::Parameters> parameters_) {params = parameters_;}
|
||||
|
||||
//! Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this
|
||||
void setParameter(PIEthernet::Parameters parameter, bool on = true) {params.setFlag(parameter, on);}
|
||||
|
||||
//! Returns if parameter "parameter" is set
|
||||
bool isParameterSet(PIEthernet::Parameters parameter) const {return params[parameter];}
|
||||
|
||||
//! Returns parameters
|
||||
PIFlags<PIEthernet::Parameters> parameters() const {return params;}
|
||||
|
||||
//PIByteArray macAddress() {if (!init_) init(); struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); memcpy(ifr.ifr_name, "eth0", 5); ioctl(sock, SIOCSIFHWADDR, &ifr); return PIByteArray(&ifr.ifr_hwaddr.sa_data, 6);}
|
||||
|
||||
//! Returns %PIEthernet type
|
||||
Type type() const {return type_;}
|
||||
|
||||
|
||||
//! Join to multicast group with address "group". Use only for UDP
|
||||
bool joinMulticastGroup(const PIString & group);
|
||||
|
||||
//! Leave multicast group with address "group". Use only for UDP
|
||||
bool leaveMulticastGroup(const PIString & group);
|
||||
|
||||
|
||||
//! Connect to TCP server with address \a readAddress(). Use only for TCP_Client
|
||||
bool connect();
|
||||
|
||||
//! Connect to TCP server with address "ip":"port". Use only for TCP_Client
|
||||
bool connect(const PIString & ip, int port) {path_ = ip + ":" + PIString::fromNumber(port); return connect();}
|
||||
|
||||
//! Connect to TCP server with address "ip_port". Use only for TCP_Client
|
||||
bool connect(const PIString & ip_port) {path_ = ip_port; return connect();}
|
||||
|
||||
//! Returns if %PIEthernet connected to TCP server. Use only for TCP_Client
|
||||
bool isConnected() const {return connected_;}
|
||||
|
||||
|
||||
//! Start listen for incoming TCP connections on address \a readAddress(). Use only for TCP_Server
|
||||
bool listen();
|
||||
|
||||
//! Start listen for incoming TCP connections on address "ip":"port". Use only for TCP_Server
|
||||
bool listen(const PIString & ip, int port) {setReadAddress(ip, port); return listen();}
|
||||
|
||||
//! Start listen for incoming TCP connections on address "ip_port". Use only for TCP_Server
|
||||
bool listen(const PIString & ip_port) {setReadAddress(ip_port); return listen();}
|
||||
|
||||
PIEthernet * client(int index) {return clients_[index];}
|
||||
int clientsCount() const {return clients_.size_s();}
|
||||
PIVector<PIEthernet * > clients() {return clients_;}
|
||||
|
||||
bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {ip_s = ip; port_s = port; if (threaded) {writeThreaded(data, size); return true;} return send(data, size);}
|
||||
bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {parseAddress(ip_port, &ip_s, &port_s); if (threaded) {writeThreaded(data, size); return true;} return send(data, size);}
|
||||
bool send(const void * data, int size, bool threaded = false) {if (threaded) {writeThreaded(data, size); return true;} return (write(data, size) == size);}
|
||||
bool send(const PIByteArray & ba, bool threaded = false) {if (threaded) {writeThreaded(ba); return true;} return (write(ba) == ba.size_s());}
|
||||
|
||||
//! Send data "data" with size "size" to address "ip":"port"
|
||||
bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {ip_s = ip; port_s = port; if (threaded) {writeThreaded(data, size); return true;} return send(data, size);}
|
||||
|
||||
//! Send data "data" with size "size" to address "ip_port"
|
||||
bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {parseAddress(ip_port, &ip_s, &port_s); if (threaded) {writeThreaded(data, size); return true;} return send(data, size);}
|
||||
|
||||
//! Send data "data" with size "size" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client
|
||||
bool send(const void * data, int size, bool threaded = false) {if (threaded) {writeThreaded(data, size); return true;} return (write(data, size) == size);}
|
||||
|
||||
//! Send data "data" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client
|
||||
bool send(const PIByteArray & data, bool threaded = false) {if (threaded) {writeThreaded(data); return true;} return (write(data) == data.size_s());}
|
||||
|
||||
|
||||
//! Wait for some data and read it to "read_to"
|
||||
int read(void * read_to, int max_size);
|
||||
|
||||
//! Send data "read_to" with size "max_size" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client
|
||||
int write(const void * data, int max_size);
|
||||
|
||||
//! Send data "data" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client
|
||||
int write(const PIByteArray & data) {return write(data.data(), data.size_s());}
|
||||
|
||||
EVENT1(newConnection, PIEthernet * , client)
|
||||
EVENT0(connected)
|
||||
EVENT1(disconnected, bool, withError)
|
||||
|
||||
|
||||
//! Flags of network interface
|
||||
enum InterfaceFlag {
|
||||
ifActive = 0x1,
|
||||
ifRunning = 0x2,
|
||||
ifBroadcast = 0x4,
|
||||
ifMulticast = 0x8,
|
||||
ifLoopback = 0x10,
|
||||
ifPTP = 0x20
|
||||
ifActive /** Is active */ = 0x1,
|
||||
ifRunning /** Is running */ = 0x2,
|
||||
ifBroadcast /** Support broadcast */ = 0x4,
|
||||
ifMulticast /** Support multicast */ = 0x8,
|
||||
ifLoopback /** Is loopback */ = 0x10,
|
||||
ifPTP /** Is point-to-point */ = 0x20
|
||||
};
|
||||
|
||||
//! %PIFlags of network interface flags
|
||||
typedef PIFlags<InterfaceFlag> InterfaceFlags;
|
||||
|
||||
|
||||
//! Network interface descriptor
|
||||
struct Interface {
|
||||
|
||||
//! System index
|
||||
int index;
|
||||
|
||||
//! System name
|
||||
PIString name;
|
||||
|
||||
//! MAC address in format "hh:hh:hh:hh:hh:hh" or empty if there is no MAC address
|
||||
PIString mac;
|
||||
|
||||
//! IP address in format "i.i.i.i" or empty if there is no IP address
|
||||
PIString address;
|
||||
|
||||
//! Netmask of IP address in format "i.i.i.i" or empty if there is no netmask
|
||||
PIString netmask;
|
||||
|
||||
//! Broadcast address in format "i.i.i.i" or empty if there is no broadcast address
|
||||
PIString broadcast;
|
||||
|
||||
//! Point-to-point address or empty if there is no point-to-point address
|
||||
PIString ptp;
|
||||
|
||||
//! Flags of interface
|
||||
InterfaceFlags flags;
|
||||
|
||||
//! Returns if interface is active
|
||||
bool isActive() const {return flags[PIEthernet::ifActive];}
|
||||
|
||||
//! Returns if interface is running
|
||||
bool isRunning() const {return flags[PIEthernet::ifRunning];}
|
||||
|
||||
//! Returns if interface support broadcast
|
||||
bool isBroadcast() const {return flags[PIEthernet::ifBroadcast];}
|
||||
|
||||
//! Returns if interface support multicast
|
||||
bool isMulticast() const {return flags[PIEthernet::ifMulticast];}
|
||||
|
||||
//! Returns if interface is loopback
|
||||
bool isLoopback() const {return flags[PIEthernet::ifLoopback];}
|
||||
|
||||
//! Returns if interface is point-to-point
|
||||
bool isPTP() const {return flags[PIEthernet::ifPTP];}
|
||||
};
|
||||
|
||||
|
||||
//! Array of \a Interface with some features
|
||||
class InterfaceList: public PIVector<PIEthernet::Interface> {
|
||||
public:
|
||||
InterfaceList(): PIVector<PIEthernet::Interface>() {}
|
||||
|
||||
//! Get interface with system index "index" or 0 if there is no one
|
||||
const Interface * getByIndex(int index) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].index == index) return &((*this)[i]); return 0;}
|
||||
|
||||
//! Get interface with system name "name" or 0 if there is no one
|
||||
const Interface * getByName(const PIString & name) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].name == name) return &((*this)[i]); return 0;}
|
||||
|
||||
//! Get interface with IP address "address" or 0 if there is no one
|
||||
const Interface * getByAddress(const PIString & address) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].address == address) return &((*this)[i]); return 0;}
|
||||
|
||||
//! Get loopback interface or 0 if there is no one
|
||||
const Interface * getLoopback() const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].isLoopback()) return &((*this)[i]); return 0;}
|
||||
};
|
||||
|
||||
|
||||
//! Returns all system network interfaces
|
||||
static InterfaceList interfaces();
|
||||
|
||||
static PIString interfaceAddress(const PIString & interface_);
|
||||
|
||||
//! Returns all system network IP addresses
|
||||
static PIStringList allAddresses();
|
||||
|
||||
static void parseAddress(const PIString & ipp, PIString * ip, int * port);
|
||||
@@ -140,11 +275,43 @@ public:
|
||||
static PIString applyMask(const PIString & ip, const PIString & mask) {struct in_addr ia; ia.s_addr = inet_addr(ip.data()) & inet_addr(mask.data()); return PIString(inet_ntoa(ia));}
|
||||
static PIString getBroadcast(const PIString & ip, const PIString & mask) {struct in_addr ia; ia.s_addr = inet_addr(ip.data()) | ~inet_addr(mask.data()); return PIString(inet_ntoa(ia));}
|
||||
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
//! \fn void newConnection(PIEthernet * client)
|
||||
//! \brief Raise on new TCP connection received
|
||||
|
||||
//! \fn void connected()
|
||||
//! \brief Raise if succesfull TCP connection
|
||||
|
||||
//! \fn void disconnected(bool withError)
|
||||
//! \brief Raise if TCP connection was closed
|
||||
|
||||
//! \}
|
||||
//! \ioparams
|
||||
//! \{
|
||||
#ifdef DOXYGEN
|
||||
//! \brief read ip, default ""
|
||||
string ip;
|
||||
|
||||
//! \brief read port, default 0
|
||||
int port;
|
||||
|
||||
//! \brief Broadcast parameter, default false
|
||||
bool broadcast;
|
||||
|
||||
//! \brief ReuseAddress parameter, default false
|
||||
bool reuseAddress;
|
||||
#endif
|
||||
//! \}
|
||||
|
||||
protected:
|
||||
PIEthernet(int sock, PIString ip_port);
|
||||
|
||||
bool configureDevice(const void * e_main, const void * e_parent = 0);
|
||||
virtual void received(void * data, int size) {;}
|
||||
|
||||
//! Executes when any read function was successful. Default implementation does nothing
|
||||
virtual void received(const void * data, int size) {;}
|
||||
|
||||
bool init();
|
||||
bool openDevice();
|
||||
|
||||
103
pievaluator.cpp
103
pievaluator.cpp
@@ -20,6 +20,103 @@
|
||||
#include "pievaluator.h"
|
||||
|
||||
|
||||
/*! \class PIEvaluator
|
||||
* \brief This class provide mathematical evaluations of custom expression
|
||||
*
|
||||
* \section PIEvaluator_sec0 Synopsis
|
||||
* %PIEvaluator developed for stream evaluations of once set expression.
|
||||
* It`s create internal list of instructions on function \a check() and
|
||||
* executes very fast on function \a evaluate(). Once given expression
|
||||
* can be evaluated any times with different variable values. Evaluator
|
||||
* supports many common mathematic functions described below. Also it`s
|
||||
* automatic puts unnecessarily signs and bracets. Processed expression
|
||||
* can be obtains with function \a expression(). If there is an error
|
||||
* in expression you can get it with function \a error(). Last evaluated
|
||||
* result you can get with function \a lastResult().
|
||||
* \section PIEvaluator_sec1 Using
|
||||
* First you should set your variables with function \a setVariable().
|
||||
* Next give your expression with function \a check() and check for error
|
||||
* with functions \a isCorrect() and \a error(). If expression is correct
|
||||
* you can get processed expression with function \a expression() and
|
||||
* evaluate it with function \a evaluate(). You can change variable values
|
||||
* without rechecking expression.
|
||||
*
|
||||
* \section PIEvaluator_sec2 Functions
|
||||
* %PIEvaluator supports arithmetical operations with complex numbers, this
|
||||
* is their list in priority order:
|
||||
* * ^ (power)
|
||||
* * * (multiply)
|
||||
* * / (divide)
|
||||
* * % (residue)
|
||||
* * + (add)
|
||||
* * - (subtract)
|
||||
*
|
||||
* In addition there are compare and logical operations:
|
||||
* * == (equal)
|
||||
* * != (not equal)
|
||||
* * > (greater)
|
||||
* * < (smaller)
|
||||
* * >= (greater or equal)
|
||||
* * <= (smaller or equal)
|
||||
* * && (and)
|
||||
* * || (or)
|
||||
*
|
||||
* Compare and logical functions works with real operators part and returns 0 or 1.
|
||||
*
|
||||
* Mathematical functions:
|
||||
* * sin(x) - sine
|
||||
* * cos(x) - cosine
|
||||
* * tg(x) - tangent
|
||||
* * ctg(x) - cotangent
|
||||
* * arcsin(x) - arcsine
|
||||
* * arccos(x) - arccosine
|
||||
* * arctg(x) -arccotangent
|
||||
* * arcctg(x) - arctangent
|
||||
* * sh(x) - hyperbolical sine
|
||||
* * ch(x) - hyperbolical cosine
|
||||
* * th(x) - hyperbolical tangent
|
||||
* * cth(x) - hyperbolical cotangent
|
||||
* * sqr(x) - square
|
||||
* * sqrt(x) - square root
|
||||
* * abs(x) - absolute value
|
||||
* * sign(x) - sign of real part (-1 or 1)
|
||||
* * exp(x) - exponent
|
||||
* * pow(x, p) - x in power p
|
||||
* * ln(x) - natural logarithm
|
||||
* * lg(x) - decimal logarithm
|
||||
* * log(x, b) - logarithm of x with base b
|
||||
* * im(x) - imaginary part of complex number
|
||||
* * re(x) - real part of complex number
|
||||
* * arg(x) - argument of complex number
|
||||
* * len(x) - length of complex number
|
||||
* * conj(x) - length of complex number
|
||||
* * rad(x) - convert degrees to radians
|
||||
* * deg(x) - convert radians to degrees
|
||||
* * j0(x) - Bessel function first kind order 0
|
||||
* * j1(x) - Bessel function first kind order 1
|
||||
* * jn(x, n) - Bessel function first kind order n
|
||||
* * y0(x) - Bessel function second kind order 0
|
||||
* * y1(x) - Bessel function second kind order 1
|
||||
* * yn(x, n) - Bessel function second kind order n
|
||||
* * random(s, f) - regular random number in range [s, f]
|
||||
* * min(x0, x1, ...) - minimum of x0, x1, ...
|
||||
* * max(x0, x1, ...) - maximum of x0, x1, ...
|
||||
* * clamp(x, a, b) - trim x on range [a, b]
|
||||
* * step(x, s) - 0 if x < s, else 1
|
||||
* * mix(x, a, b) - interpolate between a and b linear for x (a * (1 - x) + b * x)
|
||||
*
|
||||
* There are some built-in constans:
|
||||
* * i (imaginary 1)
|
||||
* * e
|
||||
* * pi
|
||||
*
|
||||
* All trigonometric functions takes angle in radians.
|
||||
*
|
||||
* \section PIEvaluator_sec3 Example
|
||||
* \snippet pievaluator.cpp main
|
||||
*/
|
||||
|
||||
|
||||
PIEvaluatorContent::PIEvaluatorContent() {
|
||||
addFunction("arcsin", 1);
|
||||
addFunction("arccos", 1);
|
||||
@@ -908,7 +1005,6 @@ inline void PIEvaluator::execFunction(const PIEvaluatorTypes::Instruction & ci)
|
||||
PIEvaluatorTypes::Function cfunc = content.function(ci.function);
|
||||
int oi = -ci.out - 1;
|
||||
complexd tmp, stmp, ttmp;
|
||||
ldouble ldtmp;
|
||||
//qDebug() << "function " << (int)cfunc.type;
|
||||
switch (cfunc.type) {
|
||||
case PIEvaluatorTypes::bfSin:
|
||||
@@ -995,8 +1091,7 @@ inline void PIEvaluator::execFunction(const PIEvaluatorTypes::Instruction & ci)
|
||||
tmpvars[oi].value = conj(value(ci.operators[0]));
|
||||
break;
|
||||
case PIEvaluatorTypes::bfSign:
|
||||
ldtmp = value(ci.operators[0]).real();
|
||||
tmpvars[oi].value = ldtmp >= 0. ? complexd_1 : -complexd_1;
|
||||
tmpvars[oi].value = value(ci.operators[0]).real() >= 0. ? complexd_1 : -complexd_1;
|
||||
break;
|
||||
case PIEvaluatorTypes::bfRad:
|
||||
tmpvars[oi].value = value(ci.operators[0]) * complexd(deg2rad, 0.);
|
||||
@@ -1045,7 +1140,7 @@ inline void PIEvaluator::execFunction(const PIEvaluatorTypes::Instruction & ci)
|
||||
tmpvars[oi].value = complexd(piClampd(tmp.real(), stmp.real(), ttmp.real()), piClampd(tmp.imag(), stmp.imag(), ttmp.imag()));
|
||||
break;
|
||||
case PIEvaluatorTypes::bfStep:
|
||||
tmpvars[oi].value = value(ci.operators[0]).real() >= value(ci.operators[1]).real() ? complexld_1 : complexld_0;
|
||||
tmpvars[oi].value = complexd(value(ci.operators[0]).real() >= value(ci.operators[1]).real() ? complexld_1 : complexld_0);
|
||||
break;
|
||||
case PIEvaluatorTypes::bfMix:
|
||||
tmp = value(ci.operators[0]);
|
||||
|
||||
@@ -122,21 +122,49 @@ private:
|
||||
class PIP_EXPORT PIEvaluator
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructs an empty evaluator
|
||||
PIEvaluator() {correct = false;}
|
||||
|
||||
~PIEvaluator() {;}
|
||||
|
||||
|
||||
//! Check mathematical expression and parse it to list of instructions
|
||||
bool check(const PIString & string);
|
||||
|
||||
//! Returns true if expression was checked succesfully
|
||||
bool isCorrect() const {return correct;}
|
||||
|
||||
//! Set variable value with name "name" to value "value". Add variable if it doesn`t exists
|
||||
int setVariable(const PIString & name, complexd value = 0.) {if (content.findVariable(name) < 0) content.addVariable(name, value); else content.setVariableValue(name, value); return content.findVariable(name);}
|
||||
|
||||
//! Set variable value with index "index" to value "value". Don`t add variable if it doesn`t exists
|
||||
void setVariable(int index, complexd value = 0.) {if (index >= 0 && index < content.variablesCount()) content.setVariableValue(index, value);}
|
||||
|
||||
void setCustomVariableValue(int index, complexd value = 0.) {content.variables[index + content.cv_count].value = value;}
|
||||
|
||||
//! Evaluate last successfully checked with function \a check() expression and returns result
|
||||
complexd evaluate();
|
||||
|
||||
//! Remove variable with name "name"
|
||||
void removeVariable(const PIString & name) {content.removeVariable(name);}
|
||||
|
||||
//! Remove all manually added variables
|
||||
void clearCustomVariables() {content.clearCustomVariables();}
|
||||
|
||||
//! Returns index of variable with name "name"
|
||||
int variableIndex(const PIString & name) const {return content.findVariable(name);}
|
||||
|
||||
//! Returns all unknown variables founded in last expression passed to \a check() function
|
||||
const PIStringList & unknownVariables() const {return unknownVars;}
|
||||
|
||||
//! Returns processed last expression passed to \a check() function
|
||||
const PIString & expression() const {return currentString;}
|
||||
|
||||
//! Returns last error description occured in \a check() function
|
||||
const PIString & error() const {return lastError;}
|
||||
|
||||
//! Returns last result of \a evaluate()
|
||||
const complexd & lastResult() const {return out;}
|
||||
|
||||
PIEvaluatorContent content;
|
||||
|
||||
25
pifile.cpp
25
pifile.cpp
@@ -20,6 +20,27 @@
|
||||
#include "pifile.h"
|
||||
|
||||
|
||||
/*! \class PIFile
|
||||
* \brief Local file
|
||||
*
|
||||
* \section PIFile_sec0 Synopsis
|
||||
* This class provide access to local file. You can manipulate
|
||||
* binary content or use this class as text stream. To binary
|
||||
* access there are function \a read(), \a write(), and many
|
||||
* \a writeBinary() functions. For write variables to file in
|
||||
* their text representation threr are many "<<" operators.
|
||||
*
|
||||
* \section PIFile_sec1 Position
|
||||
* Each opened file has a read/write position - logical position
|
||||
* in the file content you read from or you write to. You can
|
||||
* find out current position with function \a pos(). Function
|
||||
* \a seek(llong position) move position to position "position",
|
||||
* \a seekToBegin() move position to the begin of file,
|
||||
* \a seekToEnd() move position to the end of file.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
bool PIFile::openDevice() {
|
||||
if (opened_) close();
|
||||
if (path_.isEmpty()) return false;
|
||||
@@ -94,11 +115,11 @@ llong PIFile::size() {
|
||||
}
|
||||
|
||||
|
||||
void PIFile::resize(llong new_size, char fill_) {
|
||||
void PIFile::resize(llong new_size, uchar fill_) {
|
||||
llong ds = new_size - size();
|
||||
if (ds == 0) return;
|
||||
if (ds > 0) {
|
||||
char * buff = new char[ds];
|
||||
uchar * buff = new uchar[ds];
|
||||
memset(buff, fill_, ds);
|
||||
write(buff, ds);
|
||||
delete[] buff;
|
||||
|
||||
148
pifile.h
148
pifile.h
@@ -26,95 +26,201 @@
|
||||
#include "piiodevice.h"
|
||||
#include <cstdio>
|
||||
|
||||
/// handlers:
|
||||
/// void clear()
|
||||
/// void resize(llong new_size, char fill = 0)
|
||||
/// void remove()
|
||||
class PIP_EXPORT PIFile: public PIIODevice
|
||||
{
|
||||
PIOBJECT(PIFile)
|
||||
public:
|
||||
|
||||
//! Constructs a file with path "path" nad open mode "type"
|
||||
PIFile(const PIString & path = PIString(), DeviceMode type = ReadWrite): PIIODevice(path, type) {setPrecision(5); openDevice();}
|
||||
|
||||
~PIFile() {close();}
|
||||
|
||||
//PIFile & operator =(const PIFile & f) {path_ = f.path_; type_ = f.type_; return *this;}
|
||||
|
||||
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);}
|
||||
void seekToEnd() {if (!opened_) return; fseek(fd, 0, SEEK_END); clearerr(fd);}
|
||||
void seekToLine(llong line) {if (!opened_) return; seekToBegin(); piForTimes (line) readLine(); clearerr(fd);} // line 0 - begin of file
|
||||
EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);}
|
||||
EVENT_HANDLER2(void, resize, llong, new_size, char, fill);
|
||||
//void fill(char c) {stream.fill(c);}
|
||||
char readChar() {return (char)fgetc(fd);}
|
||||
PIString readLine();
|
||||
llong readAll(void * data);
|
||||
PIByteArray readAll(bool forceRead = false);
|
||||
EVENT_HANDLER0(void, remove) {close(); std::remove(path_.data());}
|
||||
|
||||
//! Immediate write all buffered data to disk
|
||||
void flush() {if (opened_) fflush(fd);}
|
||||
|
||||
//! Move read/write position to "position"
|
||||
void seek(llong position) {if (!opened_) return; fseek(fd, position, SEEK_SET); clearerr(fd);}
|
||||
|
||||
//! Move read/write position to the begin of the file
|
||||
void seekToBegin() {if (!opened_) return; fseek(fd, 0, SEEK_SET); clearerr(fd);}
|
||||
|
||||
//! Move read/write position to the end of the file
|
||||
void seekToEnd() {if (!opened_) return; fseek(fd, 0, SEEK_END); clearerr(fd);}
|
||||
|
||||
//! Move read/write position to text line number "line"
|
||||
void seekToLine(llong line) {if (!opened_) return; seekToBegin(); piForTimes (line) readLine(); clearerr(fd);} // line 0 - begin of file
|
||||
//void fill(char c) {stream.fill(c);}
|
||||
|
||||
//! Read one char and return it
|
||||
char readChar() {return (char)fgetc(fd);}
|
||||
|
||||
//! Read one text line and return it
|
||||
PIString readLine();
|
||||
|
||||
//! Read all file content to "data" and return readed bytes count. Position leaved unchanged
|
||||
llong readAll(void * data);
|
||||
|
||||
//! Read all file content to byte array and return it. Position leaved unchanged
|
||||
PIByteArray readAll(bool forceRead = false);
|
||||
|
||||
|
||||
//! Set file path to "path" and reopen file if need
|
||||
void setPath(const PIString & path) {path_ = path; if (opened_) openDevice();}
|
||||
|
||||
//! Returns file size
|
||||
llong size();
|
||||
|
||||
//! Returns read/write position
|
||||
llong pos() {if (!opened_) return -1; return ftell(fd);}
|
||||
|
||||
//! Returns if position is at the end of file
|
||||
bool isEnd() {if (!opened_) return true; return (feof(fd) || ferror(fd));}
|
||||
|
||||
//! Returns if file is empty
|
||||
bool isEmpty() {return (size() <= 0);}
|
||||
|
||||
int precision() const {return prec;}
|
||||
void setPrecision(int prec_) {prec = prec_; if (prec >= 0) prec_str = "." + itos(prec_); else prec_str = "";}
|
||||
|
||||
//! Returns float numbers write precision
|
||||
int precision() const {return prec_;}
|
||||
|
||||
//! Set float numbers write precision to "prec_" digits
|
||||
void setPrecision(int prec) {prec_ = prec; if (prec_ >= 0) prec_str = "." + itos(prec_); else prec_str = "";}
|
||||
|
||||
|
||||
//! Read from file to "read_to" no more than "max_size" and return readed bytes count
|
||||
int read(void * read_to, int max_size) {if (!canRead() || fd == 0) return -1; return fread(read_to, max_size, 1, fd);}
|
||||
|
||||
//! Write to file "data" with size "max_size" and return written bytes count
|
||||
int write(const void * data, int max_size) {if (!canWrite() || fd == 0) return -1; return fwrite(data, max_size, 1, fd);}
|
||||
|
||||
PIFile & writeToBinLog(ushort id, const void * data, int size) {if (!isWriteable() || fd == 0) return *this; writeBinary(id).writeBinary((ushort)size); write(data, size); flush(); return *this;}
|
||||
|
||||
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const char v) {write(&v, sizeof(v)); return *this;}
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const short v) {write(&v, sizeof(v)); return *this;}
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const int v) {write(&v, sizeof(v)); return *this;}
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const long v) {write(&v, sizeof(v)); return *this;}
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const llong v) {write(&v, sizeof(v)); return *this;}
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const uchar v) {write(&v, sizeof(v)); return *this;}
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const ushort v) {write(&v, sizeof(v)); return *this;}
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const uint v) {write(&v, sizeof(v)); return *this;}
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const ulong v) {write(&v, sizeof(v)); return *this;}
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const ullong v) {write(&v, sizeof(v)); return *this;}
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const float v) {write(&v, sizeof(v)); return *this;}
|
||||
//! Write to file binary content of "v"
|
||||
PIFile & writeBinary(const double v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
PIFile & operator =(const PIFile & f) {path_ = f.path_; mode_ = f.mode_; return *this;}
|
||||
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(const char v) {if (canWrite() && fd != 0) write(&v, 1); return *this;}
|
||||
//PIFile & operator <<(const string & v) {write(v.c_str(), v.size()); return *this;}
|
||||
//! Write to file string "v"
|
||||
PIFile & operator <<(const PIString & v) {if (canWrite() && fd != 0) write(v.data(), v.lengthAscii()); return *this;}
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(const PIByteArray & v) {if (canWrite() && fd != 0) write(v.data(), v.size()); return *this;}
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(short v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%hd", v); return *this;}
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(int v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%d", v); return *this;}
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(long v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%ld", v); return *this;}
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(llong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%lld", v); return *this;}
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(uchar v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%u", int(v)); return *this;}
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(ushort v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%hu", v); return *this;}
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(uint v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%u", v); return *this;}
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(ulong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%lu", v); return *this;}
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(ullong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%llu", v); return *this;}
|
||||
//! Write to file text representation of "v" with precision \a precision()
|
||||
PIFile & operator <<(float v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "f").c_str(), v); return *this;}
|
||||
//! Write to file text representation of "v" with precision \a precision()
|
||||
PIFile & operator <<(double v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "lf").c_str(), v); return *this;}
|
||||
|
||||
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(char & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hhn", &v); return *this;}
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(short & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hn", &v); return *this;}
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(int & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%n", &v); return *this;}
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(long & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%ln", &v); return *this;}
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(llong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lln", &v); return *this;}
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(uchar & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hhn", &v); return *this;}
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(ushort & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hn", &v); return *this;}
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(uint & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%n", &v); return *this;}
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(ulong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%ln", &v); return *this;}
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(ullong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lln", &v); return *this;}
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(float & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%f", &v); return *this;}
|
||||
//! Read from file text representation of "v"
|
||||
PIFile & operator >>(double & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lf", &v); return *this;}
|
||||
|
||||
|
||||
EVENT_HANDLER(void, clear) {close(); fd = fopen(path_.data(), "w"); if (fd != 0) fclose(fd); fd = 0; opened_ = false; open();}
|
||||
EVENT_HANDLER0(void, remove) {close(); std::remove(path_.data());}
|
||||
EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);}
|
||||
EVENT_HANDLER2(void, resize, llong, new_size, uchar, fill);
|
||||
|
||||
|
||||
//! Returns not opened temporary file with open mode "mode"
|
||||
static PIFile openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite) {return PIFile(PIString(tmpnam(0)), mode);}
|
||||
|
||||
//! Returns if file with path "path" does exists
|
||||
static bool isExists(const PIString & path);
|
||||
|
||||
//! Remove file with path "path" and returns if remove was successful
|
||||
static bool remove(const PIString & path) {return std::remove(path.data()) == 0;}
|
||||
|
||||
//! \handlers
|
||||
//! \{
|
||||
|
||||
//! \fn void clear()
|
||||
//! \brief Raise on new TCP connection received
|
||||
|
||||
//! \fn void resize(llong new_size)
|
||||
//! \brief Resize file to "new_size" with "fill" filling
|
||||
|
||||
//! \fn void resize(llong new_size, uchar fill)
|
||||
//! \brief Resize file to "new_size" with "fill" filling
|
||||
|
||||
//! \fn void remove()
|
||||
//! \brief Remove file
|
||||
|
||||
//! \}
|
||||
//! \ioparams
|
||||
//! \{
|
||||
#ifdef DOXYGEN
|
||||
#endif
|
||||
//! \}
|
||||
|
||||
protected:
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
@@ -123,7 +229,7 @@ private:
|
||||
PIString strType(const PIIODevice::DeviceMode type) {switch (type) {case PIIODevice::ReadOnly: return "rb"; case WriteOnly: return "ab"; case ReadWrite: return "a+b";} return "rb";}
|
||||
|
||||
FILE * fd;
|
||||
int ret, prec;
|
||||
int ret, prec_;
|
||||
string prec_str;
|
||||
|
||||
};
|
||||
|
||||
184
piincludes.cpp
184
piincludes.cpp
@@ -25,7 +25,12 @@ bool piDebug = true;
|
||||
string ifconfigPath;
|
||||
|
||||
PIInit piInit;
|
||||
lconv * currentLocale = std::localeconv();
|
||||
lconv * currentLocale =
|
||||
#ifdef ANDROID
|
||||
0;
|
||||
#else
|
||||
std::localeconv();
|
||||
#endif
|
||||
#ifdef HAS_LOCALE
|
||||
static locale_t currentLocale_t = 0;
|
||||
#endif
|
||||
@@ -37,25 +42,6 @@ clock_serv_t __pi_mac_clock;
|
||||
PIMutex __PICout_mutex__;
|
||||
|
||||
|
||||
/*! \class PICout
|
||||
* \brief Class for formatted output similar std::cout
|
||||
*
|
||||
* \section PICout_sec0 Synopsis
|
||||
* This class provide many stream operators for output with some features.
|
||||
* Output to PICout is thread-sequential, i.e. doesn`t mixed from parallel
|
||||
* threads.
|
||||
*
|
||||
* \section PICout_sec1 Features
|
||||
* - insertion spaces between entries
|
||||
* - insertion new line at the end of output
|
||||
* - strings are quoted
|
||||
* - custom output operator can be easily written
|
||||
*
|
||||
* \section PICout_ex0 Example
|
||||
* \snippet picout.cpp 0
|
||||
*/
|
||||
|
||||
|
||||
#ifdef WINDOWS
|
||||
FILETIME __pi_ftjan1970;
|
||||
long long __pi_perf_freq = -1;
|
||||
@@ -91,7 +77,7 @@ PIInit::PIInit() {
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
|
||||
// Timers init
|
||||
SYSTEMTIME jan1970 = {1970, 1, 4, 1, 0, 0, 0, 0};
|
||||
SYSTEMTIME jan1970 = {1970, 1, 4, 1, 0, 14, 15, 0};
|
||||
SystemTimeToFileTime(&jan1970, &__pi_ftjan1970);
|
||||
LARGE_INTEGER pf;
|
||||
pf.QuadPart = -1;
|
||||
@@ -193,7 +179,6 @@ PICout PICout::operator<<(const PICoutAction v) {
|
||||
break;
|
||||
case PICoutManipulators::HideCursor:
|
||||
#ifdef WINDOWS
|
||||
CONSOLE_CURSOR_INFO curinfo;
|
||||
GetConsoleCursorInfo(hOut, &curinfo);
|
||||
curinfo.bVisible = false;
|
||||
SetConsoleCursorInfo(hOut, &curinfo);
|
||||
@@ -201,6 +186,22 @@ PICout PICout::operator<<(const PICoutAction v) {
|
||||
printf("\e[?25l");
|
||||
#endif
|
||||
break;
|
||||
case PICoutManipulators::ClearScreen:
|
||||
#ifdef WINDOWS
|
||||
/// TODO !!!
|
||||
/*GetConsoleCursorInfo(hOut, &curinfo);
|
||||
curinfo.bVisible = false;
|
||||
SetConsoleCursorInfo(hOut, &curinfo);
|
||||
|
||||
SetConsoleCursorPosition(hOut, ulcoord);
|
||||
FillConsoleOutputAttribute(hOut, dattr, width * (height + 1), ulcoord, &written);
|
||||
FillConsoleOutputCharacter(hOut, ' ', width * (height + 1), ulcoord, &written);*/
|
||||
#else
|
||||
printf("\e[H\e[J");
|
||||
#endif
|
||||
break;
|
||||
case PICoutManipulators::SaveContol: saveControl(); break;
|
||||
case PICoutManipulators::RestoreControl: restoreControl(); break;
|
||||
default: break;
|
||||
};
|
||||
return *this;
|
||||
@@ -231,6 +232,10 @@ PICout PICout::operator <<(const float v) {space(); std::cout << v; return *this
|
||||
|
||||
PICout PICout::operator <<(const double v) {space(); std::cout << v; return *this;}
|
||||
|
||||
PICout PICout::operator <<(const void * v) {space(); std::cout << "0x" << PIString::fromNumber(ullong(v), 16); return *this;}
|
||||
|
||||
PICout PICout::operator <<(const PIObject * v) {space(); std::cout << v->className() << "*(" << "0x" << PIString::fromNumber(ullong(v), 16) << ", \"" << v->name() << "\")"; return *this;}
|
||||
|
||||
#undef PINUMERICCOUT
|
||||
|
||||
|
||||
@@ -294,6 +299,28 @@ void PICout::applyFormat(PICoutFormat f) {
|
||||
}
|
||||
|
||||
|
||||
/*! \class PICout
|
||||
* \brief Class for formatted output similar std::cout
|
||||
*
|
||||
* \section PICout_sec0 Synopsis
|
||||
* This class provide many stream operators for output with some features.
|
||||
* Output to PICout is thread-sequential, i.e. doesn`t mixed from parallel
|
||||
* threads.
|
||||
*
|
||||
* \section PICout_sec1 Features
|
||||
* - insertion spaces between entries
|
||||
* - insertion new line at the end of output
|
||||
* - strings are quoted
|
||||
* - custom output operator can be easily written
|
||||
*
|
||||
* \section PICout_ex0 Usage
|
||||
* \snippet picout.cpp 0
|
||||
*
|
||||
* \section PICout_ex1 Writing your own output operator
|
||||
* \snippet picout.cpp own
|
||||
*/
|
||||
|
||||
|
||||
/*! \mainpage What is PIP
|
||||
* PIP - Platform-Independent Primitives - is crossplatform library for C++ developers.
|
||||
* It is wrap around STL and pure C++. This library can help developers write non-GUI
|
||||
@@ -323,8 +350,113 @@ void PICout::applyFormat(PICoutFormat f) {
|
||||
* * peering net node (\a PIPeer)
|
||||
* * process (\a PIProcess)
|
||||
* * state machine (\a PIStateMachine)
|
||||
* \n Basic using of PIP described at page \ref using_basic
|
||||
*
|
||||
* \page using_basic Getting started
|
||||
* blablabla
|
||||
* \n \n Basic using of PIP described at page \ref using_basic */
|
||||
|
||||
|
||||
/*! \page using_basic Getting started
|
||||
* Many novice programmers are solved many common task with system integrity: output to console,
|
||||
* keyboard buttons press detecting, working with serial ports, ethernet or files, and many other.
|
||||
* These tasks can solve this library, and code, based only on PIP will be compile and work
|
||||
* similar on many systems: Windows, any Linux, Red Hat, FreeBSD, MacOS X and QNX.
|
||||
* Typical application on PIP looks like this: \n
|
||||
\code{.cpp}
|
||||
#include <pip.h>
|
||||
|
||||
|
||||
// declare key press handler
|
||||
void key_event(char key, void * );
|
||||
|
||||
|
||||
PIConsole console(false, key_event); // don`t start now, key handler is "key_event"
|
||||
|
||||
|
||||
// some vars
|
||||
int i = 2, j = 3;
|
||||
|
||||
|
||||
// implicit key press handler
|
||||
void key_event(char key, void * ) {
|
||||
switch (key) {
|
||||
case '-':
|
||||
i--;
|
||||
break;
|
||||
case '+':
|
||||
i++;
|
||||
break;
|
||||
case '(':
|
||||
j--;
|
||||
break;
|
||||
case ')':
|
||||
j++;
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class MainClass: public PITimer {
|
||||
PIOBJECT(MainClass)
|
||||
public:
|
||||
MainClass() {}
|
||||
protected:
|
||||
void tick(void * data, int delimiter) {
|
||||
piCout << "timer tick";
|
||||
// timer tick
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
MainClass main_class;
|
||||
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
// enabling auto-detection of exit button press, by default 'Q' (shift+q)
|
||||
console.enableExitCapture();
|
||||
|
||||
// if we want to parse command-line arguments
|
||||
PICLI cli(argc, argv);
|
||||
cli.addArgument("console"); // "-c" or "--console"
|
||||
cli.addArgument("debug"); // "-d" or "--debug"
|
||||
|
||||
// enabling or disabling global debug flag
|
||||
piDebug = cli.hasArgument("debug");
|
||||
|
||||
// configure console
|
||||
console.addTab("first tab", '1');
|
||||
console.addString("PIP console", 1, PIConsole::Bold);
|
||||
console.addVariable("int var (i)", &i, 1);
|
||||
console.addVariable("int green var (j)", &j, 1, PIConsole::Green);
|
||||
console.addString("'-' - i--", 2);
|
||||
console.addString("'+' - i++", 2);
|
||||
console.addString("'(' - j--", 2);
|
||||
console.addString("')' - j++", 2);
|
||||
console.addTab("second tab", '2');
|
||||
console.addString("col 1", 1);
|
||||
console.addString("col 2", 2);
|
||||
console.addString("col 3", 3);
|
||||
console.setTab("first tab");
|
||||
|
||||
// start output to console if "console" argument exists
|
||||
if (cli.hasArgument("console"))
|
||||
console.start();
|
||||
|
||||
// start main class, e.g. 40 Hz
|
||||
main_class.start(25.);
|
||||
|
||||
// wait for 'Q' press, independently if console is started or not
|
||||
console.waitForFinish();
|
||||
|
||||
return 0;
|
||||
};
|
||||
\endcode
|
||||
* This code demonstrates simple interactive configurable program, which can be started with console
|
||||
* display or not, and with debug or not. \b MainClass is central class that also can be inherited from
|
||||
* \a PIThread and reimplement \a run() function.
|
||||
* \n Many PIP classes has events and event handlers, which can be connected one to another.
|
||||
* Details you can see at \a PIObject reference page (\ref PIObject_sec0).
|
||||
* \n To configure your program from file use \a PIConfig.
|
||||
* \n If you want more information see \ref using_advanced */
|
||||
|
||||
|
||||
/*! \page using_advanced Advanced using
|
||||
* Sorry, creativity crisis xD
|
||||
*/
|
||||
118
piincludes.h
118
piincludes.h
@@ -1,8 +1,8 @@
|
||||
/*! \file piincludes.h
|
||||
* \brief Global includes of PIP
|
||||
*
|
||||
* This file include all needed STL and declare many useful
|
||||
* macros and functions
|
||||
* This file include all needed system headers, STL
|
||||
* and declare many useful macros and functions
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -27,7 +27,7 @@
|
||||
#define PIINCLUDES_H
|
||||
|
||||
//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
|
||||
#define PIP_VERSION 0x000306
|
||||
#define PIP_VERSION 0x000307
|
||||
|
||||
//! Major value of PIP version
|
||||
#define PIP_VERSION_MAJOR (PIP_VERSION & 0xFF0000) >> 16
|
||||
@@ -39,7 +39,7 @@
|
||||
#define PIP_VERSION_REVISION PIP_VERSION & 0xFF
|
||||
|
||||
//! Suffix of PIP version
|
||||
#define PIP_VERSION_SUFFIX "_r3"
|
||||
#define PIP_VERSION_SUFFIX ""
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
@@ -58,6 +58,9 @@
|
||||
//! Macro is defined when host is Mac OS
|
||||
# define MAC_OS
|
||||
|
||||
//! Macro is defined when host is Android
|
||||
# define ANDROID
|
||||
|
||||
//! Macro is defined when host is any Linux
|
||||
# define LINUX
|
||||
|
||||
@@ -76,6 +79,9 @@
|
||||
//! Macro is defined when PIP use "rt" library for timers implementation
|
||||
# define PIP_TIMER_RT
|
||||
|
||||
//! Define this macro to use STL implementation of containers, else PIP implementation will be used
|
||||
# define PIP_CONTAINERS_STL
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__WIN64__)
|
||||
@@ -90,11 +96,18 @@
|
||||
#if defined(__APPLE__) || defined(__MACH__)
|
||||
# define MAC_OS
|
||||
#endif
|
||||
#if defined(__ANDROID__) || defined(_ANDROID_) || defined(ANDROID)
|
||||
# ifndef ANDROID
|
||||
# define ANDROID
|
||||
# endif
|
||||
#endif
|
||||
#ifndef WINDOWS
|
||||
# ifndef QNX
|
||||
# ifndef FREE_BSD
|
||||
# ifndef MAC_OS
|
||||
# define LINUX
|
||||
# ifndef ANDROID
|
||||
# define LINUX
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
@@ -106,10 +119,15 @@
|
||||
# ifdef LINUX
|
||||
# define HAS_LOCALE
|
||||
# endif
|
||||
# pragma GCC diagnostic ignored "-Wformat"
|
||||
# pragma GCC diagnostic ignored "-Wformat-extra-args"
|
||||
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
# endif
|
||||
# ifdef ANDROID
|
||||
# pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
# pragma GCC diagnostic ignored "-Wextra"
|
||||
# pragma GCC diagnostic ignored "-Wliteral-suffix"
|
||||
# endif
|
||||
# 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)
|
||||
@@ -212,13 +230,17 @@
|
||||
# include <fcntl.h>
|
||||
# include <sys/ioctl.h>
|
||||
# include <net/if.h>
|
||||
# include <ifaddrs.h>
|
||||
# ifdef QNX
|
||||
# include <net/if_dl.h>
|
||||
# include <hw/nicinfo.h>
|
||||
# include <sys/dcmd_io-net.h>
|
||||
# include <pthread.h>
|
||||
# ifndef ANDROID
|
||||
# include <ifaddrs.h>
|
||||
# endif
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
# include "ifaddrs_3rd.h"
|
||||
# define tcdrain(fd) ioctl(fd, TCSBRK, 1)
|
||||
inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;}
|
||||
inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;}
|
||||
#endif
|
||||
#ifdef MAC_OS
|
||||
# include <mach/mach_traps.h>
|
||||
# include <mach/mach.h>
|
||||
@@ -228,14 +250,8 @@
|
||||
typedef long time_t;
|
||||
extern clock_serv_t __pi_mac_clock;
|
||||
#endif
|
||||
#ifndef QNX
|
||||
# ifndef WINDOWS
|
||||
# ifndef FREE_BSD
|
||||
# ifndef MAC_OS
|
||||
# define environ __environ
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#ifdef LINUX
|
||||
# define environ __environ
|
||||
#endif
|
||||
#if !defined(WINDOWS) && !defined(MAC_OS)
|
||||
# define PIP_TIMER_RT
|
||||
@@ -289,7 +305,7 @@ template<typename T> inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;}
|
||||
|
||||
/*! \brief Templated function return round of float falue
|
||||
* \details Round is the nearest integer value \n
|
||||
* There is some macros:
|
||||
* There are some macros:
|
||||
* - \c piRoundf for "float"
|
||||
* - \c piRoundd for "double"
|
||||
*
|
||||
@@ -299,7 +315,7 @@ template<typename T> inline int piRound(const T & v) {return int(v >= T(0.) ? v
|
||||
|
||||
/*! \brief Templated function return floor of float falue
|
||||
* \details Floor is the largest integer that is not greater than value \n
|
||||
* There is some macros:
|
||||
* There are some macros:
|
||||
* - \c piFloorf for "float"
|
||||
* - \c piFloord for "double"
|
||||
*
|
||||
@@ -309,7 +325,7 @@ template<typename T> inline int piFloor(const T & v) {return v < T(0) ? int(v) -
|
||||
|
||||
/*! \brief Templated function return ceil of float falue
|
||||
* \details Ceil is the smallest integer that is not less than value \n
|
||||
* There is some macros:
|
||||
* There are some macros:
|
||||
* - \c piCeilf for "float"
|
||||
* - \c piCeild for "double"
|
||||
*
|
||||
@@ -319,7 +335,7 @@ template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) :
|
||||
|
||||
/*! \brief Templated function return absolute of numeric falue
|
||||
* \details Absolute is the positive or equal 0 value \n
|
||||
* There is some macros:
|
||||
* There are some macros:
|
||||
* - \c piAbss for "short"
|
||||
* - \c piAbsi for "int"
|
||||
* - \c piAbsl for "long"
|
||||
@@ -332,7 +348,7 @@ template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) :
|
||||
template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
|
||||
|
||||
/*! \brief Templated function return minimum of two values
|
||||
* \details There is some macros:
|
||||
* \details There are some macros:
|
||||
* - \c piMins for "short"
|
||||
* - \c piMini for "int"
|
||||
* - \c piMinl for "long"
|
||||
@@ -345,7 +361,7 @@ template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
|
||||
template<typename T> inline T piMin(const T & f, const T & s) {return ((f > s) ? s : f);}
|
||||
|
||||
/*! \brief Templated function return minimum of tree values
|
||||
* \details There is some macros:
|
||||
* \details There are some macros:
|
||||
* - \c piMins for "short"
|
||||
* - \c piMini for "int"
|
||||
* - \c piMinl for "long"
|
||||
@@ -358,7 +374,7 @@ template<typename T> inline T piMin(const T & f, const T & s) {return ((f > s) ?
|
||||
template<typename T> inline T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));}
|
||||
|
||||
/*! \brief Templated function return maximum of two values
|
||||
* \details There is some macros:
|
||||
* \details There are some macros:
|
||||
* - \c piMaxs for "short"
|
||||
* - \c piMaxi for "int"
|
||||
* - \c piMaxl for "long"
|
||||
@@ -371,7 +387,7 @@ template<typename T> inline T piMin(const T & f, const T & s, const T & t) {retu
|
||||
template<typename T> inline T piMax(const T & f, const T & s) {return ((f < s) ? s : f);}
|
||||
|
||||
/*! \brief Templated function return maximum of tree values
|
||||
* \details There is some macros:
|
||||
* \details There are some macros:
|
||||
* - \c piMaxs for "short"
|
||||
* - \c piMaxi for "int"
|
||||
* - \c piMaxl for "long"
|
||||
@@ -385,7 +401,7 @@ template<typename T> inline T piMax(const T & f, const T & s, const T & t) {retu
|
||||
|
||||
/*! \brief Templated function return clamped value
|
||||
* \details Clamped is the not greater than "max" and not lesser than "min" value \n
|
||||
* There is some macros:
|
||||
* There are some macros:
|
||||
* - \c piClamps for "short"
|
||||
* - \c piClampi for "int"
|
||||
* - \c piClampl for "long"
|
||||
@@ -457,7 +473,12 @@ inline double round(const double & v) {return floor(v + 0.5);}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
inline ushort letobe_s(ushort v) {return v = (v << 8) | (v >> 8);}
|
||||
inline ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);}
|
||||
inline uint letobe_i(uint v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
|
||||
//inline ullong letobe_ll(ullong v) {return (v >> 56) | ((v >> 40) & 0xFF00L) | ((v >> 24) & 0xFF0000L) | ((v >> 8) & 0xFF000000L) | ((v << 8) & 0xFF00000000L) | ((v << 24) & 0xFF0000000000L) | ((v << 40) & 0xFF000000000000L) | ((v << 56) & 0xFF00000000000000L);}
|
||||
inline void letobe_s(ushort * v) {*v = letobe_s(*v);}
|
||||
inline void letobe_i(uint * v) {*v = letobe_i(*v);}
|
||||
//inline void letobe_ll(ullong * v) {*v = letobe_ll(*v);}
|
||||
inline bool atob(const string & str) {return str == "1" ? true : false;}
|
||||
inline string btos(const bool num) {return num ? "0" : "1";}
|
||||
inline string itos(const int num) {
|
||||
@@ -635,12 +656,20 @@ private:
|
||||
int flags;
|
||||
};
|
||||
|
||||
//! Macro used for conditional (piDebug) output to PICout
|
||||
#define piCout if (piDebug) PICout()
|
||||
#ifdef DOXYGEN
|
||||
|
||||
//! Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject
|
||||
#define piCoutObj if (piDebug && debug_) PICout() << (PIString("[") + debugName() + " \"" + name() + "\"]")
|
||||
//! \brief Macro used for conditional (piDebug) output to PICout
|
||||
# define piCout
|
||||
|
||||
//! \relatesalso PIObject \brief Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject
|
||||
# define piCoutObj
|
||||
|
||||
#else
|
||||
# define piCout if (piDebug) PICout()
|
||||
# define piCoutObj if (piDebug && debug_) PICout() << "" << (PIString("[") + className() + " \"" + name() + "\"]")
|
||||
#endif
|
||||
|
||||
class PIObject;
|
||||
class PIMutex;
|
||||
extern PIMutex __PICout_mutex__;
|
||||
|
||||
@@ -658,10 +687,13 @@ namespace PICoutManipulators {
|
||||
|
||||
//! \brief Enum contains immediate action
|
||||
enum PIP_EXPORT PICoutAction {
|
||||
Flush /*! Flush the output */,
|
||||
Backspace /*! Remove last symbol */,
|
||||
ShowCursor /*! Show cursor */,
|
||||
HideCursor /*! Hide cursor */
|
||||
Flush /*! Flush the output */,
|
||||
Backspace /*! Remove last symbol */,
|
||||
ShowCursor /*! Show cursor */,
|
||||
HideCursor /*! Hide cursor */,
|
||||
ClearScreen /*! Clear the screen */,
|
||||
SaveContol /*! Save control flags, equivalent to \a saveControl() */,
|
||||
RestoreControl /*! Restore control flags, equivalent to \a restoreControl() */
|
||||
};
|
||||
|
||||
//! \brief Enum contains control of PICout
|
||||
@@ -710,7 +742,7 @@ typedef PIFlags<PICoutControl> PICoutControls;
|
||||
|
||||
class PIP_EXPORT PICout {
|
||||
public:
|
||||
//! Default constructor with default features
|
||||
//! Default constructor with default features (AddSpaces and AddNewLine)
|
||||
PICout(PIFlags<PICoutControl> controls = AddSpaces | AddNewLine);
|
||||
|
||||
PICout(const PICout & other): fo_(other.fo_), cc_(true), fc_(false), cnb_(other.cnb_), attr_(other.attr_), co_(other.co_) {;}
|
||||
@@ -759,9 +791,13 @@ public:
|
||||
PICout operator <<(const float v);
|
||||
|
||||
//! Output operator for <tt>"double"</tt> values
|
||||
PICout operator <<(const double v);
|
||||
|
||||
//! Output operator for pointers
|
||||
PICout operator <<(const double v);
|
||||
PICout operator <<(const void * v);
|
||||
|
||||
//! Output operator for PIObject and ancestors
|
||||
PICout operator <<(const PIObject * v);
|
||||
|
||||
//! Output operator for \a PICoutSpecialChar values
|
||||
PICout operator <<(const PICoutSpecialChar v) {
|
||||
|
||||
@@ -61,6 +61,20 @@
|
||||
* every reopen timeout if reopen enabled. Reopen timeout is set by \a setReopenTimeout(),
|
||||
* reopen enable is set by \a setReopenEnabled().
|
||||
*
|
||||
* \section PIIODevice_sec6 Configuration
|
||||
* This is virtual function \a configureDevice() which executes when \a configure()
|
||||
* executes. This function takes two arguments: "e_main" and "e_parent" as void*. There
|
||||
* are pointers to PIConfig::Entry entries of section "section" and their parent. If
|
||||
* there is no parent "e_parent" = 0. Function \a configure() set three parameters of
|
||||
* device: "reopenEnabled", "reopenTimeout" and "threadedReadBufferSize", then execute
|
||||
* function \a configureDevice().
|
||||
* \n Each ancestor of %PIIODevice reimlements \a configureDevice() function to be able
|
||||
* to be confured from configuration file. This parameters described at section
|
||||
* "Configurable parameters" in the class reference. Usage example:
|
||||
* \snippet piiodevice.cpp configure
|
||||
* Implement example:
|
||||
* \snippet piiodevice.cpp configureDevice
|
||||
*
|
||||
* \section PIIODevice_ex0 Example
|
||||
* \snippet piiodevice.cpp 0
|
||||
*/
|
||||
@@ -186,6 +200,21 @@ void PIIODevice::run() {
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PIIODevice::readForTime(double timeout_ms) {
|
||||
PIByteArray str;
|
||||
if (timeout_ms <= 0.) return str;
|
||||
int ret;
|
||||
uchar td[threadedReadBufferSize()];
|
||||
timer.reset();
|
||||
while (timer.elapsed_m() < timeout_ms) {
|
||||
ret = read(td, threadedReadBufferSize());
|
||||
if (ret <= 0) msleep(1);
|
||||
else str.append(td, ret);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
ullong PIIODevice::writeThreaded(const PIByteArray & data) {
|
||||
write_thread.lock();
|
||||
write_queue.enqueue(PIPair<PIByteArray, ullong>(data, tri));
|
||||
|
||||
20
piiodevice.h
20
piiodevice.h
@@ -155,7 +155,10 @@ public:
|
||||
//! 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"
|
||||
//! Read from device for "timeout_ms" milliseconds and return readed data as PIByteArray. Timeout should to be greater than 0
|
||||
PIByteArray readForTime(double timeout_ms);
|
||||
|
||||
//! Write "data" to device
|
||||
int write(const PIByteArray & data) {return write(data.data(), data.size_s());}
|
||||
|
||||
|
||||
@@ -167,7 +170,7 @@ public:
|
||||
|
||||
|
||||
//! Configure device from section "section" of file "config_file", if "parent_section" parent section also will be read
|
||||
bool configure(const PIString & config_file, const PIString & section, bool parent_section = true);
|
||||
bool configure(const PIString & config_file, const PIString & section, bool parent_section = false);
|
||||
|
||||
|
||||
EVENT_HANDLER(bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
|
||||
@@ -229,6 +232,19 @@ public:
|
||||
//! \brief Raise if write thread succesfull write some data of task with ID "id"
|
||||
|
||||
//! \}
|
||||
//! \ioparams
|
||||
//! \{
|
||||
#ifdef DOXYGEN
|
||||
//! \brief setReopenEnabled, default "true"
|
||||
bool reopenEnabled;
|
||||
|
||||
//! \brief setReopenTimeout in ms, default 1000
|
||||
int reopenTimeout;
|
||||
|
||||
//! \brief setThreadedReadBufferSize in bytes, default 4096
|
||||
int threadedReadBufferSize;
|
||||
#endif
|
||||
//! \}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -20,6 +20,22 @@
|
||||
#include "pikbdlistener.h"
|
||||
|
||||
|
||||
/** \class PIKbdListener
|
||||
* \brief Keyboard console input listener
|
||||
* \details This class provide listening of console keyboard input.
|
||||
* There is two ways to receive pressed key:
|
||||
* * external static functionwith format "void func(char key, void * data)"
|
||||
* * event \a keyPressed()
|
||||
*
|
||||
* Also there is static variable \a exiting which by default is set to
|
||||
* \b false. If \a enableExitCapture() was called and listener was started
|
||||
* with function \a start(), this variable will be set to \b true if exit
|
||||
* key will be pressed. By default exit key is 'Q' = shift + 'q'.
|
||||
* To wait for this variable changes to \b true there is WAIT_FOR_EXIT macro
|
||||
* \snippet pikbdlistener.cpp main
|
||||
* */
|
||||
|
||||
|
||||
bool PIKbdListener::exiting;
|
||||
|
||||
PIKbdListener::PIKbdListener(KBFunc slot, void * data_): PIThread() {
|
||||
@@ -117,8 +133,10 @@ void PIKbdListener::run() {
|
||||
PIKbdListener::exiting = true;
|
||||
return;
|
||||
}
|
||||
keyPressed(lc, data);
|
||||
if (ret_func != 0 && ret > 0) ret_func(lc, data);
|
||||
if (ret > 0) {
|
||||
keyPressed(lc, data);
|
||||
if (ret_func != 0) ret_func(lc, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! \file pikbdlistener.h
|
||||
* \brief Keyboard console input listerner
|
||||
* \brief Keyboard console input listener
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -32,45 +32,75 @@
|
||||
|
||||
typedef void (*KBFunc)(char, void * );
|
||||
|
||||
/// events:
|
||||
/// keyPressed(char key, void * data)
|
||||
///
|
||||
/// handlers:
|
||||
/// void enableExitCapture(char key = 'Q')
|
||||
/// void setActive(bool yes = true)
|
||||
class PIP_EXPORT PIKbdListener: public PIThread
|
||||
{
|
||||
PIOBJECT(PIKbdListener)
|
||||
friend class PIConsole;
|
||||
public:
|
||||
|
||||
//! Special keyboard keys
|
||||
enum SpecialSymbol {
|
||||
UpArrow = -1,
|
||||
DownArrow = -2,
|
||||
RightArrow = -3,
|
||||
LeftArrow = -4,
|
||||
CtrlUpArrow = -5,
|
||||
CtrlDownArrow = -6,
|
||||
CtrlRightArrow = -7,
|
||||
CtrlLeftArrow = -8
|
||||
UpArrow /** Up arrow key */ = -1,
|
||||
DownArrow /** Down arrow key */ = -2,
|
||||
RightArrow /** Right arrow key */ = -3,
|
||||
LeftArrow /** Left arrow key */ = -4,
|
||||
CtrlUpArrow /** Ctrl + Up arrow key */ = -5,
|
||||
CtrlDownArrow /** Ctrl + Down arrow key */ = -6,
|
||||
CtrlRightArrow /** Ctrl + Right arrow key */ = -7,
|
||||
CtrlLeftArrow /** Ctrl + Left arrow key */ = -8
|
||||
};
|
||||
|
||||
// slot is any function format "void <func>(char, void * )"
|
||||
//! Constructs keyboard listener with external function "slot" and custom data "data"
|
||||
PIKbdListener(KBFunc slot = 0, void * data = 0);
|
||||
|
||||
~PIKbdListener() {terminate(); end();}
|
||||
|
||||
|
||||
//! Set custom data to "data"
|
||||
void setData(void * data_) {data = data_;}
|
||||
void setSlot(KBFunc slot_) {ret_func = slot_;}
|
||||
|
||||
//! Set external function to "slot"
|
||||
void setSlot(KBFunc slot) {ret_func = slot;}
|
||||
|
||||
//! Returns if exit key if awaiting
|
||||
bool exitCaptured() const {return exit_enabled;}
|
||||
|
||||
//! Returns exit key, default 'Q'
|
||||
char exitKey() const {return exit_key;}
|
||||
|
||||
|
||||
//! Returns if keyboard listening is active (not running!)
|
||||
bool isActive() {return is_active;}
|
||||
|
||||
EVENT_HANDLER( void, enableExitCapture) {enableExitCapture('Q');}
|
||||
EVENT_HANDLER1(void, enableExitCapture, char, key) {exit_enabled = true; exit_key = key;}
|
||||
void disableExitCapture() {exit_enabled = false;}
|
||||
bool exitCaptured() const {return exit_enabled;}
|
||||
char exitKey() const {return exit_key;}
|
||||
bool isActive() {return is_active;}
|
||||
EVENT_HANDLER(void, disableExitCapture) {exit_enabled = false;}
|
||||
EVENT_HANDLER(void, setActive) {setActive(true);}
|
||||
EVENT_HANDLER1(void, setActive, bool, yes);
|
||||
|
||||
EVENT2(keyPressed, char, key, void * , data)
|
||||
|
||||
//! \handlers
|
||||
//! \{
|
||||
|
||||
//! \fn void enableExitCapture(char key = 'Q')
|
||||
//! \brief Enable exit key "key" awaiting
|
||||
|
||||
//! \fn void disableExitCapture()
|
||||
//! \brief Disable exit key awaiting
|
||||
|
||||
//! \fn void setActive(bool yes = true)
|
||||
//! \brief Set keyboard listening is active or not
|
||||
|
||||
//! \}
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
//! \fn void keyPressed(char key, void * data)
|
||||
//! \brief Raise on key "key" pressed, "data" is custom data
|
||||
|
||||
//! \}
|
||||
|
||||
static bool exiting;
|
||||
|
||||
private:
|
||||
@@ -78,8 +108,6 @@ private:
|
||||
void run();
|
||||
void end();
|
||||
|
||||
void raiseSpecial();
|
||||
|
||||
KBFunc ret_func;
|
||||
char exit_key;
|
||||
bool exit_enabled, is_active;
|
||||
|
||||
21
pimultiprotocol.cpp
Normal file
21
pimultiprotocol.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Multiprotocol
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pimultiprotocol.h"
|
||||
|
||||
59
pimutex.cpp
Normal file
59
pimutex.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Mutex
|
||||
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 "pimutex.h"
|
||||
|
||||
|
||||
/** \class PIMutex
|
||||
* \brief Mutex
|
||||
* \details
|
||||
* \section PIMutex_sec0 Synopsis
|
||||
* %PIMutex provides synchronization blocks between several threads.
|
||||
* Using mutex guarantees execution of some code only one of threads.
|
||||
* Mutex contains logic state and functions to change it: \a lock(),
|
||||
* \a unlock() and \a tryLock().
|
||||
*
|
||||
* \section PIMutex_sec1 Usage
|
||||
* Block of code that should to be executed only one thread simultaniously
|
||||
* should to be started with \a lock() and ended with \a unlock().
|
||||
* \snippet pimutex.cpp main
|
||||
* "mutex" in this example is one for all threads.
|
||||
*
|
||||
* */
|
||||
|
||||
|
||||
PIMutex::PIMutex() {
|
||||
#ifdef WINDOWS
|
||||
mutex = CreateMutex(0, false, 0);
|
||||
#else
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutex_init(&mutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PIMutex::~PIMutex() {
|
||||
#ifdef WINDOWS
|
||||
if (mutex != 0) CloseHandle(mutex);
|
||||
#else
|
||||
pthread_mutex_destroy(&mutex);
|
||||
#endif
|
||||
}
|
||||
65
pimutex.h
65
pimutex.h
@@ -24,41 +24,58 @@
|
||||
#define PIMUTEX_H
|
||||
|
||||
#include "piincludes.h"
|
||||
#ifndef WINDOWS
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
class PIP_EXPORT PIMutex
|
||||
{
|
||||
public:
|
||||
#ifndef WINDOWS
|
||||
PIMutex() {
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
//pthread_mutexattr_settype(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_mutex_init(&mutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
~PIMutex() {pthread_mutex_destroy(&mutex);}
|
||||
|
||||
void lock() {pthread_mutex_lock(&mutex);}
|
||||
void unlock() {pthread_mutex_unlock(&mutex);}
|
||||
bool tryLock() {return (pthread_mutex_trylock(&mutex) == 0);}
|
||||
//! Constructs unlocked mutex
|
||||
PIMutex();
|
||||
|
||||
~PIMutex();
|
||||
|
||||
|
||||
//! \brief Lock mutex
|
||||
//! \details If mutex is unlocked it set to locked state and returns immediate.
|
||||
//! If mutex is already locked function blocks until mutex will be unlocked
|
||||
void lock() {
|
||||
#ifdef WINDOWS
|
||||
WaitForSingleObject(mutex, INFINITE);
|
||||
#else
|
||||
PIMutex() {mutex = CreateMutex(0, false, 0);}
|
||||
~PIMutex() {CloseHandle(mutex);}
|
||||
|
||||
void lock() {WaitForSingleObject(mutex, INFINITE);}
|
||||
void unlock() {ReleaseMutex(mutex);}
|
||||
bool tryLock() {return (WaitForSingleObject(mutex, 0) == WAIT_OBJECT_0);}
|
||||
pthread_mutex_lock(&mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! \brief Unlock mutex
|
||||
//! \details In any case this function returns immediate
|
||||
void unlock() {
|
||||
#ifdef WINDOWS
|
||||
ReleaseMutex(mutex);
|
||||
#else
|
||||
pthread_mutex_unlock(&mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! \brief Try to lock mutex
|
||||
//! \details If mutex is unlocked it set to locked state and returns "true" immediate.
|
||||
//! If mutex is already locked function returns immediate an returns "false"
|
||||
bool tryLock() {
|
||||
#ifdef WINDOWS
|
||||
return (WaitForSingleObject(mutex, 0) == WAIT_OBJECT_0);
|
||||
#else
|
||||
return (pthread_mutex_trylock(&mutex) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
#ifndef WINDOWS
|
||||
pthread_mutex_t mutex;
|
||||
#ifdef WINDOWS
|
||||
void *
|
||||
#else
|
||||
void * mutex;
|
||||
pthread_mutex_t
|
||||
#endif
|
||||
mutex;
|
||||
|
||||
};
|
||||
|
||||
|
||||
33
piobject.cpp
33
piobject.cpp
@@ -22,6 +22,39 @@
|
||||
PIVector<PIObject * > PIObject::objects;
|
||||
|
||||
|
||||
/** \class PIObject
|
||||
* \brief This is base class for any classes which use events -> handlers mechanism.
|
||||
* \details
|
||||
* \section PIObject_sec0 Events and Event handlers
|
||||
* %PIObject provide notification mechanism similar Qt but implemented
|
||||
* on language capabilities without any special preprocessors or compilers.
|
||||
* Any class inherits PIObject should use macro \a PIOBJECT() immediate
|
||||
* after declaration to proper compile.
|
||||
*
|
||||
* Event is a some abstract event that can be raised at any time.
|
||||
* Event is a function but declared with special macro \a EVENT().
|
||||
* To raise event simply execute event function.
|
||||
*
|
||||
* Event handler is a function but declared with special macro
|
||||
* \a EVENT_HANDLER(). You can use event handlers as ordinary functions.
|
||||
*
|
||||
* Main goal of this mechanism is perform abstract connections between
|
||||
* various objects. This functionality provide macro \a CONNECT() which
|
||||
* connect some event of first object to some event handler or event of
|
||||
* second object. Each event can be connected any times to any event handlers.
|
||||
*
|
||||
* \image html events_handlers.png
|
||||
*
|
||||
* Example: \snippet piobject.cpp main
|
||||
* Result:
|
||||
\code{.cpp}
|
||||
handler B: 2 , 0.5
|
||||
handler A: event to handler
|
||||
handler A: event to event
|
||||
\endcode
|
||||
*/
|
||||
|
||||
|
||||
void PIObject::piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h) {
|
||||
PIObject * o = findByName(src);
|
||||
if (o == 0) {
|
||||
|
||||
46
piobject.h
46
piobject.h
@@ -31,7 +31,7 @@
|
||||
#ifdef DOXYGEN
|
||||
|
||||
|
||||
/// \relatesalso PIObject \brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER
|
||||
/// \relatesalso PIObject \brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER and correct piCoutObj output
|
||||
#define PIOBJECT(name)
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
#else
|
||||
|
||||
|
||||
#define PIOBJECT(obj) typedef obj __PIObject__; public: virtual const char * debugName() const {return #obj;} private:
|
||||
#define PIOBJECT(obj) typedef obj __PIObject__; public: virtual const char * className() const {return #obj;} private:
|
||||
|
||||
#define EVENT_HANDLER0(ret, name) static ret __stat_eh_##name##__(void * o) {return ((__PIObject__*)o)->name();} ret name()
|
||||
#define EVENT_HANDLER1(ret, name, a0, n0) static ret __stat_eh_##name##__(void * o, a0 n0) {return ((__PIObject__*)o)->name(n0);} ret name(a0 n0)
|
||||
@@ -221,49 +221,22 @@
|
||||
|
||||
typedef void (*Handler)(void * );
|
||||
|
||||
/** \brief This is base class for any classes which use events -> handlers mechanism.
|
||||
* \details
|
||||
* \section PIObject_sec0 Events and Event handlers
|
||||
* %PIObject provide notification mechanism similar Qt but implemented
|
||||
* on language capabilities without any special preprocessors or compilers.
|
||||
* Any class inherits PIObject should use macro \a PIOBJECT() immediate
|
||||
* after declaration to proper compile.
|
||||
*
|
||||
* Event is a some abstract event that can be raised at any time.
|
||||
* Event is a function but declared with special macro \a EVENT().
|
||||
* To raise event simply execute event function.
|
||||
*
|
||||
* Event handler is a function but declared with special macro
|
||||
* \a EVENT_HANDLER(). You can use event handlers as ordinary functions.
|
||||
*
|
||||
* Main goal of this mechanism is perform abstract connections between
|
||||
* various objects. This functionality provide macro \a CONNECT() which
|
||||
* connect some event of first object to some event handler or event of
|
||||
* second object. Each event can be connected any times to any event handlers.
|
||||
*
|
||||
* Example: \snippet piobject.cpp main
|
||||
* Result:
|
||||
\code{.cpp}
|
||||
handler B: 2 , 0.5
|
||||
handler A: event to handler
|
||||
handler A: event to event
|
||||
\endcode
|
||||
*/
|
||||
class PIP_EXPORT PIObject
|
||||
{
|
||||
friend class PIObjectManager;
|
||||
public:
|
||||
|
||||
//! Contructs PIObject with name "name"
|
||||
PIObject(const PIString & name = PIString()) {piMonitor.objects++; setName(name); dname_ = "PIObject"; objects << this; debug_ = true;}
|
||||
~PIObject() {piMonitor.objects--; objects.removeAll(this);}
|
||||
PIObject(const PIString & name = PIString()) {piMonitor.objects++; setName(name); objects << this; debug_ = true;}
|
||||
|
||||
virtual ~PIObject() {piMonitor.objects--; objects.removeAll(this);}
|
||||
|
||||
|
||||
//! Returns object name
|
||||
const PIString & name() const {return name_;}
|
||||
|
||||
//! Returns object class name for debug
|
||||
virtual const char * debugName() const {return dname_.data();}
|
||||
//! Returns object class name
|
||||
virtual const char * className() const {return "PIObject";}
|
||||
|
||||
//! Return if debug of this object is active
|
||||
bool debug() const {return debug_;}
|
||||
@@ -272,9 +245,6 @@ public:
|
||||
//! Set object name
|
||||
void setName(const PIString & name) {name_ = name;}
|
||||
|
||||
//! Set object debug active
|
||||
void setDebugName(const PIString & name) {dname_ = name;}
|
||||
|
||||
//! Set object debug active
|
||||
void setDebug(bool debug) {debug_ = debug;}
|
||||
|
||||
@@ -493,7 +463,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
PIString name_, dname_;
|
||||
PIString name_;
|
||||
bool debug_;
|
||||
|
||||
private:
|
||||
|
||||
1
pip.h
1
pip.h
@@ -30,4 +30,5 @@
|
||||
#include "pipeer.h"
|
||||
#include "picrc.h"
|
||||
#include "pistatemachine.h"
|
||||
#include "picollection.h"
|
||||
#include "piusb.h"
|
||||
|
||||
47
pip.pro
47
pip.pro
@@ -9,7 +9,7 @@ INCLUDEPATH += .
|
||||
QT -= core gui
|
||||
CONFIG -= qt
|
||||
CONFIG += dll
|
||||
VERSION = 0.3.6
|
||||
VERSION = 0.3.7
|
||||
|
||||
# Input
|
||||
HEADERS += \
|
||||
@@ -47,7 +47,10 @@ HEADERS += \
|
||||
picli.h \
|
||||
pichar.h \
|
||||
pibytearray.h \
|
||||
pibitarray.h
|
||||
pibitarray.h \
|
||||
picollection.h \
|
||||
ifaddrs_3rd.h \
|
||||
pidiagnostics.h
|
||||
SOURCES += main.cpp \
|
||||
pivariable.cpp \
|
||||
pitimer.cpp \
|
||||
@@ -75,9 +78,45 @@ SOURCES += main.cpp \
|
||||
piconfig.cpp \
|
||||
picodec.cpp \
|
||||
picli.cpp \
|
||||
pibytearray.cpp
|
||||
pibytearray.cpp \
|
||||
picollection.cpp \
|
||||
ifaddrs_3rd.c \
|
||||
pidiagnostics.cpp
|
||||
win32 {
|
||||
LIBS += -lws2_32 -lIphlpapi
|
||||
} else {
|
||||
LIBS = -lpthread -lrt
|
||||
android {
|
||||
} else {
|
||||
LIBS = -lpthread -lrt
|
||||
}
|
||||
}
|
||||
|
||||
OTHER_FILES += \
|
||||
android/AndroidManifest.xml \
|
||||
android/res/layout/splash.xml \
|
||||
android/res/values/libs.xml \
|
||||
android/res/values/strings.xml \
|
||||
android/res/values-de/strings.xml \
|
||||
android/res/values-el/strings.xml \
|
||||
android/res/values-es/strings.xml \
|
||||
android/res/values-et/strings.xml \
|
||||
android/res/values-fa/strings.xml \
|
||||
android/res/values-fr/strings.xml \
|
||||
android/res/values-id/strings.xml \
|
||||
android/res/values-it/strings.xml \
|
||||
android/res/values-ja/strings.xml \
|
||||
android/res/values-ms/strings.xml \
|
||||
android/res/values-nb/strings.xml \
|
||||
android/res/values-nl/strings.xml \
|
||||
android/res/values-pl/strings.xml \
|
||||
android/res/values-pt-rBR/strings.xml \
|
||||
android/res/values-ro/strings.xml \
|
||||
android/res/values-rs/strings.xml \
|
||||
android/res/values-ru/strings.xml \
|
||||
android/res/values-zh-rCN/strings.xml \
|
||||
android/res/values-zh-rTW/strings.xml \
|
||||
android/src/org/kde/necessitas/ministro/IMinistro.aidl \
|
||||
android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl \
|
||||
android/src/org/qtproject/qt5/android/bindings/QtActivity.java \
|
||||
android/src/org/qtproject/qt5/android/bindings/QtApplication.java \
|
||||
android/version.xml
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[Project]
|
||||
Manager=KDevCMakeManager
|
||||
Name=pip_0.3.6
|
||||
@@ -5,8 +5,8 @@
|
||||
# endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,3,6,0
|
||||
PRODUCTVERSION 0,3,6,0
|
||||
FILEVERSION 0,3,7,0
|
||||
PRODUCTVERSION 0,3,7,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
@@ -23,7 +23,7 @@ VS_VERSION_INFO VERSIONINFO
|
||||
BEGIN
|
||||
VALUE "CompanyName", "\0"
|
||||
VALUE "FileDescription", "\0"
|
||||
VALUE "FileVersion", "0.3.6.0\0"
|
||||
VALUE "FileVersion", "0.3.7.0\0"
|
||||
VALUE "LegalCopyright", "\0"
|
||||
VALUE "OriginalFilename", "pip0.dll\0"
|
||||
VALUE "ProductName", "pip\0"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,3,6,0
|
||||
PRODUCTVERSION 0,3,6,0
|
||||
FILEVERSION 0,3,7,0
|
||||
PRODUCTVERSION 0,3,7,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
FILEFLAGS 0x0L
|
||||
FILEOS VOS__WINDOWS32
|
||||
@@ -19,7 +19,7 @@ VS_VERSION_INFO VERSIONINFO
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Peri4\0"
|
||||
VALUE "FileDescription", "Platform-Independent Primitives\0"
|
||||
VALUE "FileVersion", "0.3.6.0\0"
|
||||
VALUE "FileVersion", "0.3.7.0\0"
|
||||
VALUE "LegalCopyright", "\0"
|
||||
VALUE "OriginalFilename", "libpip.dll\0"
|
||||
VALUE "ProductName", "PIP\0"
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
# 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 */
|
||||
|
||||
@@ -20,6 +20,44 @@
|
||||
#include "pipacketextractor.h"
|
||||
|
||||
|
||||
/** \class PIPacketExtractor
|
||||
* \brief Packets extractor
|
||||
* \details
|
||||
* \section PIPacketExtractor_sec0 Synopsis
|
||||
* This class implements packet recognition by header and custom validating
|
||||
* algorithm from data stream. Stream is formed from child %PIIODevice
|
||||
* passed from contructor or with function \a setDevice().
|
||||
*
|
||||
* \section PIPacketExtractor_sec1 Principle of work
|
||||
* %PIPacketExtractor works with child %PIIODevice. \a read and \a write
|
||||
* functions directly call child device functions. You should start threaded
|
||||
* read of \b extractor to proper work. Extractor read data from child device,
|
||||
* form continuous buffer and analyze it.
|
||||
*
|
||||
* \subsection PIPacketExtractor_sec1_0 Analysis
|
||||
* There is three parameters:
|
||||
* * header content
|
||||
* * header size
|
||||
* * payload size
|
||||
*
|
||||
* Extractor can detect packet with compare your header with readed data.
|
||||
* It is default implementation of function \a packetHeaderValidate().
|
||||
* If header validating passed, function \a packetValidate() will be called.
|
||||
* If either of this function return \b false extractor shifts by one byte
|
||||
* and takes next header. If both functions returns \b true extractor shifts
|
||||
* by whole packet size.
|
||||
* \image html packet_detection.png
|
||||
*
|
||||
* \subsection PIPacketExtractor_sec1_1 Variants
|
||||
* If header size = 0 and payload size = 0 there is no analysis will be done,
|
||||
* and function \a packetValidate() anyway will be called immediately after
|
||||
* successfully read from child device. \n
|
||||
* If header size = 0 but payload size != 0 extractor will be call function
|
||||
* \a packetValidate() each payload size bytes.
|
||||
*
|
||||
* */
|
||||
|
||||
|
||||
PIPacketExtractor::PIPacketExtractor(PIIODevice * device_, void * recHeaderPtr, int recHeaderSize, int recDataSize) {
|
||||
ret_func_header = 0;
|
||||
setPacketData(recHeaderPtr, recHeaderSize, recDataSize);
|
||||
@@ -37,47 +75,53 @@ void PIPacketExtractor::setDevice(PIIODevice * device_) {
|
||||
|
||||
|
||||
bool PIPacketExtractor::threadedRead(uchar * readed, int size_) {
|
||||
//cout << "extractor readed " << size_ << endl;
|
||||
memcpy(buffer.data(allReaded), readed, size_);
|
||||
allReaded += size_;
|
||||
if (allReaded < packetSize + addSize) return true;
|
||||
if (headerSize > 0) {
|
||||
if (allReaded + curInd >= buffer_size) {
|
||||
memcpy(sbuffer.data(), buffer.data(), buffer_size);
|
||||
memcpy(buffer.data(), sbuffer.data(buffer_size - packetSize), allReaded);
|
||||
allReaded = packetSize;
|
||||
addSize = curInd = 0;
|
||||
}
|
||||
while (!packetHeaderValidate((uchar * )headerPtr, buffer.data(curInd), headerSize)) {
|
||||
curInd++; missed++;
|
||||
if (packetSize > 0) missed_packets = missed / packetSize;
|
||||
if (curInd > addSize) {
|
||||
addSize += packetSize;
|
||||
return true;
|
||||
while (allReaded >= packetSize + addSize && allReaded > 0) {
|
||||
if (headerSize > 0) {
|
||||
if (allReaded + curInd >= buffer_size) {
|
||||
memcpy(sbuffer.data(), buffer.data(), buffer_size);
|
||||
memcpy(buffer.data(), sbuffer.data(buffer_size - packetSize), allReaded);
|
||||
allReaded = packetSize;
|
||||
addSize = curInd = 0;
|
||||
}
|
||||
}
|
||||
memcpy(mheader.data(), buffer.data(curInd), headerSize);
|
||||
if (headerPtr != 0) memcpy(headerPtr, buffer.data(curInd), headerSize);
|
||||
if (!packetValidate(buffer.data(curInd + headerSize), dataSize)) {
|
||||
curInd++; missed++;
|
||||
if (packetSize > 0) missed_packets = missed / packetSize;
|
||||
return true;
|
||||
}
|
||||
memcpy(sbuffer.data(), buffer.data(), allReaded);
|
||||
memcpy(buffer.data(), sbuffer.data(packetSize + curInd), allReaded);
|
||||
allReaded -= packetSize + curInd;
|
||||
curInd = addSize = 0;
|
||||
} else {
|
||||
if (dataSize == 0) {
|
||||
packetValidate(buffer.data(), size_);
|
||||
bool brk = false;
|
||||
while (!packetHeaderValidate((uchar * )headerPtr, buffer.data(curInd), headerSize)) {
|
||||
curInd++; missed++;
|
||||
if (packetSize > 0) missed_packets = missed / packetSize;
|
||||
if (curInd > addSize) {
|
||||
addSize += packetSize;
|
||||
brk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (brk) continue;
|
||||
memcpy(mheader.data(), buffer.data(curInd), headerSize);
|
||||
if (headerPtr != 0) memcpy(headerPtr, buffer.data(curInd), headerSize);
|
||||
if (!packetValidate(buffer.data(curInd + headerSize), dataSize)) {
|
||||
curInd++; missed++;
|
||||
if (packetSize > 0) missed_packets = missed / packetSize;
|
||||
continue;
|
||||
}
|
||||
packetReceived(buffer.data(curInd), packetSize);
|
||||
memcpy(sbuffer.data(), buffer.data(), allReaded);
|
||||
memcpy(buffer.data(), sbuffer.data(size_), allReaded);
|
||||
allReaded -= size_;
|
||||
memcpy(buffer.data(), sbuffer.data(packetSize + curInd), allReaded);
|
||||
allReaded -= packetSize + curInd;
|
||||
curInd = addSize = 0;
|
||||
} else {
|
||||
packetValidate(buffer.data(), dataSize);
|
||||
memcpy(sbuffer.data(), buffer.data(), allReaded);
|
||||
memcpy(buffer.data(), sbuffer.data(packetSize), allReaded);
|
||||
allReaded -= packetSize;
|
||||
if (dataSize == 0) {
|
||||
if (packetValidate(buffer.data(), size_))
|
||||
packetReceived(buffer.data(), size_);
|
||||
memcpy(sbuffer.data(), buffer.data(), allReaded);
|
||||
memcpy(buffer.data(), sbuffer.data(size_), allReaded);
|
||||
allReaded -= size_;
|
||||
} else {
|
||||
if (packetValidate(buffer.data(), dataSize))
|
||||
packetReceived(buffer.data(), dataSize);
|
||||
memcpy(sbuffer.data(), buffer.data(), allReaded);
|
||||
memcpy(buffer.data(), sbuffer.data(packetSize), allReaded);
|
||||
allReaded -= packetSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -31,33 +31,79 @@ typedef bool (*HeaderCheckFunc)(void * , uchar * , uchar * , int );
|
||||
|
||||
class PIP_EXPORT PIPacketExtractor: public PIIODevice
|
||||
{
|
||||
PIOBJECT(PIPacketExtractor)
|
||||
public:
|
||||
PIPacketExtractor(PIIODevice * device_ = 0, void * recHeaderPtr = 0, int recHeaderSize = 0, int recDataSize = 0);
|
||||
virtual ~PIPacketExtractor() {}
|
||||
|
||||
//! Contructs extractor with child device "device_", header content pointer "recHeaderPtr", header size "recHeaderSize" and payload size "recDataSize"
|
||||
PIPacketExtractor(PIIODevice * device_ = 0, void * recHeaderPtr = 0, int recHeaderSize = 0, int recDataSize = 0);
|
||||
|
||||
virtual ~PIPacketExtractor() {stop();}
|
||||
|
||||
|
||||
//! Returns child %device
|
||||
PIIODevice * device() {return dev;}
|
||||
|
||||
//! Set child %device to "device_"
|
||||
void setDevice(PIIODevice * device_);
|
||||
|
||||
|
||||
//! Returns buffer size
|
||||
int bufferSize() const {return buffer_size;}
|
||||
|
||||
//! Set buffer size to "new_size" bytes, should be at least greater than whole packet size
|
||||
void setBufferSize(int new_size) {buffer_size = new_size; buffer.resize(buffer_size); sbuffer.resize(buffer_size); memset(buffer.data(), 0, buffer.size()); memset(sbuffer.data(), 0, sbuffer.size());}
|
||||
|
||||
void setHeaderCheckSlot(HeaderCheckFunc f) {ret_func_header = f;}
|
||||
|
||||
//! Set header content pointer "recHeaderPtr", header size "recHeaderSize" and payload size "recDataSize"
|
||||
void setPacketData(void * recHeaderPtr, int recHeaderSize, int recDataSize) {headerPtr = recHeaderPtr; headerSize = recHeaderSize; dataSize = recDataSize; packetSize = headerSize + dataSize; if (headerSize > 0) mheader.resize(headerSize);}
|
||||
|
||||
|
||||
//! Returns missed by validating functions bytes count
|
||||
ullong missedBytes() const {return missed;}
|
||||
|
||||
//! Returns missed by validating functions packets count, = missedBytes() / packetSize
|
||||
ullong missedPackets() const {if (packetSize == 0) return missed; return missed / packetSize;}
|
||||
|
||||
//! Returns pointer to \a missedBytes() count. Useful for output to PIConsole
|
||||
const ullong * missedBytes_ptr() const {return &missed;}
|
||||
|
||||
//! Returns pointer to \a missedPackets() count. Useful for output to PIConsole
|
||||
const ullong * missedPackets_ptr() const {return &missed_packets;}
|
||||
|
||||
|
||||
//! Returns last successfully validated header as byte array
|
||||
PIByteArray lastHeader() {return mheader;}
|
||||
|
||||
|
||||
//! Directly call \a read() function of child %device
|
||||
int read(void * read_to, int max_size) {if (dev == 0) return -1; return dev->read(read_to, max_size);}
|
||||
|
||||
//! Directly call \a write() function of child %device
|
||||
int write(const void * data, int max_size) {if (dev == 0) return -1; return dev->write(data, max_size);}
|
||||
|
||||
EVENT2(packetReceived, uchar * , data, int, size)
|
||||
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
//! \fn void packetReceived(uchar * data, int size)
|
||||
//! \brief Raise on successfull \a packetValidate() function
|
||||
|
||||
//! \}
|
||||
|
||||
protected:
|
||||
virtual bool packetValidate(uchar * rec, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, rec, size); return true;}
|
||||
|
||||
/** \brief Function to validate header
|
||||
* \param src Your header content passed from constructor or with function \a setPacketData()
|
||||
* \param rec Received header
|
||||
* \param size Header size
|
||||
* \details Default implementation returns by-byte "src" with "rec" compare result */
|
||||
virtual bool packetHeaderValidate(uchar * src, uchar * rec, int size) {if (ret_func_header != 0) return ret_func_header(ret_data_, src, rec, size); for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;}
|
||||
|
||||
//! Function to validate packet paylod after successfully header validate. Default implementation returns \b true
|
||||
virtual bool packetValidate(uchar * rec, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, rec, size); return true;}
|
||||
|
||||
private:
|
||||
bool threadedRead(uchar * readed, int size);
|
||||
bool openDevice() {if (dev == 0) return false; return dev->open();}
|
||||
|
||||
41
piprocess.h
41
piprocess.h
@@ -51,11 +51,13 @@ public:
|
||||
virtual ~PIProcess();
|
||||
|
||||
int exitCode() const {return exit_code;}
|
||||
int pID() const {
|
||||
#ifdef WINDOWS
|
||||
int pID() const {return pi.dwProcessId;}
|
||||
return pi.dwProcessId;
|
||||
#else
|
||||
int pID() const {return pid;}
|
||||
return pid;
|
||||
#endif
|
||||
}
|
||||
|
||||
void setGrabInput(bool yes) {g_in = yes;}
|
||||
void setGrabOutput(bool yes) {g_out = yes;}
|
||||
@@ -69,18 +71,6 @@ public:
|
||||
PIString workingDirectory() const {return wd;}
|
||||
void setWorkingDirectory(const PIString & path) {wd = path;}
|
||||
void resetWorkingDirectory() {wd.clear();}
|
||||
EVENT_HANDLER1(void, exec, const PIString & , program) {args.clear(); args << program; exec_();}
|
||||
EVENT_HANDLER2(void, exec, const PIString & , program, const PIString & , arg) {args.clear(); args << program << arg; exec_();}
|
||||
EVENT_HANDLER3(void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2) {args.clear(); args << program << arg1 << arg2; exec_();}
|
||||
EVENT_HANDLER4(void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2, const PIString & , arg3) {args.clear(); args << program << arg1 << arg2 << arg3; exec_();}
|
||||
EVENT_HANDLER2(void, exec, const PIString & , program, const PIStringList & , args_) {args << program << args_; exec_();}
|
||||
#ifdef WINDOWS
|
||||
EVENT_HANDLER(void, terminate) {if (is_exec) if (!TerminateProcess(pi.hProcess, 0)) return; pi.dwProcessId = 0;}
|
||||
#else
|
||||
EVENT_HANDLER(void, terminate) {if (is_exec) kill(pid, SIGKILL); pid = 0;}
|
||||
#endif
|
||||
EVENT_HANDLER(bool, waitForFinish) {return waitForFinish(60000);}
|
||||
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs) {return PIThread::waitForFinish(timeout_msecs);}
|
||||
PIByteArray readOutput() {f_out.open(PIIODevice::ReadOnly); return f_out.readAll();}
|
||||
PIByteArray readError() {f_err.open(PIIODevice::ReadOnly); return f_err.readAll();}
|
||||
|
||||
@@ -89,16 +79,33 @@ public:
|
||||
void removeEnvironmentVariable(const PIString & variable);
|
||||
void setEnvironmentVariable(const PIString & variable, const PIString & value);
|
||||
|
||||
static PIStringList currentEnvironment() {PIStringList l; int i = 0; while (environ[i] != 0) {l << environ[i]; ++i;} return l;}
|
||||
EVENT_HANDLER1(void, exec, const PIString & , program) {args.clear(); args << program; exec_();}
|
||||
EVENT_HANDLER2(void, exec, const PIString & , program, const PIString & , arg) {args.clear(); args << program << arg; exec_();}
|
||||
EVENT_HANDLER3(void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2) {args.clear(); args << program << arg1 << arg2; exec_();}
|
||||
EVENT_HANDLER4(void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2, const PIString & , arg3) {args.clear(); args << program << arg1 << arg2 << arg3; exec_();}
|
||||
EVENT_HANDLER2(void, exec, const PIString & , program, const PIStringList & , args_) {args << program << args_; exec_();}
|
||||
EVENT_HANDLER(void, terminate) {
|
||||
#ifdef WINDOWS
|
||||
static int currentPID() {return GetCurrentProcessId();}
|
||||
if (is_exec) if (!TerminateProcess(pi.hProcess, 0)) return; pi.dwProcessId = 0;
|
||||
#else
|
||||
static int currentPID() {return getpid();}
|
||||
if (is_exec) kill(pid, SIGKILL); pid = 0;
|
||||
#endif
|
||||
}
|
||||
EVENT_HANDLER(bool, waitForFinish) {return waitForFinish(60000);}
|
||||
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs) {return PIThread::waitForFinish(timeout_msecs);}
|
||||
|
||||
EVENT1(execStarted, PIString, program)
|
||||
EVENT2(execFinished, PIString, program, int, exit_code)
|
||||
|
||||
static PIStringList currentEnvironment() {PIStringList l; int i = 0; while (environ[i] != 0) {l << environ[i]; ++i;} return l;}
|
||||
static int currentPID() {
|
||||
#ifdef WINDOWS
|
||||
return GetCurrentProcessId();
|
||||
#else
|
||||
return getpid();
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void run();
|
||||
void exec_();
|
||||
|
||||
492
piprotocol.cpp
492
piprotocol.cpp
@@ -20,6 +20,16 @@
|
||||
#include "piprotocol.h"
|
||||
|
||||
|
||||
/** \class PIProtocol
|
||||
* \brief
|
||||
* \details
|
||||
* \section PIProtocol_sec0 Synopsis
|
||||
*
|
||||
*
|
||||
*
|
||||
* */
|
||||
|
||||
|
||||
PIProtocol::PIProtocol(const PIString & config, const PIString & name_, void * recHeaderPtr, int recHeaderSize, void * recDataPtr, int recDataSize, void * sendDataPtr_, int sendDataSize_): PIObject() {
|
||||
init();
|
||||
protName = name_;
|
||||
@@ -30,16 +40,256 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name_, void * r
|
||||
devReceiverState = devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
PIConfig::Entry & b(conf.getValue(name_)),
|
||||
& rb(b.getValue("receiver")),
|
||||
& sb(b.getValue("sender"));
|
||||
|
||||
init_receiver(b, rb, config);
|
||||
init_sender(b, sb, config);
|
||||
|
||||
headerPtr = (uchar * )recHeaderPtr;
|
||||
headerSize = recHeaderSize;
|
||||
dataPtr = (uchar * )recDataPtr;
|
||||
dataSize = recDataSize;
|
||||
sendDataPtr = (uchar * )sendDataPtr_;
|
||||
sendDataSize = sendDataSize_;
|
||||
packet_ext->setPacketData(recHeaderPtr, recHeaderSize, recDataSize);
|
||||
}
|
||||
|
||||
|
||||
PIProtocol::~PIProtocol() {
|
||||
//cout << "prot " << protName << " delete\n";
|
||||
if (history_write_rec) {
|
||||
if (history_file_rec.isEmpty()) {
|
||||
history_file_rec.close();
|
||||
history_file_rec.remove();
|
||||
}
|
||||
history_file_rec.close();
|
||||
}
|
||||
if (history_write_send) {
|
||||
if (history_file_send.isEmpty()) {
|
||||
history_file_send.close();
|
||||
history_file_send.remove();
|
||||
}
|
||||
history_file_send.close();
|
||||
}
|
||||
delete diagTimer;
|
||||
delete sendTimer;
|
||||
delete secTimer;
|
||||
delete packet_ext;
|
||||
if (eth != 0) delete eth;
|
||||
if (ser != 0) delete ser;
|
||||
}
|
||||
|
||||
|
||||
void PIProtocol::init() {
|
||||
packet_ext = new PIPacketExtractor();
|
||||
packet_ext->setThreadedReadData(this);
|
||||
packet_ext->setThreadedReadSlot(receiveEvent);
|
||||
packet_ext->setHeaderCheckSlot(headerValidateEvent);
|
||||
work = new_mp_prot = history_write_rec = history_write_send = false;
|
||||
eth = 0;
|
||||
ser = 0;
|
||||
ret_func = 0;
|
||||
mp_owner = 0;
|
||||
net_diag = PIProtocol::Unknown;
|
||||
cur_pckt = 0;
|
||||
diagTimer = 0;
|
||||
timeout_ = 3.f;
|
||||
sendTimer = new PITimer(sendEvent, this);
|
||||
diagTimer = new PITimer(diagEvent, this);
|
||||
secTimer = new PITimer(secEvent, this);
|
||||
wrong_count = receive_count = send_count = missed_count = 0;
|
||||
packets_in_sec = packets_out_sec = bytes_in_sec = bytes_out_sec = 0;
|
||||
immediate_freq = integral_freq = ifreq = 0.f;
|
||||
headerPtr = dataPtr = sendDataPtr = 0;
|
||||
headerSize = dataSize = sendDataSize = 0;
|
||||
type_rec = type_send = PIProtocol::None;
|
||||
devSenderState = devReceiverState = "Unknown";
|
||||
devSenderName = devReceiverName = "no device";
|
||||
history_rsize_rec = history_rsize_send = "no file";
|
||||
secTimer->start(1000.);
|
||||
/*addEvent("receiver started");
|
||||
addEvent("receiver stopped");
|
||||
addEvent("sender started");
|
||||
addEvent("sender stopped");
|
||||
addEvent<bool>("received");
|
||||
addEvent<PIProtocol::Quality>("quality changed");
|
||||
addEventHandler<float>(HANDLER(PIProtocol, startReceive));
|
||||
addEventHandler<float>(HANDLER(PIProtocol, startSend));
|
||||
addEventHandler(HANDLER(PIProtocol, start));
|
||||
addEventHandler(HANDLER(PIProtocol, stopReceive));
|
||||
addEventHandler(HANDLER(PIProtocol, stopSend));
|
||||
addEventHandler(HANDLER(PIProtocol, stop));*/
|
||||
}
|
||||
|
||||
|
||||
void PIProtocol::init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config) {
|
||||
int ps, gps;
|
||||
bool ok, gok, flag, gflag, has_dev = false;
|
||||
float freq, gfreq;
|
||||
PIFlags<PISerial::Parameters> pp(0);
|
||||
PIString dev, gdev;
|
||||
|
||||
if (sb.isEntryExists("ip") && sb.isEntryExists("device")) {
|
||||
piCoutObj << "Ambiguous sender type in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
dev = sb.getValue("ip", "", &ok);
|
||||
gdev = b.getValue("ip", "", &gok);
|
||||
has_dev = false;
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) dev = gdev;
|
||||
if (gok && ok && (dev != gdev)) {
|
||||
piCoutObj << "Ambiguous sender type in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
ps = sb.getValue("port", 0, &ok);
|
||||
gps = b.getValue("port", 0, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) ps = gps;
|
||||
if (gok && ok && (ps != gps)) {
|
||||
piCoutObj << "Ambiguous send port in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
type_send = PIProtocol::Ethernet;
|
||||
if (eth == 0) eth = new PIEthernet();
|
||||
setSenderAddress(dev, ps);
|
||||
//setReceiverAddress(dev, ps);
|
||||
has_dev = true;
|
||||
flag = sb.getValue("reconnectEnabled", true, &ok);
|
||||
gflag = b.getValue("reconnectEnabled", true, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCoutObj << "Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
eth->setReopenEnabled(flag);
|
||||
}
|
||||
freq = sb.getValue("reconnectTimeout", 1., &ok);
|
||||
gfreq = b.getValue("reconnectTimeout", 1., &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) freq = gfreq;
|
||||
if (gok && ok && (freq != gfreq)) {
|
||||
piCoutObj << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
eth->setReopenTimeout(freq * 1000);
|
||||
}
|
||||
/*if (sendDataPtr_ == 0)
|
||||
piCoutObj << "Warning: null send data pointer!";
|
||||
if (sendDataSize_ == 0)
|
||||
piCoutObj << "Warning: null send data size!";*/
|
||||
} else {
|
||||
piCoutObj << "Can`t find \"" << name_ << ".sender.port\" or \"" << name_ << ".port\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
}
|
||||
dev = sb.getValue("device", "", &ok);
|
||||
gdev = b.getValue("device", "", &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) dev = gdev;
|
||||
if (gok && ok && (dev != gdev)) {
|
||||
piCoutObj << "Ambiguous sender type in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
ps = sb.getValue("speed", 0, &ok);
|
||||
gps = b.getValue("speed", 0, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) ps = gps;
|
||||
if (gok && ok && (ps != gps)) {
|
||||
piCoutObj << "Ambiguous send \"speed\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
flag = sb.getValue("parity", false, &ok);
|
||||
gflag = b.getValue("parity", false, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCoutObj << "Ambiguous send \"parity\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
pp.setFlag(PISerial::ParityControl, flag);
|
||||
}
|
||||
flag = sb.getValue("twoStopBits", false, &ok);
|
||||
gflag = b.getValue("twoStopBits", false, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCoutObj << "Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
pp.setFlag(PISerial::TwoStopBits, flag);
|
||||
}
|
||||
} else {
|
||||
piCoutObj << "Can`t find \"" << name_ << ".sender.speed\" or \"" << name_ << ".speed\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
type_send = PIProtocol::Serial;
|
||||
if (ser == 0) ser = new PISerial(dev);
|
||||
setSenderDevice(dev, (PISerial::Speed)ps);
|
||||
ser->setOutSpeed((PISerial::Speed)ps);
|
||||
ser->setParameters(pp);
|
||||
has_dev = true;
|
||||
/*if (sendDataPtr_ == 0)
|
||||
piCoutObj << "Warning: null send data pointer!";
|
||||
if (sendDataSize_ == 0)
|
||||
piCoutObj << "Warning: null send data size!";*/
|
||||
}
|
||||
history_write_send = sb.getValue("writeHistory", false, &ok);
|
||||
bool ghist = b.getValue("writeHistory", false, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) history_write_send = ghist;
|
||||
if (gok && ok && (history_write_send != ghist)) {
|
||||
piCoutObj << "Ambiguous sender history in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
if (history_write_send) {
|
||||
history_path_send = sb.getValue("historyFile", "./history_" + protName + "_send_" +
|
||||
date2string(currentDate(), "__dd_mm_yyyy_") +
|
||||
time2string(currentTime(), "_hh_mm_ss_")).value();
|
||||
history_id_send = sb.getValue("historyID", 0, &ok);
|
||||
if (!ok) {
|
||||
history_id_send = protName.toByteArray().checksumCRC16() + 1;
|
||||
piCoutObj << "Warning: no sender history ID defined, write with ID = " << history_id_send;
|
||||
}
|
||||
history_file_send.open(history_path_send, PIIODevice::WriteOnly);
|
||||
}
|
||||
}
|
||||
freq = sb.getValue("frequency", -1.f, &ok);
|
||||
gfreq = b.getValue("frequency", -1.f, &gok);
|
||||
if (gok && !ok) freq = gfreq;
|
||||
if (gok && ok && (freq != gfreq)) {
|
||||
piCoutObj << "Ambiguous sender frequency in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
if (freq > 0.f && !has_dev)
|
||||
piCoutObj << "Warning: no sender device and not null send frequency!";
|
||||
setSenderFrequency(freq);
|
||||
}
|
||||
|
||||
|
||||
void PIProtocol::init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config) {
|
||||
int ps, gps;
|
||||
bool ok, gok, flag, gflag, has_dev = false;
|
||||
float freq, gfreq;
|
||||
PIFlags<PISerial::Parameters> pp(0);
|
||||
PIConfig::Entry & b(conf.getValue(name_)),
|
||||
& rb(b.getValue("receiver")),
|
||||
& sb(b.getValue("sender"));
|
||||
PIString dev, gdev;
|
||||
|
||||
/// receiver section
|
||||
if (rb.isEntryExists("ip") && rb.isEntryExists("device")) {
|
||||
piCoutObj << "Ambiguous receiver type in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
@@ -91,10 +341,10 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name_, void * r
|
||||
}
|
||||
eth->setReopenTimeout(freq * 1000);
|
||||
}
|
||||
if (recDataPtr == 0)
|
||||
/*if (recDataPtr == 0)
|
||||
piCoutObj << "Warning: null receive data pointer!";
|
||||
if (recDataSize == 0)
|
||||
piCoutObj << "Warning: null receive data size!";
|
||||
piCoutObj << "Warning: null receive data size!";*/
|
||||
} else {
|
||||
piCoutObj << "Can`t find \"" << name_ << ".receiver.port\" or \"" << name_ << ".port\" in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
@@ -161,10 +411,10 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name_, void * r
|
||||
ser->setVTime(ps);
|
||||
}
|
||||
has_dev = true;
|
||||
if (recDataPtr == 0)
|
||||
/*if (recDataPtr == 0)
|
||||
piCoutObj << "Warning: null receive data pointer!";
|
||||
if (recDataSize == 0)
|
||||
piCoutObj << "Warning: null receive data size!";
|
||||
piCoutObj << "Warning: null receive data size!";*/
|
||||
} else {
|
||||
piCoutObj << "Can`t find \"" << name_ << ".receiver.speed\" or \"" << name_ << ".speed\" in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
@@ -207,232 +457,6 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name_, void * r
|
||||
piCoutObj << "Warning: diconnect timeout <= 0 s!";
|
||||
timeout_ = (tm < 0.f) ? 0.f : tm;
|
||||
setExpectedFrequency(freq);
|
||||
|
||||
/// sender section
|
||||
if (sb.isEntryExists("ip") && sb.isEntryExists("device")) {
|
||||
piCoutObj << "Ambiguous sender type in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
dev = sb.getValue("ip", "", &ok);
|
||||
gdev = b.getValue("ip", "", &gok);
|
||||
has_dev = false;
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) dev = gdev;
|
||||
if (gok && ok && (dev != gdev)) {
|
||||
piCoutObj << "Ambiguous sender type in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
ps = sb.getValue("port", 0, &ok);
|
||||
gps = b.getValue("port", 0, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) ps = gps;
|
||||
if (gok && ok && (ps != gps)) {
|
||||
piCoutObj << "Ambiguous send port in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
type_send = PIProtocol::Ethernet;
|
||||
if (eth == 0) eth = new PIEthernet();
|
||||
setSenderAddress(dev, ps);
|
||||
//setReceiverAddress(dev, ps);
|
||||
has_dev = true;
|
||||
flag = sb.getValue("reconnectEnabled", true, &ok);
|
||||
gflag = b.getValue("reconnectEnabled", true, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCoutObj << "Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
eth->setReopenEnabled(flag);
|
||||
}
|
||||
freq = sb.getValue("reconnectTimeout", 1., &ok);
|
||||
gfreq = b.getValue("reconnectTimeout", 1., &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) freq = gfreq;
|
||||
if (gok && ok && (freq != gfreq)) {
|
||||
piCoutObj << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
|
||||
devReceiverState = "Config error";
|
||||
return;
|
||||
}
|
||||
eth->setReopenTimeout(freq * 1000);
|
||||
}
|
||||
if (sendDataPtr_ == 0)
|
||||
piCoutObj << "Warning: null send data pointer!";
|
||||
if (sendDataSize_ == 0)
|
||||
piCoutObj << "Warning: null send data size!";
|
||||
} else {
|
||||
piCoutObj << "Can`t find \"" << name_ << ".sender.port\" or \"" << name_ << ".port\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
}
|
||||
dev = sb.getValue("device", "", &ok);
|
||||
gdev = b.getValue("device", "", &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) dev = gdev;
|
||||
if (gok && ok && (dev != gdev)) {
|
||||
piCoutObj << "Ambiguous sender type in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
ps = sb.getValue("speed", 0, &ok);
|
||||
gps = b.getValue("speed", 0, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) ps = gps;
|
||||
if (gok && ok && (ps != gps)) {
|
||||
piCoutObj << "Ambiguous send \"speed\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
flag = sb.getValue("parity", false, &ok);
|
||||
gflag = b.getValue("parity", false, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCoutObj << "Ambiguous send \"parity\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
pp.setFlag(PISerial::ParityControl, flag);
|
||||
}
|
||||
flag = sb.getValue("twoStopBits", false, &ok);
|
||||
gflag = b.getValue("twoStopBits", false, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) flag = gflag;
|
||||
if (gok && ok && (flag != gflag)) {
|
||||
piCoutObj << "Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
pp.setFlag(PISerial::TwoStopBits, flag);
|
||||
}
|
||||
} else {
|
||||
piCoutObj << "Can`t find \"" << name_ << ".sender.speed\" or \"" << name_ << ".speed\" in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
type_send = PIProtocol::Serial;
|
||||
if (ser == 0) ser = new PISerial(dev);
|
||||
setSenderDevice(dev, (PISerial::Speed)ps);
|
||||
ser->setOutSpeed((PISerial::Speed)ps);
|
||||
ser->setParameters(pp);
|
||||
has_dev = true;
|
||||
if (sendDataPtr_ == 0)
|
||||
piCoutObj << "Warning: null send data pointer!";
|
||||
if (sendDataSize_ == 0)
|
||||
piCoutObj << "Warning: null send data size!";
|
||||
}
|
||||
history_write_send = sb.getValue("writeHistory", false, &ok);
|
||||
ghist = b.getValue("writeHistory", false, &gok);
|
||||
if (ok || gok) {
|
||||
if (gok && !ok) history_write_send = ghist;
|
||||
if (gok && ok && (history_write_send != ghist)) {
|
||||
piCoutObj << "Ambiguous sender history in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
if (history_write_send) {
|
||||
history_path_send = sb.getValue("historyFile", "./history_" + protName + "_send_" +
|
||||
date2string(currentDate(), "__dd_mm_yyyy_") +
|
||||
time2string(currentTime(), "_hh_mm_ss_")).value();
|
||||
history_id_send = sb.getValue("historyID", 0, &ok);
|
||||
if (!ok) {
|
||||
history_id_send = protName.toByteArray().checksumCRC16() + 1;
|
||||
piCoutObj << "Warning: no sender history ID defined, write with ID = " << history_id_send;
|
||||
}
|
||||
history_file_send.open(history_path_send, PIIODevice::WriteOnly);
|
||||
}
|
||||
}
|
||||
freq = sb.getValue("frequency", -1.f, &ok);
|
||||
gfreq = b.getValue("frequency", -1.f, &gok);
|
||||
if (gok && !ok) freq = gfreq;
|
||||
if (gok && ok && (freq != gfreq)) {
|
||||
piCoutObj << "Ambiguous sender frequency in \"" << config << "\"!";
|
||||
devSenderState = "Config error";
|
||||
return;
|
||||
}
|
||||
if (freq > 0.f && !has_dev)
|
||||
piCoutObj << "Warning: no sender device and not null send frequency!";
|
||||
setSenderFrequency(freq);
|
||||
|
||||
headerPtr = (uchar * )recHeaderPtr;
|
||||
headerSize = recHeaderSize;
|
||||
dataPtr = (uchar * )recDataPtr;
|
||||
dataSize = recDataSize;
|
||||
sendDataPtr = (uchar * )sendDataPtr_;
|
||||
sendDataSize = sendDataSize_;
|
||||
packet_ext->setPacketData(recHeaderPtr, recHeaderSize, recDataSize);
|
||||
}
|
||||
|
||||
|
||||
PIProtocol::~PIProtocol() {
|
||||
//cout << "prot " << protName << " delete\n";
|
||||
if (history_write_rec) {
|
||||
if (history_file_rec.isEmpty()) {
|
||||
history_file_rec.close();
|
||||
history_file_rec.remove();
|
||||
}
|
||||
history_file_rec.close();
|
||||
}
|
||||
if (history_write_send) {
|
||||
if (history_file_send.isEmpty()) {
|
||||
history_file_send.close();
|
||||
history_file_send.remove();
|
||||
}
|
||||
history_file_send.close();
|
||||
}
|
||||
delete diagTimer;
|
||||
delete sendTimer;
|
||||
delete secTimer;
|
||||
if (eth != 0) delete eth;
|
||||
if (ser != 0) delete ser;
|
||||
delete packet_ext;
|
||||
}
|
||||
|
||||
|
||||
void PIProtocol::init() {
|
||||
packet_ext = new PIPacketExtractor();
|
||||
packet_ext->setThreadedReadData(this);
|
||||
packet_ext->setThreadedReadSlot(receiveEvent);
|
||||
packet_ext->setHeaderCheckSlot(headerValidateEvent);
|
||||
work = new_mp_prot = history_write_rec = history_write_send = false;
|
||||
eth = 0;
|
||||
ser = 0;
|
||||
ret_func = 0;
|
||||
mp_owner = 0;
|
||||
net_diag = PIProtocol::Unknown;
|
||||
cur_pckt = 0;
|
||||
diagTimer = 0;
|
||||
timeout_ = 3.f;
|
||||
sendTimer = new PITimer(sendEvent, this);
|
||||
diagTimer = new PITimer(diagEvent, this);
|
||||
secTimer = new PITimer(secEvent, this);
|
||||
wrong_count = receive_count = send_count = missed_count = 0;
|
||||
packets_in_sec = packets_out_sec = bytes_in_sec = bytes_out_sec = 0;
|
||||
immediate_freq = integral_freq = ifreq = 0.f;
|
||||
headerPtr = dataPtr = sendDataPtr = 0;
|
||||
headerSize = dataSize = sendDataSize = 0;
|
||||
type_rec = type_send = PIProtocol::None;
|
||||
devSenderState = devReceiverState = "Unknown";
|
||||
devSenderName = devReceiverName = "no device";
|
||||
history_rsize_rec = history_rsize_send = "no file";
|
||||
secTimer->start(1000.);
|
||||
/*addEvent("receiver started");
|
||||
addEvent("receiver stopped");
|
||||
addEvent("sender started");
|
||||
addEvent("sender stopped");
|
||||
addEvent<bool>("received");
|
||||
addEvent<PIProtocol::Quality>("quality changed");
|
||||
addEventHandler<float>(HANDLER(PIProtocol, startReceive));
|
||||
addEventHandler<float>(HANDLER(PIProtocol, startSend));
|
||||
addEventHandler(HANDLER(PIProtocol, start));
|
||||
addEventHandler(HANDLER(PIProtocol, stopReceive));
|
||||
addEventHandler(HANDLER(PIProtocol, stopSend));
|
||||
addEventHandler(HANDLER(PIProtocol, stop));*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
18
piprotocol.h
18
piprotocol.h
@@ -1,5 +1,5 @@
|
||||
/*! \file piprotocol.h
|
||||
* \brief Highly configurable from file device
|
||||
* \brief Highly configurable from file I/O channel
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -76,12 +76,24 @@ class PIP_EXPORT PIProtocol: public PIObject
|
||||
friend class PIMultiProtocol;
|
||||
enum Type {None, Serial, Ethernet};
|
||||
public:
|
||||
|
||||
//! Contructs an empty unconfigured protocol
|
||||
PIProtocol(): PIObject() {init();}
|
||||
|
||||
//! Contructs protocol configured from file "config", config file section "name"
|
||||
PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0,
|
||||
void * recDataPtr = 0, int recDataSize = 0, void * sendDataPtr = 0, int sendDataSize = 0); // from config
|
||||
|
||||
virtual ~PIProtocol();
|
||||
|
||||
enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5};
|
||||
//! Connection quality
|
||||
enum Quality {
|
||||
Unknown /** Unknown, no one packet received yet */ = 1,
|
||||
Failure /** No connection, no one correct packet received for last period */ = 2,
|
||||
Bad /** Bad connection, correct packets received <= 20% */ = 3,
|
||||
Average /** Average connection, correct packets received > 20% and <= 80% */ = 4,
|
||||
Good /** Good connection, correct packets received > 80% */ = 5
|
||||
};
|
||||
|
||||
EVENT_HANDLER0(void, startReceive) {startReceive(-1.f);}
|
||||
EVENT_HANDLER1(void, startReceive, float, exp_frequency); // if "frequency = -1" used last passed value
|
||||
@@ -191,6 +203,8 @@ protected:
|
||||
virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending
|
||||
|
||||
void init();
|
||||
void init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config);
|
||||
void init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config);
|
||||
void check_state();
|
||||
void calc_freq();
|
||||
void calc_diag();
|
||||
|
||||
41
piqueue.h
Normal file
41
piqueue.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*! \file picontainers.h
|
||||
* \brief Queue container
|
||||
*
|
||||
* This file declare PIQueue
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Queue container
|
||||
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 PIQUEUE_H
|
||||
#define PIQUEUE_H
|
||||
|
||||
#include "pivector.h"
|
||||
|
||||
template<typename T>
|
||||
class PIP_EXPORT PIQueue: public PIVector<T> {
|
||||
public:
|
||||
PIQueue() {;}
|
||||
PIVector<T> & enqueue(const T & v) {PIVector<T>::push_front(v); return *this;}
|
||||
T dequeue() {return PIVector<T>::take_back();}
|
||||
T & head() {return PIVector<T>::back();}
|
||||
const T & head() const {return PIVector<T>::back();}
|
||||
PIVector<T> toVector() {PIVector<T> v(PIVector<T>::size()); for (uint i = 0; i < PIVector<T>::size(); ++i) v[i] = PIVector<T>::at(i); return v;}
|
||||
};
|
||||
|
||||
#endif // PIQUEUE_H
|
||||
395
piserial.cpp
395
piserial.cpp
@@ -19,39 +19,49 @@
|
||||
|
||||
#include "piserial.h"
|
||||
#include "piconfig.h"
|
||||
#include "pidir.h"
|
||||
|
||||
|
||||
PISerial::PISerial(const PIString & device, void * data_, ReadRetFunc slot): PIIODevice(device, ReadWrite) {
|
||||
/*! \class PISerial
|
||||
* \brief Serial device
|
||||
*
|
||||
* \section PISerial_sec0 Synopsis
|
||||
* This class provide access to serial device, e.g. COM port. It can read,
|
||||
* write, wait for write. There are several read and write functions.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
PISerial::PISerial(): PIIODevice("", ReadWrite) {
|
||||
piMonitor.serials++;
|
||||
setPriority(piHigh);
|
||||
path_ = device;
|
||||
data = data_;
|
||||
fd = -1;
|
||||
headerPtr = 0;
|
||||
block_read = true;
|
||||
params = 0;
|
||||
ispeed = ospeed = S115200;
|
||||
vtime = 1;
|
||||
ret_func_ = slot;
|
||||
#ifdef WINDOWS
|
||||
hCom = 0;
|
||||
#endif
|
||||
ispeed = ospeed = S115200;
|
||||
dbits = 8;
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
PISerial::PISerial(void * data_, ReadRetFunc slot): PIIODevice("", ReadWrite) {
|
||||
PISerial::PISerial(const PIString & device_, PISerial::Speed speed_, PIFlags<PISerial::Parameters> params_): PIIODevice(device_, ReadWrite) {
|
||||
piMonitor.serials++;
|
||||
setPriority(piHigh);
|
||||
data = data_;
|
||||
path_ = device_;
|
||||
fd = -1;
|
||||
headerPtr = 0;
|
||||
params = 0;
|
||||
block_read = true;
|
||||
params = params_;
|
||||
ispeed = ospeed = speed_;
|
||||
vtime = 1;
|
||||
ret_func_ = slot;
|
||||
#ifdef WINDOWS
|
||||
hCom = 0;
|
||||
#endif
|
||||
ispeed = ospeed = S115200;
|
||||
dbits = 8;
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -104,16 +114,16 @@ bool PISerial::isPin(int number) const {
|
||||
bool PISerial::setBit(int bit, bool on, const PIString & bname) {
|
||||
#ifndef WINDOWS
|
||||
if (fd < 0) {
|
||||
piCoutObj << "set" << bname << " error: \"" << path_ << "\" is not opened!";
|
||||
piCoutObj << "setBit" << bname << " error: \"" << path_ << "\" is not opened!";
|
||||
return false;
|
||||
}
|
||||
if (ioctl(fd, on ? TIOCMBIS : TIOCMBIC, &bit) < 0) {
|
||||
piCoutObj << "set" << bname << " error: " << errorString();
|
||||
piCoutObj << "setBit" << bname << " error: " << errorString();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
piCoutObj << "set" << bname << " doesn`t implemented on Windows, sorry :-(";
|
||||
piCoutObj << "setBit" << bname << " doesn`t implemented on Windows, sorry :-(";
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -122,15 +132,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) {
|
||||
piCoutObj << "is" << bname << " error: \"" << path_ << "\" is not opened!";
|
||||
piCoutObj << "isBit" << bname << " error: \"" << path_ << "\" is not opened!";
|
||||
return false;
|
||||
}
|
||||
int ret = 0;
|
||||
if (ioctl(fd, TIOCMGET, &ret) < 0)
|
||||
piCoutObj << "is" << bname << " error: " << errorString();
|
||||
piCoutObj << "isBit" << bname << " error: " << errorString();
|
||||
return ret & bit;
|
||||
#else
|
||||
piCoutObj << "set" << bname << " doesn`t implemented on Windows, sorry :-(";
|
||||
piCoutObj << "isBit" << bname << " doesn`t implemented on Windows, sorry :-(";
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -142,20 +152,18 @@ bool PISerial::closeDevice() {
|
||||
stop();
|
||||
PIThread::terminate();
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
if (fd != -1) {
|
||||
#ifdef WINDOWS
|
||||
SetCommState(hCom, &sdesc);
|
||||
SetCommMask(hCom, mask);
|
||||
CloseHandle(hCom);
|
||||
fd = -1;
|
||||
}
|
||||
hCom = 0;
|
||||
#else
|
||||
if (fd != -1) {
|
||||
tcsetattr(fd, TCSANOW, &sdesc);
|
||||
::close(fd);
|
||||
#endif
|
||||
fd = -1;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -187,8 +195,16 @@ int PISerial::convertSpeed(PISerial::Speed speed) {
|
||||
}
|
||||
|
||||
|
||||
/** \brief Advanced read function
|
||||
* \details Read to pointer "read_to" no more than "max_size" and no longer
|
||||
* than "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be
|
||||
* wait forever until "max_size" will be readed. If size <= 0 function
|
||||
* immediate returns \b false. For read data with unknown size use function
|
||||
* \a readData().
|
||||
* \returns \b True if readed bytes count = "max_size", else \b false
|
||||
* \sa \a readData() */
|
||||
bool PISerial::read(void * data, int size, double timeout_ms) {
|
||||
if (data == 0) return false;
|
||||
if (data == 0 || size <= 0) return false;
|
||||
int ret, all = 0;
|
||||
if (timeout_ms > 0.) {
|
||||
setReadIsBlocking(false);
|
||||
@@ -215,50 +231,19 @@ bool PISerial::read(void * data, int size, double timeout_ms) {
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PISerial::readData(int size, double timeout_ms) {
|
||||
int ret, all = 0;
|
||||
uchar td[1024];
|
||||
PIByteArray str;
|
||||
if (timeout_ms > 0.) {
|
||||
setReadIsBlocking(false);
|
||||
timer.reset();
|
||||
if (size <= 0) {
|
||||
while (timer.elapsed_m() < timeout_ms) {
|
||||
ret = ::read(fd, td, 1024);
|
||||
if (ret <= 0) msleep(1);
|
||||
else str << PIByteArray(td, ret);
|
||||
}
|
||||
} else {
|
||||
while (all < size && timer.elapsed_m() < timeout_ms) {
|
||||
ret = ::read(fd, td, size - all);
|
||||
if (ret <= 0) msleep(1);
|
||||
else {
|
||||
str << PIByteArray(td, ret);
|
||||
all += ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setReadIsBlocking(true);
|
||||
all = ::read(fd, td, 1);
|
||||
str << PIByteArray(td, all);
|
||||
while (all < size) {
|
||||
ret = ::read(fd, td, size - all);
|
||||
if (ret <= 0) msleep(1);
|
||||
else {
|
||||
str << PIByteArray(td, ret);
|
||||
all += ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Advanced read function
|
||||
* \details Read all or no more than "size" and no longer than
|
||||
* "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be
|
||||
* wait forever until "size" will be readed. If "size" <= 0
|
||||
* function will be read all until "timeout_ms" elaped. \n If size <= 0
|
||||
* and "timeout_ms" <= 0 function immediate returns empty string.
|
||||
* \n This function similar to \a readData() but returns data as string.
|
||||
* \sa \a readData() */
|
||||
PIString PISerial::read(int size, double timeout_ms) {
|
||||
PIString str;
|
||||
if (size <= 0 && timeout_ms <= 0.) return str;
|
||||
int ret, all = 0;
|
||||
uchar td[1024];
|
||||
PIString str;
|
||||
if (timeout_ms > 0.) {
|
||||
setReadIsBlocking(false);
|
||||
timer.reset();
|
||||
@@ -291,6 +276,57 @@ PIString PISerial::read(int size, double timeout_ms) {
|
||||
}
|
||||
}
|
||||
}
|
||||
received(str.data(), str.size_s());
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Advanced read function
|
||||
* \details Read all or no more than "size" and no longer than
|
||||
* "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be
|
||||
* wait forever until "size" will be readed. If "size" <= 0
|
||||
* function will be read all until "timeout_ms" elaped. \n If size <= 0
|
||||
* and "timeout_ms" <= 0 function immediate returns empty byte array.
|
||||
* \n This function similar to \a read() but returns data as byte array.
|
||||
* \sa \a read() */
|
||||
PIByteArray PISerial::readData(int size, double timeout_ms) {
|
||||
PIByteArray str;
|
||||
if (size <= 0 && timeout_ms <= 0.) return str;
|
||||
int ret, all = 0;
|
||||
uchar td[1024];
|
||||
if (timeout_ms > 0.) {
|
||||
setReadIsBlocking(false);
|
||||
timer.reset();
|
||||
if (size <= 0) {
|
||||
while (timer.elapsed_m() < timeout_ms) {
|
||||
ret = ::read(fd, td, 1024);
|
||||
if (ret <= 0) msleep(1);
|
||||
else str.append(td, ret);
|
||||
}
|
||||
} else {
|
||||
while (all < size && timer.elapsed_m() < timeout_ms) {
|
||||
ret = ::read(fd, td, size - all);
|
||||
if (ret <= 0) msleep(1);
|
||||
else {
|
||||
str.append(td, ret);
|
||||
all += ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setReadIsBlocking(true);
|
||||
all = ::read(fd, td, 1);
|
||||
str.append(td, all);
|
||||
while (all < size) {
|
||||
ret = ::read(fd, td, size - all);
|
||||
if (ret <= 0) msleep(1);
|
||||
else {
|
||||
str.append(td, ret);
|
||||
all += ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
received(str.data(), str.size_s());
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -301,41 +337,12 @@ bool PISerial::openDevice() {
|
||||
if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;}
|
||||
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) {
|
||||
if (hCom == INVALID_HANDLE_VALUE) {
|
||||
piCoutObj << "Unable to open \"" << path_ << "\"";
|
||||
fd = -1;
|
||||
return false;
|
||||
}
|
||||
fd = 0;
|
||||
COMMTIMEOUTS times;
|
||||
times.ReadIntervalTimeout = vtime;
|
||||
times.ReadTotalTimeoutConstant = 1;
|
||||
times.ReadTotalTimeoutMultiplier = 0;
|
||||
times.WriteTotalTimeoutConstant = 1;
|
||||
times.WriteTotalTimeoutMultiplier = 0;
|
||||
if (SetCommTimeouts(hCom, ×) == -1) {
|
||||
piCoutObj << "Unable to set timeouts for \"" << path_ << "\"";
|
||||
CloseHandle(hCom);
|
||||
fd = -1;
|
||||
return false;
|
||||
}
|
||||
GetCommMask(hCom, &mask);
|
||||
SetCommMask(hCom, EV_RXCHAR);
|
||||
GetCommState(hCom, &sdesc);
|
||||
desc = sdesc;
|
||||
desc.DCBlength = sizeof(desc);
|
||||
desc.BaudRate = convertSpeed(ispeed);
|
||||
desc.ByteSize = 8;
|
||||
if (params[PISerial::ParityControl]) {
|
||||
desc.fParity = 1;
|
||||
desc.Parity = params[PISerial::ParityOdd] ? 1 : 2;
|
||||
}
|
||||
desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT;
|
||||
if (SetCommState(hCom, &desc) == -1) {
|
||||
piCoutObj << "Unable to set comm state for \"" << path_ << "\"";
|
||||
CloseHandle(hCom);
|
||||
fd = -1;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
int om = 0;
|
||||
switch (mode_) {
|
||||
@@ -345,17 +352,62 @@ bool PISerial::openDevice() {
|
||||
}
|
||||
//cout << "init ser " << path_ << " mode " << om << " param " << params << endl;
|
||||
fd = ::open(path_.data(), O_NOCTTY | om);
|
||||
if(fd == -1) {
|
||||
if (fd == -1) {
|
||||
piCoutObj << "Unable to open \"" << path_ << "\"";
|
||||
return false;
|
||||
}
|
||||
|
||||
tcgetattr(fd, &desc);
|
||||
sdesc = desc;
|
||||
desc.c_iflag = desc.c_oflag = desc.c_lflag = desc.c_cflag = 0;
|
||||
desc.c_cflag = CLOCAL | CSIZE | CS8;
|
||||
//piCoutObj << "Initialized " << path_;
|
||||
#endif
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PISerial::applySettings() {
|
||||
#ifdef WINDOWS
|
||||
if (fd == -1) return;
|
||||
COMMTIMEOUTS times;
|
||||
times.ReadIntervalTimeout = block_read ? vtime : MAXDWORD;
|
||||
times.ReadTotalTimeoutConstant = block_read ? 1 : 0;
|
||||
times.ReadTotalTimeoutMultiplier = 0;
|
||||
times.WriteTotalTimeoutConstant = 1;
|
||||
times.WriteTotalTimeoutMultiplier = 0;
|
||||
if (SetCommTimeouts(hCom, ×) == -1)
|
||||
piCoutObj << "Unable to set timeouts for \"" << path_ << "\"";
|
||||
GetCommMask(hCom, &mask);
|
||||
SetCommMask(hCom, EV_RXCHAR);
|
||||
GetCommState(hCom, &sdesc);
|
||||
desc = sdesc;
|
||||
desc.DCBlength = sizeof(desc);
|
||||
desc.BaudRate = convertSpeed(ispeed);
|
||||
if (dbits >= 5 && dbits <= 8)
|
||||
desc.ByteSize = dbits;
|
||||
else
|
||||
desc.ByteSize = 8;
|
||||
if (params[PISerial::ParityControl]) {
|
||||
desc.fParity = 1;
|
||||
desc.Parity = params[PISerial::ParityOdd] ? 1 : 2;
|
||||
}
|
||||
desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT;
|
||||
if (SetCommState(hCom, &desc) == -1) {
|
||||
piCoutObj << "Unable to set comm state for \"" << path_ << "\"";
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (fd == -1) return;
|
||||
tcgetattr(fd, &desc);
|
||||
desc.c_oflag = desc.c_lflag = desc.c_cflag = 0;
|
||||
desc.c_iflag = IGNBRK;
|
||||
desc.c_cflag = CLOCAL | HUPCL;
|
||||
switch (dbits) {
|
||||
case 5: desc.c_cflag |= (CSIZE & CS5); break;
|
||||
case 6: desc.c_cflag |= (CSIZE & CS6); break;
|
||||
case 7: desc.c_cflag |= (CSIZE & CS7); break;
|
||||
case 8: default: desc.c_cflag |= (CSIZE & CS8); break;
|
||||
};
|
||||
if (isReadable()) desc.c_cflag |= CREAD;
|
||||
if (params[PISerial::HardwareFlowControl]) desc.c_cflag |= CRTSCTS;
|
||||
if (params[PISerial::TwoStopBits]) desc.c_cflag |= CSTOPB;
|
||||
if (params[PISerial::ParityControl]) {
|
||||
desc.c_iflag |= INPCK;
|
||||
@@ -369,19 +421,37 @@ bool PISerial::openDevice() {
|
||||
cfsetospeed(&desc, convertSpeed(ospeed));
|
||||
|
||||
tcflush(fd, TCIOFLUSH);
|
||||
fcntl(fd, F_SETFL, 0);
|
||||
fcntl(fd, F_SETFL, block_read ? 0 : O_NONBLOCK);
|
||||
|
||||
if(tcsetattr(fd, TCSANOW, &desc) < 0) {
|
||||
piCoutObj << "Can`t set attributes for \"" << path_ << "\"";
|
||||
::close(fd);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
//piCoutObj << "Initialized " << path_;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PISerial::setReadIsBlocking(bool yes) {
|
||||
block_read = yes;
|
||||
#ifdef WINDOWS
|
||||
COMMTIMEOUTS times;
|
||||
times.ReadIntervalTimeout = yes ? vtime : MAXDWORD;
|
||||
times.ReadTotalTimeoutConstant = yes ? 1 : 0;
|
||||
times.ReadTotalTimeoutMultiplier = 0;
|
||||
times.WriteTotalTimeoutConstant = 1;
|
||||
times.WriteTotalTimeoutMultiplier = 0;
|
||||
if (isOpened()) SetCommTimeouts(hCom, ×);
|
||||
#else
|
||||
if (isOpened()) fcntl(fd, F_SETFL, yes ? 0 : O_NONBLOCK);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** \brief Basic read function
|
||||
* \details Read to pointer "read_to" no more than "max_size". If read is
|
||||
* set to blocking this function will be wait at least one byte.
|
||||
* \returns Readed bytes count
|
||||
* \sa \a readData() */
|
||||
int PISerial::read(void * read_to, int max_size) {
|
||||
#ifdef WINDOWS
|
||||
if (!canRead()) return -1;
|
||||
@@ -426,8 +496,121 @@ bool PISerial::configureDevice(const void * e_main, const void * e_parent) {
|
||||
PIConfig::Entry * ep = (PIConfig::Entry * )e_parent;
|
||||
setDevice(readDeviceSetting<PIString>("device", device(), em, ep));
|
||||
setSpeed((PISerial::Speed)(readDeviceSetting<int>("speed", (int)ospeed, em, ep)));
|
||||
setDataBitsCount(readDeviceSetting<int>("dataBitsCount", dataBitsCount(), em, ep));
|
||||
setParameter(PISerial::ParityControl, readDeviceSetting<bool>("parityControl", isParameterSet(PISerial::ParityControl), em, ep));
|
||||
setParameter(PISerial::ParityOdd, readDeviceSetting<bool>("parityOdd", isParameterSet(PISerial::ParityOdd), em, ep));
|
||||
setParameter(PISerial::TwoStopBits, readDeviceSetting<bool>("twoStopBits", isParameterSet(PISerial::TwoStopBits), em, ep));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
PIVector<int> PISerial::availableSpeeds() {
|
||||
PIVector<int> spds;
|
||||
spds << 50 << 75 << 110 << 300 << 600 << 1200 << 2400 << 4800 <<
|
||||
9600 << 19200 << 38400 << 57600 << 115200 << 1500000 <<
|
||||
2000000 << 2500000 << 3000000 << 3500000 << 4000000;
|
||||
return spds;
|
||||
}
|
||||
|
||||
|
||||
PIStringList PISerial::availableDevices(bool test) {
|
||||
PIStringList dl;
|
||||
#ifdef WINDOWS
|
||||
HKEY key = 0;
|
||||
RegOpenKey(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", &key);
|
||||
if (key != 0) {
|
||||
char name[256], data[1024];
|
||||
DWORD name_len = 256, data_len = 1024, type = 0, index = 0;
|
||||
while (RegEnumValue(key, index, name, &name_len, NULL, &type, (uchar * )data, &data_len) == ERROR_SUCCESS) {
|
||||
dl << PIString(data);
|
||||
index++;
|
||||
}
|
||||
RegCloseKey(key);
|
||||
}
|
||||
#else
|
||||
# ifndef ANDROID
|
||||
PIStringList prefixes;
|
||||
# ifdef QNX
|
||||
prefixes << "ser";
|
||||
# else
|
||||
prefixes << "ttyS" << "ttyO" << "ttyUSB" << "ttyACM" << "ttyGS"
|
||||
<< "ttyMI" << "ttymxc" << "ttyAMA" << "rfcomm" << "ircomm";
|
||||
# ifdef FREE_BSD
|
||||
prefixes << "cu";
|
||||
# endif
|
||||
PIFile file_prefixes("/proc/tty/drivers", PIIODevice::ReadOnly);
|
||||
if (file_prefixes.open()) {
|
||||
PIString fc = file_prefixes.readAll(true), line, cpref;
|
||||
PIStringList words;
|
||||
file_prefixes.close();
|
||||
while (!fc.isEmpty()) {
|
||||
words.clear();
|
||||
line = fc.takeLine();
|
||||
if (line.isEmpty()) break;
|
||||
while (!line.isEmpty())
|
||||
words << line.takeWord();
|
||||
if (words.size_s() < 2) break;
|
||||
if (words.back() != "serial") continue;
|
||||
cpref = words[1];
|
||||
int li = cpref.findLast("/");
|
||||
if (li > 0) cpref.cutLeft(li + 1);
|
||||
prefixes << cpref;
|
||||
}
|
||||
prefixes.removeDuplicates();
|
||||
}
|
||||
# endif
|
||||
PIDir dir("/dev");
|
||||
PIVector<PIDir::DirEntry> de = dir.entries();
|
||||
piForeachC (PIDir::DirEntry & e, de) {
|
||||
piForeachC (PIString & p, prefixes) {
|
||||
if (e.name.left(p.size_s()) != p) continue;
|
||||
dl << "/dev/" + e.name;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
if (test) {
|
||||
for (int i = 0; i < dl.size_s(); ++i) {
|
||||
#ifdef WINDOWS
|
||||
void * hCom = CreateFileA(dl[i].data(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
|
||||
if (hCom == INVALID_HANDLE_VALUE) {
|
||||
#else
|
||||
int fd = ::open(dl[i].data(), O_NOCTTY | O_RDONLY);
|
||||
if (fd == -1) {
|
||||
#endif
|
||||
dl.remove(i);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
int void_ = 0;
|
||||
bool rok = true;
|
||||
#ifdef WINDOWS
|
||||
/*COMMTIMEOUTS times;
|
||||
times.ReadIntervalTimeout = MAXDWORD;
|
||||
times.ReadTotalTimeoutConstant = 0;
|
||||
times.ReadTotalTimeoutMultiplier = 0;
|
||||
times.WriteTotalTimeoutConstant = 1;
|
||||
times.WriteTotalTimeoutMultiplier = 0;
|
||||
SetCommTimeouts(hCom, ×);
|
||||
if (ReadFile(hCom, &void_, 1, &readed_, 0) == 0)
|
||||
rok = GetLastError() == ;*/
|
||||
#else
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
if (::read(fd, &void_, 1) == -1)
|
||||
rok = errno != EIO;
|
||||
|
||||
#endif
|
||||
if (!rok) {
|
||||
dl.remove(i);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
CloseHandle(hCom);
|
||||
#else
|
||||
::close(fd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return dl;
|
||||
}
|
||||
|
||||
188
piserial.h
188
piserial.h
@@ -90,29 +90,35 @@
|
||||
# define CRTSCTS 020000000000
|
||||
#endif
|
||||
|
||||
|
||||
class PIP_EXPORT PISerial: public PIIODevice {
|
||||
public:
|
||||
// slot is any function format "bool <func>(void*, uchar*, int)"
|
||||
// slot_header is any function format "bool <func>(void*, uchar*, uchar*, int)"
|
||||
PISerial(const PIString & device, void * data = 0, ReadRetFunc slot = 0);
|
||||
PISerial(void * data = 0, ReadRetFunc slot = 0);
|
||||
~PISerial();
|
||||
|
||||
enum Parameters {ParityControl = 0x1, ParityOdd = 0x2, TwoStopBits = 0x4, HardwareFlowControl = 0x8};
|
||||
//! Contructs an empty %PISerial
|
||||
PISerial();
|
||||
|
||||
//! \brief Parameters of PISerial
|
||||
enum Parameters {
|
||||
ParityControl /*! Enable parity check and generate */ = 0x1,
|
||||
ParityOdd /*! Parity is odd instead of even */ = 0x2,
|
||||
TwoStopBits /*! Two stop bits instead of one */ = 0x4
|
||||
};
|
||||
|
||||
//! \brief Speed of PISerial
|
||||
enum Speed {
|
||||
S50 = 50,
|
||||
S75 = 75,
|
||||
S110 = 110,
|
||||
S300 = 300,
|
||||
S600 = 600,
|
||||
S1200 = 1200,
|
||||
S2400 = 2400,
|
||||
S4800 = 4800,
|
||||
S9600 = 9600,
|
||||
S19200 = 19200,
|
||||
S38400 = 38400,
|
||||
S57600 = 57600,
|
||||
S115200 = 115200,
|
||||
S50 /*! 50 baud */ = 50,
|
||||
S75 /*! 75 baud */ = 75,
|
||||
S110 /*! 110 baud */ = 110,
|
||||
S300 /*! 300 baud */ = 300,
|
||||
S600 /*! 600 baud */ = 600,
|
||||
S1200 /*! 1200 baud */ = 1200,
|
||||
S2400 /*! 2400 baud */ = 2400,
|
||||
S4800 /*! 4800 baud */ = 4800,
|
||||
S9600 /*! 9600 baud */ = 9600,
|
||||
S19200 /*! 19200 baud */ = 19200,
|
||||
S38400 /*! 38400 baud */ = 38400,
|
||||
S57600 /*! 57600 baud */ = 57600,
|
||||
S115200 /*! 115200 baud */ = 115200,
|
||||
S1500000 = 1500000, // Linux only
|
||||
S2000000 = 2000000, // Linux only
|
||||
S2500000 = 2500000, // Linux only
|
||||
@@ -121,20 +127,49 @@ public:
|
||||
S4000000 = 4000000 // Linux only
|
||||
};
|
||||
|
||||
void setData(void * d) {data = d;}
|
||||
//! Contructs %PISerial with device name "device", speed "speed" and parameters "params"
|
||||
PISerial(const PIString & device, PISerial::Speed speed = S115200, PIFlags<PISerial::Parameters> params = 0);
|
||||
|
||||
//void setSlot(SerialFunc func) {ret_func = func;}
|
||||
void setSpeed(PISerial::Speed speed) {ospeed = ispeed = speed;}
|
||||
void setOutSpeed(PISerial::Speed speed) {ospeed = speed;}
|
||||
void setInSpeed(PISerial::Speed speed) {ispeed = speed;}
|
||||
void setDevice(const PIString & dev) {path_ = dev;}
|
||||
~PISerial();
|
||||
|
||||
void setParameters(PIFlags<PISerial::Parameters> parameters_) {params = parameters_;}
|
||||
void setParameter(PISerial::Parameters parameter, bool on = true) {params.setFlag(parameter, on);}
|
||||
|
||||
//! Set both input and output speed to "speed"
|
||||
void setSpeed(PISerial::Speed speed) {ospeed = ispeed = speed; applySettings();}
|
||||
|
||||
//! Set output speed to "speed"
|
||||
void setOutSpeed(PISerial::Speed speed) {ospeed = speed; applySettings();}
|
||||
|
||||
//! Set input speed to "speed"
|
||||
void setInSpeed(PISerial::Speed speed) {ispeed = speed; applySettings();}
|
||||
|
||||
//! Set device name to "dev"
|
||||
void setDevice(const PIString & dev) {path_ = dev; if (isOpened()) {close(); open();};}
|
||||
|
||||
|
||||
//! Set parameters to "parameters_"
|
||||
void setParameters(PIFlags<PISerial::Parameters> parameters_) {params = parameters_; applySettings();}
|
||||
|
||||
//! Set parameter "parameter" to "on" state
|
||||
void setParameter(PISerial::Parameters parameter, bool on = true) {params.setFlag(parameter, on); applySettings();}
|
||||
|
||||
//! Returns if parameter "parameter" is set
|
||||
bool isParameterSet(PISerial::Parameters parameter) const {return params[parameter];}
|
||||
|
||||
//! Returns parameters
|
||||
PIFlags<PISerial::Parameters> parameters() const {return params;}
|
||||
|
||||
|
||||
//! Set data bits count. Valid range is from 5 to 8, befault is 8
|
||||
void setDataBitsCount(int bits) {dbits = bits; applySettings();}
|
||||
|
||||
//! Returns data bits count
|
||||
int dataBitsCount() const {return dbits;}
|
||||
|
||||
|
||||
//! Set pin number "number" to logic level "on". Valid numbers are 4 (DTR) and 7 (RTS)
|
||||
bool setPin(int number, bool on);
|
||||
|
||||
//! Returns pin number "number" logic level. Valid numbers range is from 1 to 9
|
||||
bool isPin(int number) const;
|
||||
|
||||
bool setLE(bool on) {return setBit(TIOCM_LE, on, "LE");} // useless function, just formally
|
||||
@@ -157,46 +192,91 @@ public:
|
||||
bool isRNG() const {return isBit(TIOCM_RNG, "RNG");}
|
||||
bool isDSR() const {return isBit(TIOCM_DSR, "DSR");}
|
||||
|
||||
void setVTime(int t) {vtime = t;}
|
||||
void setVTime(int t) {vtime = t; applySettings();}
|
||||
|
||||
void setReadIsBlocking(bool yes) {
|
||||
#ifdef WINDOWS
|
||||
COMMTIMEOUTS times;
|
||||
times.ReadIntervalTimeout = yes ? vtime : MAXDWORD;
|
||||
times.ReadTotalTimeoutConstant = yes ? 1 : 0;
|
||||
times.ReadTotalTimeoutMultiplier = 0;
|
||||
times.WriteTotalTimeoutConstant = 1;
|
||||
times.WriteTotalTimeoutMultiplier = 0;
|
||||
if (isOpened()) SetCommTimeouts(hCom, ×);
|
||||
#else
|
||||
if (isOpened()) fcntl(fd, F_SETFL, yes ? 0 : O_NONBLOCK);
|
||||
|
||||
//! Set read is blocking for function read(void * read_to, int max_size)
|
||||
void setReadIsBlocking(bool yes);
|
||||
|
||||
|
||||
//! Returns device name
|
||||
const PIString & device() const {return path_;}
|
||||
|
||||
//! Returns output speed
|
||||
PISerial::Speed outSpeed() const {return ospeed;}
|
||||
|
||||
//! Returns input speed
|
||||
PISerial::Speed inSpeed() const {return ispeed;}
|
||||
|
||||
int VTime() const {return vtime;}
|
||||
|
||||
|
||||
//! Discard all buffered input and output data
|
||||
void flush() {
|
||||
#ifndef WINDOWS
|
||||
if (fd != -1) tcflush(fd, TCIOFLUSH);
|
||||
#endif
|
||||
}
|
||||
|
||||
const PIString & device() const {return path_;}
|
||||
PISerial::Speed outSpeed() const {return ospeed;}
|
||||
PISerial::Speed inSpeed() const {return ispeed;}
|
||||
int VTime() const {return vtime;}
|
||||
|
||||
#ifndef WINDOWS
|
||||
void flush() {if (fd != -1) tcflush(fd, TCIOFLUSH);}
|
||||
#endif
|
||||
|
||||
int read(void * read_to, int max_size);
|
||||
bool read(void * data, int size, double timeout_ms);
|
||||
bool read(void * read_to, int max_size, double timeout_ms);
|
||||
PIString read(int size = -1, double timeout_ms = 1000.);
|
||||
PIByteArray readData(int size = -1, double timeout_ms = 1000.);
|
||||
|
||||
int write(const void * data, int max_size, bool wait);
|
||||
int write(const void * data, int max_size) {return write(data, max_size, false);}
|
||||
|
||||
//! \brief Write to device data "data" with maximum size "max_size" and wait for data written if "wait" is \b true.
|
||||
//! \returns sended bytes count
|
||||
int write(const void * data, int max_size, bool wait = false);
|
||||
|
||||
//! \brief Write to device data "data" with maximum size "size" and wait for data written if "wait" is \b true.
|
||||
//! \returns \b true if sended bytes count = "size"
|
||||
bool send(const void * data, int size, bool wait = false) {return (write(data, size, wait) == size);}
|
||||
|
||||
//! \brief Write to device string "data" and wait for data written if "wait" is \b true.
|
||||
//! \returns \b true if sended bytes count = size of string
|
||||
bool send(const PIString & data, bool wait = false) {return (write(data.data(), data.lengthAscii(), wait) == data.size_s());}
|
||||
|
||||
//! \brief Write to device byte array "data" and wait for data written if "wait" is \b true.
|
||||
//! \returns \b true if sended bytes count = size of string
|
||||
bool send(const PIByteArray & data, bool wait = false) {return (write(data.data(), data.size_s(), wait) == data.size_s());}
|
||||
|
||||
|
||||
//! \brief Returns all available speeds for serial devices
|
||||
static PIVector<int> availableSpeeds();
|
||||
|
||||
//! \brief Returns all available system devices. If "test" each device will be tried to open
|
||||
static PIStringList availableDevices(bool test = false);
|
||||
|
||||
//! \ioparams
|
||||
//! \{
|
||||
#ifdef DOXYGEN
|
||||
//! \brief device, default ""
|
||||
string device;
|
||||
|
||||
//! \brief input/output speed, default 115200
|
||||
int speed;
|
||||
|
||||
//! \brief dataBitsCount, default 8
|
||||
int dataBitsCount;
|
||||
|
||||
//! \brief parityControl, default false
|
||||
bool parityControl;
|
||||
|
||||
//! \brief parityOdd, default false
|
||||
bool parityOdd;
|
||||
|
||||
//! \brief twoStopBits, default false
|
||||
bool twoStopBits;
|
||||
#endif
|
||||
//! \}
|
||||
|
||||
protected:
|
||||
bool configureDevice(const void * e_main, const void * e_parent = 0);
|
||||
virtual void received(void * data, int size) {;}
|
||||
|
||||
//! Executes when any read function was successful. Default implementation does nothing
|
||||
virtual void received(const void * data, int size) {;}
|
||||
|
||||
void applySettings();
|
||||
int convertSpeed(PISerial::Speed speed);
|
||||
bool setBit(int bit, bool on, const PIString & bname);
|
||||
bool isBit(int bit, const PIString & bname) const;
|
||||
@@ -213,10 +293,10 @@ protected:
|
||||
termios desc, sdesc;
|
||||
uint readed;
|
||||
#endif
|
||||
int fd, vtime;
|
||||
int fd, vtime, dbits;
|
||||
bool block_read;
|
||||
PISerial::Speed ospeed, ispeed;
|
||||
PITimer timer;
|
||||
void * headerPtr, * data;
|
||||
PIFlags<PISerial::Parameters> params;
|
||||
|
||||
};
|
||||
|
||||
32
pisignals.h
32
pisignals.h
@@ -30,23 +30,23 @@ class PIP_EXPORT PISignals
|
||||
{
|
||||
public:
|
||||
enum Signal {
|
||||
Interrupt = 0x01, // Term Interrupt from keyboard
|
||||
Illegal = 0x02, // Core Illegal Instruction
|
||||
Abort = 0x04, // Core Abort signal from abort
|
||||
FPE = 0x08, // Core Floating point exception
|
||||
SegFault = 0x10, // Core Invalid memory reference
|
||||
Termination = 0x20, // Term Termination signal
|
||||
Interrupt /** Interrupt from keyboard */ = 0x01, // Term Interrupt from keyboard
|
||||
Illegal /** Illegal Instruction */ = 0x02, // Core Illegal Instruction
|
||||
Abort /** Abort signal */ = 0x04, // Core Abort signal from abort
|
||||
FPE /** Floating point exception */ = 0x08, // Core Floating point exception
|
||||
SegFault /** Invalid memory reference */ = 0x10, // Core Invalid memory reference
|
||||
Termination /** Termination signal */ = 0x20, // Term Termination signal
|
||||
#ifndef WINDOWS
|
||||
Hangup = 0x40, // Term Hangup detected on controlling terminal or death of controlling process
|
||||
Quit = 0x80, // Core Quit from keyboard
|
||||
Kill = 0x100, // Term Kill signal
|
||||
BrokenPipe = 0x200, // Term Broken pipe: write to pipe with no readers
|
||||
Timer = 0x400, // Term Timer signal from alarm
|
||||
UserDefined1 = 0x800, // Term User-defined signal 1
|
||||
UserDefined2 = 0x1000, // Term User-defined signal 2
|
||||
ChildStopped = 0x2000, // Ign Child stopped or terminated
|
||||
Continue = 0x4000, // Cont Continue if stopped
|
||||
StopProcess = 0x8000, // Stop Stop process
|
||||
Hangup = 0x40, // Term Hangup detected on controlling terminal or death of controlling process
|
||||
Quit = 0x80, // Core Quit from keyboard
|
||||
Kill = 0x100, // Term Kill signal
|
||||
BrokenPipe = 0x200, // Term Broken pipe: write to pipe with no readers
|
||||
Timer = 0x400, // Term Timer signal from alarm
|
||||
UserDefined1 = 0x800, // Term User-defined signal 1
|
||||
UserDefined2 = 0x1000, // Term User-defined signal 2
|
||||
ChildStopped = 0x2000, // Ign Child stopped or terminated
|
||||
Continue = 0x4000, // Cont Continue if stopped
|
||||
StopProcess = 0x8000, // Stop Stop process
|
||||
StopTTY = 0x10000, // Stop Stop typed at tty
|
||||
StopTTYInput = 0x20000, // Stop tty input for background process
|
||||
StopTTYOutput = 0x40000, // Stop tty output for background process
|
||||
|
||||
41
pistack.h
Normal file
41
pistack.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*! \file picontainers.h
|
||||
* \brief Stack container
|
||||
*
|
||||
* This file declare PIStack
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Stack container
|
||||
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 PISTACK_H
|
||||
#define PISTACK_H
|
||||
|
||||
#include "pivector.h"
|
||||
|
||||
template<typename T>
|
||||
class PIP_EXPORT PIStack: public PIVector<T> {
|
||||
public:
|
||||
PIStack() {;}
|
||||
PIVector<T> & push(const T & v) {PIVector<T>::push_back(v); return *this;}
|
||||
T pop() {return PIVector<T>::take_back();}
|
||||
T & top() {return PIVector<T>::back();}
|
||||
const T & top() const {return PIVector<T>::back();}
|
||||
PIVector<T> toVector() {PIVector<T> v(PIVector<T>::size()); for (uint i = 0; i < PIVector<T>::size(); ++i) v[i] = PIVector<T>::at(i); return v;}
|
||||
};
|
||||
|
||||
#endif // PISTACK_H
|
||||
49
pistring.cpp
49
pistring.cpp
@@ -85,7 +85,7 @@ void PIString::appendFromChars(const char * c, int s) {
|
||||
push_back(PIChar(c[i]));
|
||||
continue;
|
||||
}
|
||||
sz = mbtowc(&wc, &c[i], 4);
|
||||
sz = mbtowc(&wc, &(c[i]), 4);
|
||||
//cout << sz << endl;
|
||||
switch (sz) {
|
||||
case 4:
|
||||
@@ -378,7 +378,10 @@ PIString PIString::takeWord() {
|
||||
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;
|
||||
if (we < 0 && ws >= 0) {
|
||||
we = i;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (ws < 0) ws = i;
|
||||
if (we >= 0) break;
|
||||
@@ -390,6 +393,37 @@ PIString PIString::takeWord() {
|
||||
}
|
||||
|
||||
|
||||
PIString PIString::takeCWord() {
|
||||
PIString ret;
|
||||
int sz = size_s(), ws = -1, we = -1;
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
PIChar c = at(i);
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
||||
if (we < 0 && ws >= 0) {
|
||||
we = i;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (ws < 0) {
|
||||
if (c.isAlpha() || c == '_')
|
||||
ws = i;
|
||||
else
|
||||
return ret;
|
||||
} else {
|
||||
if (!c.isAlpha() && !c.isDigit() && c != '_') {
|
||||
we = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (we >= 0) break;
|
||||
}
|
||||
}
|
||||
ret = mid(ws, we - ws);
|
||||
cutLeft(we < 0 ? sz : we);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString PIString::takeLine() {
|
||||
int sz = size_s(), le = -1;
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
@@ -528,13 +562,16 @@ int PIString::lengthAscii() const {
|
||||
|
||||
const char * PIString::data() const {
|
||||
data_.clear();
|
||||
int wc;
|
||||
uint wc;
|
||||
uchar tc;
|
||||
//printf("PIString::data %d\n", size_s());
|
||||
for (int i = 0, j = 0; i < size_s(); ++i) {
|
||||
wc = at(i).toInt();
|
||||
wc = uint(at(i).toInt());
|
||||
//printf("__%d_%d\n", i, wc);
|
||||
while (tc = wc & 0xFF, tc) {
|
||||
data_.push_back(uchar(tc)); ++j;
|
||||
wc >>= 8;
|
||||
//printf("____%d\n", wc);
|
||||
}
|
||||
/*if (at(i).isAscii())
|
||||
data_.push_back(uchar(at(i).toAscii()));
|
||||
@@ -550,11 +587,11 @@ const char * PIString::data() const {
|
||||
|
||||
string PIString::convertToStd() const {
|
||||
string s;
|
||||
int wc;
|
||||
uint wc;
|
||||
uchar tc;
|
||||
if (size() > 0) {
|
||||
for (int i = 0; i < length(); ++i) {
|
||||
wc = at(i).toInt();
|
||||
wc = uint(at(i).toInt());
|
||||
while (tc = wc & 0xFF, tc) {
|
||||
s.push_back(char(tc));
|
||||
wc >>= 8;
|
||||
|
||||
89
pistring.h
89
pistring.h
@@ -35,7 +35,7 @@ class PIP_EXPORT PIString: public PIVector<PIChar>
|
||||
{
|
||||
public:
|
||||
//! Contructs an empty string
|
||||
PIString() {reserve(256); piMonitor.strings++; piMonitor.containers--;}
|
||||
PIString(): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--;}
|
||||
|
||||
//inline PIString & operator +=(const char c) {push_back(c); return *this;}
|
||||
PIString & operator +=(const PIChar & c) {push_back(c); return *this;}
|
||||
@@ -51,43 +51,43 @@ public:
|
||||
//PIString(const char c) {*this += c;}
|
||||
|
||||
//! Contructs string with single symbol "c"
|
||||
PIString(const PIChar & c) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += c;}
|
||||
PIString(const PIChar & c): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += c;}
|
||||
|
||||
/*! \brief Contructs string from c-string "str"
|
||||
* \details "str" should be null-terminated\n
|
||||
* Example: \snippet pistring.cpp PIString(char * ) */
|
||||
PIString(const char * str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
|
||||
PIString(const char * str): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
|
||||
|
||||
/*! \brief Contructs string from \c wchar_t c-string "str"
|
||||
* \details "str" should be null-terminated\n
|
||||
* Example: \snippet pistring.cpp PIString(wchar_t * ) */
|
||||
PIString(const wchar_t * str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
|
||||
PIString(const wchar_t * str): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
|
||||
|
||||
//! Contructs string from std::string "str"
|
||||
PIString(const string & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
|
||||
PIString(const string & str): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
|
||||
|
||||
#ifdef HAS_LOCALE
|
||||
PIString(const wstring & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
|
||||
PIString(const wstring & str): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
|
||||
#endif
|
||||
|
||||
//! Contructs string from byte array "ba"
|
||||
PIString(const PIByteArray & ba) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += ba;}
|
||||
PIString(const PIByteArray & ba): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += ba;}
|
||||
|
||||
/*! \brief Contructs string from "len" characters of buffer "str"
|
||||
* \details Example: \snippet pistring.cpp PIString(char * , int) */
|
||||
PIString(const char * str, const int len) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += string(str, len);}
|
||||
PIString(const char * str, const int len): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += string(str, len);}
|
||||
|
||||
/*! \brief Contructs string as sequence of characters "c" of buffer with length "len"
|
||||
* \details Example: \snippet pistring.cpp PIString(int, char) */
|
||||
PIString(const int len, const char c) {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
|
||||
PIString(const int len, const char c): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
|
||||
|
||||
/*! \brief Contructs string as sequence of symbols "c" of buffer with length "len"
|
||||
* \details Example: \snippet pistring.cpp PIString(int, PIChar) */
|
||||
PIString(const int len, const PIChar & c) {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
|
||||
|
||||
PIString(const int len, const PIChar & c): PIVector<PIChar>() {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
|
||||
/*
|
||||
//! Contructs string from other string "str"
|
||||
PIString(const PIString & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; uint len = str.size(); for (uint i = 0; i < len; ++i) push_back(str[i]);}
|
||||
|
||||
*/
|
||||
~PIString() {piMonitor.strings--; piMonitor.containers++;}
|
||||
|
||||
|
||||
@@ -344,22 +344,28 @@ public:
|
||||
|
||||
/*! \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() */
|
||||
* \sa \a takeWord(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
|
||||
PIString takeSymbol();
|
||||
|
||||
/*! \brief Take a word from the begin of this string and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::takeWord
|
||||
* \sa \a takeSymbol(), \a takeLine(), \a takeNumber(), \a takeRange() */
|
||||
* \sa \a takeSymbol(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
|
||||
PIString takeWord();
|
||||
|
||||
/*! \brief Take a word with letters, numbers and '_' symbols from the
|
||||
* begin of this string and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::takeCWord
|
||||
* \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
|
||||
PIString takeCWord();
|
||||
|
||||
/*! \brief Take a line from the begin of this string and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::takeLine
|
||||
* \sa \a takeSymbol(), \a takeWord(), \a takeNumber(), \a takeRange() */
|
||||
* \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeNumber(), \a takeRange() */
|
||||
PIString takeLine();
|
||||
|
||||
/*! \brief Take a number with C-format from the begin of this string and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::takeNumber
|
||||
* \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeRange() */
|
||||
* \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeLine(), \a takeRange() */
|
||||
PIString takeNumber();
|
||||
|
||||
/*! \brief Take a range between "start" and "end" symbols from the begin of this
|
||||
@@ -454,8 +460,8 @@ public:
|
||||
bool isEmpty() const {return (size() == 0 || *this == "");}
|
||||
|
||||
|
||||
//! \brief Return \c true if string equal "true" or "on" or positive numeric value
|
||||
bool toBool() const {PIString s(*this); if (atof(s.toNativeDecimalPoints().data()) > 0. || s.trimmed().toLowerCase() == "true" || s.trimmed().toLowerCase() == "on") return true; return false;}
|
||||
//! \brief Return \c true if string equal "true", "yes", "on" or positive not null numeric value
|
||||
bool toBool() const {PIString s(*this); if (atof(s.toNativeDecimalPoints().data()) > 0. || s.trimmed().toLowerCase() == "true" || s.trimmed().toLowerCase() == "yes" || s.trimmed().toLowerCase() == "on") return true; return false;}
|
||||
|
||||
//! \brief Return \c char numeric value of string
|
||||
char toChar() const;
|
||||
@@ -494,15 +500,15 @@ public:
|
||||
|
||||
//! \brief Return \c float numeric value of string
|
||||
//! \details Example: \snippet pistring.cpp PIString::toFloat
|
||||
float toFloat() const {PIString s(*this); return (float)atof(s.toNativeDecimalPoints().data());}
|
||||
float toFloat() const {return (float)atof(toNativeDecimalPoints().data());}
|
||||
|
||||
//! \brief Return \c double numeric value of string
|
||||
//! \details Example: \snippet pistring.cpp PIString::toFloat
|
||||
double toDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());}
|
||||
double toDouble() const {return atof(toNativeDecimalPoints().data());}
|
||||
|
||||
//! \brief Return \c ldouble numeric value of string
|
||||
//! \details Example: \snippet pistring.cpp PIString::toFloat
|
||||
ldouble toLDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());}
|
||||
ldouble toLDouble() const {return atof(toNativeDecimalPoints().data());}
|
||||
|
||||
//inline PIString & setNumber(const char value) {clear(); *this += itos(value); return *this;}
|
||||
|
||||
@@ -558,35 +564,35 @@ public:
|
||||
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const short value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
|
||||
static PIString fromNumber(const short value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
|
||||
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
|
||||
static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
|
||||
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
|
||||
static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
|
||||
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const uint value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
|
||||
static PIString fromNumber(const uint value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
|
||||
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const long value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
|
||||
static PIString fromNumber(const long value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
|
||||
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const ulong value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
|
||||
static PIString fromNumber(const ulong value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
|
||||
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const llong & value, int base = 10, bool * ok = 0) {return fromNumberBase(value, base, ok);}
|
||||
static PIString fromNumber(const llong & value, int base = 10, bool * ok = 0) {return fromNumberBaseS(value, base, ok);}
|
||||
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const ullong & value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
|
||||
static PIString fromNumber(const ullong & value, int base = 10, bool * ok = 0) {return fromNumberBaseU(value, base, ok);}
|
||||
|
||||
//! \brief Return string contains numeric representation of "value"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromFloat
|
||||
@@ -611,13 +617,15 @@ private:
|
||||
static const char toBaseN[];
|
||||
static const int fromBaseN[];
|
||||
|
||||
static PIString fromNumberBase(const llong value, int base = 10, bool * ok = 0) {
|
||||
static PIString fromNumberBaseS(const llong value, int base = 10, bool * ok = 0) {
|
||||
if (value == 0) return PIString("0");
|
||||
if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();}
|
||||
if (ok != 0) *ok = true;
|
||||
if (base == 10) return itos(value);
|
||||
PIString ret;
|
||||
llong v = value < 0 ? -value : value, cn, b = base;
|
||||
while (v >= base) {
|
||||
llong v = value < 0 ? -value : value, cn;
|
||||
int b = base;
|
||||
while (v >= llong(base)) {
|
||||
cn = v % b;
|
||||
v /= b;
|
||||
//cout << int(cn) << ", " << int(v) << endl;
|
||||
@@ -627,6 +635,23 @@ private:
|
||||
if (value < 0) ret.push_front('-');
|
||||
return ret;
|
||||
}
|
||||
static PIString fromNumberBaseU(const ullong value, int base = 10, bool * ok = 0) {
|
||||
if (value == 0) return PIString("0");
|
||||
if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();}
|
||||
if (ok != 0) *ok = true;
|
||||
if (base == 10) return itos(value);
|
||||
PIString ret;
|
||||
ullong v = value, cn;
|
||||
int b = base;
|
||||
while (v >= ullong(base)) {
|
||||
cn = v % b;
|
||||
v /= b;
|
||||
//cout << int(cn) << ", " << int(v) << endl;
|
||||
ret.push_front(PIChar(toBaseN[cn]));
|
||||
}
|
||||
if (v > 0) ret.push_front(PIChar(toBaseN[v]));
|
||||
return ret;
|
||||
}
|
||||
static llong toNumberBase(const PIString & value, int base = -1, bool * ok = 0) {
|
||||
PIString v = value.trimmed();
|
||||
if (base < 0) {
|
||||
|
||||
12
pithread.cpp
12
pithread.cpp
@@ -108,7 +108,11 @@ PIThread::~PIThread() {
|
||||
piMonitor.threads--;
|
||||
if (!running || thread == 0) return;
|
||||
#ifndef WINDOWS
|
||||
# ifdef ANDROID
|
||||
pthread_kill(thread, SIGSTOP);
|
||||
# else
|
||||
pthread_cancel(thread);
|
||||
# endif
|
||||
#else
|
||||
TerminateThread(thread, 0);
|
||||
CloseHandle(thread);
|
||||
@@ -169,7 +173,11 @@ void PIThread::terminate() {
|
||||
if (thread == 0) return;
|
||||
running = false;
|
||||
#ifndef WINDOWS
|
||||
# ifdef ANDROID
|
||||
pthread_kill(thread, SIGSTOP);
|
||||
# else
|
||||
pthread_cancel(thread);
|
||||
# endif
|
||||
#else
|
||||
TerminateThread(thread, 0);
|
||||
CloseHandle(thread);
|
||||
@@ -181,8 +189,10 @@ void PIThread::terminate() {
|
||||
|
||||
void * PIThread::thread_function(void * t) {
|
||||
#ifndef WINDOWS
|
||||
# ifndef ANDROID
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||
# endif
|
||||
#else
|
||||
__PISetTimerResolution();
|
||||
#endif
|
||||
@@ -212,8 +222,10 @@ void * PIThread::thread_function(void * t) {
|
||||
|
||||
void * PIThread::thread_function_once(void * t) {
|
||||
#ifndef WINDOWS
|
||||
# ifndef ANDROID
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||
# endif
|
||||
#else
|
||||
__PISetTimerResolution();
|
||||
#endif
|
||||
|
||||
@@ -708,7 +708,8 @@ PISystemTime currentSystemTime() {
|
||||
sft.dwHighDateTime++;
|
||||
} else
|
||||
sft.dwLowDateTime = ft.dwLowDateTime - __pi_ftjan1970.dwLowDateTime;
|
||||
return PISystemTime(sft.dwHighDateTime * 100 + sft.dwLowDateTime / 10000000, (sft.dwLowDateTime % 10000000) * 100);
|
||||
ullong lt = ullong(sft.dwHighDateTime) * 0x100000000U + ullong(sft.dwLowDateTime);
|
||||
return PISystemTime(lt / 10000000U, (lt % 10000000U) * 100U);
|
||||
//long t_cur = GetCurrentTime();
|
||||
//return PISystemTime(t_cur / 1000, (t_cur % 1000) * 1000000);
|
||||
#else
|
||||
|
||||
17
pitimer.h
17
pitimer.h
@@ -134,6 +134,9 @@ private:
|
||||
|
||||
};
|
||||
|
||||
//! \relatesalso PICout \relatesalso PIByteArray \brief Output operator to PICout
|
||||
inline PICout operator <<(PICout s, const PISystemTime & v) {s.setControl(0, true); s.space(); s << "(" << v.seconds << " s, " << v.nanoseconds << " ns)"; s.restoreControl(); return s;}
|
||||
|
||||
//! \relatesalso PISystemTime \relatesalso PIByteArray \brief Output operator to PIByteArray
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PISystemTime & v) {s << v.seconds << v.nanoseconds; return s;}
|
||||
|
||||
@@ -200,19 +203,7 @@ inline bool operator !=(const PIDateTime & t0, const PIDateTime & t1) {return !(
|
||||
inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);}
|
||||
inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);}
|
||||
|
||||
/// events:
|
||||
/// void timeout(void * data, int delimiter)
|
||||
///
|
||||
/// handlers:
|
||||
/// void start(double msecs)
|
||||
/// void deferredStart(double interval_msecs, double delay_msecs)
|
||||
/// void deferredStart(double interval_msecs, const PIDateTime & start_datetime)
|
||||
/// void stop()
|
||||
/// bool waitForFinish(int timeout_msecs = -1)
|
||||
/// void reset()
|
||||
/// void clearDelimiters()
|
||||
/// void lock()
|
||||
/// void unlock()
|
||||
|
||||
class PIP_EXPORT PITimer
|
||||
#ifndef PIP_TIMER_RT
|
||||
: public PIThread
|
||||
|
||||
@@ -166,7 +166,7 @@ uint PIVariant::variableSize(const PIVariant::Type & var) {
|
||||
}
|
||||
|
||||
|
||||
double PIVariant::variableValue(const char * var_ptr, const PIVariant::Type & var) {
|
||||
double PIVariant::variableValue(const void * var_ptr, const PIVariant::Type & var) {
|
||||
switch (var) {
|
||||
case PIVariant::Bool: return (double)(*((bool * )var_ptr));
|
||||
case PIVariant::Char: return (double)(*((char * )var_ptr));
|
||||
@@ -194,22 +194,22 @@ void PIVariable::setVariable(const PIString & str) {
|
||||
}
|
||||
|
||||
|
||||
void PIVariable::writeVariable(char * dest) {
|
||||
void PIVariable::writeVariable(void * dest) {
|
||||
switch (type_) {
|
||||
case PIVariant::Bool: *((bool * )((long)dest + offset)) = value_ > 0.; return;
|
||||
case PIVariant::Char: *((char * )((long)dest + offset)) = char(value_); return;
|
||||
case PIVariant::Short: *((short * )((long)dest + offset)) = short(value_); return;
|
||||
case PIVariant::Int: *((int * )((long)dest + offset)) = int(value_); return;
|
||||
case PIVariant::Long: *((long * )((long)dest + offset)) = long(value_); return;
|
||||
case PIVariant::LLong: *((llong * )((long)dest + offset)) = llong(value_); return;
|
||||
case PIVariant::UChar: *((uchar * )((long)dest + offset)) = uchar(value_); return;
|
||||
case PIVariant::UShort: *((ushort * )((long)dest + offset)) = ushort(value_); return;
|
||||
case PIVariant::UInt: *((uint * )((long)dest + offset)) = uint(value_); return;
|
||||
case PIVariant::ULong: *((ulong * )((long)dest + offset)) = ulong(value_); return;
|
||||
case PIVariant::ULLong: *((ullong * )((long)dest + offset)) = ullong(value_); return;
|
||||
case PIVariant::Float: *((float * )((long)dest + offset)) = float(value_); return;
|
||||
case PIVariant::Double: *((double * )((long)dest + offset)) = value_; return;
|
||||
case PIVariant::LDouble: *((ldouble * )((long)dest + offset)) = ldouble(value_); return;
|
||||
case PIVariant::Bool: *((bool * )((ullong)dest + offset)) = value_ > 0.; return;
|
||||
case PIVariant::Char: *((char * )((ullong)dest + offset)) = char(value_); return;
|
||||
case PIVariant::Short: *((short * )((ullong)dest + offset)) = short(value_); return;
|
||||
case PIVariant::Int: *((int * )((ullong)dest + offset)) = int(value_); return;
|
||||
case PIVariant::Long: *((long * )((ullong)dest + offset)) = long(value_); return;
|
||||
case PIVariant::LLong: *((llong * )((ullong)dest + offset)) = llong(value_); return;
|
||||
case PIVariant::UChar: *((uchar * )((ullong)dest + offset)) = uchar(value_); return;
|
||||
case PIVariant::UShort: *((ushort * )((ullong)dest + offset)) = ushort(value_); return;
|
||||
case PIVariant::UInt: *((uint * )((ullong)dest + offset)) = uint(value_); return;
|
||||
case PIVariant::ULong: *((ulong * )((ullong)dest + offset)) = ulong(value_); return;
|
||||
case PIVariant::ULLong: *((ullong * )((ullong)dest + offset)) = ullong(value_); return;
|
||||
case PIVariant::Float: *((float * )((ullong)dest + offset)) = float(value_); return;
|
||||
case PIVariant::Double: *((double * )((ullong)dest + offset)) = value_; return;
|
||||
case PIVariant::LDouble: *((ldouble * )((ullong)dest + offset)) = ldouble(value_); return;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@@ -236,13 +236,13 @@ void PIStruct::parseFile(const PIString & file) {
|
||||
}
|
||||
|
||||
|
||||
void PIStruct::readData(const char * data) {
|
||||
void PIStruct::readData(const void * data) {
|
||||
for (uint i = 0; i < vars.size(); ++i)
|
||||
vars[i].readVariable(data);
|
||||
}
|
||||
|
||||
|
||||
void PIStruct::writeData(char * data) {
|
||||
void PIStruct::writeData(void * data) {
|
||||
for (uint i = 0; i < vars.size(); ++i)
|
||||
vars[i].writeVariable(data);
|
||||
}
|
||||
|
||||
121
pivariable.h
121
pivariable.h
@@ -46,55 +46,55 @@ public:
|
||||
PIVariant(const PIString & v) {setValue(v);}
|
||||
PIVariant(const PIStringList & v) {setValue(v);}
|
||||
|
||||
inline void setValue(const char * v) {setValue(PIString(v));}
|
||||
inline void setValue(const bool & v) {type = PIVariant::Bool; vBool = v;}
|
||||
inline void setValue(const char & v) {type = PIVariant::Char; vChar = v;}
|
||||
inline void setValue(const short & v) {type = PIVariant::Short; vShort = v;}
|
||||
inline void setValue(const int & v) {type = PIVariant::Int; vInt = v;}
|
||||
inline void setValue(const long & v) {type = PIVariant::Long; vLong = v;}
|
||||
inline void setValue(const llong & v) {type = PIVariant::LLong; vLLong = v;}
|
||||
inline void setValue(const uchar & v) {type = PIVariant::UChar; vUChar = v;}
|
||||
inline void setValue(const ushort & v) {type = PIVariant::UShort; vUShort = v;}
|
||||
inline void setValue(const uint & v) {type = PIVariant::UInt; vUInt = v;}
|
||||
inline void setValue(const ulong & v) {type = PIVariant::ULong; vULong = v;}
|
||||
inline void setValue(const ullong & v) {type = PIVariant::ULLong; vULLong = v;}
|
||||
inline void setValue(const float & v) {type = PIVariant::Float; vFloat = v;}
|
||||
inline void setValue(const double & v) {type = PIVariant::Double; vDouble = v;}
|
||||
inline void setValue(const ldouble & v) {type = PIVariant::LDouble; vLDouble = v;}
|
||||
inline void setValue(const PIString & v) {type = PIVariant::String; vString = v;}
|
||||
inline void setValue(const PIStringList & v) {type = PIVariant::StringList; vStringList = v;}
|
||||
void setValue(const char * v) {setValue(PIString(v));}
|
||||
void setValue(const bool & v) {type = PIVariant::Bool; vBool = v;}
|
||||
void setValue(const char & v) {type = PIVariant::Char; vChar = v;}
|
||||
void setValue(const short & v) {type = PIVariant::Short; vShort = v;}
|
||||
void setValue(const int & v) {type = PIVariant::Int; vInt = v;}
|
||||
void setValue(const long & v) {type = PIVariant::Long; vLong = v;}
|
||||
void setValue(const llong & v) {type = PIVariant::LLong; vLLong = v;}
|
||||
void setValue(const uchar & v) {type = PIVariant::UChar; vUChar = v;}
|
||||
void setValue(const ushort & v) {type = PIVariant::UShort; vUShort = v;}
|
||||
void setValue(const uint & v) {type = PIVariant::UInt; vUInt = v;}
|
||||
void setValue(const ulong & v) {type = PIVariant::ULong; vULong = v;}
|
||||
void setValue(const ullong & v) {type = PIVariant::ULLong; vULLong = v;}
|
||||
void setValue(const float & v) {type = PIVariant::Float; vFloat = v;}
|
||||
void setValue(const double & v) {type = PIVariant::Double; vDouble = v;}
|
||||
void setValue(const ldouble & v) {type = PIVariant::LDouble; vLDouble = v;}
|
||||
void setValue(const PIString & v) {type = PIVariant::String; vString = v;}
|
||||
void setValue(const PIStringList & v) {type = PIVariant::StringList; vStringList = v;}
|
||||
void setValueOnly(const PIString & v);
|
||||
inline PIString typeName() const {return PIVariant::toString(type);}
|
||||
inline double doubleValue() const {return PIVariant::variableValue(&vChar, type);}
|
||||
PIString typeName() const {return PIVariant::toString(type);}
|
||||
double doubleValue() const {return PIVariant::variableValue(&vChar, type);}
|
||||
PIString stringValue() const;
|
||||
inline void typeFromString(const PIString & str) {type = PIVariant::fromString(str);}
|
||||
inline PIString typeToString() const {return PIVariant::toString(type);}
|
||||
inline uint size() {if (type != PIVariant::String && type != PIVariant::StringList) return PIVariant::variableSize(type); if (type == PIVariant::String) return vString.size(); else return vStringList.contentSize();}
|
||||
inline PIString writeToString() const {return typeName() + ":" + stringValue();}
|
||||
void typeFromString(const PIString & str) {type = PIVariant::fromString(str);}
|
||||
PIString typeToString() const {return PIVariant::toString(type);}
|
||||
uint size() {if (type != PIVariant::String && type != PIVariant::StringList) return PIVariant::variableSize(type); if (type == PIVariant::String) return vString.size(); else return vStringList.contentSize();}
|
||||
PIString writeToString() const {return typeName() + ":" + stringValue();}
|
||||
|
||||
#ifdef QNX
|
||||
inline void operator =(const PIVariant & v) {type = v.type; vLDouble = v.vLDouble; vString = v.vString; vStringList = v.vStringList;}
|
||||
void operator =(const PIVariant & v) {type = v.type; vLDouble = v.vLDouble; vString = v.vString; vStringList = v.vStringList;}
|
||||
#endif
|
||||
inline void operator =(const char * v) {setValue(PIString(v));}
|
||||
inline void operator =(const bool & v) {type = PIVariant::Bool; vBool = v;}
|
||||
inline void operator =(const char & v) {type = PIVariant::Char; vChar = v;}
|
||||
inline void operator =(const short & v) {type = PIVariant::Short; vShort = v;}
|
||||
inline void operator =(const int & v) {type = PIVariant::Int; vInt = v;}
|
||||
inline void operator =(const long & v) {type = PIVariant::Long; vLong = v;}
|
||||
inline void operator =(const llong & v) {type = PIVariant::LLong; vLLong = v;}
|
||||
inline void operator =(const uchar & v) {type = PIVariant::UChar; vUChar = v;}
|
||||
inline void operator =(const ushort & v) {type = PIVariant::UShort; vUShort = v;}
|
||||
inline void operator =(const uint & v) {type = PIVariant::UInt; vUInt = v;}
|
||||
inline void operator =(const ulong & v) {type = PIVariant::ULong; vULong = v;}
|
||||
inline void operator =(const ullong & v) {type = PIVariant::ULLong; vULLong = v;}
|
||||
inline void operator =(const float & v) {type = PIVariant::Float; vFloat = v;}
|
||||
inline void operator =(const double & v) {type = PIVariant::Double; vDouble = v;}
|
||||
inline void operator =(const ldouble & v) {type = PIVariant::LDouble; vLDouble = v;}
|
||||
inline void operator =(const PIString & v) {type = PIVariant::String; vString = v;}
|
||||
inline void operator =(const PIStringList & v) {type = PIVariant::StringList; vStringList = v;}
|
||||
void operator =(const char * v) {setValue(PIString(v));}
|
||||
void operator =(const bool & v) {type = PIVariant::Bool; vBool = v;}
|
||||
void operator =(const char & v) {type = PIVariant::Char; vChar = v;}
|
||||
void operator =(const short & v) {type = PIVariant::Short; vShort = v;}
|
||||
void operator =(const int & v) {type = PIVariant::Int; vInt = v;}
|
||||
void operator =(const long & v) {type = PIVariant::Long; vLong = v;}
|
||||
void operator =(const llong & v) {type = PIVariant::LLong; vLLong = v;}
|
||||
void operator =(const uchar & v) {type = PIVariant::UChar; vUChar = v;}
|
||||
void operator =(const ushort & v) {type = PIVariant::UShort; vUShort = v;}
|
||||
void operator =(const uint & v) {type = PIVariant::UInt; vUInt = v;}
|
||||
void operator =(const ulong & v) {type = PIVariant::ULong; vULong = v;}
|
||||
void operator =(const ullong & v) {type = PIVariant::ULLong; vULLong = v;}
|
||||
void operator =(const float & v) {type = PIVariant::Float; vFloat = v;}
|
||||
void operator =(const double & v) {type = PIVariant::Double; vDouble = v;}
|
||||
void operator =(const ldouble & v) {type = PIVariant::LDouble; vLDouble = v;}
|
||||
void operator =(const PIString & v) {type = PIVariant::String; vString = v;}
|
||||
void operator =(const PIStringList & v) {type = PIVariant::StringList; vStringList = v;}
|
||||
|
||||
bool operator ==(const PIVariant & v) const;
|
||||
inline bool operator !=(const PIVariant & v) const {return !(*this == v);}
|
||||
bool operator !=(const PIVariant & v) const {return !(*this == v);}
|
||||
|
||||
PIVariant::Type type;
|
||||
union {
|
||||
@@ -122,7 +122,7 @@ private:
|
||||
static PIVariant::Type fromString(const PIString & str);
|
||||
static PIString toString(const PIVariant::Type & var);
|
||||
static uint variableSize(const PIVariant::Type & var);
|
||||
static double variableValue(const char * var_ptr, const PIVariant::Type & var);
|
||||
static double variableValue(const void * var_ptr, const PIVariant::Type & var);
|
||||
|
||||
};
|
||||
|
||||
@@ -135,14 +135,14 @@ public:
|
||||
~PIVariable() {;}
|
||||
|
||||
void setVariable(const PIString & str);
|
||||
void writeVariable(char * dest);
|
||||
inline void readVariable(const char * var_ptr) {value_ = PIVariant::variableValue((char * )((long)var_ptr + offset), type_);}
|
||||
inline PIVariant::Type type() const {return type_;}
|
||||
inline uint size() const {return size_;}
|
||||
inline const PIString & name() {return name_;}
|
||||
inline void setName(const PIString & str) {name_ = str;}
|
||||
inline double value() const {return value_;}
|
||||
inline void setValue(const double & val) {value_ = val;}
|
||||
void writeVariable(void * dest);
|
||||
void readVariable(const void * var_ptr) {value_ = PIVariant::variableValue((char * )((long)var_ptr + offset), type_);}
|
||||
PIVariant::Type type() const {return type_;}
|
||||
uint size() const {return size_;}
|
||||
const PIString & name() {return name_;}
|
||||
void setName(const PIString & str) {name_ = str;}
|
||||
double value() const {return value_;}
|
||||
void setValue(const double & val) {value_ = val;}
|
||||
|
||||
int offset;
|
||||
|
||||
@@ -175,19 +175,20 @@ public:
|
||||
PIStruct(const PIString & str) {parseFile(str);}
|
||||
|
||||
void parseFile(const PIString & file);
|
||||
void readData(const char * data);
|
||||
void writeData(char * data);
|
||||
inline void clear() {vars.clear(); size_ = 0;}
|
||||
inline uint count() const {return vars.size();}
|
||||
inline uint size() const {return size_;}
|
||||
inline const PIString & name() {return name_;}
|
||||
inline void setName(const PIString & str) {name_ = str;}
|
||||
inline PIVariable & operator[](const uint & index) {return vars[index];}
|
||||
inline PIVariable & operator[](const PIString & name) {for (uint i = 0; i < vars.size(); ++i) if (vars[i].name() == name) return vars[i];}
|
||||
void readData(const void * data);
|
||||
void writeData(void * data);
|
||||
void clear() {vars.clear(); size_ = 0;}
|
||||
uint count() const {return vars.size();}
|
||||
uint size() const {return size_;}
|
||||
const PIString & name() {return name_;}
|
||||
void setName(const PIString & str) {name_ = str;}
|
||||
PIVariable & operator[](const uint & index) {return vars[index];}
|
||||
PIVariable & operator[](const PIString & name) {for (uint i = 0; i < vars.size(); ++i) if (vars[i].name() == name) return vars[i]; return def;}
|
||||
|
||||
private:
|
||||
uint size_;
|
||||
PIString name_;
|
||||
PIVariable def;
|
||||
PIVector<PIVariable> vars;
|
||||
|
||||
};
|
||||
|
||||
439
pivector.h
Normal file
439
pivector.h
Normal file
@@ -0,0 +1,439 @@
|
||||
/*! \file picontainers.h
|
||||
* \brief Dynamic array of any type
|
||||
*
|
||||
* This file declare PIVector
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Dynamic array of any type
|
||||
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 PIVECTOR_H
|
||||
#define PIVECTOR_H
|
||||
|
||||
#include "piincludes.h"
|
||||
|
||||
|
||||
#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN)
|
||||
|
||||
|
||||
template <typename T>
|
||||
class PIVector {
|
||||
public:
|
||||
PIVector(): __piv_data__(0), __piv_size__(0), __piv_rsize__(0) {
|
||||
//printf("new vector 1 %p (%s) ... !{\n", this, typeid(T).name());
|
||||
//printf("(s=%d, d=%p) }!\n", int(__piv_size__), __piv_data__);
|
||||
}
|
||||
PIVector(const PIVector<T> & other): __piv_data__(0), __piv_size__(0), __piv_rsize__(0) {
|
||||
//printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name());
|
||||
alloc(other.__piv_size__);
|
||||
for (ullong i = 0; i < __piv_size__; ++i)
|
||||
new(__piv_data__ + i)T(other.__piv_data__[i]);
|
||||
//printf("(s=%d, d=%p) }!\n", int(__piv_size__), __piv_data__);
|
||||
}
|
||||
PIVector(ullong __piv_size__, const T & f = T()): __piv_data__(0), __piv_size__(0), __piv_rsize__(0) {
|
||||
//printf("new vector 3 %p (%s) ... !{\n", this, typeid(T).name());
|
||||
resize(__piv_size__, f);
|
||||
//printf("(s=%d, d=%p) }!\n", int(__piv_size__), __piv_data__);
|
||||
}
|
||||
~PIVector() {
|
||||
//printf("delete vector %p (%s) (s=%d, d=%p) ... ~{\n", this, typeid(T).name(), int(__piv_size__), __piv_data__);
|
||||
deleteT(__piv_data__, __piv_size__);
|
||||
dealloc();
|
||||
_reset();
|
||||
//printf("}~\n");
|
||||
}
|
||||
|
||||
PIVector<T> & operator =(const PIVector<T> & other) {
|
||||
if (this == &other) return *this;
|
||||
bool tj, oj;
|
||||
tj = (__piv_size__ != 0 && __piv_data__ == 0);// || (__piv_size__ == 0 && __piv_data__ != 0);
|
||||
oj = (other.__piv_size__ != 0 && other.__piv_data__ == 0);// || (other.__piv_size__ == 0 && other.__piv_data__ != 0);
|
||||
//printf("operator= (%p = %p) (s=%d, d=%p, o.s=%d, o.d=%p) (%d, %d) ... o[\n", this, &other, int(__piv_size__), __piv_data__, int(other.__piv_size__), other.__piv_data__, int(tj), int(oj));
|
||||
if (tj) {
|
||||
printf("JUNK this\n");
|
||||
_reset();
|
||||
} else {
|
||||
clear();
|
||||
}
|
||||
/*if (__piv_size__ == other.__piv_size__) {
|
||||
for (ullong i = 0; i < __piv_size__; ++i)
|
||||
__piv_data__[i] = other.__piv_data__[i];
|
||||
return *this;
|
||||
}*/
|
||||
if (!oj) {
|
||||
alloc(other.__piv_size__);
|
||||
//zeroRaw(__piv_data__, __piv_size__);
|
||||
for (ullong i = 0; i < __piv_size__; ++i)
|
||||
new(__piv_data__ + i)T(other.__piv_data__[i]); //__piv_data__[i] = other.__piv_data__[i];
|
||||
} else {
|
||||
printf("JUNK other\n");
|
||||
}
|
||||
//printf("o]\n");
|
||||
return *this;
|
||||
}
|
||||
|
||||
typedef T value_type;
|
||||
|
||||
class iterator {
|
||||
friend class PIVector<T>;
|
||||
private:
|
||||
iterator(PIVector<T> * v, ullong p): parent(v), pos(p) {}
|
||||
PIVector<T> * parent;
|
||||
ullong pos;
|
||||
public:
|
||||
iterator(): parent(0) {}
|
||||
T & operator *() {return (*parent)[pos];}
|
||||
const T & operator *() const {return (*parent)[pos];}
|
||||
void operator ++() {++pos;}
|
||||
void operator ++(int) {++pos;}
|
||||
void operator --() {--pos;}
|
||||
void operator --(int) {--pos;}
|
||||
bool operator ==(const iterator & it) const {return (pos == it.pos);}
|
||||
bool operator !=(const iterator & it) const {return (pos != it.pos);}
|
||||
};
|
||||
|
||||
class const_iterator {
|
||||
friend class PIVector<T>;
|
||||
private:
|
||||
const_iterator(const PIVector<T> * v, ullong p): parent(v), pos(p) {}
|
||||
const PIVector<T> * parent;
|
||||
ullong pos;
|
||||
public:
|
||||
const_iterator(): parent(0) {}
|
||||
//T & operator *() {return (*parent)[pos];}
|
||||
const T & operator *() const {return (*parent)[pos];}
|
||||
void operator ++() {++pos;}
|
||||
void operator ++(int) {++pos;}
|
||||
void operator --() {--pos;}
|
||||
void operator --(int) {--pos;}
|
||||
bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
|
||||
bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
|
||||
};
|
||||
|
||||
class reverse_iterator {
|
||||
friend class PIVector<T>;
|
||||
private:
|
||||
reverse_iterator(PIVector<T> * v, ullong p): parent(v), pos(p) {}
|
||||
PIVector<T> * parent;
|
||||
ullong pos;
|
||||
public:
|
||||
reverse_iterator(): parent(0) {}
|
||||
T & operator *() {return (*parent)[pos];}
|
||||
const T & operator *() const {return (*parent)[pos];}
|
||||
void operator ++() {--pos;}
|
||||
void operator ++(int) {--pos;}
|
||||
void operator --() {++pos;}
|
||||
void operator --(int) {++pos;}
|
||||
bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);}
|
||||
bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);}
|
||||
};
|
||||
|
||||
class const_reverse_iterator {
|
||||
friend class PIVector<T>;
|
||||
private:
|
||||
const_reverse_iterator(const PIVector<T> * v, ullong p): parent(v), pos(p) {}
|
||||
const PIVector<T> * parent;
|
||||
ullong pos;
|
||||
public:
|
||||
const_reverse_iterator(): parent(0) {}
|
||||
//T & operator *() {return (*parent)[pos];}
|
||||
const T & operator *() const {return (*parent)[pos];}
|
||||
void operator ++() {--pos;}
|
||||
void operator ++(int) {--pos;}
|
||||
void operator --() {++pos;}
|
||||
void operator --(int) {++pos;}
|
||||
bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
|
||||
bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
|
||||
};
|
||||
|
||||
iterator begin() {return iterator(this, 0);}
|
||||
iterator end() {return iterator(this, __piv_size__);}
|
||||
const_iterator begin() const {return const_iterator(this, 0);}
|
||||
const_iterator end() const {return const_iterator(this, __piv_size__);}
|
||||
reverse_iterator rbegin() {return reverse_iterator(this, __piv_size__ - 1);}
|
||||
reverse_iterator rend() {return reverse_iterator(this, -1);}
|
||||
const_reverse_iterator rbegin() const {return const_reverse_iterator(this, __piv_size__ - 1);}
|
||||
const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
|
||||
|
||||
ullong size() const {return __piv_size__;}
|
||||
int size_s() const {return __piv_size__;}
|
||||
ullong length() const {return __piv_size__;}
|
||||
bool isEmpty() const {return (__piv_size__ == 0);}
|
||||
|
||||
T & operator [](ullong index) {return __piv_data__[index];}
|
||||
T & at(ullong index) {return __piv_data__[index];}
|
||||
const T & operator [](ullong index) const {return __piv_data__[index];}
|
||||
const T & at(ullong index) const {return __piv_data__[index];}
|
||||
T & back() {return __piv_data__[__piv_size__ - 1];}
|
||||
const T & back() const {return __piv_data__[__piv_size__ - 1];}
|
||||
T & front() {return __piv_data__[0];}
|
||||
const T & front() const {return __piv_data__[0];}
|
||||
bool operator ==(const PIVector<T> & t) const {if (__piv_size__ != t.__piv_size__) return false; for (ullong i = 0; i < __piv_size__; ++i) if (t[i] != __piv_data__[i]) return false; return true;}
|
||||
bool operator !=(const PIVector<T> & t) const {if (__piv_size__ != t.__piv_size__) return true; for (ullong i = 0; i < __piv_size__; ++i) if (t[i] != __piv_data__[i]) return true; return false;}
|
||||
bool contains(const T & v) const {for (ullong i = 0; i < __piv_size__; ++i) if (v == __piv_data__[i]) return true; return false;}
|
||||
int etries(const T & v) const {int ec = 0; for (ullong i = 0; i < __piv_size__; ++i) if (v == __piv_data__[i]) ++ec; return ec;}
|
||||
|
||||
T * data(ullong index = 0) {return &(__piv_data__[index]);}
|
||||
const T * data(ullong index = 0) const {return &(__piv_data__[index]);}
|
||||
PIVector<T> & clear() {resize(0); return *this;}
|
||||
PIVector<T> & fill(const T & f = T()) {
|
||||
//if (sizeof(T) == 1) memset(__piv_data__, f, __piv_size__);
|
||||
deleteT(__piv_data__, __piv_size__);
|
||||
//zeroRaw(__piv_data__, __piv_size__);
|
||||
for (ullong i = 0; i < __piv_size__; ++i)
|
||||
new(__piv_data__ + i)T(f);
|
||||
return *this;
|
||||
}
|
||||
PIVector<T> & assign(const T & f = T()) {return fill(f);}
|
||||
PIVector<T> & resize(ullong new_size, const T & f = T()) {
|
||||
if (new_size < __piv_size__) {
|
||||
T * de = &(__piv_data__[new_size]);
|
||||
deleteT(de, __piv_size__ - new_size);
|
||||
__piv_size__ = new_size;
|
||||
}
|
||||
if (new_size > __piv_size__) {
|
||||
ullong os = __piv_size__;
|
||||
alloc(new_size);
|
||||
//if (sizeof(T) == 1) memset(&(__piv_data__[os]), f, ds);
|
||||
//zeroRaw(&(__piv_data__[os]), new_size - os);
|
||||
for (ullong i = os; i < new_size; ++i) new(__piv_data__ + i)T(f);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
PIVector<T> & reserve(ullong new_size) {if (new_size <= __piv_rsize__) return *this; ullong os = __piv_size__; alloc(new_size); __piv_size__ = os; return *this;}
|
||||
|
||||
PIVector<T> & insert(ullong index, const T & v = T()) {
|
||||
alloc(__piv_size__ + 1);
|
||||
if (index < __piv_size__ - 1) {
|
||||
ullong os = __piv_size__ - index - 1;
|
||||
T * pd = newRaw(os);
|
||||
memcpy(pd, &(__piv_data__[index]), os * sizeof(T));
|
||||
memcpy(&(__piv_data__[index + 1]), pd, os * sizeof(T));
|
||||
deleteRaw(pd);
|
||||
}
|
||||
//zeroRaw(&(__piv_data__[index]), 1);
|
||||
new(__piv_data__ + index)T(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PIVector<T> & remove(ullong index, ullong count = 1) {
|
||||
if (index + count >= __piv_size__) {
|
||||
resize(index);
|
||||
return *this;
|
||||
}
|
||||
ullong os = __piv_size__ - index - count;
|
||||
T * pd = newRaw(os), * de = &(__piv_data__[index]);
|
||||
deleteT(de, count);
|
||||
memcpy(pd, &(__piv_data__[index + count]), os * sizeof(T));
|
||||
memcpy(&(__piv_data__[index]), pd, os * sizeof(T));
|
||||
deleteRaw(pd);
|
||||
__piv_size__ -= count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(PIVector<T> & other) {
|
||||
piSwap<T*>(__piv_data__, other.__piv_data__);
|
||||
piSwap<ullong>(__piv_size__, other.__piv_size__);
|
||||
piSwap<ullong>(__piv_rsize__, other.__piv_rsize__);
|
||||
}
|
||||
|
||||
typedef int (*CompareFunc)(const T * , const T * );
|
||||
static int compare_func(const T * t0, const T * t1) {return (*t0) == (*t1) ? 0 : ((*t0) < (*t1) ? -1 : 1);}
|
||||
PIVector<T> & sort(CompareFunc compare = compare_func) {qsort(__piv_data__, __piv_size__, sizeof(T), (int(*)(const void * , const void * ))compare); return *this;}
|
||||
|
||||
PIVector<T> & enlarge(llong __piv_size__) {llong ns = size_s() + __piv_size__; if (ns <= 0) clear(); else resize(ullong(ns)); return *this;}
|
||||
|
||||
PIVector<T> & removeOne(const T & v) {for (ullong i = 0; i < __piv_size__; ++i) if (__piv_data__[i] == v) {remove(i); return *this;} return *this;}
|
||||
PIVector<T> & removeAll(const T & v) {for (ullong i = 0; i < __piv_size__; ++i) if (__piv_data__[i] == v) {remove(i); --i;} return *this;}
|
||||
|
||||
PIVector<T> & push_back(const T & v) {alloc(__piv_size__ + 1); new(__piv_data__ + __piv_size__ - 1)T(v); return *this;}
|
||||
PIVector<T> & append(const T & v) {return push_back(v);}
|
||||
PIVector<T> & operator <<(const T & v) {return push_back(v);}
|
||||
|
||||
PIVector<T> & push_front(const T & v) {insert(0, v); return *this;}
|
||||
PIVector<T> & prepend(const T & v) {return push_front(v);}
|
||||
|
||||
PIVector<T> & pop_back() {if (__piv_size__ == 0) return *this; resize(__piv_size__ - 1); return *this;}
|
||||
PIVector<T> & pop_front() {if (__piv_size__ == 0) return *this; remove(0); return *this;}
|
||||
|
||||
T take_back() {T t(back()); pop_back(); return t;}
|
||||
T take_front() {T t(front()); pop_front(); return t;}
|
||||
|
||||
private:
|
||||
void _reset() {__piv_size__ = __piv_rsize__ = 0; __piv_data__ = 0;}
|
||||
ullong asize(ullong s) {
|
||||
if (s == 0) return 0;
|
||||
if (__piv_rsize__ + __piv_rsize__ >= s && __piv_rsize__ < s)
|
||||
return __piv_rsize__ + __piv_rsize__;
|
||||
ullong t = 0, s_ = s - 1;
|
||||
while (s_ >> t) ++t;
|
||||
return (1 << t);
|
||||
}
|
||||
T * newRaw(ullong s) {
|
||||
//cout << std::dec << " ![("<<this<<")newRaw " << s << " elements ... <\n" << endl;
|
||||
//uchar * ret = new uchar[s * sizeof(T)];
|
||||
uchar * ret = (uchar*)(malloc(s * sizeof(T)));//new uchar[];
|
||||
//zeroRaw((T*)ret, s);
|
||||
//cout << std::hex << " > (new 0x" << (llong)ret << ") ok]!" << endl;
|
||||
return (T*)ret;
|
||||
}
|
||||
void deleteT(T * d, ullong sz) {
|
||||
//cout << " ~[("<<this<<")deleteT " << std::dec << sz << " elements " << std::hex << "0x" << (llong)d << " ... <\n" << endl;
|
||||
if ((uchar*)d != 0) {
|
||||
for (ullong i = 0; i < sz; ++i)
|
||||
d[i].~T();
|
||||
//zeroRaw(d, sz);
|
||||
}
|
||||
//cout << " > ok]~" << endl;
|
||||
}
|
||||
void deleteRaw(T *& d) {
|
||||
//cout << " ~[("<<this<<")deleteRaw " << std::dec << __piv_rsize__ << " elements " << std::hex << "0x" << (llong)d << " ... <\n" << endl;
|
||||
if ((uchar*)d != 0) free((uchar*)d);
|
||||
d = 0;
|
||||
//cout << " > ok]~" << endl;
|
||||
}
|
||||
void zeroRaw(T * d, ullong s) {
|
||||
//cout << " ~[("<<this<<")zeroRaw " << std::dec << s << " elements " << std::hex << "0x" << (llong)d << " ... <\n" << endl;
|
||||
if ((uchar*)d != 0) memset(d, 0, s*sizeof(T));
|
||||
//cout << " > ok]~" << endl;
|
||||
}
|
||||
void dealloc() {deleteRaw(__piv_data__);}
|
||||
void alloc(ullong new_size) {
|
||||
if (new_size <= __piv_rsize__) {
|
||||
__piv_size__ = new_size;
|
||||
return;
|
||||
}
|
||||
//int os = __piv_size__;
|
||||
__piv_size__ = new_size;
|
||||
ullong as = asize(new_size);
|
||||
if (as == __piv_rsize__) return;
|
||||
|
||||
//cout << std::hex << " ![("<<this<<")realloc " << __piv_data__ << " data ... <\n" << endl;
|
||||
__piv_data__ = (T*)(realloc(__piv_data__, as*sizeof(T)));
|
||||
//zeroRaw(&(__piv_data__[os]), as - os);
|
||||
__piv_rsize__ = as;
|
||||
//cout << std::hex << " > (new 0x" << (llong)__piv_data__ << ") ok]!" << endl;
|
||||
/*__piv_rsize__ = as;
|
||||
T * pd = newRaw(__piv_rsize__);
|
||||
if (os > 0 && __piv_data__ != 0) {
|
||||
memcpy(pd, __piv_data__, os * sizeof(T));
|
||||
deleteRaw(__piv_data__);
|
||||
}
|
||||
__piv_data__ = pd;*/
|
||||
}
|
||||
|
||||
T * __piv_data__;
|
||||
ullong __piv_size__, __piv_rsize__;
|
||||
};
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
template<typename T, typename Allocator = std::allocator<T> >
|
||||
class PIP_EXPORT PIVector: public vector<T, Allocator> {
|
||||
typedef PIVector<T, Allocator> _CVector;
|
||||
typedef vector<T, Allocator> _stlc;
|
||||
public:
|
||||
|
||||
PIVector() {piMonitor.containers++;}
|
||||
PIVector(uint size, const T & value = T()) {piMonitor.containers++; _stlc::resize(size, value);}
|
||||
~PIVector() {piMonitor.containers--;}
|
||||
|
||||
const T & at(uint index) const {return (*this)[index];}
|
||||
T & at(uint index) {return (*this)[index];}
|
||||
const T * data(uint index = 0) const {return &(*this)[index];}
|
||||
T * data(uint index = 0) {return &(*this)[index];}
|
||||
|
||||
#ifdef DOXYGEN
|
||||
uint size() const;
|
||||
#endif
|
||||
|
||||
int size_s() const {return static_cast<int>(_stlc::size());}
|
||||
bool isEmpty() const {return _stlc::empty();}
|
||||
bool has(const T & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;}
|
||||
int etries(const T & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;}
|
||||
|
||||
typedef int (*CompareFunc)(const T * , const T * );
|
||||
|
||||
static int compare_func(const T * t0, const T * t1) {return (*t0) == (*t1) ? 0 : ((*t0) < (*t1) ? -1 : 1);}
|
||||
#ifdef DOXYGEN
|
||||
|
||||
void resize(uint size, const T & new_type = T());
|
||||
PIVector<T, Allocator> & enlarge(uint size);
|
||||
void clear();
|
||||
PIVector<T, Allocator> & sort(CompareFunc compare = compare_func) {qsort(&at(0), _stlc::size(), sizeof(T), (int(*)(const void * , const void * ))compare); return *this;}
|
||||
PIVector<T, Allocator> & fill(const T & t) {_stlc::assign(_stlc::size(), t); return *this;}
|
||||
T & back();
|
||||
const T & back() const;
|
||||
T & front();
|
||||
const T & front() const;
|
||||
PIVector<T, Allocator> & push_back(const T & t);
|
||||
PIVector<T, Allocator> & push_front(const T & t) {_stlc::insert(_stlc::begin(), t); return *this;}
|
||||
PIVector<T, Allocator> & pop_back();
|
||||
PIVector<T, Allocator> & pop_front() {_stlc::erase(_stlc::begin()); return *this;}
|
||||
T take_back() {T t(_stlc::back()); _stlc::pop_back(); return t;}
|
||||
T take_front() {T t(_stlc::front()); pop_front(); return t;}
|
||||
PIVector<T, Allocator> & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
|
||||
PIVector<T, Allocator> & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
|
||||
PIVector<T, Allocator> & removeOne(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;}
|
||||
PIVector<T, Allocator> & removeAll(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;}
|
||||
PIVector<T, Allocator> & insert(uint pos, const T & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
|
||||
PIVector<T, Allocator> & insert(uint pos, const PIVector<T, Allocator> & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;}
|
||||
T & operator [](uint index);
|
||||
const T & operator [](uint index) const;
|
||||
PIVector<T, Allocator> & operator <<(const T & t) {_stlc::push_back(t); return *this;}
|
||||
PIVector<T, Allocator> & operator <<(const PIVector<T, Allocator> & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
|
||||
bool operator ==(const PIVector<T, Allocator> & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;}
|
||||
bool operator !=(const PIVector<T, Allocator> & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;}
|
||||
bool contains(const T & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
|
||||
|
||||
#else
|
||||
_CVector & enlarge(int size_) {int ns = size_s() + size_; if (ns <= 0) _stlc::clear(); else _stlc::resize(ns); return *this;}
|
||||
_CVector & sort(CompareFunc compare = compare_func) {qsort(&at(0), _stlc::size(), sizeof(T), (int(*)(const void * , const void * ))compare); return *this;}
|
||||
_CVector & fill(const T & t) {_stlc::assign(_stlc::size(), t); return *this;}
|
||||
_CVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;}
|
||||
_CVector & push_front(const T & t) {_stlc::insert(_stlc::begin(), t); return *this;}
|
||||
T take_front() {T t(_stlc::front()); pop_front(); return t;}
|
||||
T take_back() {T t(_stlc::back()); _stlc::pop_back(); return t;}
|
||||
_CVector & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
|
||||
_CVector & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
|
||||
_CVector & removeOne(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;}
|
||||
_CVector & removeAll(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;}
|
||||
_CVector & insert(uint pos, const T & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
|
||||
_CVector & insert(uint pos, const _CVector & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;}
|
||||
_CVector & operator <<(const T & t) {_stlc::push_back(t); return *this;}
|
||||
_CVector & operator <<(const _CVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
|
||||
bool operator ==(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;}
|
||||
bool operator !=(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;}
|
||||
bool contains(const T & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIVector<T> & v) {s << "{"; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;}
|
||||
|
||||
template<typename T>
|
||||
inline PICout operator <<(PICout s, const PIVector<T> & v) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;}
|
||||
|
||||
|
||||
#endif // PIVECTOR_H
|
||||
Reference in New Issue
Block a user