Initial commit based on common repo commit ffeb9c9b
This commit is contained in:
		
							
								
								
									
										13
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					/*.config
 | 
				
			||||||
 | 
					/*.creator
 | 
				
			||||||
 | 
					/*.files
 | 
				
			||||||
 | 
					/*.includes
 | 
				
			||||||
 | 
					/*.user
 | 
				
			||||||
 | 
					*.pyc
 | 
				
			||||||
 | 
					nbproject
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					*bower*
 | 
				
			||||||
 | 
					CMakeCache.txt
 | 
				
			||||||
 | 
					CMakeFiles/
 | 
				
			||||||
 | 
					.idea/
 | 
				
			||||||
 | 
					.sass-cache/
 | 
				
			||||||
							
								
								
									
										26
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					PROJECT(LIBCAPS)
 | 
				
			||||||
 | 
					CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Modules)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FIND_PACKAGE(Boost REQUIRED)
 | 
				
			||||||
 | 
					FIND_PACKAGE(OpenSSL REQUIRED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INCLUDE_DIRECTORIES(libs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ADD_DEFINITIONS("-DCAPS_FEATURES_ANY=0")
 | 
				
			||||||
 | 
					#ADD_DEFINITIONS("-DCAPS_FEATURES_MSEED=0")
 | 
				
			||||||
 | 
					#ADD_DEFINITIONS("-DCAPS_FEATURES_RAW=0")
 | 
				
			||||||
 | 
					#ADD_DEFINITIONS("-DCAPS_FEATURES_FIXED_RAW=0")
 | 
				
			||||||
 | 
					#ADD_DEFINITIONS("-DCAPS_FEATURES_RTCM2=0")
 | 
				
			||||||
 | 
					#ADD_DEFINITIONS("-DCAPS_FEATURES_BACKFILLING=0")
 | 
				
			||||||
 | 
					#ADD_DEFINITIONS("-DCAPS_FEATURES_JOURNAL=0")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OPTION(LIBCAPS_PYTHON_WRAPPER "Create Python wrappers" ON)
 | 
				
			||||||
 | 
					OPTION(LIBCAPS_EXAMPLES "Build and install example applications" OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SUBDIRS(libs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(LIBCAPS_EXAMPLES)
 | 
				
			||||||
 | 
						SUBDIRS(examples)
 | 
				
			||||||
 | 
					ENDIF()
 | 
				
			||||||
							
								
								
									
										341
									
								
								Modules/FindBoost.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										341
									
								
								Modules/FindBoost.cmake
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,341 @@
 | 
				
			|||||||
 | 
					# - Find the Boost includes and libraries.
 | 
				
			||||||
 | 
					# The following variables are set if Boost is found.  If Boost is not
 | 
				
			||||||
 | 
					# found, Boost_FOUND is set to false.
 | 
				
			||||||
 | 
					#  Boost_FOUND                  - True when the Boost include directory is found.
 | 
				
			||||||
 | 
					#  Boost_INCLUDE_DIRS           - the path to where the boost include files are.
 | 
				
			||||||
 | 
					#  Boost_LIBRARY_DIRS           - The path to where the boost library files are.
 | 
				
			||||||
 | 
					#  Boost_LIB_DIAGNOSTIC_DEFINITIONS - Only set if using Windows.
 | 
				
			||||||
 | 
					#  Boost_<library>_FOUND        - True if the Boost <library> is found.
 | 
				
			||||||
 | 
					#  Boost_<library>_INCLUDE_DIRS - The include path for Boost <library>.
 | 
				
			||||||
 | 
					#  Boost_<library>_LIBRARIES    - The libraries to link to to use Boost <library>.
 | 
				
			||||||
 | 
					#  Boost_LIBRARIES              - The libraries to link to to use all Boost libraries.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The following variables can be set to configure how Boost is found:
 | 
				
			||||||
 | 
					#  Boost_LIB_PREFIX             - Look for Boost libraries prefixed with this, e.g. "lib"
 | 
				
			||||||
 | 
					#  Boost_LIB_SUFFIX             - Look for Boost libraries ending with this, e.g. "vc80-mt"
 | 
				
			||||||
 | 
					#  Boost_LIB_SUFFIX_DEBUG       - As for Boost_LIB_SUFFIX but for debug builds, e.g. "vs80-mt-gd"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# If you have installed Boost in a non-standard location or you have
 | 
				
			||||||
 | 
					# just staged the boost files using bjam then you have three
 | 
				
			||||||
 | 
					# options. In the following comments, it is assumed that <Your Path>
 | 
				
			||||||
 | 
					# points to the root directory of the include directory of Boost. e.g
 | 
				
			||||||
 | 
					# If you have put boost in C:\development\Boost then <Your Path> is
 | 
				
			||||||
 | 
					# "C:/development/Boost" and in this directory there will be two
 | 
				
			||||||
 | 
					# directories called "include" and "lib".
 | 
				
			||||||
 | 
					# 1) After CMake runs, set Boost_INCLUDE_DIR to <Your Path>/include/boost<-version>
 | 
				
			||||||
 | 
					# 2) Use CMAKE_INCLUDE_PATH to set a path to <Your Path>/include. This will allow FIND_PATH()
 | 
				
			||||||
 | 
					#    to locate Boost_INCLUDE_DIR by utilizing the PATH_SUFFIXES option. e.g.
 | 
				
			||||||
 | 
					#    SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "<Your Path>/include")
 | 
				
			||||||
 | 
					# 3) Set an environment variable called ${BOOST_ROOT} that points to the root of where you have
 | 
				
			||||||
 | 
					#    installed Boost, e.g. <Your Path>. It is assumed that there is at least a subdirectory called
 | 
				
			||||||
 | 
					#    include in this path.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Note:
 | 
				
			||||||
 | 
					#  1) If you are just using the boost headers, then you do not need to use
 | 
				
			||||||
 | 
					#     Boost_LIBRARY_DIRS in your CMakeLists.txt file.
 | 
				
			||||||
 | 
					#  2) If Boost has not been installed, then when setting Boost_LIBRARY_DIRS
 | 
				
			||||||
 | 
					#     the script will look for /lib first and, if this fails, then for /stage/lib.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Usage:
 | 
				
			||||||
 | 
					# In your CMakeLists.txt file do something like this:
 | 
				
			||||||
 | 
					# ...
 | 
				
			||||||
 | 
					# # Boost
 | 
				
			||||||
 | 
					# FIND_PACKAGE(Boost)
 | 
				
			||||||
 | 
					# ...
 | 
				
			||||||
 | 
					# INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
 | 
				
			||||||
 | 
					# LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# In Windows, we make the assumption that, if the Boost files are installed, the default directory
 | 
				
			||||||
 | 
					# will be C:\boost.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# TODO:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 1) Automatically find the Boost library files and eliminate the need
 | 
				
			||||||
 | 
					#    to use Link Directories.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(WIN32)
 | 
				
			||||||
 | 
					  # In windows, automatic linking is performed, so you do not have to specify the libraries.
 | 
				
			||||||
 | 
					  # If you are linking to a dynamic runtime, then you can choose to link to either a static or a
 | 
				
			||||||
 | 
					  # dynamic Boost library, the default is to do a static link.  You can alter this for a specific
 | 
				
			||||||
 | 
					  # library "whatever" by defining BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to
 | 
				
			||||||
 | 
					  # be linked dynamically.  Alternatively you can force all Boost libraries to dynamic link by
 | 
				
			||||||
 | 
					  # defining BOOST_ALL_DYN_LINK.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # This feature can be disabled for Boost library "whatever" by defining BOOST_WHATEVER_NO_LIB,
 | 
				
			||||||
 | 
					  # or for all of Boost by defining BOOST_ALL_NO_LIB.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # If you want to observe which libraries are being linked against then defining
 | 
				
			||||||
 | 
					  # BOOST_LIB_DIAGNOSTIC will cause the auto-linking code to emit a #pragma message each time
 | 
				
			||||||
 | 
					  # a library is selected for linking.
 | 
				
			||||||
 | 
					  SET(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC")
 | 
				
			||||||
 | 
					ENDIF(WIN32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET(BOOST_INCLUDE_PATH_DESCRIPTION "directory containing the boost include files. E.g /usr/local/include/boost-1_33_1 or c:\\boost\\include\\boost-1_33_1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET(BOOST_DIR_MESSAGE "Set the Boost_INCLUDE_DIR cmake cache entry to the ${BOOST_INCLUDE_PATH_DESCRIPTION}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET(BOOST_DIR_SEARCH $ENV{BOOST_ROOT})
 | 
				
			||||||
 | 
					IF(BOOST_DIR_SEARCH)
 | 
				
			||||||
 | 
					  FILE(TO_CMAKE_PATH ${BOOST_DIR_SEARCH} BOOST_DIR_SEARCH)
 | 
				
			||||||
 | 
					  SET(BOOST_DIR_SEARCH ${BOOST_DIR_SEARCH}/include)
 | 
				
			||||||
 | 
					ENDIF(BOOST_DIR_SEARCH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(WIN32)
 | 
				
			||||||
 | 
					  SET(BOOST_DIR_SEARCH
 | 
				
			||||||
 | 
					    ${BOOST_DIR_SEARCH}
 | 
				
			||||||
 | 
					    C:/boost/include
 | 
				
			||||||
 | 
					    D:/boost/include
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					ENDIF(WIN32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add in some path suffixes. These will have to be updated whenever a new Boost version comes out.
 | 
				
			||||||
 | 
					SET(SUFFIX_FOR_PATH
 | 
				
			||||||
 | 
					 boost-1_35_1
 | 
				
			||||||
 | 
					 boost-1_35_0
 | 
				
			||||||
 | 
					 boost-1_35
 | 
				
			||||||
 | 
					 boost-1_34_1
 | 
				
			||||||
 | 
					 boost-1_34_0
 | 
				
			||||||
 | 
					 boost-1_34
 | 
				
			||||||
 | 
					 boost-1_33_1
 | 
				
			||||||
 | 
					 boost-1_33_0
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Look for an installation.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					FIND_PATH(Boost_INCLUDE_DIR NAMES boost/config.hpp PATH_SUFFIXES ${SUFFIX_FOR_PATH} PATHS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Look in other places.
 | 
				
			||||||
 | 
					  ${BOOST_DIR_SEARCH}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Help the user find it if we cannot.
 | 
				
			||||||
 | 
					  DOC "The ${BOOST_INCLUDE_PATH_DESCRIPTION}"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Assume we didn't find it.
 | 
				
			||||||
 | 
					SET(Boost_FOUND 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Now try to get the include and library path.
 | 
				
			||||||
 | 
					IF(Boost_INCLUDE_DIR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Look for the boost library path.
 | 
				
			||||||
 | 
					  # Note that the user may not have installed any libraries
 | 
				
			||||||
 | 
					  # so it is quite possible the Boost_LIBRARY_PATH may not exist.
 | 
				
			||||||
 | 
					  SET(Boost_LIBRARY_DIR ${Boost_INCLUDE_DIR})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  IF("${Boost_LIBRARY_DIR}" MATCHES "boost-[0-9]+")
 | 
				
			||||||
 | 
					    GET_FILENAME_COMPONENT(Boost_LIBRARY_DIR ${Boost_LIBRARY_DIR} PATH)
 | 
				
			||||||
 | 
					  ENDIF ("${Boost_LIBRARY_DIR}" MATCHES "boost-[0-9]+")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  IF("${Boost_LIBRARY_DIR}" MATCHES "/include$")
 | 
				
			||||||
 | 
					    # Strip off the trailing "/include" in the path.
 | 
				
			||||||
 | 
					    GET_FILENAME_COMPONENT(Boost_LIBRARY_DIR ${Boost_LIBRARY_DIR} PATH)
 | 
				
			||||||
 | 
					  ENDIF("${Boost_LIBRARY_DIR}" MATCHES "/include$")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  IF(EXISTS "${Boost_LIBRARY_DIR}/lib")
 | 
				
			||||||
 | 
					    SET (Boost_LIBRARY_DIR ${Boost_LIBRARY_DIR}/lib)
 | 
				
			||||||
 | 
					  ELSE(EXISTS "${Boost_LIBRARY_DIR}/lib")
 | 
				
			||||||
 | 
					    IF(EXISTS "${Boost_LIBRARY_DIR}/stage/lib")
 | 
				
			||||||
 | 
					      SET(Boost_LIBRARY_DIR ${Boost_LIBRARY_DIR}/stage/lib)
 | 
				
			||||||
 | 
					    ELSE(EXISTS "${Boost_LIBRARY_DIR}/stage/lib")
 | 
				
			||||||
 | 
					      SET(Boost_LIBRARY_DIR "")
 | 
				
			||||||
 | 
					    ENDIF(EXISTS "${Boost_LIBRARY_DIR}/stage/lib")
 | 
				
			||||||
 | 
					  ENDIF(EXISTS "${Boost_LIBRARY_DIR}/lib")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  IF(EXISTS "${Boost_INCLUDE_DIR}")
 | 
				
			||||||
 | 
					    SET(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR})
 | 
				
			||||||
 | 
					    # We have found boost. It is possible that the user has not
 | 
				
			||||||
 | 
					    # compiled any libraries so we set Boost_FOUND to be true here.
 | 
				
			||||||
 | 
					    SET(Boost_FOUND 1)
 | 
				
			||||||
 | 
					    MARK_AS_ADVANCED(Boost_INCLUDE_DIR)
 | 
				
			||||||
 | 
					  ENDIF(EXISTS "${Boost_INCLUDE_DIR}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  IF(Boost_LIBRARY_DIR AND EXISTS "${Boost_LIBRARY_DIR}")
 | 
				
			||||||
 | 
					    SET(Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR})
 | 
				
			||||||
 | 
					  ENDIF(Boost_LIBRARY_DIR AND EXISTS "${Boost_LIBRARY_DIR}")
 | 
				
			||||||
 | 
					ENDIF(Boost_INCLUDE_DIR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Find boost libraries
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# List of library suffixes to search, e.g. libboost_date_time-gcc
 | 
				
			||||||
 | 
					SET(BOOST_SUFFIX_SEARCH 
 | 
				
			||||||
 | 
					  gcc
 | 
				
			||||||
 | 
					  il
 | 
				
			||||||
 | 
					  mt
 | 
				
			||||||
 | 
					  s
 | 
				
			||||||
 | 
					  mt-s
 | 
				
			||||||
 | 
					  mgw
 | 
				
			||||||
 | 
					  mgw-mt
 | 
				
			||||||
 | 
					  mgw-s
 | 
				
			||||||
 | 
					  mgw-mt-s
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# List of all boost libraries
 | 
				
			||||||
 | 
					SET(BOOST_ALL_LIBRARIES 
 | 
				
			||||||
 | 
					  date_time
 | 
				
			||||||
 | 
					  filesystem
 | 
				
			||||||
 | 
					  graph
 | 
				
			||||||
 | 
					  iostreams
 | 
				
			||||||
 | 
					  program_options
 | 
				
			||||||
 | 
					  python
 | 
				
			||||||
 | 
					  regex
 | 
				
			||||||
 | 
					  serialization
 | 
				
			||||||
 | 
					  signals
 | 
				
			||||||
 | 
					  system
 | 
				
			||||||
 | 
					  test
 | 
				
			||||||
 | 
					  thread
 | 
				
			||||||
 | 
					  wave
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MACRO(LIST_CONTAINS LIST value var)
 | 
				
			||||||
 | 
					  SET(${var})
 | 
				
			||||||
 | 
					  FOREACH (value2 ${${LIST}})
 | 
				
			||||||
 | 
					    IF (${value} STREQUAL ${value2})
 | 
				
			||||||
 | 
					      SET(${var} TRUE)
 | 
				
			||||||
 | 
					    ENDIF (${value} STREQUAL ${value2})
 | 
				
			||||||
 | 
					  ENDFOREACH (value2)
 | 
				
			||||||
 | 
					ENDMACRO(LIST_CONTAINS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Macro to find boost library called name
 | 
				
			||||||
 | 
					MACRO(BOOST_FIND_LIBRARY name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # User can specify a particular build variant via the variables:
 | 
				
			||||||
 | 
					  #   Boost_LIB_PREFIX, Boost_LIB_SUFFIX, Boost_LIB_SUFFIX_DEBUG
 | 
				
			||||||
 | 
					  # otherwise we'll search the BOOST_SUFFIX_SEARCH list
 | 
				
			||||||
 | 
					  SET(BOOST_LIB_NAMES ${Boost_LIB_PREFIX}boost_${name})
 | 
				
			||||||
 | 
					  IF(NOT Boost_LIB_SUFFIX)
 | 
				
			||||||
 | 
					    FOREACH(suffix ${BOOST_SUFFIX_SEARCH})
 | 
				
			||||||
 | 
					      SET(BOOST_LIB_NAMES ${BOOST_LIB_NAMES} ${Boost_LIB_PREFIX}boost_${name}-${suffix})
 | 
				
			||||||
 | 
					    ENDFOREACH(suffix)
 | 
				
			||||||
 | 
					  ELSE(NOT Boost_LIB_SUFFIX)
 | 
				
			||||||
 | 
					    SET(BOOST_LIB_NAMES ${Boost_LIB_PREFIX}boost_${name}-${Boost_LIB_SUFFIX})
 | 
				
			||||||
 | 
					  ENDIF(NOT Boost_LIB_SUFFIX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Find the library in the Boost_LIBRARY_DIRS. We exclude the default path to
 | 
				
			||||||
 | 
					  # support cross compilation
 | 
				
			||||||
 | 
					  FIND_LIBRARY(Boost_${name}_LIBRARY 
 | 
				
			||||||
 | 
					    NAMES ${BOOST_LIB_NAMES}
 | 
				
			||||||
 | 
					    PATHS ${Boost_LIBRARY_DIRS} NO_DEFAULT_PATH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  IF(NOT Boost_${name}_LIBRARY)
 | 
				
			||||||
 | 
					    # Find the library in the Boost_LIBRARY_DIRS
 | 
				
			||||||
 | 
					    FIND_LIBRARY(Boost_${name}_LIBRARY 
 | 
				
			||||||
 | 
					      NAMES ${BOOST_LIB_NAMES}
 | 
				
			||||||
 | 
					      PATHS ${Boost_LIBRARY_DIRS})
 | 
				
			||||||
 | 
					  ENDIF(NOT Boost_${name}_LIBRARY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # For MSVC builds find debug library
 | 
				
			||||||
 | 
					  IF(WIN32 AND MSVC AND Boost_${name}_LIBRARY)
 | 
				
			||||||
 | 
					    FIND_LIBRARY(Boost_${name}_LIBRARY_DEBUG ${Boost_LIB_PREFIX}boost_${name}-${Boost_LIB_SUFFIX_DEBUG})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IF(MSVC_IDE)
 | 
				
			||||||
 | 
					      IF(Boost_${name}_LIBRARY AND Boost_${name}_LIBRARY_DEBUG)
 | 
				
			||||||
 | 
					        SET(Boost_${name}_LIBRARIES debug ${Boost_${name}_LIBRARY_DEBUG} optimized ${Boost_${name}_LIBRARY})
 | 
				
			||||||
 | 
					      ELSE(Boost_${name}_LIBRARY AND Boost_${name}_LIBRARY_DEBUG)
 | 
				
			||||||
 | 
					        MESSAGE(FATAL_ERROR "Could not find the debug and release version of Boost ${name} library.")
 | 
				
			||||||
 | 
					      ENDIF(Boost_${name}_LIBRARY AND Boost_${name}_LIBRARY_DEBUG)
 | 
				
			||||||
 | 
					    ELSE(MSVC_IDE)
 | 
				
			||||||
 | 
					      STRING(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_TOLOWER)
 | 
				
			||||||
 | 
					      IF(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug)
 | 
				
			||||||
 | 
					        SET(Boost_${name}_LIBRARIES ${Boost_${name}_LIBRARY_DEBUG})
 | 
				
			||||||
 | 
					      ELSE(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug)
 | 
				
			||||||
 | 
					        SET(Boost_${name}_LIBRARIES ${Boost_${name}_LIBRARY})
 | 
				
			||||||
 | 
					      ENDIF(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug)
 | 
				
			||||||
 | 
					    ENDIF(MSVC_IDE)
 | 
				
			||||||
 | 
					  ELSE(WIN32 AND MSVC AND Boost_${name}_LIBRARY)
 | 
				
			||||||
 | 
					    SET(Boost_${name}_LIBRARIES ${Boost_${name}_LIBRARY})
 | 
				
			||||||
 | 
					  ENDIF(WIN32 AND MSVC AND Boost_${name}_LIBRARY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # If we've got it setup appropriate variables or issue error message
 | 
				
			||||||
 | 
					  IF(Boost_${name}_LIBRARY)
 | 
				
			||||||
 | 
					    SET(Boost_${name}_FOUND 1)
 | 
				
			||||||
 | 
					    SET(Boost_${name}_INCLUDE_DIRS ${Boost_INCLUDE_DIR})
 | 
				
			||||||
 | 
					    MARK_AS_ADVANCED(Boost_${name}_LIBRARY Boost_${name}_LIBRARY_DEBUG)
 | 
				
			||||||
 | 
					    IF(NOT Boost_FIND_QUIETLY)
 | 
				
			||||||
 | 
					      MESSAGE(STATUS "Found boost_${name} library.")
 | 
				
			||||||
 | 
					    ENDIF(NOT Boost_FIND_QUIETLY)
 | 
				
			||||||
 | 
					  ELSE(Boost_${name}_LIBRARY)
 | 
				
			||||||
 | 
					    IF(NOT Boost_FIND_QUIETLY)
 | 
				
			||||||
 | 
					      #MESSAGE(STATUS "Boost ${name} library was not found.")
 | 
				
			||||||
 | 
					    ELSE(NOT Boost_FIND_QUIETLY)
 | 
				
			||||||
 | 
					      IF(Boost_FIND_REQUIRED_${name})
 | 
				
			||||||
 | 
					        MESSAGE(FATAL_ERROR "Could NOT find required Boost ${name} library.")
 | 
				
			||||||
 | 
					      ENDIF(Boost_FIND_REQUIRED_${name})
 | 
				
			||||||
 | 
					    ENDIF(NOT Boost_FIND_QUIETLY)  
 | 
				
			||||||
 | 
					  ENDIF(Boost_${name}_LIBRARY)
 | 
				
			||||||
 | 
					ENDMACRO(BOOST_FIND_LIBRARY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(Boost_LIBRARY_DIRS)
 | 
				
			||||||
 | 
					  # If the user specified required components e.g. via 
 | 
				
			||||||
 | 
					  # FIND_PACKAGE(Boost REQUIRED date_time regex)
 | 
				
			||||||
 | 
					  # find (just) those libraries. Otherwise find all libraries.
 | 
				
			||||||
 | 
					  IF(Boost_FIND_COMPONENTS)
 | 
				
			||||||
 | 
					    SET(Boost_FIND_LIBRARIES ${Boost_FIND_COMPONENTS})
 | 
				
			||||||
 | 
					    # Boost_filesystem is a special case and needs the additional
 | 
				
			||||||
 | 
					    # linkage of Boost_system as well on some systems. So we search for
 | 
				
			||||||
 | 
					    # Boost_system as well and add it later to Boost_filesystem_LIBRARIES.
 | 
				
			||||||
 | 
					    LIST_CONTAINS(Boost_FIND_LIBRARIES "filesystem" has_fs)
 | 
				
			||||||
 | 
					    IF(has_fs)
 | 
				
			||||||
 | 
					      LIST_CONTAINS(Boost_FIND_LIBRARIES "system" has_s)
 | 
				
			||||||
 | 
					      IF(NOT has_s)
 | 
				
			||||||
 | 
					        SET(Boost_FIND_LIBRARIES ${Boost_FIND_LIBRARIES} system)
 | 
				
			||||||
 | 
					      ENDIF(NOT has_s)
 | 
				
			||||||
 | 
					    ENDIF(has_fs)
 | 
				
			||||||
 | 
					  ELSE(Boost_FIND_COMPONENTS)
 | 
				
			||||||
 | 
					    SET(Boost_FIND_LIBRARIES ${BOOST_ALL_LIBRARIES})
 | 
				
			||||||
 | 
					  ENDIF(Boost_FIND_COMPONENTS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SET(Boost_MISSING_REQUIRED_COMPONENTS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SET(Boost_LIBRARIES)
 | 
				
			||||||
 | 
					  FOREACH(library ${Boost_FIND_LIBRARIES})
 | 
				
			||||||
 | 
					    BOOST_FIND_LIBRARY(${library})
 | 
				
			||||||
 | 
					    IF(Boost_${library}_FOUND)
 | 
				
			||||||
 | 
					      SET(Boost_LIBRARIES ${Boost_LIBRARIES} ${Boost_${library}_LIBRARIES})
 | 
				
			||||||
 | 
					    ELSE(Boost_${library}_FOUND)
 | 
				
			||||||
 | 
					      IF(Boost_FIND_REQUIRED AND Boost_FIND_COMPONENTS)
 | 
				
			||||||
 | 
					        IF(Boost_FIND_REQUIRED_${library})
 | 
				
			||||||
 | 
					          SET(Boost_MISSING_COMPONENTS 1)
 | 
				
			||||||
 | 
					          SET(
 | 
				
			||||||
 | 
					            Boost_MISSING_REQUIRED_COMPONENTS
 | 
				
			||||||
 | 
					              ${Boost_MISSING_REQUIRED_COMPONENTS}
 | 
				
			||||||
 | 
					              ${library}
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					        ENDIF(Boost_FIND_REQUIRED_${library})
 | 
				
			||||||
 | 
					      ENDIF(Boost_FIND_REQUIRED AND Boost_FIND_COMPONENTS)
 | 
				
			||||||
 | 
					    ENDIF(Boost_${library}_FOUND)
 | 
				
			||||||
 | 
					  ENDFOREACH(library)
 | 
				
			||||||
 | 
					ENDIF(Boost_LIBRARY_DIRS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(Boost_filesystem_FOUND)
 | 
				
			||||||
 | 
					  IF(Boost_system_FOUND)
 | 
				
			||||||
 | 
					    SET(Boost_filesystem_LIBRARIES ${Boost_filesystem_LIBRARIES} ${Boost_system_LIBRARIES})
 | 
				
			||||||
 | 
					  ENDIF(Boost_system_FOUND)
 | 
				
			||||||
 | 
					ENDIF(Boost_filesystem_FOUND)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(NOT Boost_FOUND)
 | 
				
			||||||
 | 
					  IF(NOT Boost_FIND_QUIETLY)
 | 
				
			||||||
 | 
					    MESSAGE(STATUS "Boost was not found. ${BOOST_DIR_MESSAGE}")
 | 
				
			||||||
 | 
					  ELSE(NOT Boost_FIND_QUIETLY)
 | 
				
			||||||
 | 
					    IF(Boost_FIND_REQUIRED)
 | 
				
			||||||
 | 
					      MESSAGE(FATAL_ERROR "Boost was not found. ${BOOST_DIR_MESSAGE}")
 | 
				
			||||||
 | 
					    ENDIF(Boost_FIND_REQUIRED)
 | 
				
			||||||
 | 
					  ENDIF(NOT Boost_FIND_QUIETLY)
 | 
				
			||||||
 | 
					ELSE(NOT Boost_FOUND)
 | 
				
			||||||
 | 
					  IF(Boost_MISSING_COMPONENTS)
 | 
				
			||||||
 | 
					    MESSAGE(STATUS "The following required Boost components are missing:")
 | 
				
			||||||
 | 
					    FOREACH(component ${Boost_MISSING_REQUIRED_COMPONENTS})
 | 
				
			||||||
 | 
					      MESSAGE(STATUS "  * boost_${component}")
 | 
				
			||||||
 | 
					    ENDFOREACH(component)
 | 
				
			||||||
 | 
					    MESSAGE(FATAL_ERROR "The Boost libraries (${Boost_FIND_COMPONENTS}) are required!")
 | 
				
			||||||
 | 
					  ENDIF(Boost_MISSING_COMPONENTS)
 | 
				
			||||||
 | 
					ENDIF(NOT Boost_FOUND)
 | 
				
			||||||
							
								
								
									
										23
									
								
								Modules/FindNumpy.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Modules/FindNumpy.cmake
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					# Try to find numarray python package
 | 
				
			||||||
 | 
					# Once done this will define
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# PYTHON_NUMPY_FOUND        - system has numarray development package and it should be used
 | 
				
			||||||
 | 
					# PYTHON_NUMPY_INCLUDE_DIR  - directory where the arrayobject.h header file can be found
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(PYTHON_EXECUTABLE)
 | 
				
			||||||
 | 
						FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/det_npp.py "from __future__ import print_function\ntry: import numpy; print(numpy.get_include())\nexcept: pass\n")
 | 
				
			||||||
 | 
						EXEC_PROGRAM("${PYTHON_EXECUTABLE}"
 | 
				
			||||||
 | 
							ARGS "\"${CMAKE_CURRENT_BINARY_DIR}/det_npp.py\""
 | 
				
			||||||
 | 
							OUTPUT_VARIABLE NUMPY_PATH
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						FILE(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/det_npp.py)
 | 
				
			||||||
 | 
					ENDIF(PYTHON_EXECUTABLE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FIND_PATH(PYTHON_NUMPY_INCLUDE_DIR numpy/arrayobject.h
 | 
				
			||||||
 | 
						"${NUMPY_PATH}/"
 | 
				
			||||||
 | 
						DOC "Directory where the numpy/arrayobject.h header file can be found. This file is part of the numpy package"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(PYTHON_NUMPY_INCLUDE_DIR)
 | 
				
			||||||
 | 
						SET (PYTHON_NUMPY_FOUND 1 CACHE INTERNAL "Python numpy development package is available")
 | 
				
			||||||
 | 
					ENDIF(PYTHON_NUMPY_INCLUDE_DIR)
 | 
				
			||||||
							
								
								
									
										74
									
								
								Modules/FindOpenSSL.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								Modules/FindOpenSSL.cmake
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					# - Try to find the OpenSSL encryption library
 | 
				
			||||||
 | 
					# Once done this will define
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#  OPENSSL_FOUND - system has the OpenSSL library
 | 
				
			||||||
 | 
					#  OPENSSL_INCLUDE_DIR - the OpenSSL include directory
 | 
				
			||||||
 | 
					#  OPENSSL_LIBRARIES - The libraries needed to use OpenSSL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Redistribution and use is allowed according to the terms of the BSD license.
 | 
				
			||||||
 | 
					# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(OPENSSL_LIBRARIES)
 | 
				
			||||||
 | 
					   SET(OpenSSL_FIND_QUIETLY TRUE)
 | 
				
			||||||
 | 
					ENDIF(OPENSSL_LIBRARIES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE)
 | 
				
			||||||
 | 
					   SET(LIB_FOUND 1)
 | 
				
			||||||
 | 
					ENDIF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FIND_PATH(OPENSSL_INCLUDE_DIR openssl/ssl.h )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(WIN32 AND MSVC)
 | 
				
			||||||
 | 
					   # /MD and /MDd are the standard values - if somone wants to use
 | 
				
			||||||
 | 
					   # others, the libnames have to change here too
 | 
				
			||||||
 | 
					   # use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   FIND_LIBRARY(SSL_EAY_DEBUG NAMES ssleay32MDd ssl ssleay32)
 | 
				
			||||||
 | 
					   FIND_LIBRARY(SSL_EAY_RELEASE NAMES ssleay32MD ssl ssleay32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   IF(MSVC_IDE)
 | 
				
			||||||
 | 
					      IF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE)
 | 
				
			||||||
 | 
					         SET(OPENSSL_LIBRARIES optimized ${SSL_EAY_RELEASE} debug ${SSL_EAY_DEBUG})
 | 
				
			||||||
 | 
					      ELSE(SSL_EAY_DEBUG AND SSL_EAY_RELEASE)
 | 
				
			||||||
 | 
					         SET(OPENSSL_LIBRARIES NOTFOUND)
 | 
				
			||||||
 | 
					         MESSAGE(STATUS "Could not find the debug and release version of openssl")
 | 
				
			||||||
 | 
					      ENDIF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE)
 | 
				
			||||||
 | 
					   ELSE(MSVC_IDE)
 | 
				
			||||||
 | 
					      STRING(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_TOLOWER)
 | 
				
			||||||
 | 
					      IF(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug)
 | 
				
			||||||
 | 
					         SET(OPENSSL_LIBRARIES ${SSL_EAY_DEBUG})
 | 
				
			||||||
 | 
					      ELSE(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug)
 | 
				
			||||||
 | 
					         SET(OPENSSL_LIBRARIES ${SSL_EAY_RELEASE})
 | 
				
			||||||
 | 
					      ENDIF(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug)
 | 
				
			||||||
 | 
					   ENDIF(MSVC_IDE)
 | 
				
			||||||
 | 
					   MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE)
 | 
				
			||||||
 | 
					ENDIF ( WIN32 AND MSVC )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FIND_LIBRARY(SSL NAMES ssl ssleay32 ssleay32MD )
 | 
				
			||||||
 | 
					FIND_LIBRARY(CRYPTO NAMES crypto)
 | 
				
			||||||
 | 
					IF ( SSL AND CRYPTO )
 | 
				
			||||||
 | 
					    SET(OPENSSL_LIBRARIES ${SSL} ${CRYPTO})
 | 
				
			||||||
 | 
					ENDIF ( SSL AND CRYPTO )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES)
 | 
				
			||||||
 | 
					   SET(OPENSSL_FOUND TRUE)
 | 
				
			||||||
 | 
					ELSE(OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES)
 | 
				
			||||||
 | 
					   SET(OPENSSL_FOUND FALSE)
 | 
				
			||||||
 | 
					ENDIF (OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF (OPENSSL_FOUND)
 | 
				
			||||||
 | 
					   IF (NOT OpenSSL_FIND_QUIETLY)
 | 
				
			||||||
 | 
					      MESSAGE(STATUS "Found OpenSSL: ${OPENSSL_LIBRARIES}")
 | 
				
			||||||
 | 
					   ENDIF (NOT OpenSSL_FIND_QUIETLY)
 | 
				
			||||||
 | 
					ELSE (OPENSSL_FOUND)
 | 
				
			||||||
 | 
					   IF (OpenSSL_FIND_REQUIRED)
 | 
				
			||||||
 | 
					      MESSAGE(FATAL_ERROR "Could NOT find OpenSSL")
 | 
				
			||||||
 | 
					   ENDIF (OpenSSL_FIND_REQUIRED)
 | 
				
			||||||
 | 
					ENDIF (OPENSSL_FOUND)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										85
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,85 @@
 | 
				
			|||||||
 | 
					# CAPS client library
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This file describes how to build the CAPS client library from source.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Runtime Dependencies
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Boost
 | 
				
			||||||
 | 
						* Program options
 | 
				
			||||||
 | 
						* Filesystem
 | 
				
			||||||
 | 
						* System
 | 
				
			||||||
 | 
					* OpenSSL
 | 
				
			||||||
 | 
					* Python*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Ubuntu 14.04
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					sudo apt-get install libboost-filesystem1.54.0 libboost-program-options1.54.0 libboost-system1.54.0 libssl0.9.8
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Ubuntu 16.04
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					sudo apt-get install libboost-filesystem1.58.0 libboost-program-options1.58.0 libboost-system1.58.0 libssl1.0.0
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Ubuntu 18.04
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					sudo apt-get install libboost-filesystem1.65.1 libboost-program-options1.65.1 libboost-system1.65.0 libssl1.1
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Ubuntu 20.04
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					sudo apt install libboost-filesystem1.71.0 libboost-program-options1.71.0 libboost-system1.71.0 libssl1.1
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### RHEL/CentOS
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					yum install boost-filesystem boost-program-options boost-system openssl
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Build Dependencies
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* CMake
 | 
				
			||||||
 | 
					* GCC, G++
 | 
				
			||||||
 | 
					* Boost
 | 
				
			||||||
 | 
					* OpenSSL
 | 
				
			||||||
 | 
					* Swig*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Ubuntu
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					 sudo apt-get install cmake gcc g++ libboost-all-dev cmake-curses-gui make libssl-dev
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					#### RHEL/CentOS
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					yum install cmake gcc-c++ openssl-devel boost-devel
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. Extract the package
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					tar xf libcapsclient-1.0.0.tar.gz
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					2. Change working directory and create a build directory
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					cd libcapsclient
 | 
				
			||||||
 | 
					mkdir build
 | 
				
			||||||
 | 
					cd build
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					3. Setup build environment
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					ccmake ..
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					4. Adjust the CMake settings to your needs
 | 
				
			||||||
 | 
					   1. Press 'c'
 | 
				
			||||||
 | 
					   2. Change the installation directory
 | 
				
			||||||
 | 
					   3. Switch on/off features e.g. examples
 | 
				
			||||||
 | 
					   4. ...
 | 
				
			||||||
 | 
					5. Press 'c' two time followed by 'g' to generate the build configuration
 | 
				
			||||||
 | 
					6. Build and install
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					make install
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										19
									
								
								examples/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								examples/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					SET(APP_NAME raw2caps)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET(SOURCES
 | 
				
			||||||
 | 
						raw2caps.cpp
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ADD_EXECUTABLE(${APP_NAME} ${SOURCES})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TARGET_LINK_LIBRARIES(${APP_NAME}
 | 
				
			||||||
 | 
						capsclient
 | 
				
			||||||
 | 
						mseed
 | 
				
			||||||
 | 
						${Boost_program_options_LIBRARY}
 | 
				
			||||||
 | 
						${Boost_filesystem_LIBRARY}
 | 
				
			||||||
 | 
						${Boost_system_LIBRARY}
 | 
				
			||||||
 | 
						${OPENSSL_LIBRARIES}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSTALL(TARGETS ${APP_NAME} DESTINATION examples)
 | 
				
			||||||
 | 
					INSTALL(DIRECTORY python DESTINATION examples)
 | 
				
			||||||
							
								
								
									
										114
									
								
								examples/python/raw2caps.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								examples/python/raw2caps.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					############################################################################
 | 
				
			||||||
 | 
					# Copyright (C) 2021 gempa GmbH                                            #
 | 
				
			||||||
 | 
					#                                                                          #
 | 
				
			||||||
 | 
					# All Rights Reserved.                                                     #
 | 
				
			||||||
 | 
					#                                                                          #
 | 
				
			||||||
 | 
					# NOTICE: All information contained herein is, and remains                 #
 | 
				
			||||||
 | 
					# the property of gempa GmbH and its suppliers, if any. The intellectual   #
 | 
				
			||||||
 | 
					# and technical concepts contained herein are proprietary to gempa GmbH    #
 | 
				
			||||||
 | 
					# and its suppliers.                                                       #
 | 
				
			||||||
 | 
					# Dissemination of this information or reproduction of this material       #
 | 
				
			||||||
 | 
					# is strictly forbidden unless prior written permission is obtained        #
 | 
				
			||||||
 | 
					# from gempa GmbH.                                                         #
 | 
				
			||||||
 | 
					############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from __future__ import absolute_import, division, print_function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import getopt
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import signal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import numpy as np
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from gempa import CAPS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					usage_info = """
 | 
				
			||||||
 | 
					raw2caps - pushes raw samples into CAPS.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: capstool [options]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Options:
 | 
				
			||||||
 | 
					    -H, --host                   host to connect to
 | 
				
			||||||
 | 
					    -h, --help                   display this help message and exit
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def usage(exitcode=0):
 | 
				
			||||||
 | 
					    sys.stderr.write(usage_info)
 | 
				
			||||||
 | 
					    return exitcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					output = CAPS.Plugin("raw2caps")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def signal_handler(sig, frame): #pylint: disable=W0613
 | 
				
			||||||
 | 
					    print('Caught Ctrl+C!')
 | 
				
			||||||
 | 
					    output.quit()
 | 
				
			||||||
 | 
					    sys.exit(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        opts, _ = getopt.getopt(sys.argv[1:], "hH:d:n:",
 | 
				
			||||||
 | 
					                                ["help", "host=", "directory=", "network="])
 | 
				
			||||||
 | 
					    except getopt.GetoptError as err:
 | 
				
			||||||
 | 
					        # print help information and exit:
 | 
				
			||||||
 | 
					        print(str(err)) # will print something like "option -a not recognized"
 | 
				
			||||||
 | 
					        return usage(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    addr = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    signal.signal(signal.SIGINT, signal_handler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for o, a in opts:
 | 
				
			||||||
 | 
					        if o in ["-h", "--help"]:
 | 
				
			||||||
 | 
					            return usage()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if o in ["-H", "--host"]:
 | 
				
			||||||
 | 
					            addr = a
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            assert False, "unhandled option"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if addr:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            host, port = addr.split(":")
 | 
				
			||||||
 | 
					        except BaseException:
 | 
				
			||||||
 | 
					            sys.stderr.write("invalid host address given: %s\n" % addr)
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        host = None
 | 
				
			||||||
 | 
					        port = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if port:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            port = int(port)
 | 
				
			||||||
 | 
					        except BaseException:
 | 
				
			||||||
 | 
					            sys.stderr.write("invalid port given: %s\n" % port)
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        port = 18003
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not host:
 | 
				
			||||||
 | 
					        host = "localhost"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    output.setHost(host)
 | 
				
			||||||
 | 
					    output.setPort(port)
 | 
				
			||||||
 | 
					    output.setBufferSize(1 << 30)
 | 
				
			||||||
 | 
					    output.enableLogging()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    startTime = CAPS.Time.GMT()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    x = np.array([1, 2], dtype=np.int32)
 | 
				
			||||||
 | 
					    res = output.push("AB", "HMA", "", "BHZ", startTime, 1, 1, "m", x,
 | 
				
			||||||
 | 
					                      CAPS.DT_INT32)
 | 
				
			||||||
 | 
					    if res != CAPS.Plugin.Success:
 | 
				
			||||||
 | 
					        sys.stderr.write("failed to send packet\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    output.close()
 | 
				
			||||||
 | 
					    return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    sys.exit(main())
 | 
				
			||||||
							
								
								
									
										112
									
								
								examples/raw2caps.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								examples/raw2caps.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 gempa GmbH                                           *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/plugin.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/mseed/steim2.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					using namespace Gempa::CAPS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_CHANNEL(out, fmt) \
 | 
				
			||||||
 | 
						va_list ap;\
 | 
				
			||||||
 | 
						va_start(ap, fmt);\
 | 
				
			||||||
 | 
						fprintf(stderr, #out"  "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n");\
 | 
				
			||||||
 | 
						va_end(ap)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LogError(const char *fmt, ...) {
 | 
				
			||||||
 | 
						LOG_CHANNEL(ERROR, fmt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LogWarning(const char *fmt, ...) {
 | 
				
			||||||
 | 
						LOG_CHANNEL(WARNING, fmt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LogNotice(const char *fmt, ...) {
 | 
				
			||||||
 | 
						LOG_CHANNEL(NOTICE, fmt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LogInfo(const char *fmt, ...) {
 | 
				
			||||||
 | 
						LOG_CHANNEL(INFO, fmt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LogDebug(const char *fmt, ...) {
 | 
				
			||||||
 | 
						LOG_CHANNEL(DEBUG, fmt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char **argv) {
 | 
				
			||||||
 | 
						if ( argc != 1 ) {
 | 
				
			||||||
 | 
							cerr << "Pushes samples to CAPS" << endl << endl;
 | 
				
			||||||
 | 
							cerr << "Usage: raw2caps" << endl;
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Setup log handlers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int verbosity = 2;
 | 
				
			||||||
 | 
						switch ( verbosity ) {
 | 
				
			||||||
 | 
							case 4: Gempa::CAPS::SetLogHandler(LL_DEBUG, LogDebug);
 | 
				
			||||||
 | 
							case 3: Gempa::CAPS::SetLogHandler(LL_INFO, LogInfo);
 | 
				
			||||||
 | 
							case 2: Gempa::CAPS::SetLogHandler(LL_WARNING, LogWarning);
 | 
				
			||||||
 | 
							case 1: Gempa::CAPS::SetLogHandler(LL_ERROR, LogError);
 | 
				
			||||||
 | 
							default: Gempa::CAPS::SetLogHandler(LL_NOTICE, LogNotice);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Plugin plugin("raw2caps");
 | 
				
			||||||
 | 
						plugin.setHost("localhost");
 | 
				
			||||||
 | 
						plugin.setPort(18003);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Enable on-the-fly MSEED Encoding
 | 
				
			||||||
 | 
					//	Steim2EncoderFactory *factory = new Steim2EncoderFactory();
 | 
				
			||||||
 | 
					//	plugin.setEncoderFactory(factory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						string networkCode = "AB";
 | 
				
			||||||
 | 
						string stationCode = "TEST";
 | 
				
			||||||
 | 
						string locationCode = "";
 | 
				
			||||||
 | 
						string channelCode = "HHZ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint16_t numerator = 100;
 | 
				
			||||||
 | 
						uint16_t denominator = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Time startTime = Time::FromString("2021-01-01 00:00:00", "%F %T");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int timingQuality = 100;
 | 
				
			||||||
 | 
						string uom = "m";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vector<int> samples;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for ( int i = 0; i < 100; ++i ) {
 | 
				
			||||||
 | 
							samples.push_back(i);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Plugin::Status ret =
 | 
				
			||||||
 | 
						    plugin.push(networkCode, stationCode, locationCode, channelCode, startTime,
 | 
				
			||||||
 | 
						                numerator, denominator, uom, samples.data(), samples.size(),
 | 
				
			||||||
 | 
						                DT_INT32, timingQuality);
 | 
				
			||||||
 | 
						if ( ret != Plugin::Success ) {
 | 
				
			||||||
 | 
							cerr << "Failed to send packet to CAPS" << endl;
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								libs/3rd-party/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								libs/3rd-party/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					subdirs(mseed)
 | 
				
			||||||
							
								
								
									
										7
									
								
								libs/3rd-party/mseed/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								libs/3rd-party/mseed/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					SET(LIB_NAME mseed)
 | 
				
			||||||
 | 
					FILE(GLOB SOURCES "*.cpp" "*.c" "*.h")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ADD_LIBRARY(${LIB_NAME} STATIC ${SOURCES})
 | 
				
			||||||
 | 
					SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES COMPILE_FLAGS -fPIC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										1183
									
								
								libs/3rd-party/mseed/fileutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1183
									
								
								libs/3rd-party/mseed/fileutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1407
									
								
								libs/3rd-party/mseed/genutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1407
									
								
								libs/3rd-party/mseed/genutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										150
									
								
								libs/3rd-party/mseed/gswap.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								libs/3rd-party/mseed/gswap.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,150 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * gswap.c:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Functions for generalized, in-pace byte swapping between LSBF and
 | 
				
			||||||
 | 
					 * MSBF byte orders.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Some standard integer types are needed, namely uint8_t and
 | 
				
			||||||
 | 
					 * uint32_t, (these are normally declared by including inttypes.h or
 | 
				
			||||||
 | 
					 * stdint.h).  Each function expects it's input to be a void pointer
 | 
				
			||||||
 | 
					 * to a quantity of the appropriate size.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * There are two versions of most routines, one that works on
 | 
				
			||||||
 | 
					 * quantities regardless of alignment (gswapX) and one that works on
 | 
				
			||||||
 | 
					 * memory aligned quantities (gswapXa).  The memory aligned versions
 | 
				
			||||||
 | 
					 * (gswapXa) are much faster than the other versions (gswapX), but the
 | 
				
			||||||
 | 
					 * memory *must* be aligned.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Written by Chad Trabant,
 | 
				
			||||||
 | 
					 *   IRIS Data Management Center
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Version: 2010.006
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lmplatform.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Swap routines that work on any (aligned or not) quantities */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ms_gswap2 ( void *data2 )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint8_t temp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  union
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    uint8_t  c[2];
 | 
				
			||||||
 | 
					  } dat;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  memcpy( &dat, data2, 2 );
 | 
				
			||||||
 | 
					  temp     = dat.c[0];
 | 
				
			||||||
 | 
					  dat.c[0] = dat.c[1];
 | 
				
			||||||
 | 
					  dat.c[1] = temp;
 | 
				
			||||||
 | 
					  memcpy( data2, &dat, 2 );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ms_gswap3 ( void *data3 )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint8_t temp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  union
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    uint8_t  c[3];
 | 
				
			||||||
 | 
					  } dat;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  memcpy( &dat, data3, 3 );
 | 
				
			||||||
 | 
					  temp     = dat.c[0];
 | 
				
			||||||
 | 
					  dat.c[0] = dat.c[2];
 | 
				
			||||||
 | 
					  dat.c[2] = temp;
 | 
				
			||||||
 | 
					  memcpy( data3, &dat, 3 );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ms_gswap4 ( void *data4 )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint8_t temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  union {
 | 
				
			||||||
 | 
					    uint8_t c[4];
 | 
				
			||||||
 | 
					  } dat;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  memcpy( &dat, data4, 4 );
 | 
				
			||||||
 | 
					  temp     = dat.c[0];
 | 
				
			||||||
 | 
					  dat.c[0] = dat.c[3];
 | 
				
			||||||
 | 
					  dat.c[3] = temp;
 | 
				
			||||||
 | 
					  temp     = dat.c[1];
 | 
				
			||||||
 | 
					  dat.c[1] = dat.c[2];
 | 
				
			||||||
 | 
					  dat.c[2] = temp;
 | 
				
			||||||
 | 
					  memcpy( data4, &dat, 4 );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ms_gswap8 ( void *data8 )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint8_t temp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  union
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    uint8_t   c[8];
 | 
				
			||||||
 | 
					  } dat;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  memcpy( &dat, data8, 8 );
 | 
				
			||||||
 | 
					  temp     = dat.c[0];
 | 
				
			||||||
 | 
					  dat.c[0] = dat.c[7];
 | 
				
			||||||
 | 
					  dat.c[7] = temp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  temp     = dat.c[1];
 | 
				
			||||||
 | 
					  dat.c[1] = dat.c[6];
 | 
				
			||||||
 | 
					  dat.c[6] = temp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  temp     = dat.c[2];
 | 
				
			||||||
 | 
					  dat.c[2] = dat.c[5];
 | 
				
			||||||
 | 
					  dat.c[5] = temp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  temp     = dat.c[3];
 | 
				
			||||||
 | 
					  dat.c[3] = dat.c[4];
 | 
				
			||||||
 | 
					  dat.c[4] = temp;
 | 
				
			||||||
 | 
					  memcpy( data8, &dat, 8 );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Swap routines that work on memory aligned quantities */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ms_gswap2a ( void *data2 )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint16_t *data = data2;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *data=(((*data>>8)&0xff) | ((*data&0xff)<<8));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ms_gswap4a ( void *data4 )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint32_t *data = data4;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *data=(((*data>>24)&0xff) | ((*data&0xff)<<24) |
 | 
				
			||||||
 | 
						 ((*data>>8)&0xff00) | ((*data&0xff00)<<8));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ms_gswap8a ( void *data8 )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint32_t *data4 = data8;
 | 
				
			||||||
 | 
					  uint32_t h0, h1;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  h0 = data4[0];
 | 
				
			||||||
 | 
					  h0 = (((h0>>24)&0xff) | ((h0&0xff)<<24) |
 | 
				
			||||||
 | 
						((h0>>8)&0xff00) | ((h0&0xff00)<<8));
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  h1 = data4[1];
 | 
				
			||||||
 | 
					  h1 = (((h1>>24)&0xff) | ((h1&0xff)<<24) |
 | 
				
			||||||
 | 
						((h1>>8)&0xff00) | ((h1&0xff00)<<8));
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  data4[0] = h1;
 | 
				
			||||||
 | 
					  data4[1] = h0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										106
									
								
								libs/3rd-party/mseed/libmseed.def
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								libs/3rd-party/mseed/libmseed.def
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					LIBRARY libmseed.dll
 | 
				
			||||||
 | 
					EXPORTS
 | 
				
			||||||
 | 
					   msr_parse
 | 
				
			||||||
 | 
					   msr_parse_selection
 | 
				
			||||||
 | 
					   msr_unpack
 | 
				
			||||||
 | 
					   msr_pack
 | 
				
			||||||
 | 
					   msr_pack_header
 | 
				
			||||||
 | 
					   msr_init
 | 
				
			||||||
 | 
					   msr_free
 | 
				
			||||||
 | 
					   msr_free_blktchain
 | 
				
			||||||
 | 
					   msr_addblockette
 | 
				
			||||||
 | 
					   msr_normalize_header
 | 
				
			||||||
 | 
					   msr_duplicate
 | 
				
			||||||
 | 
					   msr_samprate
 | 
				
			||||||
 | 
					   msr_nomsamprate
 | 
				
			||||||
 | 
					   msr_starttime
 | 
				
			||||||
 | 
					   msr_starttime_uc
 | 
				
			||||||
 | 
					   msr_endtime
 | 
				
			||||||
 | 
					   msr_srcname
 | 
				
			||||||
 | 
					   msr_print
 | 
				
			||||||
 | 
					   msr_host_latency
 | 
				
			||||||
 | 
					   ms_detect
 | 
				
			||||||
 | 
					   ms_parse_raw
 | 
				
			||||||
 | 
					   mst_init
 | 
				
			||||||
 | 
					   mst_free
 | 
				
			||||||
 | 
					   mst_initgroup
 | 
				
			||||||
 | 
					   mst_freegroup
 | 
				
			||||||
 | 
					   mst_findmatch
 | 
				
			||||||
 | 
					   mst_findadjacent
 | 
				
			||||||
 | 
					   mst_addmsr
 | 
				
			||||||
 | 
					   mst_addspan
 | 
				
			||||||
 | 
					   mst_addmsrtogroup
 | 
				
			||||||
 | 
					   mst_addtracetogroup
 | 
				
			||||||
 | 
					   mst_groupheal
 | 
				
			||||||
 | 
					   mst_groupsort
 | 
				
			||||||
 | 
					   mst_srcname
 | 
				
			||||||
 | 
					   mst_printtracelist
 | 
				
			||||||
 | 
					   mst_printsynclist
 | 
				
			||||||
 | 
					   mst_printgaplist
 | 
				
			||||||
 | 
					   mst_pack
 | 
				
			||||||
 | 
					   mst_packgroup
 | 
				
			||||||
 | 
					   mstl_init
 | 
				
			||||||
 | 
					   mstl_free
 | 
				
			||||||
 | 
					   mstl_addmsr
 | 
				
			||||||
 | 
					   mstl_printtracelist
 | 
				
			||||||
 | 
					   mstl_printsynclist
 | 
				
			||||||
 | 
					   mstl_printgaplist
 | 
				
			||||||
 | 
					   ms_readmsr
 | 
				
			||||||
 | 
					   ms_readmsr_r
 | 
				
			||||||
 | 
					   ms_readmsr_main
 | 
				
			||||||
 | 
					   ms_readtraces
 | 
				
			||||||
 | 
					   ms_readtraces_timewin
 | 
				
			||||||
 | 
					   ms_readtraces_selection
 | 
				
			||||||
 | 
					   ms_readtracelist
 | 
				
			||||||
 | 
					   ms_readtracelist_timewin
 | 
				
			||||||
 | 
					   ms_readtracelist_selection
 | 
				
			||||||
 | 
					   msr_writemseed
 | 
				
			||||||
 | 
					   mst_writemseed
 | 
				
			||||||
 | 
					   mst_writemseedgroup
 | 
				
			||||||
 | 
					   ms_recsrcname
 | 
				
			||||||
 | 
					   ms_splitsrcname
 | 
				
			||||||
 | 
					   ms_strncpclean
 | 
				
			||||||
 | 
					   ms_strncpopen
 | 
				
			||||||
 | 
					   ms_doy2md
 | 
				
			||||||
 | 
					   ms_md2doy
 | 
				
			||||||
 | 
					   ms_btime2hptime
 | 
				
			||||||
 | 
					   ms_btime2isotimestr
 | 
				
			||||||
 | 
					   ms_btime2mdtimestr
 | 
				
			||||||
 | 
					   ms_btime2seedtimestr
 | 
				
			||||||
 | 
					   ms_hptime2btime
 | 
				
			||||||
 | 
					   ms_hptime2isotimestr
 | 
				
			||||||
 | 
					   ms_hptime2mdtimestr
 | 
				
			||||||
 | 
					   ms_hptime2seedtimestr
 | 
				
			||||||
 | 
					   ms_time2hptime
 | 
				
			||||||
 | 
					   ms_seedtimestr2hptime
 | 
				
			||||||
 | 
					   ms_timestr2hptime
 | 
				
			||||||
 | 
					   ms_nomsamprate
 | 
				
			||||||
 | 
					   ms_genfactmult
 | 
				
			||||||
 | 
					   ms_ratapprox
 | 
				
			||||||
 | 
					   ms_bigendianhost
 | 
				
			||||||
 | 
					   ms_dabs
 | 
				
			||||||
 | 
					   ms_samplesize
 | 
				
			||||||
 | 
					   ms_encodingstr
 | 
				
			||||||
 | 
					   ms_blktdesc
 | 
				
			||||||
 | 
					   ms_blktlen
 | 
				
			||||||
 | 
					   ms_errorstr
 | 
				
			||||||
 | 
					   ms_log
 | 
				
			||||||
 | 
					   ms_log_l
 | 
				
			||||||
 | 
					   ms_loginit
 | 
				
			||||||
 | 
					   ms_loginit_l
 | 
				
			||||||
 | 
					   ms_matchselect
 | 
				
			||||||
 | 
					   msr_matchselect
 | 
				
			||||||
 | 
					   ms_addselect
 | 
				
			||||||
 | 
					   ms_addselect_comp
 | 
				
			||||||
 | 
					   ms_readselectionsfile
 | 
				
			||||||
 | 
					   ms_freeselections
 | 
				
			||||||
 | 
					   ms_printselections
 | 
				
			||||||
 | 
					   ms_gswap2
 | 
				
			||||||
 | 
					   ms_gswap3
 | 
				
			||||||
 | 
					   ms_gswap4
 | 
				
			||||||
 | 
					   ms_gswap8
 | 
				
			||||||
 | 
					   ms_gswap2a
 | 
				
			||||||
 | 
					   ms_gswap4a
 | 
				
			||||||
 | 
					   ms_gswap8a
 | 
				
			||||||
 | 
					   msr_unpack_steim2
 | 
				
			||||||
 | 
					   msr_unpack_steim1
 | 
				
			||||||
							
								
								
									
										735
									
								
								libs/3rd-party/mseed/libmseed.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										735
									
								
								libs/3rd-party/mseed/libmseed.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,735 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * libmseed.h:
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Interface declarations for the Mini-SEED library (libmseed).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU Library General Public License
 | 
				
			||||||
 | 
					 * as published by the Free Software Foundation; either version 2 of
 | 
				
			||||||
 | 
					 * the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library 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
 | 
				
			||||||
 | 
					 * Library General Public License (GNU-LGPL) for more details.  The
 | 
				
			||||||
 | 
					 * GNU-LGPL and further information can be found here:
 | 
				
			||||||
 | 
					 * http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Written by Chad Trabant
 | 
				
			||||||
 | 
					 * IRIS Data Management Center
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LIBMSEED_H
 | 
				
			||||||
 | 
					#define LIBMSEED_H 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lmplatform.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LIBMSEED_VERSION "2.13"
 | 
				
			||||||
 | 
					#define LIBMSEED_RELEASE "2014.234"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MINRECLEN   128      /* Minimum Mini-SEED record length, 2^7 bytes */
 | 
				
			||||||
 | 
					                             /* Note: the SEED specification minimum is 256 */
 | 
				
			||||||
 | 
					#define MAXRECLEN   1048576  /* Maximum Mini-SEED record length, 2^20 bytes */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SEED data encoding types */
 | 
				
			||||||
 | 
					#define DE_ASCII       0
 | 
				
			||||||
 | 
					#define DE_INT16       1
 | 
				
			||||||
 | 
					#define DE_INT32       3
 | 
				
			||||||
 | 
					#define DE_FLOAT32     4
 | 
				
			||||||
 | 
					#define DE_FLOAT64     5
 | 
				
			||||||
 | 
					#define DE_STEIM1      10
 | 
				
			||||||
 | 
					#define DE_STEIM2      11
 | 
				
			||||||
 | 
					#define DE_GEOSCOPE24  12
 | 
				
			||||||
 | 
					#define DE_GEOSCOPE163 13
 | 
				
			||||||
 | 
					#define DE_GEOSCOPE164 14
 | 
				
			||||||
 | 
					#define DE_CDSN        16
 | 
				
			||||||
 | 
					#define DE_SRO         30
 | 
				
			||||||
 | 
					#define DE_DWWSSN      32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Library return and error code values, error values should always be negative */
 | 
				
			||||||
 | 
					#define MS_ENDOFFILE        1        /* End of file reached return value */
 | 
				
			||||||
 | 
					#define MS_NOERROR          0        /* No error */
 | 
				
			||||||
 | 
					#define MS_GENERROR        -1        /* Generic unspecified error */
 | 
				
			||||||
 | 
					#define MS_NOTSEED         -2        /* Data not SEED */
 | 
				
			||||||
 | 
					#define MS_WRONGLENGTH     -3        /* Length of data read was not correct */
 | 
				
			||||||
 | 
					#define MS_OUTOFRANGE      -4        /* SEED record length out of range */
 | 
				
			||||||
 | 
					#define MS_UNKNOWNFORMAT   -5        /* Unknown data encoding format */
 | 
				
			||||||
 | 
					#define MS_STBADCOMPFLAG   -6        /* Steim, invalid compression flag(s) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Define the high precision time tick interval as 1/modulus seconds */
 | 
				
			||||||
 | 
					/* Default modulus of 1000000 defines tick interval as a microsecond */
 | 
				
			||||||
 | 
					#define HPTMODULUS 1000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Error code for routines that normally return a high precision time.
 | 
				
			||||||
 | 
					 * The time value corresponds to '1902/1/1 00:00:00.000000' with the
 | 
				
			||||||
 | 
					 * default HPTMODULUS */
 | 
				
			||||||
 | 
					#define HPTERROR -2145916800000000LL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Macros to scale between Unix/POSIX epoch time & high precision time */
 | 
				
			||||||
 | 
					#define MS_EPOCH2HPTIME(X) X * (hptime_t) HPTMODULUS
 | 
				
			||||||
 | 
					#define MS_HPTIME2EPOCH(X) X / HPTMODULUS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Macro to test a character for data record indicators */
 | 
				
			||||||
 | 
					#define MS_ISDATAINDICATOR(X) (X=='D' || X=='R' || X=='Q' || X=='M')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Macro to test default sample rate tolerance: abs(1-sr1/sr2) < 0.0001 */
 | 
				
			||||||
 | 
					#define MS_ISRATETOLERABLE(A,B) (ms_dabs (1.0 - (A / B)) < 0.0001)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Macro to test for sane year and day values, used primarily to
 | 
				
			||||||
 | 
					 * determine if byte order swapping is needed.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Year : between 1900 and 2100
 | 
				
			||||||
 | 
					 * Day  : between 1 and 366
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This test is non-unique (non-deterministic) for days 1, 256 and 257
 | 
				
			||||||
 | 
					 * in the year 2056 because the swapped values are also within range.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define MS_ISVALIDYEARDAY(Y,D) (Y >= 1900 && Y <= 2100 && D >= 1 && D <= 366)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Macro to test memory for a SEED data record signature by checking
 | 
				
			||||||
 | 
					 * SEED data record header values at known byte offsets to determine
 | 
				
			||||||
 | 
					 * if the memory contains a valid record.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Offset = Value
 | 
				
			||||||
 | 
					 * [0-5]  = Digits, spaces or NULL, SEED sequence number
 | 
				
			||||||
 | 
					 *     6  = Data record quality indicator
 | 
				
			||||||
 | 
					 *     7  = Space or NULL [not valid SEED]
 | 
				
			||||||
 | 
					 *     24 = Start hour (0-23)
 | 
				
			||||||
 | 
					 *     25 = Start minute (0-59)
 | 
				
			||||||
 | 
					 *     26 = Start second (0-60)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Usage:
 | 
				
			||||||
 | 
					 *   MS_ISVALIDHEADER ((char *)X)  X buffer must contain at least 27 bytes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define MS_ISVALIDHEADER(X) (                                           \
 | 
				
			||||||
 | 
					  (isdigit ((unsigned char) *(X)) || *(X) == ' ' || !*(X) ) &&		\
 | 
				
			||||||
 | 
					  (isdigit ((unsigned char) *(X+1)) || *(X+1) == ' ' || !*(X+1) ) &&	\
 | 
				
			||||||
 | 
					  (isdigit ((unsigned char) *(X+2)) || *(X+2) == ' ' || !*(X+2) ) &&	\
 | 
				
			||||||
 | 
					  (isdigit ((unsigned char) *(X+3)) || *(X+3) == ' ' || !*(X+3) ) &&	\
 | 
				
			||||||
 | 
					  (isdigit ((unsigned char) *(X+4)) || *(X+4) == ' ' || !*(X+4) ) &&	\
 | 
				
			||||||
 | 
					  (isdigit ((unsigned char) *(X+5)) || *(X+5) == ' ' || !*(X+5) ) &&	\
 | 
				
			||||||
 | 
					  MS_ISDATAINDICATOR(*(X+6)) &&						\
 | 
				
			||||||
 | 
					  (*(X+7) == ' ' || *(X+7) == '\0') &&					\
 | 
				
			||||||
 | 
					  (int)(*(X+24)) >= 0 && (int)(*(X+24)) <= 23 &&			\
 | 
				
			||||||
 | 
					  (int)(*(X+25)) >= 0 && (int)(*(X+25)) <= 59 &&			\
 | 
				
			||||||
 | 
					  (int)(*(X+26)) >= 0 && (int)(*(X+26)) <= 60)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Macro to test memory for a blank/noise SEED data record signature
 | 
				
			||||||
 | 
					 * by checking for a valid SEED sequence number and padding characters
 | 
				
			||||||
 | 
					 * to determine if the memory contains a valid blank/noise record.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Offset = Value
 | 
				
			||||||
 | 
					 * [0-5]  = Digits or NULL, SEED sequence number
 | 
				
			||||||
 | 
					 * [6-47] = Space character (ASCII 32), remainder of fixed header
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Usage:
 | 
				
			||||||
 | 
					 *   MS_ISVALIDBLANK ((char *)X)  X buffer must contain at least 27 bytes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define MS_ISVALIDBLANK(X) ((isdigit ((unsigned char) *(X)) || !*(X) ) &&     \
 | 
				
			||||||
 | 
								    (isdigit ((unsigned char) *(X+1)) || !*(X+1) ) && \
 | 
				
			||||||
 | 
								    (isdigit ((unsigned char) *(X+2)) || !*(X+2) ) && \
 | 
				
			||||||
 | 
								    (isdigit ((unsigned char) *(X+3)) || !*(X+3) ) && \
 | 
				
			||||||
 | 
								    (isdigit ((unsigned char) *(X+4)) || !*(X+4) ) && \
 | 
				
			||||||
 | 
								    (isdigit ((unsigned char) *(X+5)) || !*(X+5) ) && \
 | 
				
			||||||
 | 
								    (*(X+6)==' ')&&(*(X+7)==' ')&&(*(X+8)==' ') &&    \
 | 
				
			||||||
 | 
								    (*(X+9)==' ')&&(*(X+10)==' ')&&(*(X+11)==' ') &&  \
 | 
				
			||||||
 | 
								    (*(X+12)==' ')&&(*(X+13)==' ')&&(*(X+14)==' ') && \
 | 
				
			||||||
 | 
								    (*(X+15)==' ')&&(*(X+16)==' ')&&(*(X+17)==' ') && \
 | 
				
			||||||
 | 
								    (*(X+18)==' ')&&(*(X+19)==' ')&&(*(X+20)==' ') && \
 | 
				
			||||||
 | 
								    (*(X+21)==' ')&&(*(X+22)==' ')&&(*(X+23)==' ') && \
 | 
				
			||||||
 | 
								    (*(X+24)==' ')&&(*(X+25)==' ')&&(*(X+26)==' ') && \
 | 
				
			||||||
 | 
								    (*(X+27)==' ')&&(*(X+28)==' ')&&(*(X+29)==' ') && \
 | 
				
			||||||
 | 
								    (*(X+30)==' ')&&(*(X+31)==' ')&&(*(X+32)==' ') && \
 | 
				
			||||||
 | 
								    (*(X+33)==' ')&&(*(X+34)==' ')&&(*(X+35)==' ') && \
 | 
				
			||||||
 | 
								    (*(X+36)==' ')&&(*(X+37)==' ')&&(*(X+38)==' ') && \
 | 
				
			||||||
 | 
								    (*(X+39)==' ')&&(*(X+40)==' ')&&(*(X+41)==' ') && \
 | 
				
			||||||
 | 
								    (*(X+42)==' ')&&(*(X+43)==' ')&&(*(X+44)==' ') && \
 | 
				
			||||||
 | 
								    (*(X+45)==' ')&&(*(X+46)==' ')&&(*(X+47)==' ') )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* A simple bitwise AND test to return 0 or 1 */
 | 
				
			||||||
 | 
					#define bit(x,y) (x&y)?1:0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Require a large (>= 64-bit) integer type for hptime_t */
 | 
				
			||||||
 | 
					typedef int64_t hptime_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* A single byte flag type */
 | 
				
			||||||
 | 
					typedef int8_t flag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SEED binary time */
 | 
				
			||||||
 | 
					typedef struct btime_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint16_t  year;
 | 
				
			||||||
 | 
					  uint16_t  day;
 | 
				
			||||||
 | 
					  uint8_t   hour;
 | 
				
			||||||
 | 
					  uint8_t   min;
 | 
				
			||||||
 | 
					  uint8_t   sec;
 | 
				
			||||||
 | 
					  uint8_t   unused;
 | 
				
			||||||
 | 
					  uint16_t  fract;
 | 
				
			||||||
 | 
					} LMP_PACKED
 | 
				
			||||||
 | 
					BTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Fixed section data of header */
 | 
				
			||||||
 | 
					struct fsdh_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  char      sequence_number[6];
 | 
				
			||||||
 | 
					  char      dataquality;
 | 
				
			||||||
 | 
					  char      reserved;
 | 
				
			||||||
 | 
					  char      station[5];
 | 
				
			||||||
 | 
					  char      location[2];
 | 
				
			||||||
 | 
					  char      channel[3];
 | 
				
			||||||
 | 
					  char      network[2];
 | 
				
			||||||
 | 
					  BTime     start_time;
 | 
				
			||||||
 | 
					  uint16_t  numsamples;
 | 
				
			||||||
 | 
					  int16_t   samprate_fact;
 | 
				
			||||||
 | 
					  int16_t   samprate_mult;
 | 
				
			||||||
 | 
					  uint8_t   act_flags;
 | 
				
			||||||
 | 
					  uint8_t   io_flags;
 | 
				
			||||||
 | 
					  uint8_t   dq_flags;
 | 
				
			||||||
 | 
					  uint8_t   numblockettes;
 | 
				
			||||||
 | 
					  int32_t   time_correct;
 | 
				
			||||||
 | 
					  uint16_t  data_offset;
 | 
				
			||||||
 | 
					  uint16_t  blockette_offset;
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 100, Sample Rate (without header) */
 | 
				
			||||||
 | 
					struct blkt_100_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  float     samprate;
 | 
				
			||||||
 | 
					  int8_t    flags;
 | 
				
			||||||
 | 
					  uint8_t   reserved[3];
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 200, Generic Event Detection (without header) */
 | 
				
			||||||
 | 
					struct blkt_200_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  float     amplitude;
 | 
				
			||||||
 | 
					  float     period;
 | 
				
			||||||
 | 
					  float     background_estimate;
 | 
				
			||||||
 | 
					  uint8_t   flags;
 | 
				
			||||||
 | 
					  uint8_t   reserved;
 | 
				
			||||||
 | 
					  BTime     time;
 | 
				
			||||||
 | 
					  char      detector[24];
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 201, Murdock Event Detection (without header) */
 | 
				
			||||||
 | 
					struct blkt_201_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  float     amplitude;
 | 
				
			||||||
 | 
					  float     period;
 | 
				
			||||||
 | 
					  float     background_estimate;
 | 
				
			||||||
 | 
					  uint8_t   flags;
 | 
				
			||||||
 | 
					  uint8_t   reserved;
 | 
				
			||||||
 | 
					  BTime     time;
 | 
				
			||||||
 | 
					  uint8_t   snr_values[6];
 | 
				
			||||||
 | 
					  uint8_t   loopback;
 | 
				
			||||||
 | 
					  uint8_t   pick_algorithm;
 | 
				
			||||||
 | 
					  char      detector[24];
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 300, Step Calibration (without header) */
 | 
				
			||||||
 | 
					struct blkt_300_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  BTime     time;
 | 
				
			||||||
 | 
					  uint8_t   numcalibrations;
 | 
				
			||||||
 | 
					  uint8_t   flags;
 | 
				
			||||||
 | 
					  uint32_t  step_duration;
 | 
				
			||||||
 | 
					  uint32_t  interval_duration;
 | 
				
			||||||
 | 
					  float     amplitude;
 | 
				
			||||||
 | 
					  char      input_channel[3];
 | 
				
			||||||
 | 
					  uint8_t   reserved;
 | 
				
			||||||
 | 
					  uint32_t  reference_amplitude;
 | 
				
			||||||
 | 
					  char      coupling[12];
 | 
				
			||||||
 | 
					  char      rolloff[12];
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 310, Sine Calibration (without header) */
 | 
				
			||||||
 | 
					struct blkt_310_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  BTime     time;
 | 
				
			||||||
 | 
					  uint8_t   reserved1;
 | 
				
			||||||
 | 
					  uint8_t   flags;
 | 
				
			||||||
 | 
					  uint32_t  duration;
 | 
				
			||||||
 | 
					  float     period;
 | 
				
			||||||
 | 
					  float     amplitude;
 | 
				
			||||||
 | 
					  char      input_channel[3];
 | 
				
			||||||
 | 
					  uint8_t   reserved2;
 | 
				
			||||||
 | 
					  uint32_t  reference_amplitude;
 | 
				
			||||||
 | 
					  char      coupling[12];
 | 
				
			||||||
 | 
					  char      rolloff[12];
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 320, Pseudo-random Calibration (without header) */
 | 
				
			||||||
 | 
					struct blkt_320_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  BTime     time;
 | 
				
			||||||
 | 
					  uint8_t   reserved1;
 | 
				
			||||||
 | 
					  uint8_t   flags;
 | 
				
			||||||
 | 
					  uint32_t  duration;
 | 
				
			||||||
 | 
					  float     ptp_amplitude;
 | 
				
			||||||
 | 
					  char      input_channel[3];
 | 
				
			||||||
 | 
					  uint8_t   reserved2;
 | 
				
			||||||
 | 
					  uint32_t  reference_amplitude;
 | 
				
			||||||
 | 
					  char      coupling[12];
 | 
				
			||||||
 | 
					  char      rolloff[12];
 | 
				
			||||||
 | 
					  char      noise_type[8];
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					/* Blockette 390, Generic Calibration (without header) */
 | 
				
			||||||
 | 
					struct blkt_390_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  BTime     time;
 | 
				
			||||||
 | 
					  uint8_t   reserved1;
 | 
				
			||||||
 | 
					  uint8_t   flags;
 | 
				
			||||||
 | 
					  uint32_t  duration;
 | 
				
			||||||
 | 
					  float     amplitude;
 | 
				
			||||||
 | 
					  char      input_channel[3];
 | 
				
			||||||
 | 
					  uint8_t   reserved2;
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 395, Calibration Abort (without header) */
 | 
				
			||||||
 | 
					struct blkt_395_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  BTime     time;
 | 
				
			||||||
 | 
					  uint8_t   reserved[2];
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 400, Beam (without header) */
 | 
				
			||||||
 | 
					struct blkt_400_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  float     azimuth;
 | 
				
			||||||
 | 
					  float     slowness;
 | 
				
			||||||
 | 
					  uint16_t  configuration;
 | 
				
			||||||
 | 
					  uint8_t   reserved[2];
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 405, Beam Delay (without header) */
 | 
				
			||||||
 | 
					struct blkt_405_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint16_t  delay_values[1];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 500, Timing (without header) */
 | 
				
			||||||
 | 
					struct blkt_500_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  float     vco_correction;
 | 
				
			||||||
 | 
					  BTime     time;
 | 
				
			||||||
 | 
					  int8_t    usec;
 | 
				
			||||||
 | 
					  uint8_t   reception_qual;
 | 
				
			||||||
 | 
					  uint32_t  exception_count;
 | 
				
			||||||
 | 
					  char      exception_type[16];
 | 
				
			||||||
 | 
					  char      clock_model[32];
 | 
				
			||||||
 | 
					  char      clock_status[128];
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 1000, Data Only SEED (without header) */
 | 
				
			||||||
 | 
					struct blkt_1000_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint8_t   encoding;
 | 
				
			||||||
 | 
					  uint8_t   byteorder;
 | 
				
			||||||
 | 
					  uint8_t   reclen;
 | 
				
			||||||
 | 
					  uint8_t   reserved;
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 1001, Data Extension (without header) */
 | 
				
			||||||
 | 
					struct blkt_1001_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint8_t   timing_qual;
 | 
				
			||||||
 | 
					  int8_t    usec;
 | 
				
			||||||
 | 
					  uint8_t   reserved;
 | 
				
			||||||
 | 
					  uint8_t   framecnt;
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette 2000, Opaque Data (without header) */
 | 
				
			||||||
 | 
					struct blkt_2000_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint16_t  length;
 | 
				
			||||||
 | 
					  uint16_t  data_offset;
 | 
				
			||||||
 | 
					  uint32_t  recnum;
 | 
				
			||||||
 | 
					  uint8_t   byteorder;
 | 
				
			||||||
 | 
					  uint8_t   flags;
 | 
				
			||||||
 | 
					  uint8_t   numheaders;
 | 
				
			||||||
 | 
					  char      payload[1];
 | 
				
			||||||
 | 
					} LMP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Blockette chain link, generic linkable blockette index */
 | 
				
			||||||
 | 
					typedef struct blkt_link_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint16_t            blktoffset;    /* Offset to this blockette */
 | 
				
			||||||
 | 
					  uint16_t            blkt_type;     /* Blockette type */
 | 
				
			||||||
 | 
					  uint16_t            next_blkt;     /* Offset to next blockette */
 | 
				
			||||||
 | 
					  void               *blktdata;      /* Blockette data */
 | 
				
			||||||
 | 
					  uint16_t            blktdatalen;   /* Length of blockette data in bytes */
 | 
				
			||||||
 | 
					  struct blkt_link_s *next;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					BlktLink;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct StreamState_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int64_t   packedrecords;           /* Count of packed records */
 | 
				
			||||||
 | 
					  int64_t   packedsamples;           /* Count of packed samples */
 | 
				
			||||||
 | 
					  int32_t   lastintsample;           /* Value of last integer sample packed */
 | 
				
			||||||
 | 
					  flag      comphistory;             /* Control use of lastintsample for compression history */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					StreamState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct MSRecord_s {
 | 
				
			||||||
 | 
					  char           *record;            /* Mini-SEED record */
 | 
				
			||||||
 | 
					  int32_t         reclen;            /* Length of Mini-SEED record in bytes */
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Pointers to SEED data record structures */
 | 
				
			||||||
 | 
					  struct fsdh_s      *fsdh;          /* Fixed Section of Data Header */
 | 
				
			||||||
 | 
					  BlktLink           *blkts;         /* Root of blockette chain */
 | 
				
			||||||
 | 
					  struct blkt_100_s  *Blkt100;       /* Blockette 100, if present */
 | 
				
			||||||
 | 
					  struct blkt_1000_s *Blkt1000;      /* Blockette 1000, if present */
 | 
				
			||||||
 | 
					  struct blkt_1001_s *Blkt1001;      /* Blockette 1001, if present */
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Common header fields in accessible form */
 | 
				
			||||||
 | 
					  int32_t         sequence_number;   /* SEED record sequence number */
 | 
				
			||||||
 | 
					  char            network[11];       /* Network designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            station[11];       /* Station designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            location[11];      /* Location designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            channel[11];       /* Channel designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            dataquality;       /* Data quality indicator */
 | 
				
			||||||
 | 
					  hptime_t        starttime;         /* Record start time, corrected (first sample) */
 | 
				
			||||||
 | 
					  double          samprate;          /* Nominal sample rate (Hz) */
 | 
				
			||||||
 | 
					  int64_t         samplecnt;         /* Number of samples in record */
 | 
				
			||||||
 | 
					  int8_t          encoding;          /* Data encoding format */
 | 
				
			||||||
 | 
					  int8_t          byteorder;         /* Original/Final byte order of record */
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Data sample fields */
 | 
				
			||||||
 | 
					  void           *datasamples;       /* Data samples, 'numsamples' of type 'sampletype'*/
 | 
				
			||||||
 | 
					  int64_t         numsamples;        /* Number of data samples in datasamples */
 | 
				
			||||||
 | 
					  char            sampletype;        /* Sample type code: a, i, f, d */
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Stream oriented state information */
 | 
				
			||||||
 | 
					  StreamState    *ststate;           /* Stream processing state information */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					MSRecord;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Container for a continuous trace, linkable */
 | 
				
			||||||
 | 
					typedef struct MSTrace_s {
 | 
				
			||||||
 | 
					  char            network[11];       /* Network designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            station[11];       /* Station designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            location[11];      /* Location designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            channel[11];       /* Channel designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            dataquality;       /* Data quality indicator */ 
 | 
				
			||||||
 | 
					  char            type;              /* MSTrace type code */
 | 
				
			||||||
 | 
					  hptime_t        starttime;         /* Time of first sample */
 | 
				
			||||||
 | 
					  hptime_t        endtime;           /* Time of last sample */
 | 
				
			||||||
 | 
					  double          samprate;          /* Nominal sample rate (Hz) */
 | 
				
			||||||
 | 
					  int64_t         samplecnt;         /* Number of samples in trace coverage */
 | 
				
			||||||
 | 
					  void           *datasamples;       /* Data samples, 'numsamples' of type 'sampletype' */
 | 
				
			||||||
 | 
					  int64_t         numsamples;        /* Number of data samples in datasamples */
 | 
				
			||||||
 | 
					  char            sampletype;        /* Sample type code: a, i, f, d */
 | 
				
			||||||
 | 
					  void           *prvtptr;           /* Private pointer for general use, unused by libmseed */
 | 
				
			||||||
 | 
					  StreamState    *ststate;           /* Stream processing state information */
 | 
				
			||||||
 | 
					  struct MSTrace_s *next;            /* Pointer to next trace */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					MSTrace;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Container for a group (chain) of traces */
 | 
				
			||||||
 | 
					typedef struct MSTraceGroup_s {
 | 
				
			||||||
 | 
					  int32_t           numtraces;       /* Number of MSTraces in the trace chain */
 | 
				
			||||||
 | 
					  struct MSTrace_s *traces;          /* Root of the trace chain */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					MSTraceGroup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Container for a continuous trace segment, linkable */
 | 
				
			||||||
 | 
					typedef struct MSTraceSeg_s {
 | 
				
			||||||
 | 
					  hptime_t        starttime;         /* Time of first sample */
 | 
				
			||||||
 | 
					  hptime_t        endtime;           /* Time of last sample */
 | 
				
			||||||
 | 
					  double          samprate;          /* Nominal sample rate (Hz) */
 | 
				
			||||||
 | 
					  int64_t         samplecnt;         /* Number of samples in trace coverage */
 | 
				
			||||||
 | 
					  void           *datasamples;       /* Data samples, 'numsamples' of type 'sampletype'*/
 | 
				
			||||||
 | 
					  int64_t         numsamples;        /* Number of data samples in datasamples */
 | 
				
			||||||
 | 
					  char            sampletype;        /* Sample type code: a, i, f, d */
 | 
				
			||||||
 | 
					  void           *prvtptr;           /* Private pointer for general use, unused by libmseed */
 | 
				
			||||||
 | 
					  struct MSTraceSeg_s *prev;         /* Pointer to previous segment */
 | 
				
			||||||
 | 
					  struct MSTraceSeg_s *next;         /* Pointer to next segment */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					MSTraceSeg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Container for a trace ID, linkable */
 | 
				
			||||||
 | 
					typedef struct MSTraceID_s {
 | 
				
			||||||
 | 
					  char            network[11];       /* Network designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            station[11];       /* Station designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            location[11];      /* Location designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            channel[11];       /* Channel designation, NULL terminated */
 | 
				
			||||||
 | 
					  char            dataquality;       /* Data quality indicator */
 | 
				
			||||||
 | 
					  char            srcname[45];       /* Source name (Net_Sta_Loc_Chan_Qual), NULL terminated */
 | 
				
			||||||
 | 
					  char            type;              /* Trace type code */
 | 
				
			||||||
 | 
					  hptime_t        earliest;          /* Time of earliest sample */
 | 
				
			||||||
 | 
					  hptime_t        latest;            /* Time of latest sample */
 | 
				
			||||||
 | 
					  void           *prvtptr;           /* Private pointer for general use, unused by libmseed */
 | 
				
			||||||
 | 
					  int32_t         numsegments;       /* Number of segments for this ID */
 | 
				
			||||||
 | 
					  struct MSTraceSeg_s *first;        /* Pointer to first of list of segments */
 | 
				
			||||||
 | 
					  struct MSTraceSeg_s *last;         /* Pointer to last of list of segments */
 | 
				
			||||||
 | 
					  struct MSTraceID_s *next;          /* Pointer to next trace */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					MSTraceID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Container for a continuous trace segment, linkable */
 | 
				
			||||||
 | 
					typedef struct MSTraceList_s {
 | 
				
			||||||
 | 
					  int32_t             numtraces;     /* Number of traces in list */
 | 
				
			||||||
 | 
					  struct MSTraceID_s *traces;        /* Pointer to list of traces */
 | 
				
			||||||
 | 
					  struct MSTraceID_s *last;          /* Pointer to last used trace in list */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					MSTraceList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Data selection structure time window definition containers */
 | 
				
			||||||
 | 
					typedef struct SelectTime_s {
 | 
				
			||||||
 | 
					  hptime_t starttime;    /* Earliest data for matching channels */
 | 
				
			||||||
 | 
					  hptime_t endtime;      /* Latest data for matching channels */
 | 
				
			||||||
 | 
					  struct SelectTime_s *next;
 | 
				
			||||||
 | 
					} SelectTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Data selection structure definition containers */
 | 
				
			||||||
 | 
					typedef struct Selections_s {
 | 
				
			||||||
 | 
					  char srcname[100];     /* Matching (globbing) source name: Net_Sta_Loc_Chan_Qual */
 | 
				
			||||||
 | 
					  struct SelectTime_s *timewindows;
 | 
				
			||||||
 | 
					  struct Selections_s *next;
 | 
				
			||||||
 | 
					} Selections;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Global variables (defined in pack.c) and macros to set/force
 | 
				
			||||||
 | 
					 * pack byte orders */
 | 
				
			||||||
 | 
					extern flag packheaderbyteorder;
 | 
				
			||||||
 | 
					extern flag packdatabyteorder;
 | 
				
			||||||
 | 
					#define MS_PACKHEADERBYTEORDER(X) (packheaderbyteorder = X);
 | 
				
			||||||
 | 
					#define MS_PACKDATABYTEORDER(X) (packdatabyteorder = X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Global variables (defined in unpack.c) and macros to set/force
 | 
				
			||||||
 | 
					 * unpack byte orders */
 | 
				
			||||||
 | 
					extern flag unpackheaderbyteorder;
 | 
				
			||||||
 | 
					extern flag unpackdatabyteorder;
 | 
				
			||||||
 | 
					#define MS_UNPACKHEADERBYTEORDER(X) (unpackheaderbyteorder = X);
 | 
				
			||||||
 | 
					#define MS_UNPACKDATABYTEORDER(X) (unpackdatabyteorder = X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Global variables (defined in unpack.c) and macros to set/force
 | 
				
			||||||
 | 
					 * encoding and fallback encoding */
 | 
				
			||||||
 | 
					extern int unpackencodingformat;
 | 
				
			||||||
 | 
					extern int unpackencodingfallback;
 | 
				
			||||||
 | 
					#define MS_UNPACKENCODINGFORMAT(X) (unpackencodingformat = X);
 | 
				
			||||||
 | 
					#define MS_UNPACKENCODINGFALLBACK(X) (unpackencodingfallback = X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Mini-SEED record related functions */
 | 
				
			||||||
 | 
					extern int           msr_parse (char *record, int recbuflen, MSRecord **ppmsr, int reclen,
 | 
				
			||||||
 | 
									flag dataflag, flag verbose);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int           msr_parse_selection ( char *recbuf, int recbuflen, int64_t *offset,
 | 
				
			||||||
 | 
										   MSRecord **ppmsr, int reclen,
 | 
				
			||||||
 | 
										   Selections *selections, flag dataflag, flag verbose );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int           msr_unpack (char *record, int reclen, MSRecord **ppmsr,
 | 
				
			||||||
 | 
									 flag dataflag, flag verbose);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int           msr_pack (MSRecord *msr, void (*record_handler) (char *, int, void *),
 | 
				
			||||||
 | 
							 	       void *handlerdata, int64_t *packedsamples, flag flush, flag verbose );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int           msr_pack_header (MSRecord *msr, flag normalize, flag verbose);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int           msr_unpack_data (MSRecord *msr, int swapflag, flag verbose);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern MSRecord*     msr_init (MSRecord *msr);
 | 
				
			||||||
 | 
					extern void          msr_free (MSRecord **ppmsr);
 | 
				
			||||||
 | 
					extern void          msr_free_blktchain (MSRecord *msr);
 | 
				
			||||||
 | 
					extern BlktLink*     msr_addblockette (MSRecord *msr, char *blktdata, int length,
 | 
				
			||||||
 | 
									       int blkttype, int chainpos);
 | 
				
			||||||
 | 
					extern int           msr_normalize_header (MSRecord *msr, flag verbose);
 | 
				
			||||||
 | 
					extern MSRecord*     msr_duplicate (MSRecord *msr, flag datadup);
 | 
				
			||||||
 | 
					extern double        msr_samprate (MSRecord *msr);
 | 
				
			||||||
 | 
					extern double        msr_nomsamprate (MSRecord *msr);
 | 
				
			||||||
 | 
					extern hptime_t      msr_starttime (MSRecord *msr);
 | 
				
			||||||
 | 
					extern hptime_t      msr_starttime_uc (MSRecord *msr);
 | 
				
			||||||
 | 
					extern hptime_t      msr_endtime (MSRecord *msr);
 | 
				
			||||||
 | 
					extern char*         msr_srcname (MSRecord *msr, char *srcname, flag quality);
 | 
				
			||||||
 | 
					extern void          msr_print (MSRecord *msr, flag details);
 | 
				
			||||||
 | 
					extern double        msr_host_latency (MSRecord *msr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int           ms_detect (const char *record, int recbuflen);
 | 
				
			||||||
 | 
					extern int           ms_parse_raw (char *record, int maxreclen, flag details, flag swapflag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* MSTrace related functions */
 | 
				
			||||||
 | 
					extern MSTrace*      mst_init (MSTrace *mst);
 | 
				
			||||||
 | 
					extern void          mst_free (MSTrace **ppmst);
 | 
				
			||||||
 | 
					extern MSTraceGroup* mst_initgroup (MSTraceGroup *mstg);
 | 
				
			||||||
 | 
					extern void          mst_freegroup (MSTraceGroup **ppmstg);
 | 
				
			||||||
 | 
					extern MSTrace*      mst_findmatch (MSTrace *startmst, char dataquality,
 | 
				
			||||||
 | 
									    char *network, char *station, char *location, char *channel);
 | 
				
			||||||
 | 
					extern MSTrace*      mst_findadjacent (MSTraceGroup *mstg, flag *whence, char dataquality,
 | 
				
			||||||
 | 
									       char *network, char *station, char *location, char *channel,
 | 
				
			||||||
 | 
									       double samprate, double sampratetol,
 | 
				
			||||||
 | 
									       hptime_t starttime, hptime_t endtime, double timetol);
 | 
				
			||||||
 | 
					extern int           mst_addmsr (MSTrace *mst, MSRecord *msr, flag whence);
 | 
				
			||||||
 | 
					extern int           mst_addspan (MSTrace *mst, hptime_t starttime,  hptime_t endtime,
 | 
				
			||||||
 | 
									  void *datasamples, int64_t numsamples,
 | 
				
			||||||
 | 
									  char sampletype, flag whence);
 | 
				
			||||||
 | 
					extern MSTrace*      mst_addmsrtogroup (MSTraceGroup *mstg, MSRecord *msr, flag dataquality,
 | 
				
			||||||
 | 
										double timetol, double sampratetol);
 | 
				
			||||||
 | 
					extern MSTrace*      mst_addtracetogroup (MSTraceGroup *mstg, MSTrace *mst);
 | 
				
			||||||
 | 
					extern int           mst_groupheal (MSTraceGroup *mstg, double timetol, double sampratetol);
 | 
				
			||||||
 | 
					extern int           mst_groupsort (MSTraceGroup *mstg, flag quality);
 | 
				
			||||||
 | 
					extern int           mst_convertsamples (MSTrace *mst, char type, flag truncate);
 | 
				
			||||||
 | 
					extern char *        mst_srcname (MSTrace *mst, char *srcname, flag quality);
 | 
				
			||||||
 | 
					extern void          mst_printtracelist (MSTraceGroup *mstg, flag timeformat,
 | 
				
			||||||
 | 
										 flag details, flag gaps);
 | 
				
			||||||
 | 
					extern void          mst_printsynclist ( MSTraceGroup *mstg, char *dccid, flag subsecond );
 | 
				
			||||||
 | 
					extern void          mst_printgaplist (MSTraceGroup *mstg, flag timeformat,
 | 
				
			||||||
 | 
									       double *mingap, double *maxgap);
 | 
				
			||||||
 | 
					extern int           mst_pack (MSTrace *mst, void (*record_handler) (char *, int, void *),
 | 
				
			||||||
 | 
								       void *handlerdata, int reclen, flag encoding, flag byteorder,
 | 
				
			||||||
 | 
								       int64_t *packedsamples, flag flush, flag verbose,
 | 
				
			||||||
 | 
								       MSRecord *mstemplate);
 | 
				
			||||||
 | 
					extern int           mst_packgroup (MSTraceGroup *mstg, void (*record_handler) (char *, int, void *),
 | 
				
			||||||
 | 
									    void *handlerdata, int reclen, flag encoding, flag byteorder,
 | 
				
			||||||
 | 
									    int64_t *packedsamples, flag flush, flag verbose,
 | 
				
			||||||
 | 
									    MSRecord *mstemplate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* MSTraceList related functions */
 | 
				
			||||||
 | 
					extern MSTraceList * mstl_init ( MSTraceList *mstl );
 | 
				
			||||||
 | 
					extern void          mstl_free ( MSTraceList **ppmstl, flag freeprvtptr );
 | 
				
			||||||
 | 
					extern MSTraceSeg *  mstl_addmsr ( MSTraceList *mstl, MSRecord *msr, flag dataquality,
 | 
				
			||||||
 | 
									   flag autoheal, double timetol, double sampratetol );
 | 
				
			||||||
 | 
					extern int           mstl_convertsamples ( MSTraceSeg *seg, char type, flag truncate );
 | 
				
			||||||
 | 
					extern void          mstl_printtracelist ( MSTraceList *mstl, flag timeformat,
 | 
				
			||||||
 | 
										   flag details, flag gaps );
 | 
				
			||||||
 | 
					extern void          mstl_printsynclist ( MSTraceList *mstl, char *dccid, flag subsecond );
 | 
				
			||||||
 | 
					extern void          mstl_printgaplist (MSTraceList *mstl, flag timeformat,
 | 
				
			||||||
 | 
										double *mingap, double *maxgap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Reading Mini-SEED records from files */
 | 
				
			||||||
 | 
					typedef struct MSFileParam_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  FILE *fp;
 | 
				
			||||||
 | 
					  char  filename[512];
 | 
				
			||||||
 | 
					  char *rawrec;
 | 
				
			||||||
 | 
					  int   readlen;
 | 
				
			||||||
 | 
					  int   readoffset;
 | 
				
			||||||
 | 
					  int   packtype;
 | 
				
			||||||
 | 
					  off_t packhdroffset;
 | 
				
			||||||
 | 
					  off_t filepos;
 | 
				
			||||||
 | 
					  off_t filesize;
 | 
				
			||||||
 | 
					  int   recordcount;
 | 
				
			||||||
 | 
					} MSFileParam;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int      ms_readmsr (MSRecord **ppmsr, const char *msfile, int reclen, off_t *fpos, int *last,
 | 
				
			||||||
 | 
								    flag skipnotdata, flag dataflag, flag verbose);
 | 
				
			||||||
 | 
					extern int      ms_readmsr_r (MSFileParam **ppmsfp, MSRecord **ppmsr, const char *msfile, int reclen,
 | 
				
			||||||
 | 
								      off_t *fpos, int *last, flag skipnotdata, flag dataflag, flag verbose);
 | 
				
			||||||
 | 
					extern int      ms_readmsr_main (MSFileParam **ppmsfp, MSRecord **ppmsr, const char *msfile, int reclen,
 | 
				
			||||||
 | 
									 off_t *fpos, int *last, flag skipnotdata, flag dataflag, Selections *selections, flag verbose);
 | 
				
			||||||
 | 
					extern int      ms_readtraces (MSTraceGroup **ppmstg, const char *msfile, int reclen, double timetol, double sampratetol,
 | 
				
			||||||
 | 
								       flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
 | 
				
			||||||
 | 
					extern int      ms_readtraces_timewin (MSTraceGroup **ppmstg, const char *msfile, int reclen, double timetol, double sampratetol,
 | 
				
			||||||
 | 
									       hptime_t starttime, hptime_t endtime, flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
 | 
				
			||||||
 | 
					extern int      ms_readtraces_selection (MSTraceGroup **ppmstg, const char *msfile, int reclen, double timetol, double sampratetol,
 | 
				
			||||||
 | 
										 Selections *selections, flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
 | 
				
			||||||
 | 
					extern int      ms_readtracelist (MSTraceList **ppmstl, const char *msfile, int reclen, double timetol, double sampratetol,
 | 
				
			||||||
 | 
									  flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
 | 
				
			||||||
 | 
					extern int      ms_readtracelist_timewin (MSTraceList **ppmstl, const char *msfile, int reclen, double timetol, double sampratetol,
 | 
				
			||||||
 | 
										  hptime_t starttime, hptime_t endtime, flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
 | 
				
			||||||
 | 
					extern int      ms_readtracelist_selection (MSTraceList **ppmstl, const char *msfile, int reclen, double timetol, double sampratetol,
 | 
				
			||||||
 | 
										    Selections *selections, flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int      msr_writemseed ( MSRecord *msr, const char *msfile, flag overwrite, int reclen,
 | 
				
			||||||
 | 
									 flag encoding, flag byteorder, flag verbose );
 | 
				
			||||||
 | 
					extern int      mst_writemseed ( MSTrace *mst, const char *msfile, flag overwrite, int reclen,
 | 
				
			||||||
 | 
									 flag encoding, flag byteorder, flag verbose );
 | 
				
			||||||
 | 
					extern int      mst_writemseedgroup ( MSTraceGroup *mstg, const char *msfile, flag overwrite,
 | 
				
			||||||
 | 
									      int reclen, flag encoding, flag byteorder, flag verbose );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* General use functions */
 | 
				
			||||||
 | 
					extern char*    ms_recsrcname (char *record, char *srcname, flag quality);
 | 
				
			||||||
 | 
					extern int      ms_splitsrcname (char *srcname, char *net, char *sta, char *loc, char *chan, char *qual);
 | 
				
			||||||
 | 
					extern int      ms_strncpclean (char *dest, const char *source, int length);
 | 
				
			||||||
 | 
					extern int      ms_strncpcleantail (char *dest, const char *source, int length);
 | 
				
			||||||
 | 
					extern int      ms_strncpopen (char *dest, const char *source, int length);
 | 
				
			||||||
 | 
					extern int      ms_doy2md (int year, int jday, int *month, int *mday);
 | 
				
			||||||
 | 
					extern int      ms_md2doy (int year, int month, int mday, int *jday);
 | 
				
			||||||
 | 
					extern hptime_t ms_btime2hptime (BTime *btime);
 | 
				
			||||||
 | 
					extern char*    ms_btime2isotimestr (BTime *btime, char *isotimestr);
 | 
				
			||||||
 | 
					extern char*    ms_btime2mdtimestr (BTime *btime, char *mdtimestr);
 | 
				
			||||||
 | 
					extern char*    ms_btime2seedtimestr (BTime *btime, char *seedtimestr);
 | 
				
			||||||
 | 
					extern int      ms_hptime2btime (hptime_t hptime, BTime *btime);
 | 
				
			||||||
 | 
					extern char*    ms_hptime2isotimestr (hptime_t hptime, char *isotimestr, flag subsecond);
 | 
				
			||||||
 | 
					extern char*    ms_hptime2mdtimestr (hptime_t hptime, char *mdtimestr, flag subsecond);
 | 
				
			||||||
 | 
					extern char*    ms_hptime2seedtimestr (hptime_t hptime, char *seedtimestr, flag subsecond);
 | 
				
			||||||
 | 
					extern hptime_t ms_time2hptime (int year, int day, int hour, int min, int sec, int usec);
 | 
				
			||||||
 | 
					extern hptime_t ms_seedtimestr2hptime (char *seedtimestr);
 | 
				
			||||||
 | 
					extern hptime_t ms_timestr2hptime (char *timestr);
 | 
				
			||||||
 | 
					extern double   ms_nomsamprate (int factor, int multiplier);
 | 
				
			||||||
 | 
					extern int      ms_genfactmult (double samprate, int16_t *factor, int16_t *multiplier);
 | 
				
			||||||
 | 
					extern int      ms_ratapprox (double real, int *num, int *den, int maxval, double precision);
 | 
				
			||||||
 | 
					extern int      ms_bigendianhost (void);
 | 
				
			||||||
 | 
					extern double   ms_dabs (double val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Lookup functions */
 | 
				
			||||||
 | 
					extern uint8_t  ms_samplesize (const char sampletype);
 | 
				
			||||||
 | 
					extern char*    ms_encodingstr (const char encoding);
 | 
				
			||||||
 | 
					extern char*    ms_blktdesc (uint16_t blkttype);
 | 
				
			||||||
 | 
					extern uint16_t ms_blktlen (uint16_t blkttype, const char *blktdata, flag swapflag);
 | 
				
			||||||
 | 
					extern char *   ms_errorstr (int errorcode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Logging facility */
 | 
				
			||||||
 | 
					#define MAX_LOG_MSG_LENGTH  200      /* Maximum length of log messages */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Logging parameters */
 | 
				
			||||||
 | 
					typedef struct MSLogParam_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  void (*log_print)(char*);
 | 
				
			||||||
 | 
					  const char *logprefix;
 | 
				
			||||||
 | 
					  void (*diag_print)(char*);
 | 
				
			||||||
 | 
					  const char *errprefix;
 | 
				
			||||||
 | 
					} MSLogParam;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int    ms_log (int level, ...);
 | 
				
			||||||
 | 
					extern int    ms_log_l (MSLogParam *logp, int level, ...);
 | 
				
			||||||
 | 
					extern void   ms_loginit (void (*log_print)(char*), const char *logprefix,
 | 
				
			||||||
 | 
								  void (*diag_print)(char*), const char *errprefix);
 | 
				
			||||||
 | 
					extern MSLogParam *ms_loginit_l (MSLogParam *logp,
 | 
				
			||||||
 | 
								         void (*log_print)(char*), const char *logprefix,
 | 
				
			||||||
 | 
								         void (*diag_print)(char*), const char *errprefix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Selection functions */
 | 
				
			||||||
 | 
					extern Selections *ms_matchselect (Selections *selections, char *srcname,
 | 
				
			||||||
 | 
									   hptime_t starttime, hptime_t endtime, SelectTime **ppselecttime);
 | 
				
			||||||
 | 
					extern Selections *msr_matchselect (Selections *selections, MSRecord *msr, SelectTime **ppselecttime);
 | 
				
			||||||
 | 
					extern int      ms_addselect (Selections **ppselections, char *srcname,
 | 
				
			||||||
 | 
								      hptime_t starttime, hptime_t endtime);
 | 
				
			||||||
 | 
					extern int      ms_addselect_comp (Selections **ppselections, char *net, char* sta, char *loc,
 | 
				
			||||||
 | 
									   char *chan, char *qual, hptime_t starttime, hptime_t endtime);
 | 
				
			||||||
 | 
					extern int      ms_readselectionsfile (Selections **ppselections, char *filename);
 | 
				
			||||||
 | 
					extern void     ms_freeselections (Selections *selections);
 | 
				
			||||||
 | 
					extern void     ms_printselections (Selections *selections);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Generic byte swapping routines */
 | 
				
			||||||
 | 
					extern void     ms_gswap2 ( void *data2 );
 | 
				
			||||||
 | 
					extern void     ms_gswap3 ( void *data3 );
 | 
				
			||||||
 | 
					extern void     ms_gswap4 ( void *data4 );
 | 
				
			||||||
 | 
					extern void     ms_gswap8 ( void *data8 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Generic byte swapping routines for memory aligned quantities */
 | 
				
			||||||
 | 
					extern void     ms_gswap2a ( void *data2 );
 | 
				
			||||||
 | 
					extern void     ms_gswap4a ( void *data4 );
 | 
				
			||||||
 | 
					extern void     ms_gswap8a ( void *data8 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Byte swap macro for the BTime struct */
 | 
				
			||||||
 | 
					#define MS_SWAPBTIME(x) \
 | 
				
			||||||
 | 
					  ms_gswap2 (x.year);   \
 | 
				
			||||||
 | 
					  ms_gswap2 (x.day);    \
 | 
				
			||||||
 | 
					  ms_gswap2 (x.fract);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* LIBMSEED_H */
 | 
				
			||||||
							
								
								
									
										65
									
								
								libs/3rd-party/mseed/lmplatform.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								libs/3rd-party/mseed/lmplatform.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * lmplatform.c:
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Platform portability routines.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU Library General Public License
 | 
				
			||||||
 | 
					 * as published by the Free Software Foundation; either version 2 of
 | 
				
			||||||
 | 
					 * the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library 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
 | 
				
			||||||
 | 
					 * Library General Public License (GNU-LGPL) for more details.  The
 | 
				
			||||||
 | 
					 * GNU-LGPL and further information can be found here:
 | 
				
			||||||
 | 
					 * http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Written by Chad Trabant, IRIS Data Management Center
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * modified: 2010.304
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Define _LARGEFILE_SOURCE to get ftello/fseeko on some systems (Linux) */
 | 
				
			||||||
 | 
					#define _LARGEFILE_SOURCE 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lmplatform.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * lmp_ftello:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return the current file position for the specified descriptor using
 | 
				
			||||||
 | 
					 * the system's closest match to the POSIX ftello.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					off_t
 | 
				
			||||||
 | 
					lmp_ftello (FILE *stream)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined(LMP_WIN32)
 | 
				
			||||||
 | 
					  return (off_t) ftell (stream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  return (off_t) ftello (stream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}  /* End of lmp_ftello() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * lmp_fseeko:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Seek to a specific file position for the specified descriptor using
 | 
				
			||||||
 | 
					 * the system's closest match to the POSIX fseeko.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					lmp_fseeko (FILE *stream, off_t offset, int whence)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined(LMP_WIN32)
 | 
				
			||||||
 | 
					  return (int) fseek (stream, (long int) offset, whence);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  return (int) fseeko (stream, offset, whence);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}  /* End of lmp_fseeko() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										166
									
								
								libs/3rd-party/mseed/lmplatform.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								libs/3rd-party/mseed/lmplatform.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,166 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * lmplatform.h:
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Platform specific headers.  This file provides a basic level of platform
 | 
				
			||||||
 | 
					 * portability.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU Library General Public License
 | 
				
			||||||
 | 
					 * as published by the Free Software Foundation; either version 2 of
 | 
				
			||||||
 | 
					 * the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library 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
 | 
				
			||||||
 | 
					 * Library General Public License (GNU-LGPL) for more details.  The
 | 
				
			||||||
 | 
					 * GNU-LGPL and further information can be found here:
 | 
				
			||||||
 | 
					 * http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Written by Chad Trabant, IRIS Data Management Center
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * modified: 2014.074
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LMPLATFORM_H
 | 
				
			||||||
 | 
					#define LMPLATFORM_H 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* On some platforms (e.g. ARM) structures are aligned on word boundaries
 | 
				
			||||||
 | 
					     by adding padding between the elements.  This library uses structs that
 | 
				
			||||||
 | 
					     map to SEED header/blockette structures that are required to have a
 | 
				
			||||||
 | 
					     layout exactly as specified, i.e. no padding.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     If "ATTRIBUTE_PACKED" is defined at compile time (e.g. -DATTRIBUTE_PACKED)
 | 
				
			||||||
 | 
					     the preprocessor will use the define below to add the "packed" attribute 
 | 
				
			||||||
 | 
					     to effected structs.  This attribute is supported by GCC and increasingly
 | 
				
			||||||
 | 
					     more compilers.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					#if defined(ATTRIBUTE_PACKED)
 | 
				
			||||||
 | 
					  #define LMP_PACKED __attribute__((packed))
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  #define LMP_PACKED
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Make some guesses about the system libraries based
 | 
				
			||||||
 | 
					   * on the architecture.  Currently the assumptions are:
 | 
				
			||||||
 | 
					   * Linux => glibc2 libraries (LMP_GLIBC2)
 | 
				
			||||||
 | 
					   * Sun => Solaris libraties (LMP_SOLARIS)
 | 
				
			||||||
 | 
					   * BSD => BSD libraries, including Apple Mac OS X (LMP_BSD)
 | 
				
			||||||
 | 
					   * WIN32 => WIN32 and Windows Sockets 2 (LMP_WIN32)
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__linux__) || defined(__linux) || defined(__CYGWIN__)
 | 
				
			||||||
 | 
					  #define LMP_GLIBC2 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #include <stdlib.h>
 | 
				
			||||||
 | 
					  #include <stdio.h>
 | 
				
			||||||
 | 
					  #include <unistd.h>
 | 
				
			||||||
 | 
					  #include <stdarg.h>
 | 
				
			||||||
 | 
					  #include <inttypes.h>
 | 
				
			||||||
 | 
					  #include <sys/socket.h>
 | 
				
			||||||
 | 
					  #include <netinet/in.h>
 | 
				
			||||||
 | 
					  #include <netdb.h>
 | 
				
			||||||
 | 
					  #include <sys/time.h>
 | 
				
			||||||
 | 
					  #include <string.h>
 | 
				
			||||||
 | 
					  #include <ctype.h>
 | 
				
			||||||
 | 
					  #include <features.h>
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					#elif defined(__sun__) || defined(__sun)
 | 
				
			||||||
 | 
					  #define LMP_SOLARIS 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #include <stdlib.h>
 | 
				
			||||||
 | 
					  #include <stdio.h>
 | 
				
			||||||
 | 
					  #include <unistd.h>
 | 
				
			||||||
 | 
					  #include <stdarg.h>
 | 
				
			||||||
 | 
					  #include <inttypes.h>
 | 
				
			||||||
 | 
					  #include <sys/socket.h>
 | 
				
			||||||
 | 
					  #include <netinet/in.h>
 | 
				
			||||||
 | 
					  #include <netdb.h>
 | 
				
			||||||
 | 
					  #include <sys/time.h>
 | 
				
			||||||
 | 
					  #include <string.h>
 | 
				
			||||||
 | 
					  #include <ctype.h>
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
 | 
				
			||||||
 | 
					  #define LMP_BSD 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #include <stdlib.h>
 | 
				
			||||||
 | 
					  #include <stdio.h>
 | 
				
			||||||
 | 
					  #include <unistd.h>
 | 
				
			||||||
 | 
					  #include <stdarg.h>
 | 
				
			||||||
 | 
					  #include <inttypes.h>
 | 
				
			||||||
 | 
					  #include <sys/socket.h>
 | 
				
			||||||
 | 
					  #include <netinet/in.h>
 | 
				
			||||||
 | 
					  #include <netdb.h>
 | 
				
			||||||
 | 
					  #include <sys/time.h>
 | 
				
			||||||
 | 
					  #include <string.h>
 | 
				
			||||||
 | 
					  #include <ctype.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#elif defined(WIN32) || defined(WIN64)
 | 
				
			||||||
 | 
					  #define LMP_WIN32 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #include <windows.h>
 | 
				
			||||||
 | 
					  #include <stdarg.h>
 | 
				
			||||||
 | 
					  #include <winsock.h>
 | 
				
			||||||
 | 
					  #include <stdio.h>
 | 
				
			||||||
 | 
					  #include <sys/types.h>
 | 
				
			||||||
 | 
					  #include <ctype.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #if defined(_MSC_VER)
 | 
				
			||||||
 | 
					    #define snprintf _snprintf
 | 
				
			||||||
 | 
					    #define vsnprintf _vsnprintf
 | 
				
			||||||
 | 
					    #define strcasecmp _stricmp
 | 
				
			||||||
 | 
					    #define strncasecmp _strnicmp
 | 
				
			||||||
 | 
					    #define strtoull _strtoui64
 | 
				
			||||||
 | 
					    #define strdup _strdup
 | 
				
			||||||
 | 
					    #define fileno _fileno
 | 
				
			||||||
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #if defined(__MINGW32__) 
 | 
				
			||||||
 | 
					    #define fstat _fstat 
 | 
				
			||||||
 | 
					    #define stat _stat 
 | 
				
			||||||
 | 
					  #endif 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  typedef signed char int8_t;
 | 
				
			||||||
 | 
					  typedef unsigned char uint8_t;
 | 
				
			||||||
 | 
					  typedef signed short int int16_t;
 | 
				
			||||||
 | 
					  typedef unsigned short int uint16_t;
 | 
				
			||||||
 | 
					  typedef signed int int32_t;
 | 
				
			||||||
 | 
					  typedef unsigned int uint32_t;
 | 
				
			||||||
 | 
					  typedef signed __int64 int64_t;
 | 
				
			||||||
 | 
					  typedef unsigned __int64 uint64_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  #include <stdlib.h>
 | 
				
			||||||
 | 
					  #include <stdio.h>
 | 
				
			||||||
 | 
					  #include <unistd.h>
 | 
				
			||||||
 | 
					  #include <stdarg.h>
 | 
				
			||||||
 | 
					  #include <inttypes.h>
 | 
				
			||||||
 | 
					  #include <sys/socket.h>
 | 
				
			||||||
 | 
					  #include <netinet/in.h>
 | 
				
			||||||
 | 
					  #include <netdb.h>
 | 
				
			||||||
 | 
					  #include <sys/time.h>
 | 
				
			||||||
 | 
					  #include <string.h>
 | 
				
			||||||
 | 
					  #include <ctype.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  typedef signed char int8_t;
 | 
				
			||||||
 | 
					  typedef unsigned char uint8_t;
 | 
				
			||||||
 | 
					  typedef signed short int int16_t;
 | 
				
			||||||
 | 
					  typedef unsigned short int uint16_t;
 | 
				
			||||||
 | 
					  typedef signed int int32_t;
 | 
				
			||||||
 | 
					  typedef unsigned int uint32_t;
 | 
				
			||||||
 | 
					  typedef signed long long int64_t;
 | 
				
			||||||
 | 
					  typedef unsigned long long uint64_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern off_t lmp_ftello (FILE *stream);
 | 
				
			||||||
 | 
					extern int lmp_fseeko (FILE *stream, off_t offset, int whence);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					#endif /* LMPLATFORM_H */
 | 
				
			||||||
							
								
								
									
										334
									
								
								libs/3rd-party/mseed/logging.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										334
									
								
								libs/3rd-party/mseed/logging.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,334 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * logging.c
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Log handling routines for libmseed
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Chad Trabant
 | 
				
			||||||
 | 
					 * IRIS Data Management Center
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * modified: 2014.197
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <stdarg.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "libmseed.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ms_loginit_main (MSLogParam *logp,
 | 
				
			||||||
 | 
							      void (*log_print)(char*), const char *logprefix,
 | 
				
			||||||
 | 
							      void (*diag_print)(char*), const char *errprefix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ms_log_main (MSLogParam *logp, int level, va_list *varlist);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Initialize the global logging parameters */
 | 
				
			||||||
 | 
					MSLogParam gMSLogParam = {NULL, NULL, NULL, NULL};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_loginit:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Initialize the global logging parameters.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See ms_loginit_main() description for usage.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ms_loginit (void (*log_print)(char*), const char *logprefix,
 | 
				
			||||||
 | 
						    void (*diag_print)(char*), const char *errprefix)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  ms_loginit_main(&gMSLogParam, log_print, logprefix, diag_print, errprefix);
 | 
				
			||||||
 | 
					}  /* End of ms_loginit() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_loginit_l:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Initialize MSLogParam specific logging parameters.  If the logging parameters
 | 
				
			||||||
 | 
					 * have not been initialized (log == NULL) new parameter space will
 | 
				
			||||||
 | 
					 * be allocated.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See ms_loginit_main() description for usage.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns a pointer to the created/re-initialized MSLogParam struct
 | 
				
			||||||
 | 
					 * on success and NULL on error.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					MSLogParam *
 | 
				
			||||||
 | 
					ms_loginit_l (MSLogParam *logp,
 | 
				
			||||||
 | 
						      void (*log_print)(char*), const char *logprefix,
 | 
				
			||||||
 | 
						      void (*diag_print)(char*), const char *errprefix)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  MSLogParam *llog;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( logp == NULL )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      llog = (MSLogParam *) malloc (sizeof(MSLogParam));
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if ( llog == NULL )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          ms_log (2, "ms_loginit_l(): Cannot allocate memory\n");
 | 
				
			||||||
 | 
					          return NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      llog->log_print = NULL;
 | 
				
			||||||
 | 
					      llog->logprefix = NULL;
 | 
				
			||||||
 | 
					      llog->diag_print = NULL;
 | 
				
			||||||
 | 
					      llog->errprefix = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      llog = logp;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  ms_loginit_main (llog, log_print, logprefix, diag_print, errprefix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return llog;
 | 
				
			||||||
 | 
					}  /* End of ms_loginit_l() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_loginit_main:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Initialize the logging subsystem.  Given values determine how ms_log()
 | 
				
			||||||
 | 
					 * and ms_log_l() emit messages.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function modifies the logging parameters in the passed MSLogParam.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Any log/error printing functions indicated must except a single
 | 
				
			||||||
 | 
					 * argument, namely a string (char *).  The ms_log() and
 | 
				
			||||||
 | 
					 * ms_log_r() functions format each message and then pass the result
 | 
				
			||||||
 | 
					 * on to the log/error printing functions.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If the log/error prefixes have been set they will be pre-pended to the
 | 
				
			||||||
 | 
					 * message.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Use NULL for the function pointers or the prefixes if they should not
 | 
				
			||||||
 | 
					 * be changed from previously set or default values.  The default behavior
 | 
				
			||||||
 | 
					 * of the logging subsystem is given in the example below.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Example: ms_loginit_main (0, (void*)&printf, NULL, (void*)&printf, "error: ");
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ms_loginit_main (MSLogParam *logp,
 | 
				
			||||||
 | 
							 void (*log_print)(char*), const char *logprefix,
 | 
				
			||||||
 | 
							 void (*diag_print)(char*), const char *errprefix)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if ( ! logp )
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ( log_print )
 | 
				
			||||||
 | 
					    logp->log_print = log_print;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( logprefix )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if ( strlen(logprefix) >= MAX_LOG_MSG_LENGTH )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  ms_log_l (logp, 2, 0, "log message prefix is too large\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  logp->logprefix = logprefix;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( diag_print )
 | 
				
			||||||
 | 
					    logp->diag_print = diag_print;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( errprefix )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if ( strlen(errprefix) >= MAX_LOG_MSG_LENGTH )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  ms_log_l (logp, 2, 0, "error message prefix is too large\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  logp->errprefix = errprefix;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return;
 | 
				
			||||||
 | 
					}  /* End of ms_loginit_main() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_log:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A wrapper to ms_log_main() that uses the global logging parameters.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See ms_log_main() description for return values.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					ms_log (int level, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int retval;
 | 
				
			||||||
 | 
					  va_list varlist;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  va_start (varlist, level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  retval = ms_log_main (&gMSLogParam, level, &varlist);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  va_end (varlist);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return retval;
 | 
				
			||||||
 | 
					}  /* End of ms_log() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_log_l:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A wrapper to ms_log_main() that uses the logging parameters in a
 | 
				
			||||||
 | 
					 * supplied MSLogParam.  If the supplied pointer is NULL the global logging
 | 
				
			||||||
 | 
					 * parameters will be used.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See ms_log_main() description for return values.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					ms_log_l (MSLogParam *logp, int level, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int retval;
 | 
				
			||||||
 | 
					  va_list varlist;
 | 
				
			||||||
 | 
					  MSLogParam *llog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ( ! logp )
 | 
				
			||||||
 | 
					    llog = &gMSLogParam;
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    llog = logp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  va_start (varlist, level);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  retval = ms_log_main (llog, level, &varlist);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  va_end (varlist);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return retval;
 | 
				
			||||||
 | 
					}  /* End of ms_log_l() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_log_main:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A standard logging/printing routine.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The function uses logging parameters specified in the supplied
 | 
				
			||||||
 | 
					 * MSLogParam.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * This function expects 2+ arguments: message level, fprintf format,
 | 
				
			||||||
 | 
					 * and fprintf arguments. 
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Three levels are recognized:
 | 
				
			||||||
 | 
					 * 0  : Normal log messages, printed using log_print with logprefix
 | 
				
			||||||
 | 
					 * 1  : Diagnostic messages, printed using diag_print with logprefix
 | 
				
			||||||
 | 
					 * 2+ : Error messagess, printed using diag_print with errprefix
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function builds the log/error message and passes to it as a
 | 
				
			||||||
 | 
					 * string (char *) to the functions defined with ms_loginit() or
 | 
				
			||||||
 | 
					 * ms_loginit_l().  If the log/error printing functions have not been
 | 
				
			||||||
 | 
					 * defined messages will be printed with fprintf, log messages to
 | 
				
			||||||
 | 
					 * stdout and error messages to stderr.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If the log/error prefix's have been set with ms_loginit() or
 | 
				
			||||||
 | 
					 * ms_loginit_l() they will be pre-pended to the message.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All messages will be truncated to the MAX_LOG_MSG_LENGTH, this includes
 | 
				
			||||||
 | 
					 * any set prefix.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns the number of characters formatted on success, and a
 | 
				
			||||||
 | 
					 * a negative value on error.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					ms_log_main (MSLogParam *logp, int level, va_list *varlist)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  static char message[MAX_LOG_MSG_LENGTH];
 | 
				
			||||||
 | 
					  int retvalue = 0;
 | 
				
			||||||
 | 
					  int presize;
 | 
				
			||||||
 | 
					  const char *format;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( ! logp )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fprintf(stderr, "ms_log_main() called without specifying log parameters");
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  message[0] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  format = va_arg (*varlist, const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ( level >= 2 )  /* Error message */
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if ( logp->errprefix != NULL )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          strncpy (message, logp->errprefix, MAX_LOG_MSG_LENGTH);
 | 
				
			||||||
 | 
					          message[MAX_LOG_MSG_LENGTH - 1] = '\0';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          strncpy (message, "Error: ", MAX_LOG_MSG_LENGTH);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      presize = strlen(message);
 | 
				
			||||||
 | 
					      retvalue = vsnprintf (&message[presize],
 | 
				
			||||||
 | 
					   			    MAX_LOG_MSG_LENGTH - presize,
 | 
				
			||||||
 | 
								    format, *varlist);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      message[MAX_LOG_MSG_LENGTH - 1] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if ( logp->diag_print != NULL )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          logp->diag_print (message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          fprintf(stderr, "%s", message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else if ( level == 1 )  /* Diagnostic message */
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if ( logp->logprefix != NULL )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          strncpy (message, logp->logprefix, MAX_LOG_MSG_LENGTH);
 | 
				
			||||||
 | 
					          message[MAX_LOG_MSG_LENGTH - 1] = '\0';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      presize = strlen(message);
 | 
				
			||||||
 | 
					      retvalue = vsnprintf (&message[presize],
 | 
				
			||||||
 | 
							            MAX_LOG_MSG_LENGTH - presize,
 | 
				
			||||||
 | 
								    format, *varlist);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      message[MAX_LOG_MSG_LENGTH - 1] = '\0';
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if ( logp->diag_print != NULL )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          logp->diag_print (message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          fprintf(stderr, "%s", message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else if ( level == 0 )  /* Normal log message */
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if ( logp->logprefix != NULL )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          strncpy (message, logp->logprefix, MAX_LOG_MSG_LENGTH);
 | 
				
			||||||
 | 
					          message[MAX_LOG_MSG_LENGTH - 1] = '\0';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      presize = strlen(message);
 | 
				
			||||||
 | 
					      retvalue = vsnprintf (&message[presize],
 | 
				
			||||||
 | 
								    MAX_LOG_MSG_LENGTH - presize,
 | 
				
			||||||
 | 
								    format, *varlist);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      message[MAX_LOG_MSG_LENGTH - 1] = '\0';
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if ( logp->log_print != NULL )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
					           logp->log_print (message);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  fprintf(stdout, "%s", message);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return retvalue;
 | 
				
			||||||
 | 
					}  /* End of ms_log_main() */
 | 
				
			||||||
							
								
								
									
										235
									
								
								libs/3rd-party/mseed/lookup.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								libs/3rd-party/mseed/lookup.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,235 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * lookup.c:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Generic lookup routines for Mini-SEED information.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Written by Chad Trabant, ORFEUS/EC-Project MEREDIAN
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * modified: 2006.346
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "libmseed.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_samplesize():
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Returns the sample size based on type code or 0 for unknown.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					uint8_t
 | 
				
			||||||
 | 
					ms_samplesize (const char sampletype)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  switch (sampletype)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    case 'a':
 | 
				
			||||||
 | 
					      return 1;
 | 
				
			||||||
 | 
					    case 'i':
 | 
				
			||||||
 | 
					    case 'f':
 | 
				
			||||||
 | 
					      return 4;
 | 
				
			||||||
 | 
					    case 'd':
 | 
				
			||||||
 | 
					      return 8;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      return 0;
 | 
				
			||||||
 | 
					    }  /* end switch */
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					}  /* End of ms_samplesize() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_encodingstr():
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Returns a string describing a data encoding format.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					char *
 | 
				
			||||||
 | 
					ms_encodingstr (const char encoding)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  switch (encoding)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    case 0:
 | 
				
			||||||
 | 
					      return "ASCII text";
 | 
				
			||||||
 | 
					    case 1:
 | 
				
			||||||
 | 
					      return "16 bit integers";
 | 
				
			||||||
 | 
					    case 2:
 | 
				
			||||||
 | 
					      return "24 bit integers";
 | 
				
			||||||
 | 
					    case 3:
 | 
				
			||||||
 | 
					      return "32 bit integers";
 | 
				
			||||||
 | 
					    case 4:
 | 
				
			||||||
 | 
					      return "IEEE floating point";
 | 
				
			||||||
 | 
					    case 5:
 | 
				
			||||||
 | 
					      return "IEEE double precision float";
 | 
				
			||||||
 | 
					    case 10:
 | 
				
			||||||
 | 
					      return "STEIM 1 Compression";
 | 
				
			||||||
 | 
					    case 11:
 | 
				
			||||||
 | 
					      return "STEIM 2 Compression";
 | 
				
			||||||
 | 
					    case 12:
 | 
				
			||||||
 | 
					      return "GEOSCOPE Muxed 24 bit int";
 | 
				
			||||||
 | 
					    case 13:
 | 
				
			||||||
 | 
					      return "GEOSCOPE Muxed 16/3 bit gain/exp";
 | 
				
			||||||
 | 
					    case 14:
 | 
				
			||||||
 | 
					      return "GEOSCOPE Muxed 16/4 bit gain/exp";
 | 
				
			||||||
 | 
					    case 15:
 | 
				
			||||||
 | 
					      return "US National Network compression";
 | 
				
			||||||
 | 
					    case 16:
 | 
				
			||||||
 | 
					      return "CDSN 16 bit gain ranged";
 | 
				
			||||||
 | 
					    case 17:
 | 
				
			||||||
 | 
					      return "Graefenberg 16 bit gain ranged";
 | 
				
			||||||
 | 
					    case 18:
 | 
				
			||||||
 | 
					      return "IPG - Strasbourg 16 bit gain";
 | 
				
			||||||
 | 
					    case 19:
 | 
				
			||||||
 | 
					      return "STEIM 3 Compression";
 | 
				
			||||||
 | 
					    case 30:
 | 
				
			||||||
 | 
					      return "SRO Gain Ranged Format";
 | 
				
			||||||
 | 
					    case 31:
 | 
				
			||||||
 | 
					      return "HGLP Format";
 | 
				
			||||||
 | 
					    case 32:
 | 
				
			||||||
 | 
					      return "DWWSSN Format";
 | 
				
			||||||
 | 
					    case 33:
 | 
				
			||||||
 | 
					      return "RSTN 16 bit gain ranged";
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      return "Unknown format code";
 | 
				
			||||||
 | 
					    }  /* end switch */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  /* End of ms_encodingstr() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_blktdesc():
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return a string describing a given blockette type or NULL if the
 | 
				
			||||||
 | 
					 * type is unknown.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					char *
 | 
				
			||||||
 | 
					ms_blktdesc (uint16_t blkttype)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  switch (blkttype)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    case 100:
 | 
				
			||||||
 | 
					      return "Sample Rate";
 | 
				
			||||||
 | 
					    case 200:
 | 
				
			||||||
 | 
					      return "Generic Event Detection";
 | 
				
			||||||
 | 
					    case 201:
 | 
				
			||||||
 | 
					      return "Murdock Event Detection";
 | 
				
			||||||
 | 
					    case 300:
 | 
				
			||||||
 | 
					      return "Step Calibration";
 | 
				
			||||||
 | 
					    case 310:
 | 
				
			||||||
 | 
					      return "Sine Calibration";
 | 
				
			||||||
 | 
					    case 320:
 | 
				
			||||||
 | 
					      return "Pseudo-random Calibration";
 | 
				
			||||||
 | 
					    case 390:
 | 
				
			||||||
 | 
					      return "Generic Calibration";
 | 
				
			||||||
 | 
					    case 395:
 | 
				
			||||||
 | 
					      return "Calibration Abort";
 | 
				
			||||||
 | 
					    case 400:
 | 
				
			||||||
 | 
					      return "Beam";
 | 
				
			||||||
 | 
					    case 500:
 | 
				
			||||||
 | 
					      return "Timing";
 | 
				
			||||||
 | 
					    case 1000:
 | 
				
			||||||
 | 
					      return "Data Only SEED";
 | 
				
			||||||
 | 
					    case 1001:
 | 
				
			||||||
 | 
					      return "Data Extension";
 | 
				
			||||||
 | 
					    case 2000:
 | 
				
			||||||
 | 
					      return "Opaque Data";
 | 
				
			||||||
 | 
					    }  /* end switch */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					}  /* End of ms_blktdesc() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_blktlen():
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns the total length of a given blockette type in bytes or 0 if
 | 
				
			||||||
 | 
					 * type unknown.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					uint16_t
 | 
				
			||||||
 | 
					ms_blktlen (uint16_t blkttype, const char *blkt, flag swapflag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint16_t blktlen = 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  switch (blkttype)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    case 100:  /* Sample Rate */
 | 
				
			||||||
 | 
					      blktlen = 12;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 200:  /* Generic Event Detection */
 | 
				
			||||||
 | 
					      blktlen = 28;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 201:  /* Murdock Event Detection */
 | 
				
			||||||
 | 
					      blktlen = 36;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 300:  /* Step Calibration */
 | 
				
			||||||
 | 
					      blktlen = 32;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 310:  /* Sine Calibration */
 | 
				
			||||||
 | 
					      blktlen = 32;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 320:  /* Pseudo-random Calibration */
 | 
				
			||||||
 | 
					      blktlen = 28;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 390:  /* Generic Calibration */
 | 
				
			||||||
 | 
					      blktlen = 28;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 395:  /* Calibration Abort */
 | 
				
			||||||
 | 
					      blktlen = 16;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 400:  /* Beam */
 | 
				
			||||||
 | 
					      blktlen = 16;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 500:  /* Timing */
 | 
				
			||||||
 | 
					      blktlen = 8;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 1000: /* Data Only SEED */
 | 
				
			||||||
 | 
					      blktlen = 8;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 1001: /* Data Extension */
 | 
				
			||||||
 | 
					      blktlen = 8;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 2000: /* Opaque Data */
 | 
				
			||||||
 | 
					      /* First 2-byte field after the blockette header is the length */
 | 
				
			||||||
 | 
					      if ( blkt )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  memcpy ((void *) &blktlen, blkt+4, sizeof (int16_t));
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap2 (&blktlen);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }  /* end switch */
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return blktlen;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					}  /* End of ms_blktlen() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_errorstr():
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return a string describing a given libmseed error code or NULL if the
 | 
				
			||||||
 | 
					 * code is unknown.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					char *
 | 
				
			||||||
 | 
					ms_errorstr (int errorcode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  switch (errorcode)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    case MS_ENDOFFILE:
 | 
				
			||||||
 | 
					      return "End of file reached";
 | 
				
			||||||
 | 
					    case MS_NOERROR:
 | 
				
			||||||
 | 
					      return "No error";
 | 
				
			||||||
 | 
					    case MS_GENERROR:
 | 
				
			||||||
 | 
					      return "Generic error";
 | 
				
			||||||
 | 
					    case MS_NOTSEED:
 | 
				
			||||||
 | 
					      return "No SEED data detected";
 | 
				
			||||||
 | 
					    case MS_WRONGLENGTH:
 | 
				
			||||||
 | 
					      return "Length of data read does not match record length";
 | 
				
			||||||
 | 
					    case MS_OUTOFRANGE:
 | 
				
			||||||
 | 
					      return "SEED record length out of range";
 | 
				
			||||||
 | 
					    case MS_UNKNOWNFORMAT:
 | 
				
			||||||
 | 
					      return "Unknown data encoding format";
 | 
				
			||||||
 | 
					    case MS_STBADCOMPFLAG:
 | 
				
			||||||
 | 
					      return "Bad Steim compression flag(s) detected";
 | 
				
			||||||
 | 
					    }				/* end switch */
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  /* End of ms_blktdesc() */
 | 
				
			||||||
							
								
								
									
										1179
									
								
								libs/3rd-party/mseed/msrutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1179
									
								
								libs/3rd-party/mseed/msrutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1065
									
								
								libs/3rd-party/mseed/pack.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1065
									
								
								libs/3rd-party/mseed/pack.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										699
									
								
								libs/3rd-party/mseed/packdata.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										699
									
								
								libs/3rd-party/mseed/packdata.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,699 @@
 | 
				
			|||||||
 | 
					/***********************************************************************
 | 
				
			||||||
 | 
					 *  Routines for packing INT_32, INT_16, FLOAT_32, FLOAT_64,
 | 
				
			||||||
 | 
					 *  STEIM1 and STEIM2 data records.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	Douglas Neuhauser						
 | 
				
			||||||
 | 
					 *	Seismological Laboratory					
 | 
				
			||||||
 | 
					 *	University of California, Berkeley				
 | 
				
			||||||
 | 
					 *	doug@seismo.berkeley.edu					
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * modified Aug 2008:
 | 
				
			||||||
 | 
					 *  - Optimize Steim 1 & 2 packing routines using small, re-used buffers.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * modified Sep 2004:
 | 
				
			||||||
 | 
					 *  - Reworked and cleaned routines for use within libmseed.
 | 
				
			||||||
 | 
					 *  - Added float32 and float64 packing routines.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Modified by Chad Trabant, IRIS Data Management Center
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * modified: 2009.111
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 1996-2004 The Regents of the University of California.
 | 
				
			||||||
 | 
					 * All Rights Reserved.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Permission to use, copy, modify, and distribute this software and its
 | 
				
			||||||
 | 
					 * documentation for educational, research and non-profit purposes,
 | 
				
			||||||
 | 
					 * without fee, and without a written agreement is hereby granted,
 | 
				
			||||||
 | 
					 * provided that the above copyright notice, this paragraph and the
 | 
				
			||||||
 | 
					 * following three paragraphs appear in all copies.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Permission to incorporate this software into commercial products may
 | 
				
			||||||
 | 
					 * be obtained from the Office of Technology Licensing, 2150 Shattuck
 | 
				
			||||||
 | 
					 * Avenue, Suite 510, Berkeley, CA  94704.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
 | 
				
			||||||
 | 
					 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
 | 
				
			||||||
 | 
					 * INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND
 | 
				
			||||||
 | 
					 * ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN
 | 
				
			||||||
 | 
					 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 | 
				
			||||||
 | 
					 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE
 | 
				
			||||||
 | 
					 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 | 
				
			||||||
 | 
					 * CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
 | 
				
			||||||
 | 
					 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <memory.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "libmseed.h"
 | 
				
			||||||
 | 
					#include "packdata.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int pad_steim_frame (DFRAMES*, int, int, int, int, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	EMPTY_BLOCK(fn,wn) (fn+wn == 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	X0  dframes->f[0].w[0].fw
 | 
				
			||||||
 | 
					#define	XN  dframes->f[0].w[1].fw
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	BIT4PACK(i,points_remaining)		   \
 | 
				
			||||||
 | 
					  (points_remaining >= 7 &&			   \
 | 
				
			||||||
 | 
					   (minbits[i] <= 4) && (minbits[i+1] <= 4) &&	   \
 | 
				
			||||||
 | 
					   (minbits[i+2] <= 4) && (minbits[i+3] <= 4) &&   \
 | 
				
			||||||
 | 
					   (minbits[i+4] <= 4) && (minbits[i+5] <= 4) &&   \
 | 
				
			||||||
 | 
					   (minbits[i+6] <= 4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	BIT5PACK(i,points_remaining)		   \
 | 
				
			||||||
 | 
					  (points_remaining >= 6 &&			   \
 | 
				
			||||||
 | 
					   (minbits[i] <= 5) && (minbits[i+1] <= 5) &&	   \
 | 
				
			||||||
 | 
					   (minbits[i+2] <= 5) && (minbits[i+3] <= 5) &&   \
 | 
				
			||||||
 | 
					   (minbits[i+4] <= 5) && (minbits[i+5] <= 5))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	BIT6PACK(i,points_remaining)		   \
 | 
				
			||||||
 | 
					  (points_remaining >= 5 &&			   \
 | 
				
			||||||
 | 
					   (minbits[i] <= 6) && (minbits[i+1] <= 6) &&	   \
 | 
				
			||||||
 | 
					   (minbits[i+2] <= 6) && (minbits[i+3] <= 6) &&   \
 | 
				
			||||||
 | 
					   (minbits[i+4] <= 6))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	BYTEPACK(i,points_remaining)		 \
 | 
				
			||||||
 | 
					  (points_remaining >= 4 &&			 \
 | 
				
			||||||
 | 
					   (minbits[i] <= 8) && (minbits[i+1] <= 8) &&	 \
 | 
				
			||||||
 | 
					   (minbits[i+2] <= 8) && (minbits[i+3] <= 8))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	BIT10PACK(i,points_remaining)		   \
 | 
				
			||||||
 | 
					  (points_remaining >= 3 &&			   \
 | 
				
			||||||
 | 
					   (minbits[i] <= 10) && (minbits[i+1] <= 10) &&   \
 | 
				
			||||||
 | 
					   (minbits[i+2] <= 10))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	BIT15PACK(i,points_remaining)		\
 | 
				
			||||||
 | 
					  (points_remaining >= 2 &&			\
 | 
				
			||||||
 | 
					   (minbits[i] <= 15) && (minbits[i+1] <= 15))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	HALFPACK(i,points_remaining)					\
 | 
				
			||||||
 | 
					  (points_remaining >= 2 && (minbits[i] <= 16) && (minbits[i+1] <= 16))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	BIT30PACK(i,points_remaining)  \
 | 
				
			||||||
 | 
					  (points_remaining >= 1 &&	       \
 | 
				
			||||||
 | 
					   (minbits[i] <= 30))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	MINBITS(diff,minbits)					       \
 | 
				
			||||||
 | 
					  if (diff >= -8 && diff < 8) minbits = 4;			       \
 | 
				
			||||||
 | 
					  else if (diff >= -16 && diff < 16) minbits = 5;		       \
 | 
				
			||||||
 | 
					  else if (diff >= -32 && diff < 32) minbits = 6;		       \
 | 
				
			||||||
 | 
					  else if (diff >= -128 && diff < 128) minbits = 8;		       \
 | 
				
			||||||
 | 
					  else if (diff >= -512 && diff < 512) minbits = 10;		       \
 | 
				
			||||||
 | 
					  else if (diff >= -16384 && diff < 16384) minbits = 15;	       \
 | 
				
			||||||
 | 
					  else if (diff >= -32768 && diff < 32768) minbits = 16;	       \
 | 
				
			||||||
 | 
					  else if (diff >= -536870912 && diff < 536870912) minbits = 30;       \
 | 
				
			||||||
 | 
					  else minbits = 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PACK(bits,n,m1,m2)  {			\
 | 
				
			||||||
 | 
					    int i = 0;					\
 | 
				
			||||||
 | 
					    unsigned int val = 0;			\
 | 
				
			||||||
 | 
					    for (i=0;i<n;i++) {				\
 | 
				
			||||||
 | 
					      val = (val<<bits) | (diff[i]&m1); 	\
 | 
				
			||||||
 | 
					    }						\
 | 
				
			||||||
 | 
					    val |= ((unsigned int)m2 << 30);		\
 | 
				
			||||||
 | 
					    dframes->f[fn].w[wn].fw = val; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_pack_int_16:							*
 | 
				
			||||||
 | 
					 *	Pack integer data into INT_16 format.				*
 | 
				
			||||||
 | 
					 *	Return: 0 on success, -1 on failure.				*
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_pack_int_16
 | 
				
			||||||
 | 
					 (int16_t    *packed,           /* output data array - packed           */
 | 
				
			||||||
 | 
					  int32_t    *data,             /* input data array                     */
 | 
				
			||||||
 | 
					  int         ns,               /* desired number of samples to pack    */
 | 
				
			||||||
 | 
					  int         max_bytes,        /* max # of bytes for output buffer     */
 | 
				
			||||||
 | 
					  int         pad,              /* flag to specify padding to max_bytes */
 | 
				
			||||||
 | 
					  int        *pnbytes,          /* number of bytes actually packed      */
 | 
				
			||||||
 | 
					  int        *pnsamples,        /* number of samples actually packed    */
 | 
				
			||||||
 | 
					  int         swapflag)         /* if data should be swapped            */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int points_remaining = ns;    /* number of samples remaining to pack  */
 | 
				
			||||||
 | 
					  int i = 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  while (points_remaining > 0 && max_bytes >= 2)
 | 
				
			||||||
 | 
					    {  /* Pack the next available data into INT_16 format */
 | 
				
			||||||
 | 
					      if ( data[i] < -32768 || data[i] > 32767 )
 | 
				
			||||||
 | 
						ms_log (2, "msr_pack_int_16(%s): input sample out of range: %d\n",
 | 
				
			||||||
 | 
							PACK_SRCNAME, data[i]);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      *packed = data[i];      
 | 
				
			||||||
 | 
					      if ( swapflag ) ms_gswap2 (packed);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      packed++;
 | 
				
			||||||
 | 
					      max_bytes -= 2;
 | 
				
			||||||
 | 
					      points_remaining--;
 | 
				
			||||||
 | 
					      i++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *pnbytes = (ns - points_remaining) * 2;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Pad miniSEED block if necessary */
 | 
				
			||||||
 | 
					  if (pad)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      memset ((void *)packed, 0, max_bytes);
 | 
				
			||||||
 | 
					      *pnbytes += max_bytes;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  *pnsamples = ns - points_remaining;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_pack_int_32:							*
 | 
				
			||||||
 | 
					 *	Pack integer data into INT_32 format.				*
 | 
				
			||||||
 | 
					 *	Return: 0 on success, -1 on failure.				*
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_pack_int_32 
 | 
				
			||||||
 | 
					 (int32_t  *packed,          /* output data array - packed              */
 | 
				
			||||||
 | 
					  int32_t  *data,            /* input data array - unpacked             */
 | 
				
			||||||
 | 
					  int       ns,              /* desired number of samples to pack       */
 | 
				
			||||||
 | 
					  int       max_bytes,       /* max # of bytes for output buffer        */
 | 
				
			||||||
 | 
					  int       pad,             /* flag to specify padding to max_bytes    */
 | 
				
			||||||
 | 
					  int      *pnbytes,         /* number of bytes actually packed         */
 | 
				
			||||||
 | 
					  int      *pnsamples,       /* number of samples actually packed       */
 | 
				
			||||||
 | 
					  int       swapflag)        /* if data should be swapped               */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int points_remaining = ns; /* number of samples remaining to pack */
 | 
				
			||||||
 | 
					  int i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (points_remaining > 0 && max_bytes >= 4)
 | 
				
			||||||
 | 
					    { /* Pack the next available data into INT_32 format */
 | 
				
			||||||
 | 
					      *packed = data[i];
 | 
				
			||||||
 | 
					      if ( swapflag ) ms_gswap4 (packed);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      packed++;
 | 
				
			||||||
 | 
					      max_bytes -= 4;
 | 
				
			||||||
 | 
					      points_remaining--;
 | 
				
			||||||
 | 
					      i++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *pnbytes = (ns - points_remaining) * 4;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Pad miniSEED block if necessary */
 | 
				
			||||||
 | 
					  if (pad)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      memset ((void *)packed, 0, max_bytes);
 | 
				
			||||||
 | 
					      *pnbytes += max_bytes;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *pnsamples = ns - points_remaining;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_pack_float_32:							*
 | 
				
			||||||
 | 
					 *	Pack float data into FLOAT32 format.				*
 | 
				
			||||||
 | 
					 *	Return: 0 on success, -1 on error.				*
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_pack_float_32 
 | 
				
			||||||
 | 
					 (float    *packed,          /* output data array - packed              */
 | 
				
			||||||
 | 
					  float    *data,            /* input data array - unpacked             */
 | 
				
			||||||
 | 
					  int       ns,              /* desired number of samples to pack       */
 | 
				
			||||||
 | 
					  int       max_bytes,       /* max # of bytes for output buffer        */
 | 
				
			||||||
 | 
					  int       pad,             /* flag to specify padding to max_bytes    */
 | 
				
			||||||
 | 
					  int      *pnbytes,         /* number of bytes actually packed         */
 | 
				
			||||||
 | 
					  int      *pnsamples,       /* number of samples actually packed       */
 | 
				
			||||||
 | 
					  int       swapflag)        /* if data should be swapped               */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int points_remaining = ns; /* number of samples remaining to pack */
 | 
				
			||||||
 | 
					  int i = 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  while (points_remaining > 0 && max_bytes >= 4)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      *packed = data[i];
 | 
				
			||||||
 | 
					      if ( swapflag ) ms_gswap4 (packed);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      packed++;
 | 
				
			||||||
 | 
					      max_bytes -= 4;
 | 
				
			||||||
 | 
					      points_remaining--;
 | 
				
			||||||
 | 
					      i++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *pnbytes = (ns - points_remaining) * 4;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Pad miniSEED block if necessary */
 | 
				
			||||||
 | 
					  if (pad)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      memset ((void *)packed, 0, max_bytes);
 | 
				
			||||||
 | 
					      *pnbytes += max_bytes;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *pnsamples = ns - points_remaining;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_pack_float_64:							*
 | 
				
			||||||
 | 
					 *	Pack double data into FLOAT64 format.				*
 | 
				
			||||||
 | 
					 *	Return: 0 on success, -1 on error.				*
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_pack_float_64 
 | 
				
			||||||
 | 
					 (double   *packed,          /* output data array - packed              */
 | 
				
			||||||
 | 
					  double   *data,            /* input data array - unpacked             */
 | 
				
			||||||
 | 
					  int       ns,              /* desired number of samples to pack       */
 | 
				
			||||||
 | 
					  int       max_bytes,       /* max # of bytes for output buffer        */
 | 
				
			||||||
 | 
					  int       pad,             /* flag to specify padding to max_bytes    */
 | 
				
			||||||
 | 
					  int      *pnbytes,         /* number of bytes actually packed         */
 | 
				
			||||||
 | 
					  int      *pnsamples,       /* number of samples actually packed       */
 | 
				
			||||||
 | 
					  int       swapflag)        /* if data should be swapped               */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int points_remaining = ns; /* number of samples remaining to pack */
 | 
				
			||||||
 | 
					  int i = 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  while (points_remaining > 0 && max_bytes >= 8)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      *packed = data[i];
 | 
				
			||||||
 | 
					      if ( swapflag ) ms_gswap8 (packed);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      packed++;
 | 
				
			||||||
 | 
					      max_bytes -= 8;
 | 
				
			||||||
 | 
					      points_remaining--;
 | 
				
			||||||
 | 
					      i++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *pnbytes = (ns - points_remaining) * 8;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Pad miniSEED block if necessary */
 | 
				
			||||||
 | 
					  if (pad)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      memset ((void *)packed, 0, max_bytes);
 | 
				
			||||||
 | 
					      *pnbytes += max_bytes;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *pnsamples = ns - points_remaining;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_pack_steim1:							*
 | 
				
			||||||
 | 
					 *	Pack data into STEIM1 data frames.				*
 | 
				
			||||||
 | 
					 *  return:								*
 | 
				
			||||||
 | 
					 *	0 on success.							*
 | 
				
			||||||
 | 
					 *	-1 on error.		           	         	        *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_pack_steim1
 | 
				
			||||||
 | 
					 (DFRAMES      *dframes,       	/* ptr to data frames                   */
 | 
				
			||||||
 | 
					  int32_t      *data,		/* ptr to unpacked data array           */
 | 
				
			||||||
 | 
					  int32_t       d0,		/* first difference value               */
 | 
				
			||||||
 | 
					  int		ns,		/* number of samples to pack            */
 | 
				
			||||||
 | 
					  int		nf,		/* total number of data frames          */
 | 
				
			||||||
 | 
					  int		pad,		/* flag to specify padding to nf        */
 | 
				
			||||||
 | 
					  int	       *pnframes,	/* number of frames actually packed     */
 | 
				
			||||||
 | 
					  int	       *pnsamples,	/* number of samples actually packed    */
 | 
				
			||||||
 | 
					  int           swapflag)       /* if data should be swapped            */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int		points_remaining = ns;
 | 
				
			||||||
 | 
					  int           points_packed = 0;
 | 
				
			||||||
 | 
					  int32_t       diff[4];        /* array of differences                 */
 | 
				
			||||||
 | 
					  uint8_t       minbits[4];     /* array of minimum bits for diffs      */
 | 
				
			||||||
 | 
					  int		i, j;
 | 
				
			||||||
 | 
					  int		mask;
 | 
				
			||||||
 | 
					  int		ipt = 0;	/* index of initial data to pack.	*/
 | 
				
			||||||
 | 
					  int		fn = 0;		/* index of initial frame to pack.	*/
 | 
				
			||||||
 | 
					  int		wn = 2;		/* index of initial word to pack.	*/
 | 
				
			||||||
 | 
					  int32_t      	itmp;
 | 
				
			||||||
 | 
					  int16_t	stmp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Calculate initial difference and minbits buffers */
 | 
				
			||||||
 | 
					  diff[0] = d0;
 | 
				
			||||||
 | 
					  MINBITS(diff[0],minbits[0]);
 | 
				
			||||||
 | 
					  for (i=1; i < 4 && i < ns; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      diff[i] = data[i] - data[i-1];
 | 
				
			||||||
 | 
					      MINBITS(diff[i],minbits[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  dframes->f[fn].ctrl = 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Set X0 and XN values in first frame */
 | 
				
			||||||
 | 
					  X0 = data[0];
 | 
				
			||||||
 | 
					  if ( swapflag ) ms_gswap4 (&X0);
 | 
				
			||||||
 | 
					  dframes->f[0].ctrl = (dframes->f[0].ctrl<<2) | STEIM1_SPECIAL_MASK;
 | 
				
			||||||
 | 
					  XN = data[ns-1];
 | 
				
			||||||
 | 
					  if ( swapflag ) ms_gswap4 (&XN);
 | 
				
			||||||
 | 
					  dframes->f[0].ctrl = (dframes->f[0].ctrl<<2) | STEIM1_SPECIAL_MASK;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  while (points_remaining > 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      points_packed = 0;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Pack the next available data into the most compact form */
 | 
				
			||||||
 | 
					      if (BYTEPACK(0,points_remaining))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  mask = STEIM1_BYTE_MASK;
 | 
				
			||||||
 | 
						  for (j=0; j<4; j++) { dframes->f[fn].w[wn].byte[j] = diff[j]; }
 | 
				
			||||||
 | 
						  points_packed = 4;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else if (HALFPACK(0,points_remaining))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  mask = STEIM1_HALFWORD_MASK;
 | 
				
			||||||
 | 
						  for (j=0; j<2; j++)
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      stmp = diff[j];
 | 
				
			||||||
 | 
						      if ( swapflag ) ms_gswap2 (&stmp);
 | 
				
			||||||
 | 
						      dframes->f[fn].w[wn].hw[j] = stmp;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  points_packed = 2;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  mask = STEIM1_FULLWORD_MASK;
 | 
				
			||||||
 | 
						  itmp = diff[0];
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap4 (&itmp);
 | 
				
			||||||
 | 
						  dframes->f[fn].w[wn].fw = itmp;
 | 
				
			||||||
 | 
						  points_packed = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Append mask for this word to current mask */
 | 
				
			||||||
 | 
					      dframes->f[fn].ctrl = (dframes->f[fn].ctrl<<2) | mask;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      points_remaining -= points_packed;
 | 
				
			||||||
 | 
					      ipt += points_packed;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Check for full frame or full block */
 | 
				
			||||||
 | 
					      if (++wn >= VALS_PER_FRAME)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap4 (&dframes->f[fn].ctrl);
 | 
				
			||||||
 | 
						  /* Reset output index to beginning of frame */
 | 
				
			||||||
 | 
						  wn = 0;
 | 
				
			||||||
 | 
						  /* If block is full, output block and reinitialize */
 | 
				
			||||||
 | 
						  if (++fn >= nf) break;
 | 
				
			||||||
 | 
						  dframes->f[fn].ctrl = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Shift and re-fill difference and minbits buffers */
 | 
				
			||||||
 | 
					      for ( i=points_packed; i < 4; i++ )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  /* Shift remaining buffer entries */
 | 
				
			||||||
 | 
						  diff[i-points_packed] = diff[i];
 | 
				
			||||||
 | 
						  minbits[i-points_packed] = minbits[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      for ( i=4-points_packed,j=ipt+(4-points_packed); i < 4 && j < ns; i++,j++ )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  /* Re-fill entries */
 | 
				
			||||||
 | 
						  diff[i] = data[j] - data[j-1];
 | 
				
			||||||
 | 
						  MINBITS(diff[i],minbits[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Update XN value in first frame */
 | 
				
			||||||
 | 
					  XN = data[(ns-1)-points_remaining];
 | 
				
			||||||
 | 
					  if ( swapflag ) ms_gswap4 (&XN);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* End of data.  Pad current frame and optionally rest of block */
 | 
				
			||||||
 | 
					  /* Do not pad and output a completely empty block */
 | 
				
			||||||
 | 
					  if ( ! EMPTY_BLOCK(fn,wn) )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      *pnframes = pad_steim_frame (dframes, fn, wn, nf, swapflag, pad);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      *pnframes = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *pnsamples = ns - points_remaining;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_pack_steim2:							*
 | 
				
			||||||
 | 
					 *	Pack data into STEIM1 data frames.				*
 | 
				
			||||||
 | 
					 *  return:								*
 | 
				
			||||||
 | 
					 *	0 on success.							*
 | 
				
			||||||
 | 
					 *	-1 on error.                                                    *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_pack_steim2
 | 
				
			||||||
 | 
					 (DFRAMES      *dframes,	/* ptr to data frames                   */
 | 
				
			||||||
 | 
					  int32_t      *data,		/* ptr to unpacked data array           */
 | 
				
			||||||
 | 
					  int32_t       d0,		/* first difference value               */
 | 
				
			||||||
 | 
					  int		ns,		/* number of samples to pack            */
 | 
				
			||||||
 | 
					  int		nf,		/* total number of data frames to pack  */
 | 
				
			||||||
 | 
					  int		pad,		/* flag to specify padding to nf        */
 | 
				
			||||||
 | 
					  int	       *pnframes,	/* number of frames actually packed     */
 | 
				
			||||||
 | 
					  int	       *pnsamples,	/* number of samples actually packed    */
 | 
				
			||||||
 | 
					  int           swapflag)       /* if data should be swapped            */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int		points_remaining = ns;
 | 
				
			||||||
 | 
					  int           points_packed = 0;
 | 
				
			||||||
 | 
					  int32_t       diff[7];        /* array of differences                 */
 | 
				
			||||||
 | 
					  uint8_t       minbits[7];     /* array of minimum bits for diffs      */
 | 
				
			||||||
 | 
					  int		i, j;
 | 
				
			||||||
 | 
					  int		mask;
 | 
				
			||||||
 | 
					  int		ipt = 0;	/* index of initial data to pack.	*/
 | 
				
			||||||
 | 
					  int		fn = 0;		/* index of initial frame to pack.	*/
 | 
				
			||||||
 | 
					  int		wn = 2;		/* index of initial word to pack.	*/
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Calculate initial difference and minbits buffers */
 | 
				
			||||||
 | 
					  diff[0] = d0;
 | 
				
			||||||
 | 
					  MINBITS(diff[0],minbits[0]);
 | 
				
			||||||
 | 
					  for (i=1; i < 7 && i < ns; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      diff[i] = data[i] - data[i-1];
 | 
				
			||||||
 | 
					      MINBITS(diff[i],minbits[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  dframes->f[fn].ctrl = 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Set X0 and XN values in first frame */
 | 
				
			||||||
 | 
					  X0 = data[0];
 | 
				
			||||||
 | 
					  if ( swapflag ) ms_gswap4 (&X0);
 | 
				
			||||||
 | 
					  dframes->f[0].ctrl = (dframes->f[0].ctrl<<2) | STEIM2_SPECIAL_MASK;
 | 
				
			||||||
 | 
					  XN = data[ns-1];
 | 
				
			||||||
 | 
					  if ( swapflag ) ms_gswap4 (&XN);
 | 
				
			||||||
 | 
					  dframes->f[0].ctrl = (dframes->f[0].ctrl<<2) | STEIM2_SPECIAL_MASK;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  while (points_remaining > 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      points_packed = 0;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Pack the next available datapoints into the most compact form */
 | 
				
			||||||
 | 
					      if (BIT4PACK(0,points_remaining))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  PACK(4,7,0x0000000f,02)
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap4 (&dframes->f[fn].w[wn].fw);
 | 
				
			||||||
 | 
						  mask = STEIM2_567_MASK;
 | 
				
			||||||
 | 
						  points_packed = 7;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else if (BIT5PACK(0,points_remaining))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  PACK(5,6,0x0000001f,01)
 | 
				
			||||||
 | 
						    if ( swapflag ) ms_gswap4 (&dframes->f[fn].w[wn].fw);
 | 
				
			||||||
 | 
						  mask = STEIM2_567_MASK;
 | 
				
			||||||
 | 
						  points_packed = 6;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else if (BIT6PACK(0,points_remaining))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  PACK(6,5,0x0000003f,00)
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap4 (&dframes->f[fn].w[wn].fw);
 | 
				
			||||||
 | 
						  mask = STEIM2_567_MASK;
 | 
				
			||||||
 | 
						  points_packed = 5;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else if (BYTEPACK(0,points_remaining))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  mask = STEIM2_BYTE_MASK;
 | 
				
			||||||
 | 
						  for (j=0; j<4; j++) dframes->f[fn].w[wn].byte[j] = diff[j];
 | 
				
			||||||
 | 
						  points_packed = 4;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else if (BIT10PACK(0,points_remaining))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  PACK(10,3,0x000003ff,03)
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap4 (&dframes->f[fn].w[wn].fw);
 | 
				
			||||||
 | 
						  mask = STEIM2_123_MASK;
 | 
				
			||||||
 | 
						  points_packed = 3;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else if (BIT15PACK(0,points_remaining))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  PACK(15,2,0x00007fff,02)
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap4 (&dframes->f[fn].w[wn].fw);
 | 
				
			||||||
 | 
						  mask = STEIM2_123_MASK;
 | 
				
			||||||
 | 
						  points_packed = 2;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else if (BIT30PACK(0,points_remaining))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  PACK(30,1,0x3fffffff,01)
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap4 (&dframes->f[fn].w[wn].fw);
 | 
				
			||||||
 | 
						  mask = STEIM2_123_MASK;
 | 
				
			||||||
 | 
						  points_packed = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  ms_log (2, "msr_pack_steim2(%s): Unable to represent difference in <= 30 bits\n",
 | 
				
			||||||
 | 
							  PACK_SRCNAME);
 | 
				
			||||||
 | 
						  return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Append mask for this word to current mask */
 | 
				
			||||||
 | 
					      dframes->f[fn].ctrl = (dframes->f[fn].ctrl<<2) | mask;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      points_remaining -= points_packed;
 | 
				
			||||||
 | 
					      ipt += points_packed;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Check for full frame or full block */
 | 
				
			||||||
 | 
					      if (++wn >= VALS_PER_FRAME)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap4 (&dframes->f[fn].ctrl);
 | 
				
			||||||
 | 
						  /* Reset output index to beginning of frame */
 | 
				
			||||||
 | 
						  wn = 0;
 | 
				
			||||||
 | 
						  /* If block is full, output block and reinitialize */
 | 
				
			||||||
 | 
						  if (++fn >= nf) break;
 | 
				
			||||||
 | 
						  dframes->f[fn].ctrl = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Shift and re-fill difference and minbits buffers */
 | 
				
			||||||
 | 
					      for ( i=points_packed; i < 7; i++ )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  /* Shift remaining buffer entries */
 | 
				
			||||||
 | 
						  diff[i-points_packed] = diff[i];
 | 
				
			||||||
 | 
						  minbits[i-points_packed] = minbits[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      for ( i=7-points_packed,j=ipt+(7-points_packed); i < 7 && j < ns; i++,j++ )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  /* Re-fill entries */
 | 
				
			||||||
 | 
						  diff[i] = data[j] - data[j-1];
 | 
				
			||||||
 | 
						  MINBITS(diff[i],minbits[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Update XN value in first frame */
 | 
				
			||||||
 | 
					  XN = data[(ns-1)-points_remaining];
 | 
				
			||||||
 | 
					  if ( swapflag ) ms_gswap4 (&XN);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* End of data.  Pad current frame and optionally rest of block */
 | 
				
			||||||
 | 
					  /* Do not pad and output a completely empty block */
 | 
				
			||||||
 | 
					  if ( ! EMPTY_BLOCK(fn,wn) )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      *pnframes = pad_steim_frame (dframes, fn, wn, nf, swapflag, pad);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      *pnframes = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *pnsamples = ns - points_remaining;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  pad_steim_frame:							*
 | 
				
			||||||
 | 
					 *	Pad the rest of the data record with null values,		*
 | 
				
			||||||
 | 
					 *	and optionally the rest of the total number of frames.		*
 | 
				
			||||||
 | 
					 *  return:								*
 | 
				
			||||||
 | 
					 *	total number of frames in record.				*
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					static int pad_steim_frame
 | 
				
			||||||
 | 
					 (DFRAMES      *dframes,
 | 
				
			||||||
 | 
					  int		fn,	    	/* current frame number.		*/
 | 
				
			||||||
 | 
					  int	    	wn,		/* current work number.			*/
 | 
				
			||||||
 | 
					  int	    	nf,		/* total number of data frames.		*/
 | 
				
			||||||
 | 
					  int		swapflag,	/* flag to swap byte order of data.	*/
 | 
				
			||||||
 | 
					  int	    	pad)		/* flag to pad # frames to nf.		*/
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  /* Finish off the current frame */
 | 
				
			||||||
 | 
					  if (wn < VALS_PER_FRAME && fn < nf)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      for (; wn < VALS_PER_FRAME; wn++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  dframes->f[fn].w[wn].fw = 0;
 | 
				
			||||||
 | 
						  dframes->f[fn].ctrl = (dframes->f[fn].ctrl<<2) | STEIM1_SPECIAL_MASK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      if ( swapflag ) ms_gswap4 (&dframes->f[fn].ctrl);
 | 
				
			||||||
 | 
					      fn++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Fill the remaining frames in the block */
 | 
				
			||||||
 | 
					  if (pad)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      for (; fn<nf; fn++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  dframes->f[fn].ctrl = STEIM1_SPECIAL_MASK;	/* mask for ctrl */
 | 
				
			||||||
 | 
						  for (wn=0; wn<VALS_PER_FRAME; wn++)
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      dframes->f[fn].w[wn].fw = 0;
 | 
				
			||||||
 | 
						      dframes->f[fn].ctrl = (dframes->f[fn].ctrl<<2) | STEIM1_SPECIAL_MASK;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap4 (&dframes->f[fn].ctrl);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return fn;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_pack_text:						       	*
 | 
				
			||||||
 | 
					 *	Pack text data into text format.  Split input data on line	*
 | 
				
			||||||
 | 
					*	breaks so as to not split lines between records.		* 
 | 
				
			||||||
 | 
					*	Return: 0 on success, -1 on error.				*
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_pack_text
 | 
				
			||||||
 | 
					 (char 	       *packed,         /* output data array - packed.		*/
 | 
				
			||||||
 | 
					  char	       *data,		/* input data array - unpacked.		*/
 | 
				
			||||||
 | 
					  int		ns,		/* desired number of samples to pack.	*/
 | 
				
			||||||
 | 
					  int		max_bytes,	/* max # of bytes for output buffer.	*/
 | 
				
			||||||
 | 
					  int		pad,		/* flag to specify padding to max_bytes.*/
 | 
				
			||||||
 | 
					  int	       *pnbytes,	/* number of bytes actually packed.	*/
 | 
				
			||||||
 | 
					  int	       *pnsamples)	/* number of samples actually packed.	*/
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int points_remaining = ns;	/* number of samples remaining to pack.	*/
 | 
				
			||||||
 | 
					  int		last = -1;
 | 
				
			||||||
 | 
					  int		nbytes;
 | 
				
			||||||
 | 
					  int		i;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Split lines only if a single line will not fit in 1 record */
 | 
				
			||||||
 | 
					  if (points_remaining > max_bytes)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      /* Look for the last newline that will fit in output buffer */
 | 
				
			||||||
 | 
					      for (i=max_bytes-1; i>=0; i--)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  if (data[i] == '\n') {
 | 
				
			||||||
 | 
						    last = i;
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						  }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      if (last < 0) last = max_bytes - 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (last < 0) last = points_remaining - 1;
 | 
				
			||||||
 | 
					  nbytes = last + 1;
 | 
				
			||||||
 | 
					  memcpy (packed, data, nbytes);
 | 
				
			||||||
 | 
					  packed += nbytes;
 | 
				
			||||||
 | 
					  max_bytes -= nbytes;
 | 
				
			||||||
 | 
					  *pnbytes = nbytes;
 | 
				
			||||||
 | 
					  *pnsamples = nbytes;
 | 
				
			||||||
 | 
					  points_remaining -= nbytes;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Pad miniSEED block if necessary */
 | 
				
			||||||
 | 
					  if (pad)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      memset ((void *)packed, 0, max_bytes);
 | 
				
			||||||
 | 
					      *pnbytes += max_bytes;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  *pnsamples = ns - points_remaining;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								libs/3rd-party/mseed/packdata.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								libs/3rd-party/mseed/packdata.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * packdata.h:
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Interface declarations for the Mini-SEED packing routines in
 | 
				
			||||||
 | 
					 * packdata.c
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * modified: 2008.220
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef	PACKDATA_H
 | 
				
			||||||
 | 
					#define	PACKDATA_H 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "steimdata.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Pointer to srcname of record being packed, declared in pack.c */
 | 
				
			||||||
 | 
					extern char *PACK_SRCNAME;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int msr_pack_int_16 (int16_t*, int32_t*, int, int, int, int*, int*, int);
 | 
				
			||||||
 | 
					extern int msr_pack_int_32 (int32_t*, int32_t*, int, int, int, int*, int*, int);
 | 
				
			||||||
 | 
					extern int msr_pack_float_32 (float*, float*, int, int, int, int*, int*, int);
 | 
				
			||||||
 | 
					extern int msr_pack_float_64 (double*, double*, int, int, int, int*, int*, int);
 | 
				
			||||||
 | 
					extern int msr_pack_steim1 (DFRAMES*, int32_t*, int32_t, int, int, int, int*, int*, int);
 | 
				
			||||||
 | 
					extern int msr_pack_steim2 (DFRAMES*, int32_t*, int32_t, int, int, int, int*, int*, int);
 | 
				
			||||||
 | 
					extern int msr_pack_text (char *, char *, int, int, int, int*, int*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										1163
									
								
								libs/3rd-party/mseed/parseutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1163
									
								
								libs/3rd-party/mseed/parseutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										680
									
								
								libs/3rd-party/mseed/selection.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										680
									
								
								libs/3rd-party/mseed/selection.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,680 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * selection.c:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Generic routines to manage selection lists.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Written by Chad Trabant unless otherwise noted
 | 
				
			||||||
 | 
					 *   IRIS Data Management Center
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * modified: 2014.197
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "libmseed.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ms_globmatch (char *string, char *pattern);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_matchselect:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Test the specified parameters for a matching selection entry.  The
 | 
				
			||||||
 | 
					 * srcname parameter may contain globbing characters.  The NULL value
 | 
				
			||||||
 | 
					 * (matching any times) for the start and end times is HPTERROR.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return Selections pointer to matching entry on successful match and
 | 
				
			||||||
 | 
					 * NULL for no match or error.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					Selections *
 | 
				
			||||||
 | 
					ms_matchselect (Selections *selections, char *srcname, hptime_t starttime,
 | 
				
			||||||
 | 
							hptime_t endtime, SelectTime **ppselecttime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Selections *findsl = NULL;
 | 
				
			||||||
 | 
					  SelectTime *findst = NULL;
 | 
				
			||||||
 | 
					  SelectTime *matchst = NULL;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( selections )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      findsl = selections;
 | 
				
			||||||
 | 
					      while ( findsl )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  if ( ms_globmatch (srcname, findsl->srcname) )
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      findst = findsl->timewindows;              
 | 
				
			||||||
 | 
						      while ( findst )
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							  if ( starttime != HPTERROR && findst->starttime != HPTERROR &&
 | 
				
			||||||
 | 
							       (starttime < findst->starttime && ! (starttime <= findst->starttime && endtime >= findst->starttime)) )
 | 
				
			||||||
 | 
							    { findst = findst->next; continue; }
 | 
				
			||||||
 | 
							  else if ( endtime != HPTERROR && findst->endtime != HPTERROR &&
 | 
				
			||||||
 | 
								    (endtime > findst->endtime && ! (starttime <= findst->endtime && endtime >= findst->endtime)) )
 | 
				
			||||||
 | 
							    { findst = findst->next; continue; }
 | 
				
			||||||
 | 
							  
 | 
				
			||||||
 | 
							  matchst = findst;
 | 
				
			||||||
 | 
							  break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  if ( matchst )
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						  else
 | 
				
			||||||
 | 
						    findsl = findsl->next;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( ppselecttime )
 | 
				
			||||||
 | 
					    *ppselecttime = matchst;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return ( matchst ) ? findsl : NULL;
 | 
				
			||||||
 | 
					} /* End of ms_matchselect() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * msr_matchselect:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A simple wrapper for calling ms_matchselect() using details from a
 | 
				
			||||||
 | 
					 * MSRecord struct.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return Selections pointer to matching entry on successful match and
 | 
				
			||||||
 | 
					 * NULL for no match or error.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					Selections *
 | 
				
			||||||
 | 
					msr_matchselect (Selections *selections, MSRecord *msr, SelectTime **ppselecttime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  char srcname[50];
 | 
				
			||||||
 | 
					  hptime_t endtime;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( ! selections || ! msr )
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  msr_srcname (msr, srcname, 1);
 | 
				
			||||||
 | 
					  endtime = msr_endtime (msr);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return ms_matchselect (selections, srcname, msr->starttime, endtime,
 | 
				
			||||||
 | 
								 ppselecttime);
 | 
				
			||||||
 | 
					} /* End of msr_matchselect() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_addselect:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Add select parameters to a specified selection list.  The srcname
 | 
				
			||||||
 | 
					 * argument may contain globbing parameters.  The NULL value (matching
 | 
				
			||||||
 | 
					 * any value) for the start and end times is HPTERROR.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return 0 on success and -1 on error.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					ms_addselect (Selections **ppselections, char *srcname,
 | 
				
			||||||
 | 
						      hptime_t starttime, hptime_t endtime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Selections *newsl = NULL;
 | 
				
			||||||
 | 
					  SelectTime *newst = NULL;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( ! ppselections || ! srcname )
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Allocate new SelectTime and populate */
 | 
				
			||||||
 | 
					  if ( ! (newst = (SelectTime *) calloc (1, sizeof(SelectTime))) )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ms_log (2, "Cannot allocate memory\n");
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  newst->starttime = starttime;
 | 
				
			||||||
 | 
					  newst->endtime = endtime;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Add new Selections struct to begining of list */
 | 
				
			||||||
 | 
					  if ( ! *ppselections )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      /* Allocate new Selections and populate */
 | 
				
			||||||
 | 
					      if ( ! (newsl = (Selections *) calloc (1, sizeof(Selections))) )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  ms_log (2, "Cannot allocate memory\n");
 | 
				
			||||||
 | 
						  return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      strncpy (newsl->srcname, srcname, sizeof(newsl->srcname));
 | 
				
			||||||
 | 
					      newsl->srcname[sizeof(newsl->srcname) - 1] = '\0';
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Add new Selections struct as first in list */
 | 
				
			||||||
 | 
					      *ppselections = newsl;
 | 
				
			||||||
 | 
					      newsl->timewindows = newst;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Selections *findsl = *ppselections;
 | 
				
			||||||
 | 
					      Selections *matchsl = 0;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Search for matching Selectlink entry */
 | 
				
			||||||
 | 
					      while ( findsl )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  if ( ! strcmp (findsl->srcname, srcname) )
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      matchsl = findsl;
 | 
				
			||||||
 | 
						      break;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  findsl = findsl->next;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if ( matchsl )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  /* Add time window selection to beginning of window list */
 | 
				
			||||||
 | 
						  newst->next = matchsl->timewindows;
 | 
				
			||||||
 | 
						  matchsl->timewindows = newst;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  /* Allocate new Selections and populate */
 | 
				
			||||||
 | 
						  if ( ! (newsl = (Selections *) calloc (1, sizeof(Selections))) )
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      ms_log (2, "Cannot allocate memory\n");
 | 
				
			||||||
 | 
						      return -1;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  strncpy (newsl->srcname, srcname, sizeof(newsl->srcname));
 | 
				
			||||||
 | 
						  newsl->srcname[sizeof(newsl->srcname) - 1] = '\0';
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  /* Add new Selections to beginning of list */
 | 
				
			||||||
 | 
						  newsl->next = *ppselections;
 | 
				
			||||||
 | 
						  *ppselections = newsl;
 | 
				
			||||||
 | 
						  newsl->timewindows = newst;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					} /* End of ms_addselect() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_addselect_comp:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Add select parameters to a specified selection list based on
 | 
				
			||||||
 | 
					 * separate name components.  The network, station, location, channel
 | 
				
			||||||
 | 
					 * and quality arguments may contain globbing parameters.  The NULL
 | 
				
			||||||
 | 
					 * value (matching any value) for the start and end times is HPTERROR.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If any of the naming parameters are not supplied (pointer is NULL)
 | 
				
			||||||
 | 
					 * a wildcard for all matches is substituted.  As a special case, if
 | 
				
			||||||
 | 
					 * the location ID (loc) is set to "--" to match a space-space/blank
 | 
				
			||||||
 | 
					 * ID it will be translated to an empty string to match libmseed's
 | 
				
			||||||
 | 
					 * notation.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return 0 on success and -1 on error.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					ms_addselect_comp (Selections **ppselections, char *net, char* sta, char *loc,
 | 
				
			||||||
 | 
							   char *chan, char *qual, hptime_t starttime, hptime_t endtime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  char srcname[100];
 | 
				
			||||||
 | 
					  char selnet[20];
 | 
				
			||||||
 | 
					  char selsta[20];
 | 
				
			||||||
 | 
					  char selloc[20];
 | 
				
			||||||
 | 
					  char selchan[20];
 | 
				
			||||||
 | 
					  char selqual[20];
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( ! ppselections )
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( net )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      strncpy (selnet, net, sizeof(selnet));
 | 
				
			||||||
 | 
					      selnet[sizeof(selnet)-1] = '\0';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    strcpy (selnet, "*");
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( sta )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      strncpy (selsta, sta, sizeof(selsta));
 | 
				
			||||||
 | 
					      selsta[sizeof(selsta)-1] = '\0';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    strcpy (selsta, "*");
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( loc )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      /* Test for special case blank location ID */
 | 
				
			||||||
 | 
					      if ( ! strcmp (loc, "--") )
 | 
				
			||||||
 | 
						selloc[0] = '\0';
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  strncpy (selloc, loc, sizeof(selloc));
 | 
				
			||||||
 | 
						  selloc[sizeof(selloc)-1] = '\0';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    strcpy (selloc, "*");
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( chan )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      strncpy (selchan, chan, sizeof(selchan));
 | 
				
			||||||
 | 
					      selchan[sizeof(selchan)-1] = '\0';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    strcpy (selchan, "*");
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( qual )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      strncpy (selqual, qual, sizeof(selqual));
 | 
				
			||||||
 | 
					      selqual[sizeof(selqual)-1] = '\0';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    strcpy (selqual, "?");
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Create the srcname globbing match for this entry */
 | 
				
			||||||
 | 
					  snprintf (srcname, sizeof(srcname), "%s_%s_%s_%s_%s",
 | 
				
			||||||
 | 
						    selnet, selsta, selloc, selchan, selqual);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Add selection to list */
 | 
				
			||||||
 | 
					  if ( ms_addselect (ppselections, srcname, starttime, endtime) )
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					} /* End of ms_addselect_comp() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_readselectionsfile:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Read a list of data selections from a file and them to the
 | 
				
			||||||
 | 
					 * specified selections list.  On errors this routine will leave
 | 
				
			||||||
 | 
					 * allocated memory unreachable (leaked), it is expected that this is
 | 
				
			||||||
 | 
					 * a program failing condition.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * As a special case if the filename is "-", selection lines will be
 | 
				
			||||||
 | 
					 * read from stdin.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns count of selections added on success and -1 on error.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					ms_readselectionsfile (Selections **ppselections, char *filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  FILE *fp;
 | 
				
			||||||
 | 
					  hptime_t starttime;
 | 
				
			||||||
 | 
					  hptime_t endtime;
 | 
				
			||||||
 | 
					  char selectline[200];
 | 
				
			||||||
 | 
					  char *selnet;
 | 
				
			||||||
 | 
					  char *selsta;
 | 
				
			||||||
 | 
					  char *selloc;
 | 
				
			||||||
 | 
					  char *selchan;
 | 
				
			||||||
 | 
					  char *selqual;
 | 
				
			||||||
 | 
					  char *selstart;
 | 
				
			||||||
 | 
					  char *selend;
 | 
				
			||||||
 | 
					  char *cp;
 | 
				
			||||||
 | 
					  char next;
 | 
				
			||||||
 | 
					  int selectcount = 0;
 | 
				
			||||||
 | 
					  int linecount = 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( ! ppselections || ! filename )
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( strcmp (filename, "-" ) )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if ( ! (fp = fopen(filename, "rb")) )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  ms_log (2, "Cannot open file %s: %s\n", filename, strerror(errno));
 | 
				
			||||||
 | 
						  return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      /* Use stdin as special case */
 | 
				
			||||||
 | 
					      fp = stdin;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  while ( fgets (selectline, sizeof(selectline)-1, fp) )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      selnet = 0;
 | 
				
			||||||
 | 
					      selsta = 0;
 | 
				
			||||||
 | 
					      selloc = 0;
 | 
				
			||||||
 | 
					      selchan = 0;
 | 
				
			||||||
 | 
					      selqual = 0;
 | 
				
			||||||
 | 
					      selstart = 0;
 | 
				
			||||||
 | 
					      selend = 0;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      linecount++;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Guarantee termination */
 | 
				
			||||||
 | 
					      selectline[sizeof(selectline)-1] = '\0';
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* End string at first newline character if any */
 | 
				
			||||||
 | 
					      if ( (cp = strchr(selectline, '\n')) )
 | 
				
			||||||
 | 
					        *cp = '\0';
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Skip empty lines */
 | 
				
			||||||
 | 
					      if ( ! strlen (selectline) )
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Skip comment lines */
 | 
				
			||||||
 | 
					      if ( *selectline == '#' )
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Parse: identify components of selection and terminate */
 | 
				
			||||||
 | 
					      cp = selectline;
 | 
				
			||||||
 | 
					      next = 1;
 | 
				
			||||||
 | 
					      while ( *cp )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  if ( *cp == ' ' || *cp == '\t' ) { *cp = '\0'; next = 1; }
 | 
				
			||||||
 | 
						  else if ( *cp == '#' ) { *cp = '\0'; break; }
 | 
				
			||||||
 | 
						  else if ( next && ! selnet ) { selnet = cp; next = 0; }
 | 
				
			||||||
 | 
						  else if ( next && ! selsta ) { selsta = cp; next = 0; }
 | 
				
			||||||
 | 
						  else if ( next && ! selloc ) { selloc = cp; next = 0; }
 | 
				
			||||||
 | 
						  else if ( next && ! selchan ) { selchan = cp; next = 0; }
 | 
				
			||||||
 | 
						  else if ( next && ! selqual ) { selqual = cp; next = 0; }
 | 
				
			||||||
 | 
						  else if ( next && ! selstart ) { selstart = cp; next = 0; }
 | 
				
			||||||
 | 
						  else if ( next && ! selend ) { selend = cp; next = 0; }
 | 
				
			||||||
 | 
						  else if ( next ) { *cp = '\0'; break; }
 | 
				
			||||||
 | 
						  cp++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Skip line if network, station, location and channel are not defined */
 | 
				
			||||||
 | 
					      if ( ! selnet || ! selsta || ! selloc || ! selchan )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  ms_log (2, "[%s] Skipping data selection line number %d\n", filename, linecount);
 | 
				
			||||||
 | 
						  continue;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if ( selstart )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  starttime = ms_seedtimestr2hptime (selstart);
 | 
				
			||||||
 | 
						  if ( starttime == HPTERROR )
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      ms_log (2, "Cannot convert data selection start time (line %d): %s\n", linecount, selstart);
 | 
				
			||||||
 | 
						      return -1;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  starttime = HPTERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if ( selend )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  endtime = ms_seedtimestr2hptime (selend);
 | 
				
			||||||
 | 
						  if ( endtime == HPTERROR )
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      ms_log (2, "Cannot convert data selection end time (line %d): %s\n",  linecount, selend);
 | 
				
			||||||
 | 
						      return -1;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  endtime = HPTERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Add selection to list */
 | 
				
			||||||
 | 
					      if ( ms_addselect_comp (ppselections, selnet, selsta, selloc, selchan, selqual, starttime, endtime) )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  ms_log (2, "[%s] Error adding selection on line %d\n", filename, linecount);
 | 
				
			||||||
 | 
						  return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      selectcount++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( fp != stdin )
 | 
				
			||||||
 | 
					    fclose (fp);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return selectcount;
 | 
				
			||||||
 | 
					} /* End of ms_readselectionsfile() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_freeselections:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Free all memory associated with a Selections struct.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ms_freeselections ( Selections *selections )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Selections *select;
 | 
				
			||||||
 | 
					  Selections *selectnext;
 | 
				
			||||||
 | 
					  SelectTime *selecttime;
 | 
				
			||||||
 | 
					  SelectTime *selecttimenext;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( selections )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      select = selections;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      while ( select )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  selectnext = select->next;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  selecttime = select->timewindows;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  while ( selecttime )
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      selecttimenext = selecttime->next;
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						      free (selecttime);
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						      selecttime = selecttimenext;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  free (select);
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  select = selectnext;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} /* End of ms_freeselections() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * ms_printselections:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Print the selections list using the ms_log() facility.
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ms_printselections ( Selections *selections )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Selections *select;
 | 
				
			||||||
 | 
					  SelectTime *selecttime;
 | 
				
			||||||
 | 
					  char starttime[50];
 | 
				
			||||||
 | 
					  char endtime[50];
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( ! selections )
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  select = selections;
 | 
				
			||||||
 | 
					  while ( select )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ms_log (0, "Selection: %s\n", select->srcname);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      selecttime = select->timewindows;
 | 
				
			||||||
 | 
					      while ( selecttime )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  if ( selecttime->starttime != HPTERROR )
 | 
				
			||||||
 | 
						    ms_hptime2seedtimestr (selecttime->starttime, starttime, 1);
 | 
				
			||||||
 | 
						  else
 | 
				
			||||||
 | 
						    strncpy (starttime, "No start time", sizeof(starttime)-1);
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  if ( selecttime->endtime != HPTERROR )
 | 
				
			||||||
 | 
						    ms_hptime2seedtimestr (selecttime->endtime, endtime, 1);
 | 
				
			||||||
 | 
						  else
 | 
				
			||||||
 | 
						    strncpy (endtime, "No end time", sizeof(endtime)-1);
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  ms_log (0, "  %30s  %30s\n", starttime, endtime);
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  selecttime = selecttime->next;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      select = select->next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					} /* End of ms_printselections() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***********************************************************************
 | 
				
			||||||
 | 
					 * robust glob pattern matcher
 | 
				
			||||||
 | 
					 * ozan s. yigit/dec 1994
 | 
				
			||||||
 | 
					 * public domain
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * glob patterns:
 | 
				
			||||||
 | 
					 *	*	matches zero or more characters
 | 
				
			||||||
 | 
					 *	?	matches any single character
 | 
				
			||||||
 | 
					 *	[set]	matches any character in the set
 | 
				
			||||||
 | 
					 *	[^set]	matches any character NOT in the set
 | 
				
			||||||
 | 
					 *		where a set is a group of characters or ranges. a range
 | 
				
			||||||
 | 
					 *		is written as two characters seperated with a hyphen: a-z denotes
 | 
				
			||||||
 | 
					 *		all characters between a to z inclusive.
 | 
				
			||||||
 | 
					 *	[-set]	set matches a literal hypen and any character in the set
 | 
				
			||||||
 | 
					 *	[]set]	matches a literal close bracket and any character in the set
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	char	matches itself except where char is '*' or '?' or '['
 | 
				
			||||||
 | 
					 *	\char	matches char, including any pattern character
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * examples:
 | 
				
			||||||
 | 
					 *	a*c		ac abc abbc ...
 | 
				
			||||||
 | 
					 *	a?c		acc abc aXc ...
 | 
				
			||||||
 | 
					 *	a[a-z]c		aac abc acc ...
 | 
				
			||||||
 | 
					 *	a[-a-z]c	a-c aac abc ...
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Revision 1.4  2004/12/26  12:38:00  ct
 | 
				
			||||||
 | 
					 * Changed function name (amatch -> globmatch), variables and
 | 
				
			||||||
 | 
					 * formatting for clarity.  Also add matching header globmatch.h.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Revision 1.3  1995/09/14  23:24:23  oz
 | 
				
			||||||
 | 
					 * removed boring test/main code.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Revision 1.2  94/12/11  10:38:15  oz
 | 
				
			||||||
 | 
					 * charset code fixed. it is now robust and interprets all
 | 
				
			||||||
 | 
					 * variations of charset [i think] correctly, including [z-a] etc.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Revision 1.1  94/12/08  12:45:23  oz
 | 
				
			||||||
 | 
					 * Initial revision
 | 
				
			||||||
 | 
					 ***********************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GLOBMATCH_TRUE    1
 | 
				
			||||||
 | 
					#define GLOBMATCH_FALSE   0
 | 
				
			||||||
 | 
					#define GLOBMATCH_NEGATE '^'       /* std char set negation char */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***********************************************************************
 | 
				
			||||||
 | 
					 * ms_globmatch:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Check if a string matches a globbing pattern.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return 0 if string does not match pattern and non-zero otherwise.
 | 
				
			||||||
 | 
					 **********************************************************************/
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					ms_globmatch (char *string, char *pattern)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int negate;
 | 
				
			||||||
 | 
					  int match;
 | 
				
			||||||
 | 
					  int c;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  while ( *pattern )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if ( !*string && *pattern != '*' )
 | 
				
			||||||
 | 
						return GLOBMATCH_FALSE;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      switch ( c = *pattern++ )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						case '*':
 | 
				
			||||||
 | 
						  while ( *pattern == '*' )
 | 
				
			||||||
 | 
						    pattern++;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  if ( !*pattern )
 | 
				
			||||||
 | 
						    return GLOBMATCH_TRUE;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  if ( *pattern != '?' && *pattern != '[' && *pattern != '\\' )
 | 
				
			||||||
 | 
						    while ( *string && *pattern != *string )
 | 
				
			||||||
 | 
						      string++;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  while ( *string )
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      if ( ms_globmatch(string, pattern) )
 | 
				
			||||||
 | 
							return GLOBMATCH_TRUE;
 | 
				
			||||||
 | 
						      string++;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  return GLOBMATCH_FALSE;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						case '?':
 | 
				
			||||||
 | 
						  if ( *string )
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						  return GLOBMATCH_FALSE;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  /* set specification is inclusive, that is [a-z] is a, z and
 | 
				
			||||||
 | 
						   * everything in between. this means [z-a] may be interpreted
 | 
				
			||||||
 | 
						   * as a set that contains z, a and nothing in between.
 | 
				
			||||||
 | 
						   */
 | 
				
			||||||
 | 
						case '[':
 | 
				
			||||||
 | 
						  if ( *pattern != GLOBMATCH_NEGATE )
 | 
				
			||||||
 | 
						    negate = GLOBMATCH_FALSE;
 | 
				
			||||||
 | 
						  else
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      negate = GLOBMATCH_TRUE;
 | 
				
			||||||
 | 
						      pattern++;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  match = GLOBMATCH_FALSE;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  while ( !match && (c = *pattern++) )
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      if ( !*pattern )
 | 
				
			||||||
 | 
							return GLOBMATCH_FALSE;
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						      if ( *pattern == '-' ) 	/* c-c */
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							  if ( !*++pattern )
 | 
				
			||||||
 | 
							    return GLOBMATCH_FALSE;
 | 
				
			||||||
 | 
							  if ( *pattern != ']' )
 | 
				
			||||||
 | 
							    {
 | 
				
			||||||
 | 
							      if ( *string == c || *string == *pattern ||
 | 
				
			||||||
 | 
								   ( *string > c && *string < *pattern ) )
 | 
				
			||||||
 | 
								match = GLOBMATCH_TRUE;
 | 
				
			||||||
 | 
							    }
 | 
				
			||||||
 | 
							  else
 | 
				
			||||||
 | 
							    {		/* c-] */
 | 
				
			||||||
 | 
							      if ( *string >= c )
 | 
				
			||||||
 | 
								match = GLOBMATCH_TRUE;
 | 
				
			||||||
 | 
							      break;
 | 
				
			||||||
 | 
							    }
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						      else			/* cc or c] */
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							  if ( c == *string )
 | 
				
			||||||
 | 
							    match = GLOBMATCH_TRUE;
 | 
				
			||||||
 | 
							  if ( *pattern != ']' )
 | 
				
			||||||
 | 
							    {
 | 
				
			||||||
 | 
							      if ( *pattern == *string )
 | 
				
			||||||
 | 
								match = GLOBMATCH_TRUE;
 | 
				
			||||||
 | 
							    }
 | 
				
			||||||
 | 
							  else
 | 
				
			||||||
 | 
							    break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						    } 
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  if ( negate == match )
 | 
				
			||||||
 | 
						    return GLOBMATCH_FALSE;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  /*
 | 
				
			||||||
 | 
						   * if there is a match, skip past the charset and continue on
 | 
				
			||||||
 | 
						   */
 | 
				
			||||||
 | 
						  while ( *pattern && *pattern != ']' )
 | 
				
			||||||
 | 
						    pattern++;
 | 
				
			||||||
 | 
						  if ( !*pattern++ )	/* oops! */
 | 
				
			||||||
 | 
						    return GLOBMATCH_FALSE;
 | 
				
			||||||
 | 
						  break;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						case '\\':
 | 
				
			||||||
 | 
						  if ( *pattern )
 | 
				
			||||||
 | 
						    c = *pattern++;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
						  if ( c != *string )
 | 
				
			||||||
 | 
						    return GLOBMATCH_FALSE;
 | 
				
			||||||
 | 
						  break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      string++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return !*string;
 | 
				
			||||||
 | 
					}  /* End of ms_globmatch() */
 | 
				
			||||||
							
								
								
									
										51
									
								
								libs/3rd-party/mseed/steimdata.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								libs/3rd-party/mseed/steimdata.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * steimdata.h:
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Declarations for Steim compression routines.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * modified: 2004.278
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef STEIMDATA_H
 | 
				
			||||||
 | 
					#define STEIMDATA_H 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STEIM1_FRAME_MAX_SAMPLES  60
 | 
				
			||||||
 | 
					#define STEIM2_FRAME_MAX_SAMPLES  105
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define VALS_PER_FRAME  15      /* # of ints for data per frame.*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STEIM1_SPECIAL_MASK     0
 | 
				
			||||||
 | 
					#define STEIM1_BYTE_MASK        1
 | 
				
			||||||
 | 
					#define STEIM1_HALFWORD_MASK    2
 | 
				
			||||||
 | 
					#define STEIM1_FULLWORD_MASK    3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STEIM2_SPECIAL_MASK     0
 | 
				
			||||||
 | 
					#define STEIM2_BYTE_MASK        1
 | 
				
			||||||
 | 
					#define STEIM2_123_MASK         2
 | 
				
			||||||
 | 
					#define STEIM2_567_MASK         3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef union u_diff {          /* union for Steim objects.     */
 | 
				
			||||||
 | 
					  int8_t          byte[4];      /* 4 1-byte differences.        */
 | 
				
			||||||
 | 
					  int16_t         hw[2];        /* 2 halfword differences.      */
 | 
				
			||||||
 | 
					  int32_t         fw;           /* 1 fullword difference.       */
 | 
				
			||||||
 | 
					} U_DIFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct frame {          /* frame in a seed data record. */
 | 
				
			||||||
 | 
					  uint32_t        ctrl;         /* control word for frame.      */
 | 
				
			||||||
 | 
					  U_DIFF          w[15];        /* compressed data.             */
 | 
				
			||||||
 | 
					} FRAME;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct dframes {        /* seed data frames.            */
 | 
				
			||||||
 | 
					    FRAME f[1];                 /* data record header frames.   */
 | 
				
			||||||
 | 
					} DFRAMES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* STEIMDATA_H */
 | 
				
			||||||
							
								
								
									
										1277
									
								
								libs/3rd-party/mseed/tracelist.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1277
									
								
								libs/3rd-party/mseed/tracelist.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1855
									
								
								libs/3rd-party/mseed/traceutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1855
									
								
								libs/3rd-party/mseed/traceutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1083
									
								
								libs/3rd-party/mseed/unpack.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1083
									
								
								libs/3rd-party/mseed/unpack.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										892
									
								
								libs/3rd-party/mseed/unpackdata.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										892
									
								
								libs/3rd-party/mseed/unpackdata.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,892 @@
 | 
				
			|||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  Routines for unpacking INT_16, INT_32, FLOAT_32, FLOAT_64,
 | 
				
			||||||
 | 
					 *  STEIM1, STEIM2, GEOSCOPE (24bit and gain ranged), CDSN, SRO
 | 
				
			||||||
 | 
					 *  and DWWSSN encoded data records.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Some routines originated and were borrowed from qlib2 by:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	Douglas Neuhauser
 | 
				
			||||||
 | 
					 *	Seismographic Station
 | 
				
			||||||
 | 
					 *	University of California, Berkeley
 | 
				
			||||||
 | 
					 *	doug@seismo.berkeley.edu
 | 
				
			||||||
 | 
					 *									
 | 
				
			||||||
 | 
					 *  Modified by Chad Trabant,
 | 
				
			||||||
 | 
					 *  (previously) ORFEUS/EC-Project MEREDIAN
 | 
				
			||||||
 | 
					 *  (currently) IRIS Data Management Center
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  modified: 2012.357
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 1996 The Regents of the University of California.
 | 
				
			||||||
 | 
					 * All Rights Reserved.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Permission to use, copy, modify, and distribute this software and its
 | 
				
			||||||
 | 
					 * documentation for educational, research and non-profit purposes,
 | 
				
			||||||
 | 
					 * without fee, and without a written agreement is hereby granted,
 | 
				
			||||||
 | 
					 * provided that the above copyright notice, this paragraph and the
 | 
				
			||||||
 | 
					 * following three paragraphs appear in all copies.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Permission to incorporate this software into commercial products may
 | 
				
			||||||
 | 
					 * be obtained from the Office of Technology Licensing, 2150 Shattuck
 | 
				
			||||||
 | 
					 * Avenue, Suite 510, Berkeley, CA  94704.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
 | 
				
			||||||
 | 
					 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
 | 
				
			||||||
 | 
					 * INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND
 | 
				
			||||||
 | 
					 * ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN
 | 
				
			||||||
 | 
					 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 | 
				
			||||||
 | 
					 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE
 | 
				
			||||||
 | 
					 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 | 
				
			||||||
 | 
					 * CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
 | 
				
			||||||
 | 
					 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <memory.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "libmseed.h"
 | 
				
			||||||
 | 
					#include "unpackdata.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX12 0x7ff         /* maximum 12 bit positive # */
 | 
				
			||||||
 | 
					#define MAX14 0x1fff        /* maximum 14 bit positive # */
 | 
				
			||||||
 | 
					#define MAX16 0x7fff        /* maximum 16 bit positive # */
 | 
				
			||||||
 | 
					#define MAX24 0x7fffff      /* maximum 24 bit positive # */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* For Steim encodings */
 | 
				
			||||||
 | 
					#define X0  pf->w[0].fw
 | 
				
			||||||
 | 
					#define XN  pf->w[1].fw
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_unpack_int_16:							*
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Unpack int_16 miniSEED data and place in supplied buffer.           *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Return: # of samples returned.                                      *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_unpack_int_16 
 | 
				
			||||||
 | 
					 (int16_t      *ibuf,		/* ptr to input data.			*/
 | 
				
			||||||
 | 
					  int		num_samples,	/* number of data samples in total.     */
 | 
				
			||||||
 | 
					  int		req_samples,	/* number of data desired by caller.	*/
 | 
				
			||||||
 | 
					  int32_t      *databuff,	/* ptr to unpacked data array.		*/
 | 
				
			||||||
 | 
					  int		swapflag)       /* if data should be swapped.	        */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int		nd = 0;		/* # of data points in packet.		*/
 | 
				
			||||||
 | 
					  int16_t	stmp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (num_samples < 0) return 0;
 | 
				
			||||||
 | 
					  if (req_samples < 0) return 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  for (nd=0; nd<req_samples && nd<num_samples; nd++) {
 | 
				
			||||||
 | 
					    stmp = ibuf[nd];
 | 
				
			||||||
 | 
					    if ( swapflag ) ms_gswap2a (&stmp);
 | 
				
			||||||
 | 
					    databuff[nd] = stmp;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return nd;
 | 
				
			||||||
 | 
					}  /* End of msr_unpack_int_16() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_unpack_int_32:							*
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Unpack int_32 miniSEED data and place in supplied buffer.           *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Return: # of samples returned.                                      *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_unpack_int_32
 | 
				
			||||||
 | 
					 (int32_t      *ibuf,		/* ptr to input data.			*/
 | 
				
			||||||
 | 
					  int		num_samples,	/* number of data samples in total.     */
 | 
				
			||||||
 | 
					  int		req_samples,	/* number of data desired by caller.	*/
 | 
				
			||||||
 | 
					  int32_t      *databuff,	/* ptr to unpacked data array.		*/
 | 
				
			||||||
 | 
					  int		swapflag)	/* if data should be swapped.	        */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int		nd = 0;		/* # of data points in packet.		*/
 | 
				
			||||||
 | 
					  int32_t    	itmp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (num_samples < 0) return 0;
 | 
				
			||||||
 | 
					  if (req_samples < 0) return 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  for (nd=0; nd<req_samples && nd<num_samples; nd++) {
 | 
				
			||||||
 | 
					    itmp = ibuf[nd];
 | 
				
			||||||
 | 
					    if ( swapflag) ms_gswap4a (&itmp);
 | 
				
			||||||
 | 
					    databuff[nd] = itmp;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return nd;
 | 
				
			||||||
 | 
					}  /* End of msr_unpack_int_32() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_unpack_float_32:	       				 	*
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Unpack float_32 miniSEED data and place in supplied buffer.	        *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Return: # of samples returned.                                      *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_unpack_float_32
 | 
				
			||||||
 | 
					 (float	       *fbuf,		/* ptr to input data.			*/
 | 
				
			||||||
 | 
					  int		num_samples,	/* number of data samples in total.     */
 | 
				
			||||||
 | 
					  int		req_samples,	/* number of data desired by caller.	*/
 | 
				
			||||||
 | 
					  float	       *databuff,	/* ptr to unpacked data array.		*/
 | 
				
			||||||
 | 
					  int		swapflag)	/* if data should be swapped.	        */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int		nd = 0;		/* # of data points in packet.		*/
 | 
				
			||||||
 | 
					  float    	ftmp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (num_samples < 0) return 0;
 | 
				
			||||||
 | 
					  if (req_samples < 0) return 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  for (nd=0; nd<req_samples && nd<num_samples; nd++) {
 | 
				
			||||||
 | 
					    memcpy (&ftmp, &fbuf[nd], sizeof(float));
 | 
				
			||||||
 | 
					    if ( swapflag ) ms_gswap4a (&ftmp);
 | 
				
			||||||
 | 
					    databuff[nd] = ftmp;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return nd;
 | 
				
			||||||
 | 
					}  /* End of msr_unpack_float_32() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_unpack_float_64:	       					*
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Unpack float_64 miniSEED data and place in supplied buffer.	        *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Return: # of samples returned.                                      *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_unpack_float_64
 | 
				
			||||||
 | 
					 (double       *fbuf,		/* ptr to input data.			*/
 | 
				
			||||||
 | 
					  int		num_samples,	/* number of data samples in total.     */
 | 
				
			||||||
 | 
					  int		req_samples,	/* number of data desired by caller.	*/
 | 
				
			||||||
 | 
					  double       *databuff,	/* ptr to unpacked data array.		*/
 | 
				
			||||||
 | 
					  int		swapflag)	/* if data should be swapped.	        */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int		nd = 0;		/* # of data points in packet.		*/
 | 
				
			||||||
 | 
					  double  	dtmp;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (num_samples < 0) return 0;
 | 
				
			||||||
 | 
					  if (req_samples < 0) return 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  for (nd=0; nd<req_samples && nd<num_samples; nd++) {
 | 
				
			||||||
 | 
					    memcpy (&dtmp, &fbuf[nd], sizeof(double));
 | 
				
			||||||
 | 
					    if ( swapflag ) ms_gswap8a (&dtmp);
 | 
				
			||||||
 | 
					    databuff[nd] = dtmp;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return nd;
 | 
				
			||||||
 | 
					}  /* End of msr_unpack_float_64() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_unpack_steim1:							*
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Unpack STEIM1 data frames and place in supplied buffer.		*
 | 
				
			||||||
 | 
					 *  See the SEED format manual for Steim-1 encoding details.            *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Return: # of samples returned or negative error code.               *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_unpack_steim1
 | 
				
			||||||
 | 
					 (FRAME	       *pf,		/* ptr to Steim1 data frames.		*/
 | 
				
			||||||
 | 
					  int		nbytes,		/* number of bytes in all data frames.	*/
 | 
				
			||||||
 | 
					  int		num_samples,	/* number of data samples in all frames.*/
 | 
				
			||||||
 | 
					  int		req_samples,	/* number of data desired by caller.	*/
 | 
				
			||||||
 | 
					  int32_t      *databuff,	/* ptr to unpacked data array.		*/
 | 
				
			||||||
 | 
					  int32_t      *diffbuff,	/* ptr to unpacked diff array.		*/
 | 
				
			||||||
 | 
					  int32_t      *px0,		/* return X0, first sample in frame.	*/
 | 
				
			||||||
 | 
					  int32_t      *pxn,		/* return XN, last sample in frame.	*/
 | 
				
			||||||
 | 
					  int		swapflag,	/* if data should be swapped.	        */
 | 
				
			||||||
 | 
					  int           verbose)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int32_t      *diff = diffbuff;
 | 
				
			||||||
 | 
					  int32_t      *data = databuff;
 | 
				
			||||||
 | 
					  int32_t      *prev;
 | 
				
			||||||
 | 
					  int	        num_data_frames = nbytes / sizeof(FRAME);
 | 
				
			||||||
 | 
					  int		nd = 0;		/* # of data points in packet.		*/
 | 
				
			||||||
 | 
					  int		fn;		/* current frame number.		*/
 | 
				
			||||||
 | 
					  int		wn;		/* current work number in the frame.	*/
 | 
				
			||||||
 | 
					  int		compflag;      	/* current compression flag.		*/
 | 
				
			||||||
 | 
					  int		nr, i;
 | 
				
			||||||
 | 
					  int32_t	last_data;
 | 
				
			||||||
 | 
					  int32_t	itmp;
 | 
				
			||||||
 | 
					  int16_t	stmp;
 | 
				
			||||||
 | 
					  uint32_t	ctrl;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (num_samples < 0) return 0;
 | 
				
			||||||
 | 
					  if (num_samples == 0) return 0;
 | 
				
			||||||
 | 
					  if (req_samples < 0) return 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Extract forward and reverse integration constants in first frame */
 | 
				
			||||||
 | 
					  *px0 = X0;
 | 
				
			||||||
 | 
					  *pxn = XN;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( swapflag )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ms_gswap4a (px0);
 | 
				
			||||||
 | 
					      ms_gswap4a (pxn);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( verbose > 2 )
 | 
				
			||||||
 | 
					    ms_log (1, "%s: forward/reverse integration constants:\nX0: %d  XN: %d\n",
 | 
				
			||||||
 | 
						    UNPACK_SRCNAME, *px0, *pxn);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Decode compressed data in each frame */
 | 
				
			||||||
 | 
					  for (fn = 0; fn < num_data_frames; fn++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      ctrl = pf->ctrl;
 | 
				
			||||||
 | 
					      if ( swapflag ) ms_gswap4a (&ctrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for (wn = 0; wn < VALS_PER_FRAME; wn++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  if (nd >= num_samples) break;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  compflag = (ctrl >> ((VALS_PER_FRAME-wn-1)*2)) & 0x3;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  switch (compflag)
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						    case STEIM1_SPECIAL_MASK:
 | 
				
			||||||
 | 
						      /* Headers info -- skip it */
 | 
				
			||||||
 | 
						      break;
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						    case STEIM1_BYTE_MASK:
 | 
				
			||||||
 | 
						      /* Next 4 bytes are 4 1-byte differences */
 | 
				
			||||||
 | 
						      for (i=0; i < 4 && nd < num_samples; i++, nd++)
 | 
				
			||||||
 | 
							*diff++ = pf->w[wn].byte[i];
 | 
				
			||||||
 | 
						      break;
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						    case STEIM1_HALFWORD_MASK:
 | 
				
			||||||
 | 
						      /* Next 4 bytes are 2 2-byte differences */
 | 
				
			||||||
 | 
						      for (i=0; i < 2 && nd < num_samples; i++, nd++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							  if ( swapflag )
 | 
				
			||||||
 | 
							    {
 | 
				
			||||||
 | 
							      stmp = pf->w[wn].hw[i];
 | 
				
			||||||
 | 
							      ms_gswap2a (&stmp);
 | 
				
			||||||
 | 
							      *diff++ = stmp;
 | 
				
			||||||
 | 
							    }
 | 
				
			||||||
 | 
							  else *diff++ = pf->w[wn].hw[i];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						      break;
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						    case STEIM1_FULLWORD_MASK:
 | 
				
			||||||
 | 
						      /* Next 4 bytes are 1 4-byte difference */
 | 
				
			||||||
 | 
						      if ( swapflag )
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							  itmp = pf->w[wn].fw;
 | 
				
			||||||
 | 
							  ms_gswap4a (&itmp);
 | 
				
			||||||
 | 
							  *diff++ = itmp;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						      else *diff++ = pf->w[wn].fw;
 | 
				
			||||||
 | 
						      nd++;
 | 
				
			||||||
 | 
						      break;
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						    default:
 | 
				
			||||||
 | 
						      /* Should NEVER get here */
 | 
				
			||||||
 | 
						      ms_log (2, "msr_unpack_steim1(%s): invalid compression flag = %d\n",
 | 
				
			||||||
 | 
							      UNPACK_SRCNAME, compflag);
 | 
				
			||||||
 | 
						      return MS_STBADCOMPFLAG;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      ++pf;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Test if the number of samples implied by the data frames is the
 | 
				
			||||||
 | 
					   * same number indicated in the header.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  if ( nd != num_samples )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ms_log (1, "Warning: msr_unpack_steim1(%s): number of samples indicated in header (%d) does not equal data (%d)\n",
 | 
				
			||||||
 | 
						      UNPACK_SRCNAME, num_samples, nd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /*	For now, assume sample count in header to be correct.		*/
 | 
				
			||||||
 | 
					  /*	One way of "trimming" data from a block is simply to reduce	*/
 | 
				
			||||||
 | 
					  /*	the sample count.  It is not clear from the documentation	*/
 | 
				
			||||||
 | 
					  /*	whether this is a valid or not, but it appears to be done	*/
 | 
				
			||||||
 | 
					  /*	by other program, so we should not complain about its effect.	*/
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  nr = req_samples;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Compute first value based on last_value from previous buffer.	*/
 | 
				
			||||||
 | 
					  /* The two should correspond in all cases EXCEPT for the first	*/
 | 
				
			||||||
 | 
					  /* record for each component (because we don't have a valid xn from	*/
 | 
				
			||||||
 | 
					  /* a previous record).  Although the Steim compression algorithm	*/
 | 
				
			||||||
 | 
					  /* defines x(-1) as 0 for the first record, this only works for the	*/
 | 
				
			||||||
 | 
					  /* first record created since coldstart of the datalogger, NOT the	*/
 | 
				
			||||||
 | 
					  /* first record of an arbitrary starting record.	                */
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* In all cases, assume x0 is correct, since we don't have x(-1).	*/
 | 
				
			||||||
 | 
					  data = databuff;
 | 
				
			||||||
 | 
					  diff = diffbuff;
 | 
				
			||||||
 | 
					  last_data = *px0;
 | 
				
			||||||
 | 
					  if (nr > 0)
 | 
				
			||||||
 | 
					    *data = *px0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Compute all but first values based on previous value               */
 | 
				
			||||||
 | 
					  prev = data - 1;
 | 
				
			||||||
 | 
					  while (--nr > 0 && --nd > 0)
 | 
				
			||||||
 | 
					    last_data = *++data = *++diff + *++prev;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* If a short count was requested compute the last sample in order    */
 | 
				
			||||||
 | 
					  /* to perform the integrity check comparison                          */
 | 
				
			||||||
 | 
					  while (--nd > 0)
 | 
				
			||||||
 | 
					    last_data = *++diff + last_data;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Verify that the last value is identical to xn = rev. int. constant */
 | 
				
			||||||
 | 
					  if (last_data != *pxn)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ms_log (1, "%s: Warning: Data integrity check for Steim-1 failed, last_data=%d, xn=%d\n",
 | 
				
			||||||
 | 
						      UNPACK_SRCNAME, last_data, *pxn);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return ((req_samples < num_samples) ? req_samples : num_samples);
 | 
				
			||||||
 | 
					}  /* End of msr_unpack_steim1() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_unpack_steim2:							*
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Unpack STEIM2 data frames and place in supplied buffer.		*
 | 
				
			||||||
 | 
					 *  See the SEED format manual for Steim-2 encoding details.            *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Return: # of samples returned or negative error code.               *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_unpack_steim2 
 | 
				
			||||||
 | 
					 (FRAME	       *pf,		/* ptr to Steim2 data frames.		*/
 | 
				
			||||||
 | 
					  int		nbytes,		/* number of bytes in all data frames.	*/
 | 
				
			||||||
 | 
					  int		num_samples,	/* number of data samples in all frames.*/
 | 
				
			||||||
 | 
					  int		req_samples,	/* number of data desired by caller.	*/
 | 
				
			||||||
 | 
					  int32_t      *databuff,	/* ptr to unpacked data array.		*/
 | 
				
			||||||
 | 
					  int32_t      *diffbuff,	/* ptr to unpacked diff array.		*/
 | 
				
			||||||
 | 
					  int32_t      *px0,		/* return X0, first sample in frame.	*/
 | 
				
			||||||
 | 
					  int32_t      *pxn,		/* return XN, last sample in frame.	*/
 | 
				
			||||||
 | 
					  int		swapflag,	/* if data should be swapped.	        */
 | 
				
			||||||
 | 
					  int           verbose)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int32_t      *diff = diffbuff;
 | 
				
			||||||
 | 
					  int32_t      *data = databuff;
 | 
				
			||||||
 | 
					  int32_t      *prev;
 | 
				
			||||||
 | 
					  int		num_data_frames = nbytes / sizeof(FRAME);
 | 
				
			||||||
 | 
					  int		nd = 0;		/* # of data points in packet.		*/
 | 
				
			||||||
 | 
					  int		fn;		/* current frame number.		*/
 | 
				
			||||||
 | 
					  int		wn;		/* current work number in the frame.	*/
 | 
				
			||||||
 | 
					  int		compflag;     	/* current compression flag.		*/
 | 
				
			||||||
 | 
					  int		nr, i;
 | 
				
			||||||
 | 
					  int		n, bits, m1, m2;
 | 
				
			||||||
 | 
					  int32_t	last_data;
 | 
				
			||||||
 | 
					  int32_t    	val;
 | 
				
			||||||
 | 
					  int8_t	dnib;
 | 
				
			||||||
 | 
					  uint32_t	ctrl;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (num_samples < 0) return 0;
 | 
				
			||||||
 | 
					  if (num_samples == 0) return 0;
 | 
				
			||||||
 | 
					  if (req_samples < 0) return 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Extract forward and reverse integration constants in first frame.*/
 | 
				
			||||||
 | 
					  *px0 = X0;
 | 
				
			||||||
 | 
					  *pxn = XN;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( swapflag )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ms_gswap4a (px0);
 | 
				
			||||||
 | 
					      ms_gswap4a (pxn);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ( verbose > 2 )
 | 
				
			||||||
 | 
					    ms_log (1, "%s: forward/reverse integration constants:  X0: %d  XN: %d\n",
 | 
				
			||||||
 | 
						    UNPACK_SRCNAME, *px0, *pxn);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Decode compressed data in each frame */
 | 
				
			||||||
 | 
					  for (fn = 0; fn < num_data_frames; fn++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      ctrl = pf->ctrl;
 | 
				
			||||||
 | 
					      if ( swapflag ) ms_gswap4a (&ctrl);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      for (wn = 0; wn < VALS_PER_FRAME; wn++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  if (nd >= num_samples) break;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  compflag = (ctrl >> ((VALS_PER_FRAME-wn-1)*2)) & 0x3;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  switch (compflag)
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						    case STEIM2_SPECIAL_MASK:
 | 
				
			||||||
 | 
						      /* Headers info -- skip it */
 | 
				
			||||||
 | 
						      break;
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						    case STEIM2_BYTE_MASK:
 | 
				
			||||||
 | 
						      /* Next 4 bytes are 4 1-byte differences */
 | 
				
			||||||
 | 
						      for (i=0; i < 4 && nd < num_samples; i++, nd++)
 | 
				
			||||||
 | 
							*diff++ = pf->w[wn].byte[i];
 | 
				
			||||||
 | 
						      break;
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						    case STEIM2_123_MASK:
 | 
				
			||||||
 | 
						      val = pf->w[wn].fw;
 | 
				
			||||||
 | 
						      if ( swapflag ) ms_gswap4a (&val);
 | 
				
			||||||
 | 
						      dnib =  val >> 30 & 0x3;
 | 
				
			||||||
 | 
						      switch (dnib)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							case 1:	/* 1 30-bit difference */
 | 
				
			||||||
 | 
							  bits = 30; n = 1; m1 = 0x3fffffff; m2 = 0x20000000; break;
 | 
				
			||||||
 | 
							case 2:	/* 2 15-bit differences */
 | 
				
			||||||
 | 
							  bits = 15; n = 2; m1 = 0x00007fff; m2 = 0x00004000; break;
 | 
				
			||||||
 | 
							case 3:	/* 3 10-bit differences */
 | 
				
			||||||
 | 
							  bits = 10; n = 3; m1 = 0x000003ff; m2 = 0x00000200; break;
 | 
				
			||||||
 | 
							default:	/*  should NEVER get here  */
 | 
				
			||||||
 | 
							  ms_log (2, "msr_unpack_steim2(%s): invalid compflag, dnib, fn, wn = %d, %d, %d, %d\n", 
 | 
				
			||||||
 | 
								  UNPACK_SRCNAME, compflag, dnib, fn, wn);
 | 
				
			||||||
 | 
							  return MS_STBADCOMPFLAG;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						      /*  Uncompress the differences */
 | 
				
			||||||
 | 
						      for (i=(n-1)*bits; i >= 0 && nd < num_samples; i-=bits, nd++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							  *diff = (val >> i) & m1;
 | 
				
			||||||
 | 
							  *diff = (*diff & m2) ? *diff | ~m1 : *diff;
 | 
				
			||||||
 | 
							  diff++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						      break;
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						    case STEIM2_567_MASK:
 | 
				
			||||||
 | 
						      val = pf->w[wn].fw;
 | 
				
			||||||
 | 
						      if ( swapflag ) ms_gswap4a (&val);
 | 
				
			||||||
 | 
						      dnib =  val >> 30 & 0x3;
 | 
				
			||||||
 | 
						      switch (dnib)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							case 0:	/*  5 6-bit differences  */
 | 
				
			||||||
 | 
							  bits = 6; n = 5; m1 = 0x0000003f; m2 = 0x00000020; break;
 | 
				
			||||||
 | 
							case 1:	/*  6 5-bit differences  */
 | 
				
			||||||
 | 
							  bits = 5; n = 6; m1 = 0x0000001f; m2 = 0x00000010; break;
 | 
				
			||||||
 | 
							case 2:	/*  7 4-bit differences  */
 | 
				
			||||||
 | 
							  bits = 4; n = 7; m1 = 0x0000000f; m2 = 0x00000008; break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
							  ms_log (2, "msr_unpack_steim2(%s): invalid compflag, dnib, fn, wn = %d, %d, %d, %d\n", 
 | 
				
			||||||
 | 
								  UNPACK_SRCNAME, compflag, dnib, fn, wn);
 | 
				
			||||||
 | 
							  return MS_STBADCOMPFLAG;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						      /* Uncompress the differences */
 | 
				
			||||||
 | 
						      for (i=(n-1)*bits; i >= 0 && nd < num_samples; i-=bits, nd++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							  *diff = (val >> i) & m1;
 | 
				
			||||||
 | 
							  *diff = (*diff & m2) ? *diff | ~m1 : *diff;
 | 
				
			||||||
 | 
							  diff++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						      break;
 | 
				
			||||||
 | 
						      
 | 
				
			||||||
 | 
						    default:
 | 
				
			||||||
 | 
						      /* Should NEVER get here */
 | 
				
			||||||
 | 
						      ms_log (2, "msr_unpack_steim2(%s): invalid compflag, fn, wn = %d, %d, %d - nsamp: %d\n",
 | 
				
			||||||
 | 
							      UNPACK_SRCNAME, compflag, fn, wn, nd);
 | 
				
			||||||
 | 
						      return MS_STBADCOMPFLAG;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      ++pf;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					  /* Test if the number of samples implied by the data frames is the
 | 
				
			||||||
 | 
					   * same number indicated in the header.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  if ( nd != num_samples )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ms_log (1, "Warning: msr_unpack_steim2(%s): number of samples indicated in header (%d) does not equal data (%d)\n",
 | 
				
			||||||
 | 
						      UNPACK_SRCNAME, num_samples, nd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*	For now, assume sample count in header to be correct.		*/
 | 
				
			||||||
 | 
					  /*	One way of "trimming" data from a block is simply to reduce	*/
 | 
				
			||||||
 | 
					  /*	the sample count.  It is not clear from the documentation	*/
 | 
				
			||||||
 | 
					  /*	whether this is a valid or not, but it appears to be done	*/
 | 
				
			||||||
 | 
					  /*	by other program, so we should not complain about its effect.	*/
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  nr = req_samples;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Compute first value based on last_value from previous buffer.	*/
 | 
				
			||||||
 | 
					  /* The two should correspond in all cases EXCEPT for the first	*/
 | 
				
			||||||
 | 
					  /* record for each component (because we don't have a valid xn from	*/
 | 
				
			||||||
 | 
					  /* a previous record).  Although the Steim compression algorithm	*/
 | 
				
			||||||
 | 
					  /* defines x(-1) as 0 for the first record, this only works for the	*/
 | 
				
			||||||
 | 
					  /* first record created since coldstart of the datalogger, NOT the	*/
 | 
				
			||||||
 | 
					  /* first record of an arbitrary starting record.	                */
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* In all cases, assume x0 is correct, since we don't have x(-1).	*/
 | 
				
			||||||
 | 
					  data = databuff;
 | 
				
			||||||
 | 
					  diff = diffbuff;
 | 
				
			||||||
 | 
					  last_data = *px0;
 | 
				
			||||||
 | 
					  if (nr > 0)
 | 
				
			||||||
 | 
					    *data = *px0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Compute all but first values based on previous value               */
 | 
				
			||||||
 | 
					  prev = data - 1;
 | 
				
			||||||
 | 
					  while (--nr > 0 && --nd > 0)
 | 
				
			||||||
 | 
					    last_data = *++data = *++diff + *++prev;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* If a short count was requested compute the last sample in order    */
 | 
				
			||||||
 | 
					  /* to perform the integrity check comparison                          */
 | 
				
			||||||
 | 
					  while (--nd > 0)
 | 
				
			||||||
 | 
					    last_data = *++diff + last_data;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Verify that the last value is identical to xn = rev. int. constant */
 | 
				
			||||||
 | 
					  if (last_data != *pxn)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ms_log (1, "%s: Warning: Data integrity check for Steim-2 failed, last_data=%d, xn=%d\n",
 | 
				
			||||||
 | 
						      UNPACK_SRCNAME, last_data, *pxn);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return ((req_samples < num_samples) ? req_samples : num_samples);
 | 
				
			||||||
 | 
					}  /* End of msr_unpack_steim2() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Defines for GEOSCOPE encoding */
 | 
				
			||||||
 | 
					#define GEOSCOPE_MANTISSA_MASK 0x0fff   /* mask for mantissa */
 | 
				
			||||||
 | 
					#define GEOSCOPE_GAIN3_MASK 0x7000      /* mask for gainrange factor */
 | 
				
			||||||
 | 
					#define GEOSCOPE_GAIN4_MASK 0xf000      /* mask for gainrange factor */
 | 
				
			||||||
 | 
					#define GEOSCOPE_SHIFT 12               /* # bits in mantissa */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_unpack_geoscope:                                                *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Unpack GEOSCOPE gain ranged data (demultiplexed only) encoded       *
 | 
				
			||||||
 | 
					 *  miniSEED data and place in supplied buffer.                         *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Return: # of samples returned.                                      *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_unpack_geoscope
 | 
				
			||||||
 | 
					 (const char   *edata,		/* ptr to encoded data.			*/
 | 
				
			||||||
 | 
					  int		num_samples,	/* number of data samples in total.     */
 | 
				
			||||||
 | 
					  int		req_samples,	/* number of data desired by caller.	*/
 | 
				
			||||||
 | 
					  float	       *databuff,	/* ptr to unpacked data array.		*/
 | 
				
			||||||
 | 
					  int           encoding,       /* specific GEOSCOPE encoding type      */
 | 
				
			||||||
 | 
					  int		swapflag)	/* if data should be swapped.	        */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int nd = 0;		/* # of data points in packet.		*/
 | 
				
			||||||
 | 
					  int mantissa;		/* mantissa from SEED data */
 | 
				
			||||||
 | 
					  int gainrange;	/* gain range factor */
 | 
				
			||||||
 | 
					  int exponent;		/* total exponent */
 | 
				
			||||||
 | 
					  int k;
 | 
				
			||||||
 | 
					  uint64_t exp2val;
 | 
				
			||||||
 | 
					  int16_t sint;
 | 
				
			||||||
 | 
					  double dsample = 0.0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  union {
 | 
				
			||||||
 | 
					    uint8_t b[4];
 | 
				
			||||||
 | 
					    uint32_t i;
 | 
				
			||||||
 | 
					  } sample32;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (num_samples < 0) return 0;
 | 
				
			||||||
 | 
					  if (req_samples < 0) return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Make sure we recognize this as a GEOSCOPE encoding format */
 | 
				
			||||||
 | 
					  if ( encoding != DE_GEOSCOPE24 &&
 | 
				
			||||||
 | 
					       encoding != DE_GEOSCOPE163 &&
 | 
				
			||||||
 | 
					       encoding != DE_GEOSCOPE164 )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ms_log (2, "msr_unpack_geoscope(%s): unrecognized GEOSCOPE encoding: %d\n",
 | 
				
			||||||
 | 
						      UNPACK_SRCNAME, encoding);
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  for (nd=0; nd<req_samples && nd<num_samples; nd++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      switch (encoding)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case DE_GEOSCOPE24:
 | 
				
			||||||
 | 
						  sample32.i = 0;
 | 
				
			||||||
 | 
						  if ( swapflag )
 | 
				
			||||||
 | 
						    for (k=0; k < 3; k++)
 | 
				
			||||||
 | 
						      sample32.b[2-k] = edata[k];
 | 
				
			||||||
 | 
						  else
 | 
				
			||||||
 | 
						    for (k=0; k < 3; k++)
 | 
				
			||||||
 | 
						      sample32.b[1+k] = edata[k];
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  mantissa = sample32.i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  /* Take 2's complement for mantissa for overflow */
 | 
				
			||||||
 | 
						  if (mantissa > MAX24) 
 | 
				
			||||||
 | 
						    mantissa -= 2 * (MAX24 + 1);
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  /* Store */
 | 
				
			||||||
 | 
						  dsample = (double) mantissa;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  break;
 | 
				
			||||||
 | 
						case DE_GEOSCOPE163:
 | 
				
			||||||
 | 
						  memcpy (&sint, edata, sizeof(int16_t));
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap2a(&sint);
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  /* Recover mantissa and gain range factor */
 | 
				
			||||||
 | 
						  mantissa = (sint & GEOSCOPE_MANTISSA_MASK);
 | 
				
			||||||
 | 
						  gainrange = (sint & GEOSCOPE_GAIN3_MASK) >> GEOSCOPE_SHIFT;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  /* Exponent is just gainrange for GEOSCOPE */
 | 
				
			||||||
 | 
						  exponent = gainrange;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  /* Calculate sample as mantissa / 2^exponent */
 | 
				
			||||||
 | 
						  exp2val = (uint64_t) 1 << exponent;
 | 
				
			||||||
 | 
						  dsample = ((double) (mantissa-2048)) / exp2val;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  break;
 | 
				
			||||||
 | 
						case DE_GEOSCOPE164:
 | 
				
			||||||
 | 
						  memcpy (&sint, edata, sizeof(int16_t));
 | 
				
			||||||
 | 
						  if ( swapflag ) ms_gswap2a(&sint);
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  /* Recover mantissa and gain range factor */
 | 
				
			||||||
 | 
						  mantissa = (sint & GEOSCOPE_MANTISSA_MASK);
 | 
				
			||||||
 | 
						  gainrange = (sint & GEOSCOPE_GAIN4_MASK) >> GEOSCOPE_SHIFT;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  /* Exponent is just gainrange for GEOSCOPE */
 | 
				
			||||||
 | 
						  exponent = gainrange;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  /* Calculate sample as mantissa / 2^exponent */
 | 
				
			||||||
 | 
						  exp2val = (uint64_t) 1 << exponent;
 | 
				
			||||||
 | 
						  dsample = ((double) (mantissa-2048)) / exp2val;
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						  break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Save sample in output array */
 | 
				
			||||||
 | 
					      databuff[nd] = (float) dsample;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Increment edata pointer depending on size */
 | 
				
			||||||
 | 
					      switch (encoding)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case DE_GEOSCOPE24:
 | 
				
			||||||
 | 
						  edata += 3;
 | 
				
			||||||
 | 
						  break;
 | 
				
			||||||
 | 
						case DE_GEOSCOPE163:
 | 
				
			||||||
 | 
						case DE_GEOSCOPE164:
 | 
				
			||||||
 | 
						  edata += 2;
 | 
				
			||||||
 | 
						  break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return nd;
 | 
				
			||||||
 | 
					}  /* End of msr_unpack_geoscope() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Defines for CDSN encoding */
 | 
				
			||||||
 | 
					#define CDSN_MANTISSA_MASK 0x3fff   /* mask for mantissa */
 | 
				
			||||||
 | 
					#define CDSN_GAINRANGE_MASK 0xc000  /* mask for gainrange factor */
 | 
				
			||||||
 | 
					#define CDSN_SHIFT 14               /* # bits in mantissa */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_unpack_cdsn:                                                    *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Unpack CDSN gain ranged data encoded miniSEED data and place in     *
 | 
				
			||||||
 | 
					 *  supplied buffer.                                                    *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Notes from original rdseed routine:                                 *
 | 
				
			||||||
 | 
					 *  CDSN data are compressed according to the formula                   *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  sample = M * (2 exp G)                                              *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  where                                                               *
 | 
				
			||||||
 | 
					 *     sample = seismic data sample                                     *
 | 
				
			||||||
 | 
					 *     M      = mantissa; biased mantissa B is written to tape          *
 | 
				
			||||||
 | 
					 *     G      = exponent of multiplier (i.e. gain range factor);        *
 | 
				
			||||||
 | 
					 *                      key K is written to tape                        *
 | 
				
			||||||
 | 
					 *     exp    = exponentiation operation                                *
 | 
				
			||||||
 | 
					 *     B      = M + 8191, biased mantissa, written to tape              *
 | 
				
			||||||
 | 
					 *     K      = key to multiplier exponent, written to tape             *
 | 
				
			||||||
 | 
					 *                      K may have any of the values 0 - 3, as follows: *
 | 
				
			||||||
 | 
					 *                      0 => G = 0, multiplier = 2 exp 0 = 1            *
 | 
				
			||||||
 | 
					 *                      1 => G = 2, multiplier = 2 exp 2 = 4            *
 | 
				
			||||||
 | 
					 *                      2 => G = 4, multiplier = 2 exp 4 = 16           *
 | 
				
			||||||
 | 
					 *                      3 => G = 7, multiplier = 2 exp 7 = 128          *
 | 
				
			||||||
 | 
					 *     Data are stored on tape in two bytes as follows:                 *
 | 
				
			||||||
 | 
					 *             fedc ba98 7654 3210 = bit number, power of two           *
 | 
				
			||||||
 | 
					 *             KKBB BBBB BBBB BBBB = form of SEED data                  *
 | 
				
			||||||
 | 
					 *             where K = key to multiplier exponent and B = biased mantissa *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *     Masks to recover key to multiplier exponent and biased mantissa  *
 | 
				
			||||||
 | 
					 *     from tape are:                                                   *
 | 
				
			||||||
 | 
					 *             fedc ba98 7654 3210 = bit number = power of two          *
 | 
				
			||||||
 | 
					 *             0011 1111 1111 1111 = 0x3fff     = mask for biased mantissa *
 | 
				
			||||||
 | 
					 *            1100 0000 0000 0000 = 0xc000     = mask for gain range key *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Return: # of samples returned.                                      *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_unpack_cdsn
 | 
				
			||||||
 | 
					 (int16_t      *edata,		/* ptr to encoded data.			*/
 | 
				
			||||||
 | 
					  int		num_samples,	/* number of data samples in total.     */
 | 
				
			||||||
 | 
					  int		req_samples,	/* number of data desired by caller.	*/
 | 
				
			||||||
 | 
					  int32_t      *databuff,	/* ptr to unpacked data array.		*/
 | 
				
			||||||
 | 
					  int		swapflag)	/* if data should be swapped.	        */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int32_t nd = 0;	/* sample count */
 | 
				
			||||||
 | 
					  int32_t mantissa;	/* mantissa */
 | 
				
			||||||
 | 
					  int32_t gainrange;	/* gain range factor */
 | 
				
			||||||
 | 
					  int32_t mult = -1;    /* multiplier for gain range */
 | 
				
			||||||
 | 
					  uint16_t sint;
 | 
				
			||||||
 | 
					  int32_t sample;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (num_samples < 0) return 0;
 | 
				
			||||||
 | 
					  if (req_samples < 0) return 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  for (nd=0; nd<req_samples && nd<num_samples; nd++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      memcpy (&sint, &edata[nd], sizeof(int16_t));
 | 
				
			||||||
 | 
					      if ( swapflag ) ms_gswap2a(&sint);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Recover mantissa and gain range factor */
 | 
				
			||||||
 | 
					      mantissa = (sint & CDSN_MANTISSA_MASK);
 | 
				
			||||||
 | 
					      gainrange = (sint & CDSN_GAINRANGE_MASK) >> CDSN_SHIFT;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Determine multiplier from the gain range factor and format definition
 | 
				
			||||||
 | 
					       * because shift operator is used later, these are powers of two */
 | 
				
			||||||
 | 
					      if ( gainrange == 0 ) mult = 0;
 | 
				
			||||||
 | 
					      else if ( gainrange == 1 ) mult = 2;
 | 
				
			||||||
 | 
					      else if ( gainrange == 2 ) mult = 4;
 | 
				
			||||||
 | 
					      else if ( gainrange == 3 ) mult = 7;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Unbias the mantissa */
 | 
				
			||||||
 | 
					      mantissa -= MAX14;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Calculate sample from mantissa and multiplier using left shift
 | 
				
			||||||
 | 
					       * mantissa << mult is equivalent to mantissa * (2 exp (mult)) */
 | 
				
			||||||
 | 
					      sample = (mantissa << mult);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Save sample in output array */
 | 
				
			||||||
 | 
					      databuff[nd] = sample;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return nd;
 | 
				
			||||||
 | 
					}  /* End of msr_unpack_cdsn() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Defines for SRO encoding */
 | 
				
			||||||
 | 
					#define SRO_MANTISSA_MASK 0x0fff   /* mask for mantissa */
 | 
				
			||||||
 | 
					#define SRO_GAINRANGE_MASK 0xf000  /* mask for gainrange factor */
 | 
				
			||||||
 | 
					#define SRO_SHIFT 12               /* # bits in mantissa */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_unpack_sro:                                                     *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Unpack SRO gain ranged data encoded miniSEED data and place in      *
 | 
				
			||||||
 | 
					 *  supplied buffer.                                                    *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Notes from original rdseed routine:                                 *
 | 
				
			||||||
 | 
					 *  SRO data are represented according to the formula                   *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  sample = M * (b exp {[m * (G + agr)] + ar})                         *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  where                                                               *
 | 
				
			||||||
 | 
					 *	sample = seismic data sample                                    *
 | 
				
			||||||
 | 
					 *	M      = mantissa                                               *
 | 
				
			||||||
 | 
					 *	G      = gain range factor                                      *
 | 
				
			||||||
 | 
					 *	b      = base to be exponentiated = 2 for SRO                   *
 | 
				
			||||||
 | 
					 *	m      = multiplier  = -1 for SRO                               *
 | 
				
			||||||
 | 
					 *	agr    = term to be added to gain range factor = 0 for SRO      *
 | 
				
			||||||
 | 
					 *	ar     = term to be added to [m * (gr + agr)]  = 10 for SRO     *
 | 
				
			||||||
 | 
					 *	exp    = exponentiation operation                               *
 | 
				
			||||||
 | 
					 *	Data are stored in two bytes as follows:                        *
 | 
				
			||||||
 | 
					 *		fedc ba98 7654 3210 = bit number, power of two          *
 | 
				
			||||||
 | 
					 *		GGGG MMMM MMMM MMMM = form of SEED data                 *
 | 
				
			||||||
 | 
					 *		where G = gain range factor and M = mantissa            *
 | 
				
			||||||
 | 
					 *	Masks to recover gain range and mantissa:                       *
 | 
				
			||||||
 | 
					 *		fedc ba98 7654 3210 = bit number = power of two         *
 | 
				
			||||||
 | 
					 *		0000 1111 1111 1111 = 0x0fff     = mask for mantissa    *
 | 
				
			||||||
 | 
					 *		1111 0000 0000 0000 = 0xf000     = mask for gain range  *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Return: # of samples returned.                                      *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_unpack_sro
 | 
				
			||||||
 | 
					 (int16_t      *edata,		/* ptr to encoded data.			*/
 | 
				
			||||||
 | 
					  int		num_samples,	/* number of data samples in total.     */
 | 
				
			||||||
 | 
					  int		req_samples,	/* number of data desired by caller.	*/
 | 
				
			||||||
 | 
					  int32_t      *databuff,	/* ptr to unpacked data array.		*/
 | 
				
			||||||
 | 
					  int		swapflag)	/* if data should be swapped.	        */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int32_t nd = 0;	/* sample count */
 | 
				
			||||||
 | 
					  int32_t mantissa;	/* mantissa */
 | 
				
			||||||
 | 
					  int32_t gainrange;	/* gain range factor */
 | 
				
			||||||
 | 
					  int32_t add2gr;       /* added to gainrage factor */
 | 
				
			||||||
 | 
					  int32_t mult;         /* multiplier for gain range */
 | 
				
			||||||
 | 
					  int32_t add2result;   /* added to multiplied gain rage */
 | 
				
			||||||
 | 
					  int32_t exponent;	/* total exponent */
 | 
				
			||||||
 | 
					  uint16_t sint;
 | 
				
			||||||
 | 
					  int32_t sample;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (num_samples < 0) return 0;
 | 
				
			||||||
 | 
					  if (req_samples < 0) return 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  add2gr = 0;
 | 
				
			||||||
 | 
					  mult = -1;
 | 
				
			||||||
 | 
					  add2result = 10;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  for (nd=0; nd<req_samples && nd<num_samples; nd++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      memcpy (&sint, &edata[nd], sizeof(int16_t));
 | 
				
			||||||
 | 
					      if ( swapflag ) ms_gswap2a(&sint);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Recover mantissa and gain range factor */
 | 
				
			||||||
 | 
					      mantissa = (sint & SRO_MANTISSA_MASK);
 | 
				
			||||||
 | 
					      gainrange = (sint & SRO_GAINRANGE_MASK) >> SRO_SHIFT;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Take 2's complement for mantissa */
 | 
				
			||||||
 | 
					      if ( mantissa > MAX12 )
 | 
				
			||||||
 | 
						mantissa -= 2 * (MAX12 + 1);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Calculate exponent, SRO exponent = 0..10 */
 | 
				
			||||||
 | 
					      exponent = (mult * (gainrange + add2gr)) + add2result;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if ( exponent < 0 || exponent > 10 )
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  ms_log (2, "msr_unpack_sro(%s): SRO gain ranging exponent out of range: %d\n",
 | 
				
			||||||
 | 
							  UNPACK_SRCNAME, exponent);
 | 
				
			||||||
 | 
						  return MS_GENERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Calculate sample as mantissa * 2^exponent */
 | 
				
			||||||
 | 
					      sample = mantissa * ( (uint64_t) 1 << exponent );
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Save sample in output array */
 | 
				
			||||||
 | 
					      databuff[nd] = sample;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return nd;
 | 
				
			||||||
 | 
					}  /* End of msr_unpack_sro() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/************************************************************************
 | 
				
			||||||
 | 
					 *  msr_unpack_dwwssn:                                                  *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Unpack DWWSSN encoded miniSEED data and place in supplied buffer.   *
 | 
				
			||||||
 | 
					 *                                                                      *
 | 
				
			||||||
 | 
					 *  Return: # of samples returned.                                      *
 | 
				
			||||||
 | 
					 ************************************************************************/
 | 
				
			||||||
 | 
					int msr_unpack_dwwssn
 | 
				
			||||||
 | 
					 (int16_t      *edata,		/* ptr to encoded data.			*/
 | 
				
			||||||
 | 
					  int		num_samples,	/* number of data samples in total.     */
 | 
				
			||||||
 | 
					  int		req_samples,	/* number of data desired by caller.	*/
 | 
				
			||||||
 | 
					  int32_t      *databuff,	/* ptr to unpacked data array.		*/
 | 
				
			||||||
 | 
					  int		swapflag)	/* if data should be swapped.	        */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int32_t nd = 0;	/* sample count */
 | 
				
			||||||
 | 
					  int32_t sample;
 | 
				
			||||||
 | 
					  uint16_t sint;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (num_samples < 0) return 0;
 | 
				
			||||||
 | 
					  if (req_samples < 0) return 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  for (nd=0; nd<req_samples && nd<num_samples; nd++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      memcpy (&sint, &edata[nd], sizeof(uint16_t));
 | 
				
			||||||
 | 
					      if ( swapflag ) ms_gswap2a(&sint);
 | 
				
			||||||
 | 
					      sample = (int32_t) sint;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Take 2's complement for sample */
 | 
				
			||||||
 | 
					      if ( sample > MAX16 )
 | 
				
			||||||
 | 
						sample -= 2 * (MAX16 + 1);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      /* Save sample in output array */
 | 
				
			||||||
 | 
					      databuff[nd] = sample;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return nd;
 | 
				
			||||||
 | 
					}  /* End of msr_unpack_dwwssn() */
 | 
				
			||||||
							
								
								
									
										40
									
								
								libs/3rd-party/mseed/unpackdata.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								libs/3rd-party/mseed/unpackdata.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * unpack.h:
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Interface declarations for the Mini-SEED unpacking routines in
 | 
				
			||||||
 | 
					 * unpackdata.c
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * modified: 2009.111
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef	UNPACKDATA_H
 | 
				
			||||||
 | 
					#define	UNPACKDATA_H 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "steimdata.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Pointer to srcname of record being unpacked, declared in unpack.c */
 | 
				
			||||||
 | 
					extern char *UNPACK_SRCNAME;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					extern int msr_unpack_int_16 (int16_t*, int, int, int32_t*, int);
 | 
				
			||||||
 | 
					extern int msr_unpack_int_32 (int32_t*, int, int, int32_t*, int);
 | 
				
			||||||
 | 
					extern int msr_unpack_float_32 (float*, int, int, float*, int);
 | 
				
			||||||
 | 
					extern int msr_unpack_float_64 (double*, int, int, double*, int);
 | 
				
			||||||
 | 
					extern int msr_unpack_steim1 (FRAME*, int, int, int, int32_t*, int32_t*,
 | 
				
			||||||
 | 
								      int32_t*, int32_t*, int, int);
 | 
				
			||||||
 | 
					extern int msr_unpack_steim2 (FRAME*, int, int, int, int32_t*, int32_t*,
 | 
				
			||||||
 | 
								      int32_t*, int32_t*, int, int);
 | 
				
			||||||
 | 
					extern int msr_unpack_geoscope (const char*, int, int, float*, int, int);
 | 
				
			||||||
 | 
					extern int msr_unpack_cdsn (int16_t*, int, int, int32_t*, int);
 | 
				
			||||||
 | 
					extern int msr_unpack_sro (int16_t*, int, int, int32_t*, int);
 | 
				
			||||||
 | 
					extern int msr_unpack_dwwssn (int16_t*, int, int, int32_t*, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										5
									
								
								libs/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								libs/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					SUBDIRS(3rd-party gempa)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(LIBCAPS_PYTHON_WRAPPER)
 | 
				
			||||||
 | 
						SUBDIRS(swig)
 | 
				
			||||||
 | 
					ENDIF()
 | 
				
			||||||
							
								
								
									
										1
									
								
								libs/gempa/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								libs/gempa/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					subdirs(caps)
 | 
				
			||||||
							
								
								
									
										150
									
								
								libs/gempa/caps/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								libs/gempa/caps/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,150 @@
 | 
				
			|||||||
 | 
					# Change Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All notable changes to the CAPS client library will be documented in this file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2021-04-21 1.0.0
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					- Set library version to 1.0.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2021-02-16
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- Allow to set maximum allowed future end time via plugin API. In additon
 | 
				
			||||||
 | 
					  add commandline and config support to the plugin application class e.g.
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  output.maxFutureEndTime = 120
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					  By default the option is set to 120 seconds.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2020-12-14
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- Support to set miniSEED record length via API
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2020-09-22
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					- Use last sample time as reference time for maximum future time check. Before
 | 
				
			||||||
 | 
					  we used the packet end time as reference time but this makes no sense in case
 | 
				
			||||||
 | 
					  of low sampled data.
 | 
				
			||||||
 | 
					- So far we used the current time as start time if journal entries exceeded the
 | 
				
			||||||
 | 
					  maximum allowed future time. With this release we use the journal time no
 | 
				
			||||||
 | 
					  matter what its value but display a warning when the journal time is more than
 | 
				
			||||||
 | 
					  one day in the future.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2020-06-22
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- Python3 byte array support to any record push
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2020-02-21
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					- Increase default timeout for acknowledgement messages from 5s to 60s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2019-09-24
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- Fix high load if packets could not be sent to CAPS. In that case the plugin
 | 
				
			||||||
 | 
					  automatically reconnects after some amount of time. If triggered under certain
 | 
				
			||||||
 | 
					  circumstances this delay was not in effect and caused unnecessarily high
 | 
				
			||||||
 | 
					  amount of connection attempts. Under some circumstances the plugin could have
 | 
				
			||||||
 | 
					  crashed due to a stack overflow.
 | 
				
			||||||
 | 
					- The quit method has now the semantics to continue pushing packets as long
 | 
				
			||||||
 | 
					  as the connection is established and only abort in case of an error without
 | 
				
			||||||
 | 
					  attempting a reconnect.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2019-09-20
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- Fix error string if not all data could be sent to the server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2019-08-19
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					- Discard packets whose end time is more than 120 seconds before the system time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2019-08-06
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- new config option ``output.addr``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- ambiguous command line option ``-h``. With this version of the library the
 | 
				
			||||||
 | 
					host and port can be set via the command line option ``--addr``.
 | 
				
			||||||
 | 
					- wrong config option parsing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2019-08-05
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- seg fault in date time parser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2019-08-02
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- Hanging TCP connections. In case of the remote side does not shutdown cleanly
 | 
				
			||||||
 | 
					the plugin did not notice that the connection is no longer available. With this
 | 
				
			||||||
 | 
					version the plugin reconnects to the server when the TCP send buffer is full and
 | 
				
			||||||
 | 
					tries to send all not acknowledged packets again.
 | 
				
			||||||
 | 
					- Do not discard packets if the packet buffer is full. Instead we block until
 | 
				
			||||||
 | 
					the server acknowledges some packets.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					- The plugin application class checks whether the configured buffer size is
 | 
				
			||||||
 | 
					below the minimum.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2019-07-05
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					- Ignore journal entries where the timestamp is more than 10 seconds
 | 
				
			||||||
 | 
					  before the system time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2018-12-19
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- Read journal from file in plugin application.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2018-12-18
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- Do not reconnect if the plugin buffer is full. Instead of we try to read
 | 
				
			||||||
 | 
					acknowledgements from the CAPS server until the plugin buffer is below the
 | 
				
			||||||
 | 
					threshold.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2018-12-17
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- Support to retrieve status information e.g. the number of buffered bytes from
 | 
				
			||||||
 | 
					  plugin.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2018-09-06
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					- Enable more verbose logging for MSEED packets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2018-07-25
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- unset variable of the raw data record
 | 
				
			||||||
 | 
					- trim function will return false in case of an unknown datatype
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2018-05-30
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- Fixed unexpected closed SSL connections
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2018-06-05
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- Fix RawDataRecord::setHeader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2018-05-16
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- RAW data end time calculation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2018-03-19
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- SSL support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2017-11-20
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- float and double support for Steim encoders. All values will be converted implicitly
 | 
				
			||||||
 | 
					to int 32 values
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2017-11-08
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- timing quality parameter to push call. By default the timing quality is set to -1.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2017-11-07
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- do not flush encoders after reconnect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2017-10-26
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- SSL support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2017-10-24
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					- packet synchronization error after reconnect
 | 
				
			||||||
							
								
								
									
										22
									
								
								libs/gempa/caps/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								libs/gempa/caps/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					SET(PACKAGE_NAME LIB_CAPS)
 | 
				
			||||||
 | 
					SET(LIB_NAME capsclient)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FILE(GLOB ${PACKAGE_NAME}_SOURCES
 | 
				
			||||||
 | 
						"*.cpp"
 | 
				
			||||||
 | 
						"mseed/*.cpp"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LIST(FILTER ${PACKAGE_NAME}_SOURCES EXCLUDE REGEX pluginapplication.cpp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IF(WIN32)
 | 
				
			||||||
 | 
						SET(${PACKAGE_NAME}_SOURCES ${${PACKAGE_NAME}_SOURCES} strptime.c)
 | 
				
			||||||
 | 
					ENDIF(WIN32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INCLUDE_DIRECTORIES(../../3rd-party/mseed)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ADD_LIBRARY(${LIB_NAME} SHARED ${${PACKAGE_NAME}_SOURCES})
 | 
				
			||||||
 | 
					SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES COMPILE_FLAGS -fPIC)
 | 
				
			||||||
 | 
					SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION 1.0.0 SOVERSION 1)
 | 
				
			||||||
 | 
					TARGET_LINK_LIBRARIES(${LIB_NAME} mseed)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSTALL(TARGETS ${LIB_NAME} DESTINATION lib)
 | 
				
			||||||
							
								
								
									
										197
									
								
								libs/gempa/caps/anypacket.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								libs/gempa/caps/anypacket.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,197 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/anypacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/riff.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <streambuf>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool AnyDataRecord::AnyHeader::put(std::streambuf &buf) const {
 | 
				
			||||||
 | 
						Endianess::Writer put(buf);
 | 
				
			||||||
 | 
						put(type, sizeof(type)-1);
 | 
				
			||||||
 | 
						dataHeader.put(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						put(endTime.year);
 | 
				
			||||||
 | 
						put(endTime.yday);
 | 
				
			||||||
 | 
						put(endTime.hour);
 | 
				
			||||||
 | 
						put(endTime.minute);
 | 
				
			||||||
 | 
						put(endTime.second);
 | 
				
			||||||
 | 
						put(endTime.usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return put.good;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AnyDataRecord::AnyDataRecord() {
 | 
				
			||||||
 | 
						strncpy(_header.type, "ANY", sizeof(_header.type));
 | 
				
			||||||
 | 
						_header.dataHeader.samplingFrequencyDenominator = 0;
 | 
				
			||||||
 | 
						_header.dataHeader.samplingFrequencyNumerator = 0;
 | 
				
			||||||
 | 
						// Just a bunch of bytes
 | 
				
			||||||
 | 
						_header.dataHeader.dataType = DT_INT8;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool AnyDataRecord::setType(const char *type) {
 | 
				
			||||||
 | 
						strncpy(_header.type, type, sizeof(_header.type));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Input clipped?
 | 
				
			||||||
 | 
						if ( _header.type[sizeof(_header.type)-1] != '\0' ) {
 | 
				
			||||||
 | 
							_header.type[sizeof(_header.type)-1] = '\0';
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *AnyDataRecord::type() const {
 | 
				
			||||||
 | 
						return _header.type;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AnyDataRecord::setStartTime(const Time &time) {
 | 
				
			||||||
 | 
						timeToTimestamp(_header.dataHeader.samplingTime, time);
 | 
				
			||||||
 | 
						_startTime = time;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AnyDataRecord::setEndTime(const Time &time) {
 | 
				
			||||||
 | 
						timeToTimestamp(_header.endTime, time);
 | 
				
			||||||
 | 
						_endTime = time;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AnyDataRecord::setSamplingFrequency(uint16_t numerator, uint16_t denominator) {
 | 
				
			||||||
 | 
						_header.dataHeader.samplingFrequencyNumerator = numerator;
 | 
				
			||||||
 | 
						_header.dataHeader.samplingFrequencyDenominator = denominator;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *AnyDataRecord::formatName() const {
 | 
				
			||||||
 | 
						return "ANY";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool AnyDataRecord::readMetaData(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
					                                 Header &header,
 | 
				
			||||||
 | 
					                                 Time &startTime, Time &endTime) {
 | 
				
			||||||
 | 
						// Read record type
 | 
				
			||||||
 | 
						buf.sgetn(_header.type, 4);
 | 
				
			||||||
 | 
						_header.type[sizeof(_header.type)-1] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size -= sizeof(_header.type)-1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !header.get(buf) ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						TimeStamp tmp;
 | 
				
			||||||
 | 
						Endianess::Reader get(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						get(tmp.year);
 | 
				
			||||||
 | 
						get(tmp.yday);
 | 
				
			||||||
 | 
						get(tmp.hour);
 | 
				
			||||||
 | 
						get(tmp.minute);
 | 
				
			||||||
 | 
						get(tmp.second);
 | 
				
			||||||
 | 
						get(tmp.usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						startTime = timestampToTime(header.samplingTime);
 | 
				
			||||||
 | 
						endTime = timestampToTime(tmp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DataRecord::Header *AnyDataRecord::header() const {
 | 
				
			||||||
 | 
						return &_header.dataHeader;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Time AnyDataRecord::startTime() const {
 | 
				
			||||||
 | 
						return _startTime;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Time AnyDataRecord::endTime() const {
 | 
				
			||||||
 | 
						return _endTime;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool AnyDataRecord::canTrim() const {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool AnyDataRecord::canMerge() const {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool AnyDataRecord::trim(const Time &start,
 | 
				
			||||||
 | 
					                         const Time &end) const {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t AnyDataRecord::dataSize(bool withHeader) const {
 | 
				
			||||||
 | 
						if ( withHeader )
 | 
				
			||||||
 | 
							return _data.size() + _header.dataSize();
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return _data.size();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DataRecord::ReadStatus AnyDataRecord::get(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
					                                          const Time &start, const Time &end,
 | 
				
			||||||
 | 
					                                          int) {
 | 
				
			||||||
 | 
						_data.clear();
 | 
				
			||||||
 | 
						size -= _header.dataSize();
 | 
				
			||||||
 | 
						if ( size < 0 ) return RS_Error;
 | 
				
			||||||
 | 
						if ( !_header.get(buf) ) return RS_Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_startTime = timestampToTime(_header.dataHeader.samplingTime);
 | 
				
			||||||
 | 
						_endTime = timestampToTime(_header.endTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( start.valid() ) {
 | 
				
			||||||
 | 
							if ( _endTime < start || (_startTime < start && _endTime == start) )
 | 
				
			||||||
 | 
								return RS_BeforeTimeWindow;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( end.valid() ) {
 | 
				
			||||||
 | 
							if ( _startTime >= end ) return RS_AfterTimeWindow;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RIFF::VectorChunk<1,false> dataChunk(_data, 0, size);
 | 
				
			||||||
 | 
						if ( !dataChunk.get(buf, size) ) return RS_Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return RS_Complete;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool AnyDataRecord::put(std::streambuf &buf, bool withHeader) const {
 | 
				
			||||||
 | 
						if ( withHeader && !_header.put(buf) ) return false;
 | 
				
			||||||
 | 
						return (int)buf.sputn(_data.data(), _data.size()) == (int)_data.size();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AnyDataRecord::setData(char *data, size_t size) {
 | 
				
			||||||
 | 
						_data.resize(size);
 | 
				
			||||||
 | 
						memcpy(_data.data(), data, size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										154
									
								
								libs/gempa/caps/anypacket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								libs/gempa/caps/anypacket.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,154 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_CUSTOMPACKET_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_CUSTOMPACKET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/endianess.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AnyDataRecord : public DataRecord {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							typedef std::vector<char> Buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct AnyHeader {
 | 
				
			||||||
 | 
								char      type[5];
 | 
				
			||||||
 | 
								Header    dataHeader;
 | 
				
			||||||
 | 
								TimeStamp endTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bool get(std::streambuf &buf) {
 | 
				
			||||||
 | 
									Endianess::Reader get(buf);
 | 
				
			||||||
 | 
									get(type, sizeof(type)-1);
 | 
				
			||||||
 | 
									type[sizeof(type)-1] = '\0';
 | 
				
			||||||
 | 
									dataHeader.get(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									get(endTime.year);
 | 
				
			||||||
 | 
									get(endTime.yday);
 | 
				
			||||||
 | 
									get(endTime.hour);
 | 
				
			||||||
 | 
									get(endTime.minute);
 | 
				
			||||||
 | 
									get(endTime.second);
 | 
				
			||||||
 | 
									get(endTime.usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return get.good;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bool put(std::streambuf &buf) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// 4 additional bytes (type) with respect to the original
 | 
				
			||||||
 | 
								// data header
 | 
				
			||||||
 | 
								int dataSize() const {
 | 
				
			||||||
 | 
									return sizeof(type)-1 +
 | 
				
			||||||
 | 
									       dataHeader.dataSize() +
 | 
				
			||||||
 | 
									       sizeof(endTime.year) +
 | 
				
			||||||
 | 
									       sizeof(endTime.yday) +
 | 
				
			||||||
 | 
									       sizeof(endTime.hour) +
 | 
				
			||||||
 | 
									       sizeof(endTime.minute) +
 | 
				
			||||||
 | 
									       sizeof(endTime.second) +
 | 
				
			||||||
 | 
									       sizeof(endTime.usec);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							AnyDataRecord();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets the format of the any record. The format can be
 | 
				
			||||||
 | 
							//! anything that fits into 4 characters. If more than
 | 
				
			||||||
 | 
							//! 4 characters are given, false is returned.
 | 
				
			||||||
 | 
							bool setType(const char *type);
 | 
				
			||||||
 | 
							const char *type() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual const char *formatName() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool readMetaData(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                          Header &header,
 | 
				
			||||||
 | 
							                          Time &startTime,
 | 
				
			||||||
 | 
							                          Time &endTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual const Header *header() const;
 | 
				
			||||||
 | 
							virtual Time startTime() const;
 | 
				
			||||||
 | 
							virtual Time endTime() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool canTrim() const;
 | 
				
			||||||
 | 
							virtual bool canMerge() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool trim(const Time &start,
 | 
				
			||||||
 | 
							                  const Time &end) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual size_t dataSize(bool withHeader) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual ReadStatus get(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                       const Time &start = Time(),
 | 
				
			||||||
 | 
							                       const Time &end = Time(),
 | 
				
			||||||
 | 
							                       int maxSize = -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool put(std::streambuf &buf, bool withHeader) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns the packet type
 | 
				
			||||||
 | 
							 * @return The packet type
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							PacketType packetType() const { return ANYPacket; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Sets the start time of the record
 | 
				
			||||||
 | 
							 * @param The start time
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							void setStartTime(const Time &time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Sets the end time of the record
 | 
				
			||||||
 | 
							 * @param The end time
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							void setEndTime(const Time &time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Sets the sampling frequency of the record
 | 
				
			||||||
 | 
							 * @param numerator The numerator
 | 
				
			||||||
 | 
							 * @param denominator The denomintor
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							void setSamplingFrequency(uint16_t numerator, uint16_t denominator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns the data vector to be filled by the caller
 | 
				
			||||||
 | 
							 * @return The pointer to the internal buffer
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							Buffer *data() { return &_data; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Initializes the internal data vector from the given buffer
 | 
				
			||||||
 | 
							 * @param The buffer to read the data from
 | 
				
			||||||
 | 
							 * @param The buffer size
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual void setData(char *data, size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							AnyHeader      _header;
 | 
				
			||||||
 | 
							Buffer         _data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Time          _startTime;
 | 
				
			||||||
 | 
							Time          _endTime;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										17
									
								
								libs/gempa/caps/api.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								libs/gempa/caps/api.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					#ifndef SC_GEMPA_CAPS_API_H
 | 
				
			||||||
 | 
					#define SC_GEMPA_CAPS_API_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(WIN32) && (defined(SC_GEMPA_CAPS_SHARED) || defined(SC_ALL_SHARED))
 | 
				
			||||||
 | 
					# if defined(SC_GEMPA_CAPS_EXPORTS)
 | 
				
			||||||
 | 
					#  define SC_GEMPA_CAPS_API __declspec(dllexport)
 | 
				
			||||||
 | 
					#  define SC_GEMPA_CAPS_TEMPLATE_EXPORT
 | 
				
			||||||
 | 
					# else
 | 
				
			||||||
 | 
					#  define SC_GEMPA_CAPS_API __declspec(dllimport)
 | 
				
			||||||
 | 
					#  define SC_GEMPA_CAPS_TEMPLATE_EXPORT extern
 | 
				
			||||||
 | 
					# endif
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					# define SC_GEMPA_CAPS_API
 | 
				
			||||||
 | 
					# define SC_GEMPA_CAPS_TEMPLATE_EXPORT
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										141
									
								
								libs/gempa/caps/application.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								libs/gempa/caps/application.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,141 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/application.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <csignal>
 | 
				
			||||||
 | 
					#include <locale.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void signalHandler(int signal) {
 | 
				
			||||||
 | 
						Gempa::CAPS::Application::Interrupt(signal);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void registerSignalHandler() {
 | 
				
			||||||
 | 
						CAPS_DEBUG("Registering signal handler");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						signal(SIGTERM, signalHandler);
 | 
				
			||||||
 | 
						signal(SIGINT, signalHandler);
 | 
				
			||||||
 | 
						signal(SIGHUP, SIG_IGN);
 | 
				
			||||||
 | 
						signal(SIGPIPE, SIG_IGN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Application* Application::_app = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Application::Application(int argc, char **argv) {
 | 
				
			||||||
 | 
						_exitRequested = false;
 | 
				
			||||||
 | 
						_argc = argc;
 | 
				
			||||||
 | 
						_argv = argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_app = this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						registerSignalHandler();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::done() {
 | 
				
			||||||
 | 
						_exitRequested = true;
 | 
				
			||||||
 | 
						 CAPS_DEBUG("leaving ::done");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int Application::exec() {
 | 
				
			||||||
 | 
						_returnCode = 1;
 | 
				
			||||||
 | 
						if ( init() ) {
 | 
				
			||||||
 | 
							_returnCode = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( !run() && _returnCode == 0 )
 | 
				
			||||||
 | 
								_returnCode = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							done();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							done();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return _returnCode;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::exit(int returnCode) {
 | 
				
			||||||
 | 
						_returnCode = returnCode;
 | 
				
			||||||
 | 
						_exitRequested = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::handleInterrupt(int signal) {
 | 
				
			||||||
 | 
						switch ( signal ) {
 | 
				
			||||||
 | 
							case SIGABRT:
 | 
				
			||||||
 | 
								exit(-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case SIGSEGV:
 | 
				
			||||||
 | 
								exit(-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								this->exit(_returnCode);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::Interrupt(int signal) {
 | 
				
			||||||
 | 
						if ( _app ) _app->handleInterrupt(signal);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Application::init() {
 | 
				
			||||||
 | 
						setlocale(LC_ALL, "C");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !initCommandLine() ) {
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !initConfiguration() ) {
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !initCommandLine() ) {
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !validateParameters() ) {
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Application::initCommandLine() {
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Application::initConfiguration() {
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Application::run() {
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Application::validateParameters() {
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										106
									
								
								libs/gempa/caps/application.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								libs/gempa/caps/application.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_APPLICATION_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_APPLICATION_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/api.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SC_GEMPA_CAPS_API Application {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Application(int argc, char **argv);
 | 
				
			||||||
 | 
							virtual ~Application() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * Exit the application and set the returnCode.
 | 
				
			||||||
 | 
							 * @param returnCode The value returned from exec()
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual void exit(int returnCode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Conventient function to simplify usage
 | 
				
			||||||
 | 
							 * @return The value returned from exec()
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							int operator()() { return exec(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief In case of an interrupt this method can be used to
 | 
				
			||||||
 | 
							 *        forward the signal to the internal signal handling.
 | 
				
			||||||
 | 
							 * @param signal
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							static void Interrupt(int signal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Cleanup method called before exec() returns.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual void done();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * Execs the mainloop and waits until exit() is called
 | 
				
			||||||
 | 
							 * or a appropriate signal has been fired (e.g. SIGTERM).
 | 
				
			||||||
 | 
							 * @return The value that was set with to exit()
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							int exec();
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief This method can be used to implement custom
 | 
				
			||||||
 | 
							 *        signal handling.
 | 
				
			||||||
 | 
							 * @param signal The emitted signal
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual void handleInterrupt(int signal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Initialization method. This method calls the initCommandLine
 | 
				
			||||||
 | 
							 *        initConfiguration and validateParameters function
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual bool init();
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Handles commandline arguments
 | 
				
			||||||
 | 
							*/
 | 
				
			||||||
 | 
							virtual bool initCommandLine();
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Handles configuration files
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual bool initConfiguration();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief This method must be implemented in the inherited class to
 | 
				
			||||||
 | 
							 *        execute the plugin specific code.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual bool run();
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief This method can be used to verify custom configuration or
 | 
				
			||||||
 | 
								      commandline parameters
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual bool validateParameters();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							bool                _exitRequested;
 | 
				
			||||||
 | 
							int                 _argc;
 | 
				
			||||||
 | 
							char              **_argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							int                 _returnCode;
 | 
				
			||||||
 | 
							static Application *_app;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										621
									
								
								libs/gempa/caps/connection.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										621
									
								
								libs/gempa/caps/connection.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,621 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/connection.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/anypacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/mseedpacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/metapacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/rawpacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/sessiontable.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/time.h>
 | 
				
			||||||
 | 
					#include <cerrno>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Time InvalidTime = Time();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool fromString(T &value, const string &str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<> inline bool fromString(int &value, const string &str) {
 | 
				
			||||||
 | 
						stringstream ss(str);
 | 
				
			||||||
 | 
						ss >> value;
 | 
				
			||||||
 | 
						return !ss.bad();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Connection::Connection() {
 | 
				
			||||||
 | 
						_port = 18002;
 | 
				
			||||||
 | 
						_server = "localhost";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_metaMode = false;
 | 
				
			||||||
 | 
						_realtime = true;
 | 
				
			||||||
 | 
						_ssl = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_sessionTable = SessionTablePtr(new SessionTable());
 | 
				
			||||||
 | 
						_sessionTable->setItemAboutToBeRemovedFunc(
 | 
				
			||||||
 | 
							bind(&Connection::onItemAboutToBeRemoved, this, placeholders::_1)
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reset();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Connection::~Connection() {
 | 
				
			||||||
 | 
						close();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Connection::setServer(const string &server) {
 | 
				
			||||||
 | 
						close();
 | 
				
			||||||
 | 
						reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t pos = server.rfind(':');
 | 
				
			||||||
 | 
						string addr = server;
 | 
				
			||||||
 | 
						int timeout = 300;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( pos == string::npos )
 | 
				
			||||||
 | 
							_server = addr;
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							_server = addr.substr(0, pos);
 | 
				
			||||||
 | 
							if ( !fromString(_port, addr.substr(pos+1)) ) {
 | 
				
			||||||
 | 
								CAPS_ERROR("invalid source address: %s", addr.c_str());
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( timeout > 0 ) {
 | 
				
			||||||
 | 
							CAPS_DEBUG("setting socket timeout to %ds", timeout);
 | 
				
			||||||
 | 
							//_socket->setSocketTimeout(timeout,0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Connection::setCredentials(const std::string &user,
 | 
				
			||||||
 | 
					                                const std::string &password) {
 | 
				
			||||||
 | 
						if ( user.empty() || password.empty() ) {
 | 
				
			||||||
 | 
							_auth.clear();
 | 
				
			||||||
 | 
							CAPS_DEBUG("authentication deactivated");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							_auth = "AUTH " + user + " " + password;
 | 
				
			||||||
 | 
							CAPS_DEBUG("credentials set: %s:***", user.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Socket* Connection::createSocket() const {
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_SSL) || CAPS_FEATURES_SSL
 | 
				
			||||||
 | 
						return _ssl? new SSLSocket() : new Socket();
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						return new Socket();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Connection::disconnect() {
 | 
				
			||||||
 | 
						if ( _socket == NULL ) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CAPS_DEBUG("disconnecting");
 | 
				
			||||||
 | 
						if ( _state != Aborted )
 | 
				
			||||||
 | 
							_state = Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_socket->shutdown();
 | 
				
			||||||
 | 
						_socket->close();
 | 
				
			||||||
 | 
						_sessionTable->reset();
 | 
				
			||||||
 | 
						_currentID = - 1;
 | 
				
			||||||
 | 
						_currentItem = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Connection::close() {
 | 
				
			||||||
 | 
						boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
					//	_state = Aborted;
 | 
				
			||||||
 | 
						disconnect();
 | 
				
			||||||
 | 
						_state = Aborted;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Connection::abort() {
 | 
				
			||||||
 | 
						boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
						if ( _state == Aborted ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("abort already requested");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _socket->isValid() && _state == Active ) {
 | 
				
			||||||
 | 
							static string line("ABORT\n");
 | 
				
			||||||
 | 
							if ( _socket->write(line.c_str(), line.size()) != (int) line.size() ) {
 | 
				
			||||||
 | 
								CAPS_ERROR("could not send abort request");
 | 
				
			||||||
 | 
								disconnect();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								CAPS_DEBUG("abort command sent");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_state = Aborted;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Connection::setTimeout(int /*seconds*/) {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Connection::addStream(const string &net, const string &sta,
 | 
				
			||||||
 | 
					                           const string &loc, const string &cha) {
 | 
				
			||||||
 | 
						return addRequest(net, sta, loc, cha, _startTime, _endTime, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Connection::addStream(const string &net, const string &sta,
 | 
				
			||||||
 | 
					                           const string &loc, const string &cha,
 | 
				
			||||||
 | 
					                           const Time &stime,
 | 
				
			||||||
 | 
					                           const Time &etime) {
 | 
				
			||||||
 | 
						return addRequest(net, sta, loc, cha, stime, etime, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Connection::addRequest(const string &net, const string &sta,
 | 
				
			||||||
 | 
					                            const string &loc, const string &cha,
 | 
				
			||||||
 | 
					                            const Time &stime,
 | 
				
			||||||
 | 
					                            const Time &etime,
 | 
				
			||||||
 | 
					                            bool receivedData) {
 | 
				
			||||||
 | 
						boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
						if ( _state != EOD ) {
 | 
				
			||||||
 | 
							if ( _state == Active )
 | 
				
			||||||
 | 
								CAPS_WARNING("cannot add streams to an active session, invoke "
 | 
				
			||||||
 | 
								             "abort() or close() first");
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								CAPS_WARNING("cannot add streams to an erroneous or aborted "
 | 
				
			||||||
 | 
								             "session, invoke reset() first");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						string streamID = net + "." + sta + "." + loc + "." + cha;
 | 
				
			||||||
 | 
						Request &req = _requests[streamID];
 | 
				
			||||||
 | 
						req.net = net;
 | 
				
			||||||
 | 
						req.sta = sta;
 | 
				
			||||||
 | 
						req.loc = loc;
 | 
				
			||||||
 | 
						req.cha = cha;
 | 
				
			||||||
 | 
						req.start = stime;
 | 
				
			||||||
 | 
						req.end = etime;
 | 
				
			||||||
 | 
						req.receivedData = receivedData;
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DataRecord* Connection::next() {
 | 
				
			||||||
 | 
						if ( !handshake() ) return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ( true ) {
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
								// skip unread bytes of previous iteration and check connection state
 | 
				
			||||||
 | 
								if ( !seekToReadLimit() || _state == Error || _state == EOD )
 | 
				
			||||||
 | 
									return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ResponseHeader responseHeader;
 | 
				
			||||||
 | 
							if ( !responseHeader.get(_socketBuf) ) {
 | 
				
			||||||
 | 
								boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
								if ( _state != Aborted)
 | 
				
			||||||
 | 
									CAPS_ERROR("could not read header");
 | 
				
			||||||
 | 
								disconnect();
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CAPS_DEBUG("read header (id/size): %i/%lu", responseHeader.id,
 | 
				
			||||||
 | 
							           (unsigned long)responseHeader.size);
 | 
				
			||||||
 | 
							_socketBuf.set_read_limit(responseHeader.size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//		if ( _abortRequested ) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// State or session table update
 | 
				
			||||||
 | 
							if ( responseHeader.id == 0 ) {
 | 
				
			||||||
 | 
								while ( responseHeader.size > 0 /*&& _state == Active*/) {
 | 
				
			||||||
 | 
									istream is(&_socketBuf);
 | 
				
			||||||
 | 
									if ( is.getline(_lineBuf, 200).fail() ) {
 | 
				
			||||||
 | 
										boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
										CAPS_ERROR("header line exceeds maximum of 200 characters");
 | 
				
			||||||
 | 
										disconnect();
 | 
				
			||||||
 | 
										return NULL;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									responseHeader.size -= is.gcount();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									SessionTable::Status status =
 | 
				
			||||||
 | 
									        _sessionTable->handleResponse(_lineBuf, is.gcount());
 | 
				
			||||||
 | 
									if ( status == SessionTable::Error ) {
 | 
				
			||||||
 | 
										boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
										disconnect();
 | 
				
			||||||
 | 
										return NULL;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ( status == SessionTable::EOD ) {
 | 
				
			||||||
 | 
										_state = EOD;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CAPS_DEBUG("reading data record");
 | 
				
			||||||
 | 
							// data
 | 
				
			||||||
 | 
							if ( _currentID != responseHeader.id ) {
 | 
				
			||||||
 | 
								_currentItem = _sessionTable->getItem(responseHeader.id);
 | 
				
			||||||
 | 
								_currentID = responseHeader.id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( _currentItem == NULL ) {
 | 
				
			||||||
 | 
									CAPS_WARNING("unknown data request ID %d", responseHeader.id);
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int size = responseHeader.size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// To improve performance CAPS uses an optimized protocol
 | 
				
			||||||
 | 
							// to deliver RAW packets. The RAW packet class can't be used
 | 
				
			||||||
 | 
							// to read the header from socket.
 | 
				
			||||||
 | 
							DataRecord *dataRecord = NULL;
 | 
				
			||||||
 | 
							if ( _currentItem->type == RawDataPacket ) {
 | 
				
			||||||
 | 
								// Read optimized header
 | 
				
			||||||
 | 
								RawResponseHeader rawResponseHeader;
 | 
				
			||||||
 | 
								if ( !rawResponseHeader.get(_socketBuf) ) {
 | 
				
			||||||
 | 
									boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
									CAPS_ERROR("failed to extract raw response header %s",
 | 
				
			||||||
 | 
									           _currentItem->streamID.c_str());
 | 
				
			||||||
 | 
									disconnect();
 | 
				
			||||||
 | 
									return NULL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Time time(rawResponseHeader.timeSeconds, rawResponseHeader.timeMicroSeconds);
 | 
				
			||||||
 | 
								size -= rawResponseHeader.dataSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Create raw record, set header and read payload
 | 
				
			||||||
 | 
								RawDataRecord *record = new RawDataRecord;
 | 
				
			||||||
 | 
								record->setStartTime(time);
 | 
				
			||||||
 | 
								record->setSamplingFrequency(_currentItem->samplingFrequency,
 | 
				
			||||||
 | 
								                             _currentItem->samplingFrequencyDivider);
 | 
				
			||||||
 | 
								record->setDataType(_currentItem->dataType);
 | 
				
			||||||
 | 
								record->getData(_socketBuf, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								dataRecord =  record;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if ( _currentItem->type == ANYPacket ) {
 | 
				
			||||||
 | 
								AnyDataRecord *record = new AnyDataRecord;
 | 
				
			||||||
 | 
								record->get(_socketBuf, size, InvalidTime, InvalidTime, size);
 | 
				
			||||||
 | 
								dataRecord = record;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if ( _currentItem->type == MSEEDPacket ) {
 | 
				
			||||||
 | 
								MSEEDDataRecord *record = new MSEEDDataRecord;
 | 
				
			||||||
 | 
								record->get(_socketBuf, size, InvalidTime, InvalidTime, size);
 | 
				
			||||||
 | 
								dataRecord = record;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if ( _currentItem->type == MetaDataPacket ) {
 | 
				
			||||||
 | 
								// Read start time from optimized header
 | 
				
			||||||
 | 
								MetaResponseHeader metaResponseHeader;
 | 
				
			||||||
 | 
								if ( !metaResponseHeader.get(_socketBuf) ) {
 | 
				
			||||||
 | 
									boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
									CAPS_ERROR("failed to extract meta information from stream %s",
 | 
				
			||||||
 | 
									           _currentItem->streamID.c_str());
 | 
				
			||||||
 | 
									disconnect();
 | 
				
			||||||
 | 
									return NULL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Time stime(metaResponseHeader.startTime.seconds,
 | 
				
			||||||
 | 
								           metaResponseHeader.endTime.microSeconds),
 | 
				
			||||||
 | 
								     etime(metaResponseHeader.endTime.seconds,
 | 
				
			||||||
 | 
								           metaResponseHeader.endTime.microSeconds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								size -= metaResponseHeader.dataSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								MetaDataRecord::MetaHeader recHeader;
 | 
				
			||||||
 | 
								recHeader.dataHeader.setSamplingTime(stime);
 | 
				
			||||||
 | 
								recHeader.setEndTime(etime);
 | 
				
			||||||
 | 
								recHeader.dataHeader.samplingFrequencyNumerator = _currentItem->samplingFrequency;
 | 
				
			||||||
 | 
								recHeader.dataHeader.samplingFrequencyDenominator = _currentItem->samplingFrequencyDivider;
 | 
				
			||||||
 | 
								recHeader.dataHeader.dataType = _currentItem->dataType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								MetaDataRecord *record = new MetaDataRecord;
 | 
				
			||||||
 | 
								record->setHeader(recHeader);
 | 
				
			||||||
 | 
								dataRecord = record;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								CAPS_ERROR("received unknown packet type %d in stream %s",
 | 
				
			||||||
 | 
								           _currentItem->type, _currentItem->streamID.c_str());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( dataRecord == NULL ) {
 | 
				
			||||||
 | 
								boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
								disconnect();
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CAPS_DEBUG("data record read");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							RequestList::iterator it = _requests.find(_currentItem->streamID);
 | 
				
			||||||
 | 
							if ( it == _requests.end() ) {
 | 
				
			||||||
 | 
								// TODO: Search request map for wildcard match. Add entry with
 | 
				
			||||||
 | 
								// streamID -> (record->endTime, wildcardItem->endTime) to
 | 
				
			||||||
 | 
								// restrict data query in case of reconnect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//			CAPS_WARNING("received unrequested record: %s: %s - %s",
 | 
				
			||||||
 | 
					//			             _currentItem->streamID.c_str(),
 | 
				
			||||||
 | 
					//			             dataRecord->startTime().iso().c_str(),
 | 
				
			||||||
 | 
					//			             dataRecord->endTime().iso().c_str());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Update request map to reflect current stream state
 | 
				
			||||||
 | 
							else if ( dataRecord->endTime() > it->second.start ) {
 | 
				
			||||||
 | 
								it->second.start = dataRecord->endTime();
 | 
				
			||||||
 | 
								it->second.receivedData = true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return dataRecord;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Connection::handshake() {
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
							if ( _state == Error || _state == Aborted) {
 | 
				
			||||||
 | 
								CAPS_ERROR("cannot read from an erroneous or aborted session, invoke "
 | 
				
			||||||
 | 
								           "reset() first");
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if ( _state == Active )
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							// _state is set to EOD
 | 
				
			||||||
 | 
							else if ( _requests.empty() ) {
 | 
				
			||||||
 | 
								CAPS_WARNING("no stream requested, invoke addStream() first");
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _socket == NULL ) {
 | 
				
			||||||
 | 
							_socket = SocketPtr(createSocket());
 | 
				
			||||||
 | 
							if ( _socket == NULL ) return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Connect to server if necessary
 | 
				
			||||||
 | 
						while ( !_socket->isValid() && _state == EOD ) {
 | 
				
			||||||
 | 
							if ( _socket->connect(_server, _port) == Socket::Success ) {
 | 
				
			||||||
 | 
								_socketBuf.setsocket(_socket.get());
 | 
				
			||||||
 | 
								CAPS_DEBUG("connection to %s:%d established", _server.c_str(), _port);
 | 
				
			||||||
 | 
					//			_state = ios_base::eofbit;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CAPS_WARNING("unable to connect to %s:%d, retrying in 5 seconds",
 | 
				
			||||||
 | 
									     _server.c_str(), _port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Wait 5 seconds and keep response latency low
 | 
				
			||||||
 | 
							for ( int i = 0; (i < 10) && _state == EOD; ++i )
 | 
				
			||||||
 | 
								usleep(500000);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _state != EOD ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//	if ( _socket->isValid() ) {
 | 
				
			||||||
 | 
					//		// Read all data from session
 | 
				
			||||||
 | 
					//		if ( !seekToReadLimit() ) return false;
 | 
				
			||||||
 | 
					////		fd_set set;
 | 
				
			||||||
 | 
					////		FD_ZERO(&set);
 | 
				
			||||||
 | 
					////		FD_SET(_socket->fd(), &set);
 | 
				
			||||||
 | 
					////		timeval t = (struct timeval) {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					////		/* select returns 0 on timeout, 1 if input/output is available, -1 on error. */
 | 
				
			||||||
 | 
					////		int retn = TEMP_FAILURE_RETRY(select(_socket->fd()+1, &set, NULL, NULL, &t));
 | 
				
			||||||
 | 
					////		if ( retn != 0 )  CAPS_ERROR("UUPS");
 | 
				
			||||||
 | 
					//	}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//	if ( _state == Aborted ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Request streams
 | 
				
			||||||
 | 
						stringstream req;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !_auth.empty() )
 | 
				
			||||||
 | 
							req << _auth << endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req << "BEGIN REQUEST" << endl
 | 
				
			||||||
 | 
						    << "META " << (_metaMode ? "ON" : "OFF") << endl
 | 
				
			||||||
 | 
							<< "REALTIME " << ( _realtime ? "ON" : "OFF") << endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// First pass: continue all previous streams
 | 
				
			||||||
 | 
						for ( RequestList::const_iterator it = _requests.begin();
 | 
				
			||||||
 | 
						      it != _requests.end() && _state == EOD; ++it ) {
 | 
				
			||||||
 | 
							if ( it->second.receivedData )
 | 
				
			||||||
 | 
								formatRequest(req, it);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Second pass: subscribe to remaining streams
 | 
				
			||||||
 | 
						for ( RequestList::iterator it = _requests.begin();
 | 
				
			||||||
 | 
						      it != _requests.end() && _state == EOD; ++it ) {
 | 
				
			||||||
 | 
							if ( !it->second.receivedData )
 | 
				
			||||||
 | 
								formatRequest(req, it);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req << "END" << endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sendRequest(req.str());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Connection::sendRequest(const string &req) {
 | 
				
			||||||
 | 
						boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _state != EOD ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CAPS_DEBUG("%s", req.c_str());
 | 
				
			||||||
 | 
						if ( _socket->write(req.c_str(), req.size()) != (int) req.size() ) {
 | 
				
			||||||
 | 
							CAPS_ERROR("could not send data request");
 | 
				
			||||||
 | 
							disconnect();
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Gempa::CAPS::ResponseHeader header;
 | 
				
			||||||
 | 
						if ( !header.get(_socketBuf) ) {
 | 
				
			||||||
 | 
							// Case to retry, connection closed by peer
 | 
				
			||||||
 | 
							CAPS_ERROR("could not read data request response header");
 | 
				
			||||||
 | 
							disconnect();
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_socketBuf.set_read_limit(header.size);
 | 
				
			||||||
 | 
						if ( header.id != 0 ) {
 | 
				
			||||||
 | 
							CAPS_ERROR("invalid data request response header id, expected 0, got %d", header.id);
 | 
				
			||||||
 | 
							disconnect();
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						CAPS_DEBUG("data request response size: %lu", (unsigned long) header.size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						istream is(&_socketBuf);
 | 
				
			||||||
 | 
						// check line length
 | 
				
			||||||
 | 
						if ( is.getline(_lineBuf, 200).fail() )
 | 
				
			||||||
 | 
							CAPS_ERROR("data request response line exceeds maximum of 200 characters");
 | 
				
			||||||
 | 
						// skip remaining header data
 | 
				
			||||||
 | 
						else if ( !seekToReadLimit(false) ) {
 | 
				
			||||||
 | 
							CAPS_ERROR("could not seek to data request response header end");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( strncasecmp(_lineBuf, "ERROR:", 6) == 0 )
 | 
				
			||||||
 | 
							CAPS_ERROR("server responded to data request with: %s", _lineBuf);
 | 
				
			||||||
 | 
						else if ( strncasecmp(_lineBuf, "STATUS OK", 9) != 0 )
 | 
				
			||||||
 | 
							CAPS_ERROR("invalid data request response: %s", _lineBuf);
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							CAPS_DEBUG("handshake complete");
 | 
				
			||||||
 | 
							_state = Active;
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						disconnect();
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Connection::seekToReadLimit(bool log) {
 | 
				
			||||||
 | 
						if ( !_socket->isValid() ) {
 | 
				
			||||||
 | 
							disconnect();
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Skip unread bytes from previous record
 | 
				
			||||||
 | 
						int skippies = _socketBuf.read_limit();
 | 
				
			||||||
 | 
						if ( skippies > 0 ) {
 | 
				
			||||||
 | 
							if ( log )
 | 
				
			||||||
 | 
								CAPS_WARNING("no seemless reading, skipping %d bytes", skippies);
 | 
				
			||||||
 | 
							if ( _socketBuf.pubseekoff(skippies, ios_base::cur, ios_base::in) < 0 ) {
 | 
				
			||||||
 | 
								CAPS_ERROR("could not seek to next header");
 | 
				
			||||||
 | 
								disconnect();
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_socketBuf.set_read_limit(-1);
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Connection::formatRequest(stringstream& req, RequestList::const_iterator it) {
 | 
				
			||||||
 | 
						req << "STREAM ADD " << it->first << endl;
 | 
				
			||||||
 | 
						req << "TIME ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int year, mon, day, hour, minute, second;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( it->second.start.valid() ) {
 | 
				
			||||||
 | 
							it->second.start.get(&year, &mon, &day, &hour, &minute, &second);
 | 
				
			||||||
 | 
							req << year << "," << mon << "," << day << ","
 | 
				
			||||||
 | 
							    << hour << "," << minute << "," << second;
 | 
				
			||||||
 | 
							if ( it->second.start.microseconds() > 0 ) {
 | 
				
			||||||
 | 
								req << "," << setfill('0') << setw(6)
 | 
				
			||||||
 | 
								    << it->second.start.microseconds() << setw(0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req << ":";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( it->second.end.valid() ) {
 | 
				
			||||||
 | 
							it->second.end.get(&year, &mon, &day, &hour, &minute, &second);
 | 
				
			||||||
 | 
							req << year << "," << mon << "," << day << ","
 | 
				
			||||||
 | 
							    << hour << "," << minute << "," << second;
 | 
				
			||||||
 | 
							if ( it->second.end.microseconds() > 0 ) {
 | 
				
			||||||
 | 
								req << "," << setfill('0') << setw(6)
 | 
				
			||||||
 | 
								    << it->second.end.microseconds() << setw(0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req << endl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Connection::onItemAboutToBeRemoved(const SessionTableItem *item) {
 | 
				
			||||||
 | 
						if ( _currentItem == item) {
 | 
				
			||||||
 | 
							_currentID = -1;
 | 
				
			||||||
 | 
							_currentItem = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// remove request since all data has been received
 | 
				
			||||||
 | 
						if ( item != NULL ) _requests.erase(item->streamID);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Connection::reset(bool clearStreams) {
 | 
				
			||||||
 | 
						boost::mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
						CAPS_DEBUG("resetting connection");
 | 
				
			||||||
 | 
						if ( _state == Active ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("cannot reset an active connection, invoking close()");
 | 
				
			||||||
 | 
							close();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					//	else if ( _state == Aborted ) {
 | 
				
			||||||
 | 
					//		fd_set set;
 | 
				
			||||||
 | 
					//		FD_ZERO(&set);
 | 
				
			||||||
 | 
					//		FD_SET(_socket->fd(), &set);
 | 
				
			||||||
 | 
					//		timeval t = (struct timeval) {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//		/* select returns 0 on timeout, 1 if input/output is available, -1 on error. */
 | 
				
			||||||
 | 
					//		while ( _socket->isValid() ) {
 | 
				
			||||||
 | 
					//			int retn = TEMP_FAILURE_RETRY(select(_socket->fd()+1, &set, NULL, NULL, &t));
 | 
				
			||||||
 | 
					//			if ( retn == 0 ) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//				if ( retn != 0 )  CAPS_ERROR("UUPS");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//	}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_state = EOD;
 | 
				
			||||||
 | 
						if ( clearStreams )
 | 
				
			||||||
 | 
							_requests.clear();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Connection::setStartTime(const Time &stime) {
 | 
				
			||||||
 | 
						_startTime = stime;
 | 
				
			||||||
 | 
						CAPS_DEBUG("set global start time to %s", _startTime.toString("%F %T.%f").c_str());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Connection::setEndTime(const Time &etime) {
 | 
				
			||||||
 | 
						_endTime = etime;
 | 
				
			||||||
 | 
						CAPS_DEBUG("set global end time to %s", _endTime.toString("%F %T.%f").c_str());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Connection::setTimeWindow(const Time &stime, const Time &etime) {
 | 
				
			||||||
 | 
						_startTime = stime;
 | 
				
			||||||
 | 
						_endTime = etime;
 | 
				
			||||||
 | 
						CAPS_DEBUG("set global timewindow to %s~%s", _startTime.toString("%F %T.%f").c_str(),
 | 
				
			||||||
 | 
						           _endTime.toString("%F %T.%f").c_str());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										180
									
								
								libs/gempa/caps/connection.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								libs/gempa/caps/connection.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,180 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_CONNECTION_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_CONNECTION_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/datetime.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/sessiontable.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/socket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <boost/shared_ptr.hpp>
 | 
				
			||||||
 | 
					#include <boost/thread/condition.hpp>
 | 
				
			||||||
 | 
					#include <boost/thread/mutex.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//#include <iostream>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SessionTableItem;
 | 
				
			||||||
 | 
					class Time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Connection {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							//! ConnectionStates:
 | 
				
			||||||
 | 
							//! EOD     -> connection not yet established or all streams finished (or aborted)
 | 
				
			||||||
 | 
							//! Active  -> connection was successfully established, data request was sent
 | 
				
			||||||
 | 
							//! Error   -> connection aborted due to server error
 | 
				
			||||||
 | 
							//! Aborted -> connection aborted by user
 | 
				
			||||||
 | 
							enum State { EOD, Active, Error, Aborted };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Constructor
 | 
				
			||||||
 | 
							Connection();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Destructor
 | 
				
			||||||
 | 
							virtual ~Connection();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets server parameter
 | 
				
			||||||
 | 
							bool setServer(const std::string &server);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Enables SSL feature
 | 
				
			||||||
 | 
							void enableSSL(bool enable) { _ssl = enable; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets user name and password
 | 
				
			||||||
 | 
							void setCredentials(const std::string &user, const std::string &password);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets meta mode. If enabled only the packet header information is
 | 
				
			||||||
 | 
							//! transmitted.
 | 
				
			||||||
 | 
							void setMetaMode(bool enable) { _metaMode = enable; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets realtime mode.
 | 
				
			||||||
 | 
							void setRealtime(bool enable) { _realtime = enable; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Disconnect from server, connection unuseable until reset() is
 | 
				
			||||||
 | 
							//! called. Thread safe.
 | 
				
			||||||
 | 
							void close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Send abort command to server, keep socket open, requires reset.
 | 
				
			||||||
 | 
							//! Thread safe.
 | 
				
			||||||
 | 
							void abort();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Adds a stream request
 | 
				
			||||||
 | 
							bool addStream(const std::string &net, const std::string &sta,
 | 
				
			||||||
 | 
							               const std::string &loc, const std::string &cha);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Adds a seismic stream requests
 | 
				
			||||||
 | 
							bool addStream(const std::string &net, const std::string &sta,
 | 
				
			||||||
 | 
							               const std::string &loc, const std::string &cha,
 | 
				
			||||||
 | 
							               const Time &stime,
 | 
				
			||||||
 | 
							               const Time &etime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Resets connection state to eof
 | 
				
			||||||
 | 
							void reset(bool clearStreams = false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets the given start time
 | 
				
			||||||
 | 
							void setStartTime(const Time &stime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets the given end time
 | 
				
			||||||
 | 
							void setEndTime(const Time &etime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets the given time window
 | 
				
			||||||
 | 
							void setTimeWindow(const Time &stime, const Time &etime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets timeout
 | 
				
			||||||
 | 
							bool setTimeout(int seconds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the next record. If the record is NULL the caller has
 | 
				
			||||||
 | 
							//! to check the state of the connection. Automatically creates a new
 | 
				
			||||||
 | 
							//! connection if required, sends data requests and evaluates updates
 | 
				
			||||||
 | 
							//! of session table. If the connection state is neither 'good' nor
 | 
				
			||||||
 | 
							//!'eof' the connection has to be resetted before invoking this method.
 | 
				
			||||||
 | 
							DataRecord* next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							State state() { return _state; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						// protected methods
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							virtual Socket* createSocket() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							typedef boost::shared_ptr<SessionTable> SessionTablePtr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct Request {
 | 
				
			||||||
 | 
								std::string      net;
 | 
				
			||||||
 | 
								std::string      sta;
 | 
				
			||||||
 | 
								std::string      loc;
 | 
				
			||||||
 | 
								std::string      cha;
 | 
				
			||||||
 | 
								Time             start;
 | 
				
			||||||
 | 
								Time             end;
 | 
				
			||||||
 | 
								bool             receivedData;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							typedef std::map<std::string, Request> RequestList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						// private methods
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							bool addRequest(const std::string &net, const std::string &sta,
 | 
				
			||||||
 | 
							                const std::string &loc, const std::string &cha,
 | 
				
			||||||
 | 
							                const Time &stime,
 | 
				
			||||||
 | 
							                const Time &etime,
 | 
				
			||||||
 | 
							                bool receivedData);
 | 
				
			||||||
 | 
							void onItemAboutToBeRemoved(const SessionTableItem *item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void disconnect();
 | 
				
			||||||
 | 
							bool handshake();
 | 
				
			||||||
 | 
							bool sendRequest(const std::string &req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool seekToReadLimit(bool log = true);
 | 
				
			||||||
 | 
							void formatRequest(std::stringstream& req, RequestList::const_iterator it);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						// private data members
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							SessionTablePtr                     _sessionTable;
 | 
				
			||||||
 | 
							RequestList                         _requests;
 | 
				
			||||||
 | 
							SocketPtr                           _socket;
 | 
				
			||||||
 | 
							socketbuf<Socket, 512>              _socketBuf;
 | 
				
			||||||
 | 
							char                                _lineBuf[201];
 | 
				
			||||||
 | 
							volatile State                      _state;
 | 
				
			||||||
 | 
							SessionTableItem                   *_currentItem;
 | 
				
			||||||
 | 
							uint16_t                            _currentID;
 | 
				
			||||||
 | 
							boost::mutex                        _mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string                         _server;
 | 
				
			||||||
 | 
							int                                 _port;
 | 
				
			||||||
 | 
							std::string                         _auth;
 | 
				
			||||||
 | 
							Time                                _startTime;
 | 
				
			||||||
 | 
							Time                                _endTime;
 | 
				
			||||||
 | 
							bool                                _realtime;
 | 
				
			||||||
 | 
							bool                                _metaMode;
 | 
				
			||||||
 | 
							bool                                _ssl;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef boost::shared_ptr<Connection> ConnectionPtr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										1063
									
								
								libs/gempa/caps/datetime.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1063
									
								
								libs/gempa/caps/datetime.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										245
									
								
								libs/gempa/caps/datetime.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								libs/gempa/caps/datetime.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,245 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_DATETIME_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_DATETIME_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef WIN32
 | 
				
			||||||
 | 
					#include <winsock2.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#include <sys/time.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct tm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TimeSpan {
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						//  Xstruction
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							TimeSpan();
 | 
				
			||||||
 | 
							TimeSpan(struct timeval*);
 | 
				
			||||||
 | 
							TimeSpan(const struct timeval&);
 | 
				
			||||||
 | 
							TimeSpan(double);
 | 
				
			||||||
 | 
							TimeSpan(long secs, long usecs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Copy constructor
 | 
				
			||||||
 | 
							TimeSpan(const TimeSpan&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						//  Operators
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							//! Comparison
 | 
				
			||||||
 | 
							bool operator==(const TimeSpan&) const;
 | 
				
			||||||
 | 
							bool operator!=(const TimeSpan&) const;
 | 
				
			||||||
 | 
							bool operator< (const TimeSpan&) const;
 | 
				
			||||||
 | 
							bool operator<=(const TimeSpan&) const;
 | 
				
			||||||
 | 
							bool operator> (const TimeSpan&) const;
 | 
				
			||||||
 | 
							bool operator>=(const TimeSpan&) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Conversion
 | 
				
			||||||
 | 
							operator double() const;
 | 
				
			||||||
 | 
							operator const timeval&() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Assignment
 | 
				
			||||||
 | 
							TimeSpan& operator=(long t);
 | 
				
			||||||
 | 
							TimeSpan& operator=(double t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Arithmetic
 | 
				
			||||||
 | 
							TimeSpan operator+(const TimeSpan&) const;
 | 
				
			||||||
 | 
							TimeSpan operator-(const TimeSpan&) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							TimeSpan& operator+=(const TimeSpan&);
 | 
				
			||||||
 | 
							TimeSpan& operator-=(const TimeSpan&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						//  Interface
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							//! Returns the absolute value of time
 | 
				
			||||||
 | 
							TimeSpan abs() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the seconds of the timespan
 | 
				
			||||||
 | 
							long seconds() const;
 | 
				
			||||||
 | 
							//! Returns the microseconds of the timespan
 | 
				
			||||||
 | 
							long microseconds() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the (possibly negative) length of the timespan in seconds
 | 
				
			||||||
 | 
							double length() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets the seconds
 | 
				
			||||||
 | 
							TimeSpan& set(long seconds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets the microseconds
 | 
				
			||||||
 | 
							TimeSpan& setUSecs(long);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Assigns the elapsed time to the passed out parameters
 | 
				
			||||||
 | 
							void elapsedTime(int* days	, int* hours = NULL,
 | 
				
			||||||
 | 
							                 int* minutes = NULL, int* seconds = NULL) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						//  Implementation
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							struct timeval _timeval;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Time : public TimeSpan {
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						// Public static data members
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							static const Time Null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						//  Xstruction
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Time();
 | 
				
			||||||
 | 
							Time(long secs, long usecs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							explicit Time(const TimeSpan&);
 | 
				
			||||||
 | 
							explicit Time(const struct timeval&);
 | 
				
			||||||
 | 
							explicit Time(struct timeval*);
 | 
				
			||||||
 | 
							explicit Time(double);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Time(int year, int month, int day,
 | 
				
			||||||
 | 
							     int hour = 0, int min = 0, int sec = 0,
 | 
				
			||||||
 | 
							     int usec = 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Copy constructor
 | 
				
			||||||
 | 
							Time(const Time&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						//  Operators
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							//! Conversion
 | 
				
			||||||
 | 
							operator bool() const;
 | 
				
			||||||
 | 
							operator time_t() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Assignment
 | 
				
			||||||
 | 
							Time& operator=(const struct timeval& t);
 | 
				
			||||||
 | 
							Time& operator=(struct timeval* t);
 | 
				
			||||||
 | 
							Time& operator=(time_t t);
 | 
				
			||||||
 | 
							Time& operator=(double t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Arithmetic
 | 
				
			||||||
 | 
							Time operator+(const TimeSpan&) const;
 | 
				
			||||||
 | 
							Time operator-(const TimeSpan&) const;
 | 
				
			||||||
 | 
							TimeSpan operator-(const Time&) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Time& operator+=(const TimeSpan&);
 | 
				
			||||||
 | 
							Time& operator-=(const TimeSpan&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						//  Interface
 | 
				
			||||||
 | 
						// ----------------------------------------------------------------------
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							//! Sets the time
 | 
				
			||||||
 | 
							Time& set(int year, int month, int day,
 | 
				
			||||||
 | 
							          int hour, int min, int sec,
 | 
				
			||||||
 | 
							          int usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Fill the parameters with the currently set time values
 | 
				
			||||||
 | 
							//! @return The error flag
 | 
				
			||||||
 | 
							bool get(int *year, int *month = NULL, int *day = NULL,
 | 
				
			||||||
 | 
							         int *hour = NULL, int *min = NULL, int *sec = NULL,
 | 
				
			||||||
 | 
							         int *usec = NULL) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Fill the parameters with the currently set time values
 | 
				
			||||||
 | 
							//! @return The error flag
 | 
				
			||||||
 | 
							bool get2(int *year, int *yday = NULL,
 | 
				
			||||||
 | 
							          int *hour = NULL, int *min = NULL, int *sec = NULL,
 | 
				
			||||||
 | 
							          int *usec = NULL) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the current localtime
 | 
				
			||||||
 | 
							static Time LocalTime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the current gmtime
 | 
				
			||||||
 | 
							static Time GMT();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/** Creates a time from the year and the day of the year
 | 
				
			||||||
 | 
							    @param year The year, including the century (for example, 1988)
 | 
				
			||||||
 | 
							    @param year_day The day of the year [0..365]
 | 
				
			||||||
 | 
							    @return The time value
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							static Time FromYearDay(int year, int year_day);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Saves the current localtime in the calling object
 | 
				
			||||||
 | 
							Time& localtime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Saves the current gmtime in the calling object
 | 
				
			||||||
 | 
							Time& gmt();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Converts the time to localtime
 | 
				
			||||||
 | 
							Time toLocalTime() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Converts the time to gmtime
 | 
				
			||||||
 | 
							Time toGMT() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns whether the date is valid or not
 | 
				
			||||||
 | 
							bool valid() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/** Converts the time to string using format fmt.
 | 
				
			||||||
 | 
							    @param fmt The format string can contain any specifiers
 | 
				
			||||||
 | 
							               as allowed for strftime. Additional the '%f'
 | 
				
			||||||
 | 
							               specifier is replaced by the fraction of the seconds.
 | 
				
			||||||
 | 
							               Example:
 | 
				
			||||||
 | 
							               toString("%FT%T.%fZ") = "1970-01-01T00:00:00.0000Z"
 | 
				
			||||||
 | 
							    @return A formatted string
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							std::string toString(const char* fmt) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * Converts the time to a string using the ISO time description
 | 
				
			||||||
 | 
							 * @return A formatted string
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							std::string iso() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * Converts a string into a time representation.
 | 
				
			||||||
 | 
							 * @param str The string representation of the time
 | 
				
			||||||
 | 
							 * @param fmt The format string containing the conversion
 | 
				
			||||||
 | 
							 *            specification (-> toString)
 | 
				
			||||||
 | 
							 * @return The conversion result
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							bool fromString(const char* str, const char* fmt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * Static method to create a time value from a string.
 | 
				
			||||||
 | 
							 * The parameters are the same as in Time::fromString.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							static Time FromString(const char* str, const char* fmt);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										246
									
								
								libs/gempa/caps/encoderfactory.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								libs/gempa/caps/encoderfactory.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,246 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2016 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "encoderfactory.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mseed/mseed.h"
 | 
				
			||||||
 | 
					#include "mseed/steim1.h"
 | 
				
			||||||
 | 
					#include "mseed/steim2.h"
 | 
				
			||||||
 | 
					#include "mseed/uncompressed.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EncoderFactory::EncoderFactory() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EncoderFactory::~EncoderFactory() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const string& EncoderFactory::errorString() const {
 | 
				
			||||||
 | 
						return _errorString;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MSEEDEncoderFactory::MSEEDEncoderFactory()
 | 
				
			||||||
 | 
					: _recordLength(9) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MSEEDEncoderFactory::setRecordLength(uint recordLength) {
 | 
				
			||||||
 | 
						if ( recordLength < 7 || recordLength > 32) {
 | 
				
			||||||
 | 
							_errorString = "MSEED record length out of range [7, 32]";
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_recordLength = uint8_t(recordLength);
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool SteimEncoderFactory::supportsRecord(DataRecord *rec) {
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						DataType dt = rec->header()->dataType;
 | 
				
			||||||
 | 
						if ( (dt == DT_INT64) || (dt == DT_FLOAT) ||
 | 
				
			||||||
 | 
							 (dt == DT_DOUBLE) ) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PacketType type = rec->packetType();
 | 
				
			||||||
 | 
						if ( type == RawDataPacket || type == FixedRawDataPacket ) {
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( type == MSEEDPacket ) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IdentityEncoderFactory::supportsRecord(DataRecord *rec) {
 | 
				
			||||||
 | 
						PacketType type = rec->packetType();
 | 
				
			||||||
 | 
						return type == RawDataPacket || type == FixedRawDataPacket;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Encoder* IdentityEncoderFactory::create(const std::string &networkCode,
 | 
				
			||||||
 | 
					                                        const std::string &stationCode,
 | 
				
			||||||
 | 
					                                        const std::string &locationCode,
 | 
				
			||||||
 | 
					                                        const std::string &channelCode,
 | 
				
			||||||
 | 
					                                        int dt,
 | 
				
			||||||
 | 
					                                        int samplingFrequencyNumerator,
 | 
				
			||||||
 | 
					                                        int samplingFrequencyDenominator) {
 | 
				
			||||||
 | 
						if ( dt == DT_INT8 ) {
 | 
				
			||||||
 | 
							MSEEDFormat *format = new MSEEDFormat(networkCode, stationCode,
 | 
				
			||||||
 | 
							                                      locationCode, channelCode,
 | 
				
			||||||
 | 
							                                      samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                      samplingFrequencyDenominator,
 | 
				
			||||||
 | 
							                                      DE_ASCII,
 | 
				
			||||||
 | 
							                                      _recordLength);
 | 
				
			||||||
 | 
							if ( format == NULL ) return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return new UncompressedMSEED<int8_t>(format,
 | 
				
			||||||
 | 
							                                     samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                     samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_INT16 ) {
 | 
				
			||||||
 | 
							MSEEDFormat *format = new MSEEDFormat(networkCode, stationCode,
 | 
				
			||||||
 | 
							                                      locationCode, channelCode,
 | 
				
			||||||
 | 
							                                      samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                      samplingFrequencyDenominator,
 | 
				
			||||||
 | 
							                                      DE_INT16,
 | 
				
			||||||
 | 
							                                      _recordLength);
 | 
				
			||||||
 | 
							if ( format == NULL ) return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return new UncompressedMSEED<int16_t>(format,
 | 
				
			||||||
 | 
							                                      samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                      samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_INT32 ) {
 | 
				
			||||||
 | 
							MSEEDFormat *format = new MSEEDFormat(networkCode, stationCode,
 | 
				
			||||||
 | 
							                                      locationCode, channelCode,
 | 
				
			||||||
 | 
							                                      samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                      samplingFrequencyDenominator,
 | 
				
			||||||
 | 
							                                      DE_INT32,
 | 
				
			||||||
 | 
							                                      _recordLength);
 | 
				
			||||||
 | 
							if ( format == NULL ) return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return new UncompressedMSEED<int32_t>(format,
 | 
				
			||||||
 | 
							                                      samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                      samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_FLOAT ) {
 | 
				
			||||||
 | 
							MSEEDFormat *format = new MSEEDFormat(networkCode, stationCode,
 | 
				
			||||||
 | 
							                                      locationCode, channelCode,
 | 
				
			||||||
 | 
							                                      samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                      samplingFrequencyDenominator,
 | 
				
			||||||
 | 
							                                      DE_FLOAT32,
 | 
				
			||||||
 | 
							                                      _recordLength);
 | 
				
			||||||
 | 
							if ( format == NULL ) return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return new UncompressedMSEED<float>(format,
 | 
				
			||||||
 | 
							                                    samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                    samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_DOUBLE ) {
 | 
				
			||||||
 | 
							MSEEDFormat *format = new MSEEDFormat(networkCode, stationCode,
 | 
				
			||||||
 | 
							                                      locationCode, channelCode,
 | 
				
			||||||
 | 
							                                      samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                      samplingFrequencyDenominator,
 | 
				
			||||||
 | 
							                                      DE_FLOAT64,
 | 
				
			||||||
 | 
							                                      _recordLength);
 | 
				
			||||||
 | 
							if ( format == NULL ) return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return new UncompressedMSEED<double>(format,
 | 
				
			||||||
 | 
							                                     samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                     samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Encoder* Steim1EncoderFactory::create(const std::string &networkCode,
 | 
				
			||||||
 | 
					                                      const std::string &stationCode,
 | 
				
			||||||
 | 
					                                      const std::string &locationCode,
 | 
				
			||||||
 | 
					                                      const std::string &channelCode,
 | 
				
			||||||
 | 
					                                      int dt,
 | 
				
			||||||
 | 
					                                      int samplingFrequencyNumerator,
 | 
				
			||||||
 | 
					                                      int samplingFrequencyDenominator) {
 | 
				
			||||||
 | 
						MSEEDFormat *format = new MSEEDFormat(networkCode, stationCode,
 | 
				
			||||||
 | 
						                                      locationCode, channelCode,
 | 
				
			||||||
 | 
						                                      samplingFrequencyNumerator,
 | 
				
			||||||
 | 
						                                      samplingFrequencyDenominator,
 | 
				
			||||||
 | 
						                                      DE_STEIM1,
 | 
				
			||||||
 | 
						                                      _recordLength);
 | 
				
			||||||
 | 
						if ( format == NULL ) return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( dt == DT_INT8 ) {
 | 
				
			||||||
 | 
							return new Steim1Encoder<int8_t>(format,
 | 
				
			||||||
 | 
							                                 samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                 samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_INT16 ) {
 | 
				
			||||||
 | 
							return new Steim1Encoder<int16_t>(format,
 | 
				
			||||||
 | 
							                                  samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                  samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_INT32 ) {
 | 
				
			||||||
 | 
							return new Steim1Encoder<int32_t>(format,
 | 
				
			||||||
 | 
							                                  samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                  samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_FLOAT ) {
 | 
				
			||||||
 | 
							return new Steim1Encoder<float>(format,
 | 
				
			||||||
 | 
							                                samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_DOUBLE ) {
 | 
				
			||||||
 | 
							return new Steim1Encoder<double>(format,
 | 
				
			||||||
 | 
							                                 samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                 samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						delete format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Encoder* Steim2EncoderFactory::create(const std::string &networkCode,
 | 
				
			||||||
 | 
					                                      const std::string &stationCode,
 | 
				
			||||||
 | 
					                                      const std::string &locationCode,
 | 
				
			||||||
 | 
					                                      const std::string &channelCode,
 | 
				
			||||||
 | 
					                                      int dt,
 | 
				
			||||||
 | 
					                                      int samplingFrequencyNumerator,
 | 
				
			||||||
 | 
					                                      int samplingFrequencyDenominator) {
 | 
				
			||||||
 | 
						MSEEDFormat *format = new MSEEDFormat(networkCode, stationCode,
 | 
				
			||||||
 | 
						                                      locationCode, channelCode,
 | 
				
			||||||
 | 
						                                      samplingFrequencyNumerator,
 | 
				
			||||||
 | 
						                                      samplingFrequencyDenominator,
 | 
				
			||||||
 | 
						                                      DE_STEIM2,
 | 
				
			||||||
 | 
						                                      _recordLength);
 | 
				
			||||||
 | 
						if ( format == NULL ) return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( dt == DT_INT8 ) {
 | 
				
			||||||
 | 
							return new Steim2Encoder<int8_t>(format,
 | 
				
			||||||
 | 
							                                 samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                 samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_INT16 ) {
 | 
				
			||||||
 | 
							return new Steim2Encoder<int16_t>(format,
 | 
				
			||||||
 | 
							                                  samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                  samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_INT32 ) {
 | 
				
			||||||
 | 
							return new Steim2Encoder<int32_t>(format,
 | 
				
			||||||
 | 
							                                  samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                  samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_FLOAT ) {
 | 
				
			||||||
 | 
							return new Steim2Encoder<float>(format,
 | 
				
			||||||
 | 
							                                samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( dt == DT_DOUBLE ) {
 | 
				
			||||||
 | 
							return new Steim2Encoder<double>(format,
 | 
				
			||||||
 | 
							                                 samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                                 samplingFrequencyDenominator);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						delete format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										164
									
								
								libs/gempa/caps/encoderfactory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								libs/gempa/caps/encoderfactory.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,164 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2016 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_ENCODERFACTORY_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_ENCODERFACTORY_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mseed/encoder.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Abstract base class of the encoder factory. Each
 | 
				
			||||||
 | 
					 * derived class must implement the create and the
 | 
				
			||||||
 | 
					 * supportsRecord method.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class EncoderFactory {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							EncoderFactory();
 | 
				
			||||||
 | 
							virtual ~EncoderFactory();
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Creates encoder from given parameter set
 | 
				
			||||||
 | 
							 * @param networkCode The nework code
 | 
				
			||||||
 | 
							 * @param stationCode The station code
 | 
				
			||||||
 | 
							 * @param locationCode The location code
 | 
				
			||||||
 | 
							 * @param channelCode The channel code
 | 
				
			||||||
 | 
							 * @param dt The data encoding
 | 
				
			||||||
 | 
							 * @param samplingFrequencyNumerator The numerator
 | 
				
			||||||
 | 
							 * @param samplingFrequencyDenominator The denominator
 | 
				
			||||||
 | 
							 * @param samplingFrequencyDenominator The timing quality
 | 
				
			||||||
 | 
							 * @return The encoder object or NULL if creation fails
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual Encoder* create(const std::string &networkCode,
 | 
				
			||||||
 | 
							                        const std::string &stationCode,
 | 
				
			||||||
 | 
							                        const std::string &locationCode,
 | 
				
			||||||
 | 
							                        const std::string &channelCode,
 | 
				
			||||||
 | 
							                        int dt,
 | 
				
			||||||
 | 
							                        int samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                        int samplingFrequencyDenominator) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Checks if an encoder factory
 | 
				
			||||||
 | 
							 * supports the given record.
 | 
				
			||||||
 | 
							 * @param rec The record to check
 | 
				
			||||||
 | 
							 * @return True if the data type is supported
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual bool supportsRecord(DataRecord *rec) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns a human readable error description
 | 
				
			||||||
 | 
							 * of the last error occured.
 | 
				
			||||||
 | 
							 * @return Error description
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							const std::string& errorString() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							std::string    _errorString;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Base class for all MSEED encoders
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class MSEEDEncoderFactory : public EncoderFactory {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							MSEEDEncoderFactory();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Sets the volume logical record length expressed as a
 | 
				
			||||||
 | 
							 * power of 2. A 512 byte record would be 9.
 | 
				
			||||||
 | 
							 * @param recLen The record length expressed as a power of 2
 | 
				
			||||||
 | 
							 * @return True if the record length is valid
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							bool setRecordLength(uint recordLength);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							uint8_t _recordLength;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Implements a general Steim encoder factory
 | 
				
			||||||
 | 
					 * interface which implements the supportsRecord method
 | 
				
			||||||
 | 
					 * only.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class SteimEncoderFactory : public MSEEDEncoderFactory  {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Checks if an encoder factory
 | 
				
			||||||
 | 
							 * supports the given record. In case of data type float or double we
 | 
				
			||||||
 | 
							 * return true but the values will casted implicitly to int32.
 | 
				
			||||||
 | 
							 * @param rec The record to check
 | 
				
			||||||
 | 
							 * @return True if the data type is supported
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							bool supportsRecord(DataRecord *rec);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief The IdentiyEncoderFactory class implements the
 | 
				
			||||||
 | 
					 * encoder factory interface and supports the creation of
 | 
				
			||||||
 | 
					 * identiy encoders.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class IdentityEncoderFactory : public MSEEDEncoderFactory {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Encoder* create(const std::string &networkCode,
 | 
				
			||||||
 | 
							                const std::string &stationCode,
 | 
				
			||||||
 | 
							                const std::string &locationCode,
 | 
				
			||||||
 | 
							                const std::string &channelCode,
 | 
				
			||||||
 | 
							                int dt,
 | 
				
			||||||
 | 
							                int samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                int samplingFrequencyDenominator);
 | 
				
			||||||
 | 
							bool supportsRecord(DataRecord *rec);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief The Steim1EncoderFactory class implements the
 | 
				
			||||||
 | 
					 * encoder factory interface and supports the creation of
 | 
				
			||||||
 | 
					 * Steim2 encoders.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class Steim1EncoderFactory : public SteimEncoderFactory {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Encoder* create(const std::string &networkCode,
 | 
				
			||||||
 | 
							                const std::string &stationCode,
 | 
				
			||||||
 | 
							                const std::string &locationCode,
 | 
				
			||||||
 | 
							                const std::string &channelCode,
 | 
				
			||||||
 | 
							                int dt,
 | 
				
			||||||
 | 
							                int samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                int samplingFrequencyDenominator);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief The Steim2EncoderFactory class implements the
 | 
				
			||||||
 | 
					 * encoder factory interface and supports the creation of
 | 
				
			||||||
 | 
					 * Steim2 encoders.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class Steim2EncoderFactory : public SteimEncoderFactory {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Encoder* create(const std::string &networkCode,
 | 
				
			||||||
 | 
							                const std::string &stationCode,
 | 
				
			||||||
 | 
							                const std::string &locationCode,
 | 
				
			||||||
 | 
							                const std::string &channelCode,
 | 
				
			||||||
 | 
							                int dt,
 | 
				
			||||||
 | 
							                int samplingFrequencyNumerator,
 | 
				
			||||||
 | 
							                int samplingFrequencyDenominator);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										210
									
								
								libs/gempa/caps/endianess.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								libs/gempa/caps/endianess.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,210 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_ENDIANESS_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_ENDIANESS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <streambuf>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					namespace Endianess {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T1, typename T2> inline const T1* lvalue(const T2 &value) {
 | 
				
			||||||
 | 
						return reinterpret_cast<const T1*>(&value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T, int swap, int size>
 | 
				
			||||||
 | 
					struct Swapper {
 | 
				
			||||||
 | 
						static T Take(const T &v) {
 | 
				
			||||||
 | 
							return v;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static void Take(T *ar, int len) {}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					struct Swapper<T,1,2> {
 | 
				
			||||||
 | 
						static T Take(const T &v) {
 | 
				
			||||||
 | 
							return *lvalue<T, uint16_t>((*reinterpret_cast<const uint16_t*>(&v) >> 0x08) |
 | 
				
			||||||
 | 
							       (*reinterpret_cast<const uint16_t*>(&v) << 0x08));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static void Take(T *ar, int len) {
 | 
				
			||||||
 | 
							for ( int i = 0; i < len; ++i )
 | 
				
			||||||
 | 
								ar[i] = Take(ar[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					struct Swapper<T,1,4> {
 | 
				
			||||||
 | 
						static T Take(const T &v) {
 | 
				
			||||||
 | 
							return *lvalue<T, uint32_t>(((*reinterpret_cast<const uint32_t*>(&v) << 24) & 0xFF000000) |
 | 
				
			||||||
 | 
							       ((*reinterpret_cast<const uint32_t*>(&v) << 8)  & 0x00FF0000) |
 | 
				
			||||||
 | 
							       ((*reinterpret_cast<const uint32_t*>(&v) >> 8)  & 0x0000FF00) |
 | 
				
			||||||
 | 
							       ((*reinterpret_cast<const uint32_t*>(&v) >> 24) & 0x000000FF));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static void Take(T *ar, int len) {
 | 
				
			||||||
 | 
							for ( int i = 0; i < len; ++i )
 | 
				
			||||||
 | 
								ar[i] = Take(ar[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					struct Swapper<T,1,8> {
 | 
				
			||||||
 | 
						static T Take(const T &v) {
 | 
				
			||||||
 | 
							return *lvalue<T, uint64_t>(((*reinterpret_cast<const uint64_t*>(&v) << 56) & 0xFF00000000000000LL) |
 | 
				
			||||||
 | 
							       ((*reinterpret_cast<const uint64_t*>(&v) << 40) & 0x00FF000000000000LL) |
 | 
				
			||||||
 | 
							       ((*reinterpret_cast<const uint64_t*>(&v) << 24) & 0x0000FF0000000000LL) |
 | 
				
			||||||
 | 
							       ((*reinterpret_cast<const uint64_t*>(&v) << 8)  & 0x000000FF00000000LL) |
 | 
				
			||||||
 | 
							       ((*reinterpret_cast<const uint64_t*>(&v) >> 8)  & 0x00000000FF000000LL) |
 | 
				
			||||||
 | 
							       ((*reinterpret_cast<const uint64_t*>(&v) >> 24) & 0x0000000000FF0000LL) |
 | 
				
			||||||
 | 
							       ((*reinterpret_cast<const uint64_t*>(&v) >> 40) & 0x000000000000FF00LL) |
 | 
				
			||||||
 | 
							       ((*reinterpret_cast<const uint64_t*>(&v) >> 56) & 0x00000000000000FFLL));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static void Take(T *ar, int len) {
 | 
				
			||||||
 | 
							for ( int i = 0; i < len; ++i )
 | 
				
			||||||
 | 
								ar[i] = Take(ar[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int size>
 | 
				
			||||||
 | 
					struct TypeMap {
 | 
				
			||||||
 | 
						typedef void ValueType;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <>
 | 
				
			||||||
 | 
					struct TypeMap<1> {
 | 
				
			||||||
 | 
						typedef uint8_t ValueType;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <>
 | 
				
			||||||
 | 
					struct TypeMap<2> {
 | 
				
			||||||
 | 
						typedef uint16_t ValueType;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <>
 | 
				
			||||||
 | 
					struct TypeMap<4> {
 | 
				
			||||||
 | 
						typedef uint32_t ValueType;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <>
 | 
				
			||||||
 | 
					struct TypeMap<8> {
 | 
				
			||||||
 | 
						typedef uint64_t ValueType;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int swap, int size>
 | 
				
			||||||
 | 
					struct ByteSwapper {
 | 
				
			||||||
 | 
						static void Take(void *ar, int len) {}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int size>
 | 
				
			||||||
 | 
					struct ByteSwapper<1,size> {
 | 
				
			||||||
 | 
						static void Take(void *ar, int len) {
 | 
				
			||||||
 | 
							typedef typename TypeMap<size>::ValueType T;
 | 
				
			||||||
 | 
							Swapper<T,1,size>::Take(reinterpret_cast<T*>(ar), len);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Current {
 | 
				
			||||||
 | 
						enum {
 | 
				
			||||||
 | 
							LittleEndian = ((0x1234 >> 8) == 0x12?1:0),
 | 
				
			||||||
 | 
							BigEndian = 1-LittleEndian
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Converter {
 | 
				
			||||||
 | 
						template <typename T>
 | 
				
			||||||
 | 
						static T ToLittleEndian(const T &v) {
 | 
				
			||||||
 | 
							return Swapper<T,Current::BigEndian,sizeof(T)>::Take(v);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						template <typename T>
 | 
				
			||||||
 | 
						static void ToLittleEndian(T *data, int len) {
 | 
				
			||||||
 | 
							Swapper<T,Current::BigEndian,sizeof(T)>::Take(data, len);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						template <typename T>
 | 
				
			||||||
 | 
						static T FromLittleEndian(const T &v) {
 | 
				
			||||||
 | 
							return Swapper<T,Current::BigEndian,sizeof(T)>::Take(v);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						template <typename T>
 | 
				
			||||||
 | 
						static T ToBigEndian(const T &v) {
 | 
				
			||||||
 | 
							return Swapper<T,Current::LittleEndian,sizeof(T)>::Take(v);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						template <typename T>
 | 
				
			||||||
 | 
						static T FromBigEndian(const T &v) {
 | 
				
			||||||
 | 
							return Swapper<T,Current::LittleEndian,sizeof(T)>::Take(v);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Reader {
 | 
				
			||||||
 | 
						Reader(std::streambuf &input) : stream(input), good(true) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void operator()(void *data, int size) {
 | 
				
			||||||
 | 
							good = stream.sgetn((char*)data, size) == size;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						template <typename T>
 | 
				
			||||||
 | 
						void operator()(T &v) {
 | 
				
			||||||
 | 
							good = stream.sgetn((char*)&v, sizeof(T)) == sizeof(T);
 | 
				
			||||||
 | 
							v = Converter::FromLittleEndian(v);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::streambuf &stream;
 | 
				
			||||||
 | 
						bool good;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Writer {
 | 
				
			||||||
 | 
						Writer(std::streambuf &output) : stream(output), good(true) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool operator()(const void *data, int size) {
 | 
				
			||||||
 | 
							return (good = stream.sputn((char*)data, size) == size);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						template <typename T>
 | 
				
			||||||
 | 
						bool operator()(T &v) {
 | 
				
			||||||
 | 
							T tmp = Converter::ToLittleEndian(v);
 | 
				
			||||||
 | 
							return (good = stream.sputn((char*)&tmp, sizeof(T)) == sizeof(T));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::streambuf &stream;
 | 
				
			||||||
 | 
						bool good;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										31
									
								
								libs/gempa/caps/log.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								libs/gempa/caps/log.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void SetLogHandler(LogLevel l, LogOutput o) {
 | 
				
			||||||
 | 
						LogHandler[l] = o;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LogOutput LogHandler[LL_QUANTITY] = { NULL, NULL, NULL, NULL, NULL, NULL };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										61
									
								
								libs/gempa/caps/log.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								libs/gempa/caps/log.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_LOG_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_LOG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum LogLevel {
 | 
				
			||||||
 | 
						LL_UNDEFINED = 0,
 | 
				
			||||||
 | 
						LL_ERROR,
 | 
				
			||||||
 | 
						LL_WARNING,
 | 
				
			||||||
 | 
						LL_NOTICE,
 | 
				
			||||||
 | 
						LL_INFO,
 | 
				
			||||||
 | 
						LL_DEBUG,
 | 
				
			||||||
 | 
						LL_QUANTITY
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CAPS_LOG_MSG(LogLevel, ...) \
 | 
				
			||||||
 | 
						do {\
 | 
				
			||||||
 | 
							if ( Gempa::CAPS::LogHandler[LogLevel] != NULL )\
 | 
				
			||||||
 | 
								Gempa::CAPS::LogHandler[LogLevel](__VA_ARGS__);\
 | 
				
			||||||
 | 
						} while(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CAPS_ERROR(...) CAPS_LOG_MSG(Gempa::CAPS::LL_ERROR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define CAPS_WARNING(...) CAPS_LOG_MSG(Gempa::CAPS::LL_WARNING, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define CAPS_NOTICE(...) CAPS_LOG_MSG(Gempa::CAPS::LL_NOTICE, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define CAPS_INFO(...) CAPS_LOG_MSG(Gempa::CAPS::LL_INFO, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define CAPS_DEBUG(...) CAPS_LOG_MSG(Gempa::CAPS::LL_DEBUG, __VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*LogOutput)(const char *, ...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern LogOutput LogHandler[LL_QUANTITY];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void SetLogHandler(LogLevel, LogOutput);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										81
									
								
								libs/gempa/caps/metapacket.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								libs/gempa/caps/metapacket.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/metapacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/riff.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MetaDataRecord::MetaHeader::setEndTime(const Time &ts) {
 | 
				
			||||||
 | 
						int year, yday, hour, min, sec, usec;
 | 
				
			||||||
 | 
						ts.get2(&year, &yday, &hour, &min, &sec, &usec);
 | 
				
			||||||
 | 
						endTime.year = year;
 | 
				
			||||||
 | 
						endTime.yday = yday;
 | 
				
			||||||
 | 
						endTime.hour = hour;
 | 
				
			||||||
 | 
						endTime.minute = min;
 | 
				
			||||||
 | 
						endTime.second = sec;
 | 
				
			||||||
 | 
						endTime.usec = usec;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MetaDataRecord::MetaDataRecord() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MetaDataRecord::Buffer *MetaDataRecord::data() {
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *MetaDataRecord::formatName() const {
 | 
				
			||||||
 | 
						return "META";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DataRecord::Header *MetaDataRecord::header() const {
 | 
				
			||||||
 | 
						return &_header.dataHeader;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Time MetaDataRecord::startTime() const {
 | 
				
			||||||
 | 
						return _startTime;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Time MetaDataRecord::endTime() const {
 | 
				
			||||||
 | 
						return _endTime;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t MetaDataRecord::dataSize(bool /*withHeader*/) const {
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DataRecord::ReadStatus MetaDataRecord::get(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
					                                          const Time &start, const Time &end,
 | 
				
			||||||
 | 
					                                          int maxBytes) {
 | 
				
			||||||
 | 
						return RS_Error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MetaDataRecord::setHeader(const MetaHeader &header) {
 | 
				
			||||||
 | 
						_header = header;
 | 
				
			||||||
 | 
						_startTime = timestampToTime(header.dataHeader.samplingTime);
 | 
				
			||||||
 | 
						_endTime = timestampToTime(header.endTime);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										143
									
								
								libs/gempa/caps/metapacket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								libs/gempa/caps/metapacket.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,143 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_METAPACKET_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_METAPACKET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/api.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API MetaResponseHeader {
 | 
				
			||||||
 | 
						struct Time {
 | 
				
			||||||
 | 
							int64_t seconds;
 | 
				
			||||||
 | 
							int32_t microSeconds;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Time  startTime;
 | 
				
			||||||
 | 
						Time  endTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool get(std::streambuf &buf) {
 | 
				
			||||||
 | 
							Endianess::Reader get(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							get(startTime.seconds);
 | 
				
			||||||
 | 
							get(startTime.microSeconds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							get(endTime.seconds);
 | 
				
			||||||
 | 
							get(endTime.microSeconds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return get.good;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int dataSize() const {
 | 
				
			||||||
 | 
							return sizeof(startTime.seconds) + sizeof(startTime.microSeconds) +
 | 
				
			||||||
 | 
							       sizeof(endTime.seconds) + sizeof(endTime.microSeconds);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MetaDataRecord : public DataRecord {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							struct MetaHeader {
 | 
				
			||||||
 | 
								Header    dataHeader;
 | 
				
			||||||
 | 
								TimeStamp endTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bool get(std::streambuf &buf) {
 | 
				
			||||||
 | 
									Endianess::Reader get(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									get(endTime.year);
 | 
				
			||||||
 | 
									get(endTime.yday);
 | 
				
			||||||
 | 
									get(endTime.hour);
 | 
				
			||||||
 | 
									get(endTime.minute);
 | 
				
			||||||
 | 
									get(endTime.second);
 | 
				
			||||||
 | 
									get(endTime.usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return get.good;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bool put(std::streambuf &buf) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								int dataSize() const {
 | 
				
			||||||
 | 
									return dataHeader.dataSize() +
 | 
				
			||||||
 | 
									       sizeof(endTime.year) +
 | 
				
			||||||
 | 
									       sizeof(endTime.yday) +
 | 
				
			||||||
 | 
									       sizeof(endTime.hour) +
 | 
				
			||||||
 | 
									       sizeof(endTime.minute) +
 | 
				
			||||||
 | 
									       sizeof(endTime.second) +
 | 
				
			||||||
 | 
									       sizeof(endTime.usec);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								void setEndTime(const Time ×tamp);
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							MetaDataRecord();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the data vector to be filled by the caller
 | 
				
			||||||
 | 
							Buffer *data();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual const char *formatName() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool readMetaData(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                          Header &header,
 | 
				
			||||||
 | 
							                          Time &startTime, Time &endTime) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual const Header *header() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets a custom header and updates all internal structures
 | 
				
			||||||
 | 
							//! based on the current data. If the data has changed, make
 | 
				
			||||||
 | 
							//! sure to call this method again. If the flag skip reading
 | 
				
			||||||
 | 
							//! is set get will not read the header information from stream
 | 
				
			||||||
 | 
							void setHeader(const MetaHeader &header);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual Time startTime() const;
 | 
				
			||||||
 | 
							virtual Time endTime() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool canTrim() const { return false; }
 | 
				
			||||||
 | 
							virtual bool canMerge() const { return false; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool trim(const Time &start, const Time &end) const { return false; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual size_t dataSize(bool withHeader) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual ReadStatus get(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                       const Time &start, const Time &end,
 | 
				
			||||||
 | 
							                       int maxBytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool put(std::streambuf &buf, bool withHeader) const { return false; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PacketType packetType() const { return MetaDataPacket; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							MetaHeader      _header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mutable Time    _startTime;
 | 
				
			||||||
 | 
							mutable Time    _endTime;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										75
									
								
								libs/gempa/caps/mseed/encoder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								libs/gempa/caps/mseed/encoder.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					/*****************************************************************************
 | 
				
			||||||
 | 
					 * encoder.h
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Abstract Encoder interface
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * (c) 2000 Andres Heinloo, GFZ Potsdam
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 2, or (at your option) any later
 | 
				
			||||||
 | 
					 * version. For more information, see http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ================
 | 
				
			||||||
 | 
					 * Change log
 | 
				
			||||||
 | 
					 * ===============
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 01.01.2013 Adapted code to CAPS client library requirements (gempa GmbH)
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CAPS_MSEED_ENCODER_H
 | 
				
			||||||
 | 
					#define CAPS_MSEED_ENCODER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "packet.h"
 | 
				
			||||||
 | 
					#include "spclock.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/datetime.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/pluginpacket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Encoder {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Encoder(int freqn, int freqd) : _clk(freqn, freqd),
 | 
				
			||||||
 | 
							    _sampleCount(0), _timingQuality(-1) {}
 | 
				
			||||||
 | 
							virtual ~Encoder() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual void push(void *sample) = 0;
 | 
				
			||||||
 | 
							virtual void flush() = 0;
 | 
				
			||||||
 | 
							virtual void reset() { _sampleCount = 0; }
 | 
				
			||||||
 | 
							virtual int type() const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const SPClock& clk() { return _clk; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setStartTime(const SPClock::INT_TIME &time) { _clk.sync_time(time); }
 | 
				
			||||||
 | 
							const SPClock::INT_TIME currentTime() const { return _clk.get_time(0); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int timingQuality() { return _timingQuality; }
 | 
				
			||||||
 | 
							void setTimingQuality(int quality) { _timingQuality = quality; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PacketPtr pop() {
 | 
				
			||||||
 | 
								if ( _packetQueue.empty() ) return PacketPtr();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								PacketPtr rec = _packetQueue.front();
 | 
				
			||||||
 | 
								_packetQueue.pop_front(); 
 | 
				
			||||||
 | 
								return rec;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							typedef std::list<PacketPtr>  PacketQueue;
 | 
				
			||||||
 | 
							SPClock      _clk;
 | 
				
			||||||
 | 
							int          _sampleCount;
 | 
				
			||||||
 | 
							PacketQueue  _packetQueue;
 | 
				
			||||||
 | 
							int          _timingQuality;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __ENCODER_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										162
									
								
								libs/gempa/caps/mseed/mseed.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								libs/gempa/caps/mseed/mseed.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,162 @@
 | 
				
			|||||||
 | 
					/*****************************************************************************
 | 
				
			||||||
 | 
					 * mseed.cpp
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Mini-SEED format implementation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * (c) 2000 Andres Heinloo, GFZ Potsdam
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 2, or (at your option) any later
 | 
				
			||||||
 | 
					 * version. For more information, see http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ================
 | 
				
			||||||
 | 
					 * Change log
 | 
				
			||||||
 | 
					 * ===============
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 01.01.2013 Adapted code to CAPS client library requirements (gempa GmbH)
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/mseedpacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/rawpacket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mseed.h"
 | 
				
			||||||
 | 
					#include "slink.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cmath>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					#include <cstdlib>
 | 
				
			||||||
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MSEEDFormat::MSEEDFormat(const std::string &netcode, const std::string &stacode,
 | 
				
			||||||
 | 
					                         const std::string &loccode, const std::string &chacode,
 | 
				
			||||||
 | 
					                         unsigned short freqn, unsigned short freqd,
 | 
				
			||||||
 | 
					                         unsigned short packtype_init,
 | 
				
			||||||
 | 
					                         uint8_t recordLength)
 | 
				
			||||||
 | 
					    : networkCode(netcode), stationCode(stacode), locationCode(loccode),
 | 
				
			||||||
 | 
					      channelCode(chacode), packType(packtype_init), recordLength(recordLength)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if(freqn == 0 || freqd == 0) {
 | 
				
			||||||
 | 
							sample_rate_factor = 0;
 | 
				
			||||||
 | 
							sample_rate_multiplier = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if(!(freqn % freqd)) {
 | 
				
			||||||
 | 
							sample_rate_factor = freqn / freqd;
 | 
				
			||||||
 | 
							sample_rate_multiplier = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if(!(freqd % freqn)) {
 | 
				
			||||||
 | 
							sample_rate_factor = -freqd / freqn;
 | 
				
			||||||
 | 
							sample_rate_multiplier = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							sample_rate_factor = -freqd;
 | 
				
			||||||
 | 
							sample_rate_multiplier = freqn;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MSEEDDataRecord *MSEEDFormat::get_buffer(const SPClock::INT_TIME &it, int usec_correction,
 | 
				
			||||||
 | 
					                                         int timing_quality, void *&dataptr, int &datalen) {
 | 
				
			||||||
 | 
						size_t buflen = 1 << recordLength;
 | 
				
			||||||
 | 
						MSEEDDataRecord *record = new MSEEDDataRecord();
 | 
				
			||||||
 | 
						record->data()->resize(buflen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char *buf = record->data()->data();
 | 
				
			||||||
 | 
						int n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sl_fsdh_s* fsdh = (sl_fsdh_s *)buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(fsdh, 0, buflen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const int start_frames = (sizeof(sl_fsdh_s) + sizeof(sl_blkt_1000_s) +
 | 
				
			||||||
 | 
						sizeof(sl_blkt_1001_s) + 63) & 0xffffffc0;    // align to 64 bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dataptr = (void *)((char *) fsdh + start_frames);
 | 
				
			||||||
 | 
						datalen = buflen - start_frames;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fsdh->dhq_indicator = 'D';
 | 
				
			||||||
 | 
						fsdh->reserved = ' ';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strncpy(fsdh->station, stationCode.c_str(), 5);
 | 
				
			||||||
 | 
						if((n = stationCode.length()) < 5) memset(fsdh->station + n, 32, 5 - n);
 | 
				
			||||||
 | 
						strncpy(fsdh->location, locationCode.c_str(), 2);
 | 
				
			||||||
 | 
						if((n = locationCode.length()) < 2) memset(fsdh->location + n, 32, 2 - n);
 | 
				
			||||||
 | 
						strncpy(fsdh->channel, channelCode.c_str(), 3);
 | 
				
			||||||
 | 
						if((n = channelCode.length()) < 3) memset(fsdh->channel + n, 32, 3 - n);
 | 
				
			||||||
 | 
						strncpy(fsdh->network, networkCode.c_str(), 2);
 | 
				
			||||||
 | 
						if((n = networkCode.length()) < 2) memset(fsdh->network + n, 32, 2 - n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int year, doy, hour, min, sec;
 | 
				
			||||||
 | 
						it.get2(&year, &doy, &hour, &min, &sec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fsdh->start_time.year = htons(year);
 | 
				
			||||||
 | 
						fsdh->start_time.day = htons(doy+1);
 | 
				
			||||||
 | 
						fsdh->start_time.hour = hour;
 | 
				
			||||||
 | 
						fsdh->start_time.min = min;
 | 
				
			||||||
 | 
						fsdh->start_time.sec = sec;
 | 
				
			||||||
 | 
						fsdh->start_time.fract = htons(it.microseconds() / 100);
 | 
				
			||||||
 | 
						fsdh->samprate_fact = (int16_t)htons(sample_rate_factor);
 | 
				
			||||||
 | 
						fsdh->samprate_mult = (int16_t)htons(sample_rate_multiplier);
 | 
				
			||||||
 | 
						fsdh->num_blockettes = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						div_t d_corr = div(usec_correction + ((usec_correction < 0) ? -50: 50), 100);
 | 
				
			||||||
 | 
						fsdh->time_correct = (int32_t)htonl(d_corr.quot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fsdh->begin_data = htons(start_frames);
 | 
				
			||||||
 | 
						fsdh->begin_blockette = htons(sizeof(sl_fsdh_s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sl_blkt_1000_s* blkt_1000 = (sl_blkt_1000_s *)((char *) fsdh + sizeof(sl_fsdh_s));
 | 
				
			||||||
 | 
						blkt_1000->blkt_type = htons(1000);          // Data Only SEED Blockette
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						blkt_1000->encoding = packType;
 | 
				
			||||||
 | 
						blkt_1000->word_swap = 1;                    // big endian
 | 
				
			||||||
 | 
						blkt_1000->rec_len = recordLength; // 9 = 512 bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( timing_quality >= 0 ) {
 | 
				
			||||||
 | 
							blkt_1000->next_blkt = htons(sizeof(sl_fsdh_s) + sizeof(sl_blkt_1000_s));
 | 
				
			||||||
 | 
							++fsdh->num_blockettes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sl_blkt_1001_s* blkt_1001 = (sl_blkt_1001_s *)((char *) fsdh +
 | 
				
			||||||
 | 
							  sizeof(sl_fsdh_s) + sizeof(sl_blkt_1000_s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							blkt_1001->blkt_type = htons(1001);      // Data Extension Blockette
 | 
				
			||||||
 | 
							blkt_1001->timing_qual = timing_quality;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							blkt_1001->usec = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return record;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MSEEDFormat::updateBuffer(MSEEDDataRecord *rec, int samples, int frames) {
 | 
				
			||||||
 | 
						sl_fsdh_s* fsdh = (sl_fsdh_s *)rec->data()->data();
 | 
				
			||||||
 | 
						char temp[7];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sprintf(temp, "%06d", (int)0);
 | 
				
			||||||
 | 
						memcpy(fsdh->sequence_number,temp,6);
 | 
				
			||||||
 | 
						fsdh->dhq_indicator = 'D';
 | 
				
			||||||
 | 
						fsdh->num_samples = htons(samples);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sl_blkt_1000_s* blkt_1000 = (sl_blkt_1000_s *)((char *) fsdh + sizeof(sl_fsdh_s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( ntohs(blkt_1000->next_blkt) != 0 ) {
 | 
				
			||||||
 | 
							sl_blkt_1001_s* blkt_1001 = (sl_blkt_1001_s *)((char *) fsdh +
 | 
				
			||||||
 | 
							                             sizeof(sl_fsdh_s) + sizeof(sl_blkt_1000_s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							blkt_1001->frame_cnt = frames;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rec->unpackHeader();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										90
									
								
								libs/gempa/caps/mseed/mseed.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								libs/gempa/caps/mseed/mseed.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					/*****************************************************************************
 | 
				
			||||||
 | 
					 * mseed.h
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Mini-SEED format implementation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * (c) 2000 Andres Heinloo, GFZ Potsdam
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 2, or (at your option) any later
 | 
				
			||||||
 | 
					 * version. For more information, see http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ================
 | 
				
			||||||
 | 
					 * Change log
 | 
				
			||||||
 | 
					 * ===============
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 01.01.2013 Adapted code to CAPS client library requirements (gempa GmbH)
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CAPS_MSEED_MSEED_H
 | 
				
			||||||
 | 
					#define CAPS_MSEED_MSEED_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "packet.h"
 | 
				
			||||||
 | 
					#include "spclock.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/mseedpacket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SEED data encoding types */
 | 
				
			||||||
 | 
					enum SEEDDataEncodingType {
 | 
				
			||||||
 | 
						DE_ASCII       = 0,
 | 
				
			||||||
 | 
						DE_INT16       = 1,
 | 
				
			||||||
 | 
						DE_INT32       = 3,
 | 
				
			||||||
 | 
						DE_FLOAT32     = 4,
 | 
				
			||||||
 | 
						DE_FLOAT64     = 5,
 | 
				
			||||||
 | 
						DE_STEIM1      = 10,
 | 
				
			||||||
 | 
						DE_STEIM2      = 11,
 | 
				
			||||||
 | 
						DE_GEOSCOPE24  = 12,
 | 
				
			||||||
 | 
						DE_GEOSCOPE163 = 13,
 | 
				
			||||||
 | 
						DE_GEOSCOPE164 = 14,
 | 
				
			||||||
 | 
						DE_CDSN        = 16,
 | 
				
			||||||
 | 
						DE_SRO         = 30,
 | 
				
			||||||
 | 
						DE_DWWSSN      = 32
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct MSEEDFormat {
 | 
				
			||||||
 | 
						MSEEDFormat(const std::string &networkCode, const std::string &stationCode,
 | 
				
			||||||
 | 
						            const std::string &locationCode, const std::string &channelCode,
 | 
				
			||||||
 | 
						            unsigned short freqn, unsigned short freqd,
 | 
				
			||||||
 | 
						            unsigned short packtype_init,
 | 
				
			||||||
 | 
						            uint8_t recLen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						template<class T>
 | 
				
			||||||
 | 
						MSEEDEncoderPacket<T>
 | 
				
			||||||
 | 
						get_packet(const SPClock::INT_TIME &it, int usec_correction, int timing_quality) {
 | 
				
			||||||
 | 
							void *dataptr = NULL;
 | 
				
			||||||
 | 
							int datalen = 0;
 | 
				
			||||||
 | 
							unsigned int size = 0;
 | 
				
			||||||
 | 
							MSEEDDataRecord *rec = get_buffer(it, usec_correction, timing_quality, dataptr, datalen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return MSEEDEncoderPacket<T>(rec, size, dataptr, datalen);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MSEEDDataRecord *get_buffer(const SPClock::INT_TIME &it, int usec_correction,
 | 
				
			||||||
 | 
						                 int timing_quality,
 | 
				
			||||||
 | 
						                 void *&dataptr, int &datalen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void updateBuffer(MSEEDDataRecord *rec, int samples, int frames);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::string    networkCode;
 | 
				
			||||||
 | 
						std::string    stationCode;
 | 
				
			||||||
 | 
						std::string    locationCode;
 | 
				
			||||||
 | 
						std::string    channelCode;
 | 
				
			||||||
 | 
						int            sample_rate_factor;
 | 
				
			||||||
 | 
						int            sample_rate_multiplier;
 | 
				
			||||||
 | 
						unsigned short packType;
 | 
				
			||||||
 | 
						int            timingQuality;
 | 
				
			||||||
 | 
						uint8_t        recordLength;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										44
									
								
								libs/gempa/caps/mseed/packet.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								libs/gempa/caps/mseed/packet.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CAPS_MSEED_PACKET_H
 | 
				
			||||||
 | 
					#define CAPS_MSEED_PACKET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/mseedpacket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> struct MSEEDEncoderPacket {
 | 
				
			||||||
 | 
						MSEEDEncoderPacket(): record(NULL), data(NULL), datalen(0) {}
 | 
				
			||||||
 | 
						MSEEDEncoderPacket(MSEEDDataRecord *rec, unsigned int size_init,
 | 
				
			||||||
 | 
						       void *data_init, unsigned short datalen_init)
 | 
				
			||||||
 | 
						    : record(rec), data(static_cast<T*>(data_init)),
 | 
				
			||||||
 | 
						      datalen(datalen_init) {}
 | 
				
			||||||
 | 
						~MSEEDEncoderPacket() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void reset() { record = NULL; data = NULL; datalen = 0; }
 | 
				
			||||||
 | 
						bool valid() const { return record != NULL; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MSEEDDataRecord *record;
 | 
				
			||||||
 | 
						T               *data;
 | 
				
			||||||
 | 
						unsigned short   datalen;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										131
									
								
								libs/gempa/caps/mseed/slink.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								libs/gempa/caps/mseed/slink.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,131 @@
 | 
				
			|||||||
 | 
					/*****************************************************************************
 | 
				
			||||||
 | 
					 * slink.h
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SeedLink protocol constants
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Token from libslink
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 2, or (at your option) any later
 | 
				
			||||||
 | 
					 * version. For more information, see http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ================
 | 
				
			||||||
 | 
					 * Change log
 | 
				
			||||||
 | 
					 * ===============
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 01.01.2013 Adapted code to CAPS client library requirements (gempa GmbH)
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CAPS_MSEED_SLINK_H
 | 
				
			||||||
 | 
					#define CAPS_MSEED_SLINK_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Portability to the XScale (ARM) architecture
 | 
				
			||||||
 | 
					   * requires a packed attribute in certain places
 | 
				
			||||||
 | 
					   * but this only works with GCC for now.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					#if defined (__GNUC__)
 | 
				
			||||||
 | 
					  #define SLP_PACKED __attribute__ ((packed))
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  #define SLP_PACKED
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SIGNATURE           "SL"     /* SeedLink header signature */
 | 
				
			||||||
 | 
					#define INFOSIGNATURE       "SLINFO" /* SeedLink INFO packet signature */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SeedLink packet types */
 | 
				
			||||||
 | 
					#define SLDATA 0     /* waveform data record */
 | 
				
			||||||
 | 
					#define SLDET  1     /* detection record */
 | 
				
			||||||
 | 
					#define SLCAL  2     /* calibration record */
 | 
				
			||||||
 | 
					#define SLTIM  3     /* timing record */
 | 
				
			||||||
 | 
					#define SLMSG  4     /* message record */
 | 
				
			||||||
 | 
					#define SLBLK  5     /* general record */
 | 
				
			||||||
 | 
					#define SLNUM  6     /* used as the error indicator (same as SLCHA) */
 | 
				
			||||||
 | 
					#define SLCHA  6     /* for requesting channel info or detectors */
 | 
				
			||||||
 | 
					#define SLINF  7     /* a non-terminating XML formatted message in a miniSEED
 | 
				
			||||||
 | 
					                        log record, used for INFO responses */
 | 
				
			||||||
 | 
					#define SLINFT 8     /* a terminating XML formatted message in a miniSEED log
 | 
				
			||||||
 | 
					                        record, used for INFO responses */
 | 
				
			||||||
 | 
					#define SLKEEP 9     /* an XML formatted message in a miniSEED log
 | 
				
			||||||
 | 
					                        record, used for keepalive/heartbeat responses */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SEED binary time (10 bytes) */
 | 
				
			||||||
 | 
					struct sl_btime_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint16_t  year;
 | 
				
			||||||
 | 
					  uint16_t  day;
 | 
				
			||||||
 | 
					  uint8_t   hour;
 | 
				
			||||||
 | 
					  uint8_t   min;
 | 
				
			||||||
 | 
					  uint8_t   sec;
 | 
				
			||||||
 | 
					  uint8_t   unused;
 | 
				
			||||||
 | 
					  uint16_t  fract;
 | 
				
			||||||
 | 
					} SLP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Fixed section data of header (48 bytes) */
 | 
				
			||||||
 | 
					struct sl_fsdh_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  char        sequence_number[6];
 | 
				
			||||||
 | 
					  char        dhq_indicator;
 | 
				
			||||||
 | 
					  char        reserved;
 | 
				
			||||||
 | 
					  char        station[5];
 | 
				
			||||||
 | 
					  char        location[2];
 | 
				
			||||||
 | 
					  char        channel[3];
 | 
				
			||||||
 | 
					  char        network[2];
 | 
				
			||||||
 | 
					  struct sl_btime_s start_time;
 | 
				
			||||||
 | 
					  uint16_t    num_samples;
 | 
				
			||||||
 | 
					  int16_t     samprate_fact;
 | 
				
			||||||
 | 
					  int16_t     samprate_mult;
 | 
				
			||||||
 | 
					  uint8_t     act_flags;
 | 
				
			||||||
 | 
					  uint8_t     io_flags;
 | 
				
			||||||
 | 
					  uint8_t     dq_flags;
 | 
				
			||||||
 | 
					  uint8_t     num_blockettes;
 | 
				
			||||||
 | 
					  int32_t     time_correct;
 | 
				
			||||||
 | 
					  uint16_t    begin_data;
 | 
				
			||||||
 | 
					  uint16_t    begin_blockette;
 | 
				
			||||||
 | 
					} SLP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 1000 Blockette (8 bytes) */
 | 
				
			||||||
 | 
					struct sl_blkt_1000_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint16_t  blkt_type;
 | 
				
			||||||
 | 
					  uint16_t  next_blkt;
 | 
				
			||||||
 | 
					  uint8_t   encoding;
 | 
				
			||||||
 | 
					  uint8_t   word_swap;
 | 
				
			||||||
 | 
					  uint8_t   rec_len;
 | 
				
			||||||
 | 
					  uint8_t   reserved;
 | 
				
			||||||
 | 
					} SLP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 1001 Blockette (8 bytes) */
 | 
				
			||||||
 | 
					struct sl_blkt_1001_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint16_t  blkt_type;
 | 
				
			||||||
 | 
					  uint16_t  next_blkt;
 | 
				
			||||||
 | 
					  int8_t    timing_qual;
 | 
				
			||||||
 | 
					  int8_t    usec;
 | 
				
			||||||
 | 
					  uint8_t   reserved;
 | 
				
			||||||
 | 
					  int8_t    frame_cnt;
 | 
				
			||||||
 | 
					} SLP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Generic struct for head of blockettes */
 | 
				
			||||||
 | 
					struct sl_blkt_head_s
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint16_t  blkt_type;
 | 
				
			||||||
 | 
					  uint16_t  next_blkt;
 | 
				
			||||||
 | 
					} SLP_PACKED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										78
									
								
								libs/gempa/caps/mseed/spclock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								libs/gempa/caps/mseed/spclock.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					/*****************************************************************************
 | 
				
			||||||
 | 
					 * spclock.h
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Stream Processor Clock
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * (c) 2000 Andres Heinloo, GFZ Potsdam
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 2, or (at your option) any later
 | 
				
			||||||
 | 
					 * version. For more information, see http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ================
 | 
				
			||||||
 | 
					 * Change log
 | 
				
			||||||
 | 
					 * ===============
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 01.01.2013 Adapted code to CAPS client library requirements (gempa GmbH)
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CAPS_MSEED_SPCLOCK_H
 | 
				
			||||||
 | 
					#define CAPS_MSEED_SPCLOCK_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/datetime.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SPClock
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    typedef Gempa::CAPS::Time INT_TIME;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					    INT_TIME itime;
 | 
				
			||||||
 | 
					    int ticks;
 | 
				
			||||||
 | 
					    int corr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    const int freqn;
 | 
				
			||||||
 | 
					    const int freqd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPClock(int freqn_init, int freqd_init): ticks(0), corr(0),
 | 
				
			||||||
 | 
					      freqn(freqn_init), freqd(freqd_init)
 | 
				
			||||||
 | 
					      {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void sync_time(const INT_TIME &time)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        itime = time;
 | 
				
			||||||
 | 
					        ticks = 0;
 | 
				
			||||||
 | 
					        corr = 0;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void tick()
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        ++ticks;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    INT_TIME get_time(int tick_diff) const
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        int64_t correctness = (double)freqd / (double)freqn * 1000000 * (ticks - tick_diff - corr);
 | 
				
			||||||
 | 
					        return itime + Gempa::CAPS::TimeSpan(long(correctness/1000000),long(correctness%1000000));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int correction() const
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        return corr;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // SPCLOCK_H
 | 
				
			||||||
							
								
								
									
										90
									
								
								libs/gempa/caps/mseed/steim1.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								libs/gempa/caps/mseed/steim1.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					/***************************************************************************** 
 | 
				
			||||||
 | 
					 * steim1.h
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Steim1 encoder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * (c) 2000 Andres Heinloo, GFZ Potsdam
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 2, or (at your option) any later
 | 
				
			||||||
 | 
					 * version. For more information, see http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ================
 | 
				
			||||||
 | 
					 * Change log
 | 
				
			||||||
 | 
					 * ===============
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 01.01.2013 Adapted code to CAPS client library requirements (gempa GmbH)
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CAPS_MSEED_STEIM1_H
 | 
				
			||||||
 | 
					#define CAPS_MSEED_STEIM1_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "encoder.h"
 | 
				
			||||||
 | 
					#include "mseed.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//*****************************************************************************
 | 
				
			||||||
 | 
					// Steim1Frame
 | 
				
			||||||
 | 
					//*****************************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Steim1Frame {
 | 
				
			||||||
 | 
						u_int32_t nibble_word;
 | 
				
			||||||
 | 
						u_int32_t sample_word[15];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//*****************************************************************************
 | 
				
			||||||
 | 
					// Steim1Encoder
 | 
				
			||||||
 | 
					//*****************************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					class Steim1Encoder: public Encoder {
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							MSEEDFormat *format;
 | 
				
			||||||
 | 
							int frame_count;
 | 
				
			||||||
 | 
							int bp;
 | 
				
			||||||
 | 
							int fp;
 | 
				
			||||||
 | 
							int spw;
 | 
				
			||||||
 | 
							int32_t last_sample;
 | 
				
			||||||
 | 
							int32_t buf[5];
 | 
				
			||||||
 | 
							u_int32_t nibble_word;
 | 
				
			||||||
 | 
							MSEEDEncoderPacket<Steim1Frame> current_packet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void update_spw(int bp);
 | 
				
			||||||
 | 
							void store(int32_t value);
 | 
				
			||||||
 | 
							void init_packet();
 | 
				
			||||||
 | 
							void finish_packet();
 | 
				
			||||||
 | 
							void update_packet();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							MSEEDEncoderPacket<Steim1Frame> get_packet() {
 | 
				
			||||||
 | 
								return format->get_packet<Steim1Frame>(_clk.get_time(bp),
 | 
				
			||||||
 | 
								                                       _clk.correction(), _timingQuality);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void queue_packet(MSEEDEncoderPacket<Steim1Frame> &pckt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int number_of_frames(const MSEEDEncoderPacket<Steim1Frame> &packet) {
 | 
				
			||||||
 | 
								return (packet.datalen >> 6);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Steim1Encoder(MSEEDFormat *format, int freqn, int freqd)
 | 
				
			||||||
 | 
							    : Encoder(freqn, freqd), format(format), frame_count(0),
 | 
				
			||||||
 | 
							      bp(0), fp(0), spw(4), last_sample(0), nibble_word(0) {}
 | 
				
			||||||
 | 
							virtual ~Steim1Encoder();
 | 
				
			||||||
 | 
							virtual void flush();
 | 
				
			||||||
 | 
							virtual void push(void *value);
 | 
				
			||||||
 | 
							virtual int type() const { return DE_STEIM1; }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "steim1.ipp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __STEIM1_H__
 | 
				
			||||||
							
								
								
									
										184
									
								
								libs/gempa/caps/mseed/steim1.ipp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								libs/gempa/caps/mseed/steim1.ipp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,184 @@
 | 
				
			|||||||
 | 
					/***************************************************************************** 
 | 
				
			||||||
 | 
					 * steim1.cc
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Steim1 encoder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * (c) 2000 Andres Heinloo, GFZ Potsdam
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 2, or (at your option) any later
 | 
				
			||||||
 | 
					 * version. For more information, see http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ================
 | 
				
			||||||
 | 
					 * Change log
 | 
				
			||||||
 | 
					 * ===============
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 01.01.2013 Adapted code to CAPS client library requirements (gempa GmbH)
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> Steim1Encoder<T>::~Steim1Encoder() {
 | 
				
			||||||
 | 
						if ( format != NULL ) delete format;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim1Encoder<T>::update_spw(int bp) {
 | 
				
			||||||
 | 
						int spw1 = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(bp < 4);
 | 
				
			||||||
 | 
						if(buf[bp] < -32768 || buf[bp] > 32767) spw1 = 1;
 | 
				
			||||||
 | 
						else if(buf[bp] < -128 || buf[bp] > 127) spw1 = 2;
 | 
				
			||||||
 | 
						if(spw1 < spw) spw = spw1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim1Encoder<T>::store(int32_t value) {
 | 
				
			||||||
 | 
						assert(bp < 4);
 | 
				
			||||||
 | 
						buf[bp] = value - last_sample;
 | 
				
			||||||
 | 
						last_sample = value;
 | 
				
			||||||
 | 
						update_spw(bp);
 | 
				
			||||||
 | 
						++bp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim1Encoder<T>::init_packet() {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						int32_t begin_sample = last_sample;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for(i = 1; i < bp; ++i) {
 | 
				
			||||||
 | 
							begin_sample -= buf[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reset();
 | 
				
			||||||
 | 
						current_packet.data[0].sample_word[0] = htonl(begin_sample);
 | 
				
			||||||
 | 
						frame_count = 0;
 | 
				
			||||||
 | 
						nibble_word = 0;
 | 
				
			||||||
 | 
						fp = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim1Encoder<T>::finish_packet() {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						int32_t end_sample = last_sample;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for(i = 0; i < bp; ++i) {
 | 
				
			||||||
 | 
							end_sample -= buf[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						current_packet.data[0].sample_word[1] = htonl(end_sample);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim1Encoder<T>::update_packet() {
 | 
				
			||||||
 | 
						unsigned int nibble = 0;
 | 
				
			||||||
 | 
						u_int32_t sample_word = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(bp < 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int used = bp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while(used > spw) {
 | 
				
			||||||
 | 
							--used;
 | 
				
			||||||
 | 
							spw = 4;
 | 
				
			||||||
 | 
							for(int i = 0; i < used; ++i) update_spw(i);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while(used < spw) spw >>= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						used = spw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch(spw) {
 | 
				
			||||||
 | 
							case 4:
 | 
				
			||||||
 | 
								nibble = 1;
 | 
				
			||||||
 | 
								sample_word = ((buf[0] & 0xff) << 24) | ((buf[1] & 0xff) << 16) |
 | 
				
			||||||
 | 
								              ((buf[2] & 0xff) <<  8) | (buf[3] & 0xff);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 2:
 | 
				
			||||||
 | 
								nibble = 2;
 | 
				
			||||||
 | 
								sample_word = ((buf[0] & 0xffff) << 16) | (buf[1] & 0xffff);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								nibble = 3;
 | 
				
			||||||
 | 
								sample_word = buf[0];
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								assert(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nibble_word |= (nibble << (30 - ((fp + 1) << 1)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spw = 4;
 | 
				
			||||||
 | 
						for(int i = 0; i < bp - used; ++i) {
 | 
				
			||||||
 | 
							buf[i] = buf[i + used];
 | 
				
			||||||
 | 
							update_spw(i);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bp -= used;
 | 
				
			||||||
 | 
						_sampleCount += used;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						current_packet.data[frame_count].nibble_word = htonl(nibble_word);
 | 
				
			||||||
 | 
						current_packet.data[frame_count].sample_word[fp] = htonl(sample_word);
 | 
				
			||||||
 | 
						if(++fp < 15) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nibble_word = 0;
 | 
				
			||||||
 | 
						fp = 0;
 | 
				
			||||||
 | 
						++frame_count;
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim1Encoder<T>::queue_packet(MSEEDEncoderPacket<Steim1Frame> &pckt) {
 | 
				
			||||||
 | 
						format->updateBuffer(pckt.record, _sampleCount, frame_count + (fp > 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Packet *packet = new Packet(DataRecordPtr(pckt.record), format->networkCode, format->stationCode,
 | 
				
			||||||
 | 
						                            format->locationCode, format->channelCode);
 | 
				
			||||||
 | 
						_packetQueue.push_back(PacketPtr(packet));
 | 
				
			||||||
 | 
						pckt.reset();
 | 
				
			||||||
 | 
						reset();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim1Encoder<T>::push(void *value) {
 | 
				
			||||||
 | 
						int32_t sample_val = *static_cast<T*>(value);
 | 
				
			||||||
 | 
						store(sample_val);
 | 
				
			||||||
 | 
						_clk.tick();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while(bp >= spw) {
 | 
				
			||||||
 | 
							if(!current_packet.valid()) {
 | 
				
			||||||
 | 
								current_packet = get_packet();
 | 
				
			||||||
 | 
								init_packet();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							update_packet();
 | 
				
			||||||
 | 
							if(frame_count == number_of_frames(current_packet)) {
 | 
				
			||||||
 | 
								finish_packet();
 | 
				
			||||||
 | 
								queue_packet(current_packet);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim1Encoder<T>::flush() {
 | 
				
			||||||
 | 
						while(bp) {
 | 
				
			||||||
 | 
							if(!current_packet.valid()) {
 | 
				
			||||||
 | 
								current_packet = get_packet();
 | 
				
			||||||
 | 
								init_packet();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							update_packet();
 | 
				
			||||||
 | 
							if(frame_count == number_of_frames(current_packet)) {
 | 
				
			||||||
 | 
								finish_packet();
 | 
				
			||||||
 | 
								queue_packet(current_packet);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(current_packet.valid()) {
 | 
				
			||||||
 | 
							finish_packet();
 | 
				
			||||||
 | 
							queue_packet(current_packet);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										94
									
								
								libs/gempa/caps/mseed/steim2.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								libs/gempa/caps/mseed/steim2.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					/*****************************************************************************
 | 
				
			||||||
 | 
					 * steim2.h
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Steim2 encoder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * (c) 2000 Andres Heinloo, GFZ Potsdam
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 2, or (at your option) any later
 | 
				
			||||||
 | 
					 * version. For more information, see http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ================
 | 
				
			||||||
 | 
					 * Change log
 | 
				
			||||||
 | 
					 * ===============
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 01.01.2013 Adapted code to CAPS client library requirements (gempa GmbH)
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CAPS_MSEED_STEIM2_H
 | 
				
			||||||
 | 
					#define CAPS_MSEED_STEIM2_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "encoder.h"
 | 
				
			||||||
 | 
					#include "mseed.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//*****************************************************************************
 | 
				
			||||||
 | 
					// Steim2Frame
 | 
				
			||||||
 | 
					//*****************************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Steim2Frame {
 | 
				
			||||||
 | 
						u_int32_t nibble_word;
 | 
				
			||||||
 | 
						u_int32_t sample_word[15];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//*****************************************************************************
 | 
				
			||||||
 | 
					// Steim2Encoder
 | 
				
			||||||
 | 
					//*****************************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					class Steim2Encoder : public Encoder {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Steim2Encoder(MSEEDFormat *format, int freqn, int freqd)
 | 
				
			||||||
 | 
							    : Encoder(freqn, freqd), format(format), frame_count(0),
 | 
				
			||||||
 | 
							  bp(0), fp(0), spw(4), last_sample(0), nibble_word(0) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual ~Steim2Encoder();
 | 
				
			||||||
 | 
							virtual void flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual void push(void *value);
 | 
				
			||||||
 | 
							virtual int type() const { return DE_STEIM2; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							void update_spw(int bp);
 | 
				
			||||||
 | 
							void store(int32_t value);
 | 
				
			||||||
 | 
							void init_packet();
 | 
				
			||||||
 | 
							void finish_packet();
 | 
				
			||||||
 | 
							void update_packet();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							MSEEDEncoderPacket<Steim2Frame> get_packet() {
 | 
				
			||||||
 | 
								return format->get_packet<Steim2Frame>(_clk.get_time(bp),
 | 
				
			||||||
 | 
								                                       _clk.correction(), _timingQuality);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void queue_packet(MSEEDEncoderPacket<Steim2Frame> &pckt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int number_of_frames(const MSEEDEncoderPacket<Steim2Frame> &packet) {
 | 
				
			||||||
 | 
								return (packet.datalen >> 6);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							MSEEDFormat *format;
 | 
				
			||||||
 | 
							int frame_count;
 | 
				
			||||||
 | 
							int bp;
 | 
				
			||||||
 | 
							int fp;
 | 
				
			||||||
 | 
							int32_t last_s;
 | 
				
			||||||
 | 
							int spw;
 | 
				
			||||||
 | 
							int32_t last_sample;
 | 
				
			||||||
 | 
							int32_t buf[8];
 | 
				
			||||||
 | 
							u_int32_t nibble_word;
 | 
				
			||||||
 | 
							MSEEDEncoderPacket<Steim2Frame> current_packet;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "steim2.ipp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __STEIM2_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										241
									
								
								libs/gempa/caps/mseed/steim2.ipp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								libs/gempa/caps/mseed/steim2.ipp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,241 @@
 | 
				
			|||||||
 | 
					/*****************************************************************************
 | 
				
			||||||
 | 
					 * steim2.cc
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Steim2 encoder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * (c) 2004 Andres Heinloo, GFZ Potsdam
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 2, or (at your option) any later
 | 
				
			||||||
 | 
					 * version. For more information, see http://www.gnu.org/
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ================
 | 
				
			||||||
 | 
					 * Change log
 | 
				
			||||||
 | 
					 * ===============
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 01.01.2013 Adapted code to CAPS client library requirements (gempa GmbH)
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> Steim2Encoder<T>::~Steim2Encoder() {
 | 
				
			||||||
 | 
						if ( format != NULL ) delete format;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim2Encoder<T>::update_spw(int bp) {
 | 
				
			||||||
 | 
						assert(bp < 7);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(buf[bp] < -536870912) {
 | 
				
			||||||
 | 
							CAPS_WARNING("%s.%s.%s.%s: value %d is too large for Steim2 encoding",
 | 
				
			||||||
 | 
							             format->networkCode.c_str(), format->stationCode.c_str(),
 | 
				
			||||||
 | 
							             format->locationCode.c_str(), format->channelCode.c_str(),
 | 
				
			||||||
 | 
							             buf[bp]);
 | 
				
			||||||
 | 
							buf[bp] = -536870912;
 | 
				
			||||||
 | 
							spw = 1;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(buf[bp] > 536870911) {
 | 
				
			||||||
 | 
							CAPS_WARNING("%s.%s.%s.%s: value %d is too large for Steim2 encoding",
 | 
				
			||||||
 | 
							             format->networkCode.c_str(), format->stationCode.c_str(),
 | 
				
			||||||
 | 
							             format->locationCode.c_str(), format->channelCode.c_str(),
 | 
				
			||||||
 | 
							             buf[bp]);
 | 
				
			||||||
 | 
							buf[bp] = 536870911;
 | 
				
			||||||
 | 
							spw = 1;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int spw1 = 7;
 | 
				
			||||||
 | 
						if(buf[bp] < -16384 || buf[bp] > 16383) spw1 = 1;
 | 
				
			||||||
 | 
						else if(buf[bp] < -512 || buf[bp] > 511) spw1 = 2;
 | 
				
			||||||
 | 
						else if(buf[bp] < -128 || buf[bp] > 127) spw1 = 3;
 | 
				
			||||||
 | 
						else if(buf[bp] < -32 || buf[bp] > 31) spw1 = 4;
 | 
				
			||||||
 | 
						else if(buf[bp] < -16 || buf[bp] > 15) spw1 = 5;
 | 
				
			||||||
 | 
						else if(buf[bp] < -8  || buf[bp] > 7) spw1 = 6;
 | 
				
			||||||
 | 
						if(spw1 < spw) spw = spw1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim2Encoder<T>::store(int32_t value) {
 | 
				
			||||||
 | 
						assert(bp < 7);
 | 
				
			||||||
 | 
						buf[bp] = value - last_sample;
 | 
				
			||||||
 | 
						last_sample = value;
 | 
				
			||||||
 | 
						update_spw(bp);
 | 
				
			||||||
 | 
						++bp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim2Encoder<T>::init_packet() {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						int32_t begin_sample = last_sample;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for(i = 1; i < bp; ++i) {
 | 
				
			||||||
 | 
							begin_sample -= buf[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reset();
 | 
				
			||||||
 | 
						current_packet.data[0].sample_word[0] = htonl(begin_sample);
 | 
				
			||||||
 | 
						frame_count = 0;
 | 
				
			||||||
 | 
						nibble_word = 0;
 | 
				
			||||||
 | 
						fp = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim2Encoder<T>::finish_packet() {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						int32_t end_sample = last_sample;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for(i = 0; i < bp; ++i) {
 | 
				
			||||||
 | 
							end_sample -= buf[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						current_packet.data[0].sample_word[1] = htonl(end_sample);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim2Encoder<T>::update_packet() {
 | 
				
			||||||
 | 
						unsigned int nibble = 0;
 | 
				
			||||||
 | 
						u_int32_t sample_word = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(bp < 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int used = bp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while(used > spw) {
 | 
				
			||||||
 | 
							--used;
 | 
				
			||||||
 | 
							spw = 7;
 | 
				
			||||||
 | 
							for(int i = 0; i < used; ++i) update_spw(i);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spw = used;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch(spw) {
 | 
				
			||||||
 | 
							case 7:
 | 
				
			||||||
 | 
								nibble = 3;
 | 
				
			||||||
 | 
								sample_word = (2U << 30) | ((buf[0] & 0xf) << 24) |
 | 
				
			||||||
 | 
									((buf[1] & 0xf) << 20) | ((buf[2] & 0xf) << 16) |
 | 
				
			||||||
 | 
									((buf[3] & 0xf) << 12) | ((buf[4] & 0xf) << 8) |
 | 
				
			||||||
 | 
									((buf[5] & 0xf) << 4) | (buf[6] & 0xf);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 6:
 | 
				
			||||||
 | 
								nibble = 3;
 | 
				
			||||||
 | 
								sample_word = (1U << 30) | ((buf[0] & 0x1f) << 25) |
 | 
				
			||||||
 | 
									((buf[1] & 0x1f) << 20) | ((buf[2] & 0x1f) << 15) |
 | 
				
			||||||
 | 
									((buf[3] & 0x1f) << 10) | ((buf[4] & 0x1f) << 5) |
 | 
				
			||||||
 | 
									(buf[5] & 0x1f);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 5:
 | 
				
			||||||
 | 
								nibble = 3;
 | 
				
			||||||
 | 
								sample_word = ((buf[0] & 0x3f) << 24) | ((buf[1] & 0x3f) << 18) |
 | 
				
			||||||
 | 
									((buf[2] & 0x3f) << 12) | ((buf[3] & 0x3f) << 6) |
 | 
				
			||||||
 | 
									(buf[4] & 0x3f);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 4:
 | 
				
			||||||
 | 
								nibble = 1;
 | 
				
			||||||
 | 
								sample_word = ((buf[0] & 0xff) << 24) | ((buf[1] & 0xff) << 16) |
 | 
				
			||||||
 | 
									((buf[2] & 0xff) <<  8) | (buf[3] & 0xff);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 3:
 | 
				
			||||||
 | 
								nibble = 2;
 | 
				
			||||||
 | 
								sample_word = (3U << 30) | ((buf[0] & 0x3ff) << 20) |
 | 
				
			||||||
 | 
									((buf[1] & 0x3ff) << 10) | (buf[2] & 0x3ff);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 2:
 | 
				
			||||||
 | 
								nibble = 2;
 | 
				
			||||||
 | 
								sample_word = (2U << 30) | ((buf[0] & 0x7fff) << 15) |
 | 
				
			||||||
 | 
									(buf[1] & 0x7fff);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								nibble = 2;
 | 
				
			||||||
 | 
								sample_word = (1U << 30) | (buf[0] & 0x3fffffff);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								assert(0);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nibble_word |= (nibble << (30 - ((fp + 1) << 1)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spw = 7;
 | 
				
			||||||
 | 
						for(int i = 0; i < bp - used; ++i) {
 | 
				
			||||||
 | 
							buf[i] = buf[i + used];
 | 
				
			||||||
 | 
							update_spw(i);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bp -= used;
 | 
				
			||||||
 | 
						_sampleCount += used;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						current_packet.data[frame_count].nibble_word = htonl(nibble_word);
 | 
				
			||||||
 | 
						current_packet.data[frame_count].sample_word[fp] = htonl(sample_word);
 | 
				
			||||||
 | 
						if(++fp < 15) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nibble_word = 0;
 | 
				
			||||||
 | 
						fp = 0;
 | 
				
			||||||
 | 
						++frame_count;
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim2Encoder<T>::queue_packet(MSEEDEncoderPacket<Steim2Frame> &pckt) {
 | 
				
			||||||
 | 
						format->updateBuffer(pckt.record, _sampleCount, frame_count + (fp > 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Packet *packet = new Packet(DataRecordPtr(pckt.record), format->networkCode, format->stationCode,
 | 
				
			||||||
 | 
						                            format->locationCode, format->channelCode);
 | 
				
			||||||
 | 
						_packetQueue.push_back(PacketPtr(packet));
 | 
				
			||||||
 | 
						pckt.reset();
 | 
				
			||||||
 | 
						reset();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim2Encoder<T>::push(void *value) {
 | 
				
			||||||
 | 
						int32_t sample_val = *static_cast<T*>(value);
 | 
				
			||||||
 | 
						store(sample_val);
 | 
				
			||||||
 | 
						_clk.tick();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ( bp >= spw ) {
 | 
				
			||||||
 | 
							if( !current_packet.valid() ) {
 | 
				
			||||||
 | 
								current_packet = get_packet();
 | 
				
			||||||
 | 
								init_packet();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							update_packet();
 | 
				
			||||||
 | 
							if ( frame_count == number_of_frames(current_packet) ) {
 | 
				
			||||||
 | 
								finish_packet();
 | 
				
			||||||
 | 
								queue_packet(current_packet);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void Steim2Encoder<T>::flush() {
 | 
				
			||||||
 | 
						while ( bp ) {
 | 
				
			||||||
 | 
							if ( !current_packet.valid() ) {
 | 
				
			||||||
 | 
								current_packet = get_packet();
 | 
				
			||||||
 | 
								init_packet();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							update_packet();
 | 
				
			||||||
 | 
							if( frame_count == number_of_frames(current_packet) ) {
 | 
				
			||||||
 | 
								finish_packet();
 | 
				
			||||||
 | 
								queue_packet(current_packet);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( current_packet.valid() ) {
 | 
				
			||||||
 | 
							finish_packet();
 | 
				
			||||||
 | 
							queue_packet(current_packet);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										84
									
								
								libs/gempa/caps/mseed/uncompressed.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								libs/gempa/caps/mseed/uncompressed.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CAPS_MSEED_UNCOMPRESSED_H
 | 
				
			||||||
 | 
					#define CAPS_MSEED_UNCOMPRESSED_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "encoder.h"
 | 
				
			||||||
 | 
					#include "mseed.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/endianess.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> class UncompressedMSEED : public Encoder {
 | 
				
			||||||
 | 
						MSEEDEncoderPacket<T> get_packet() {
 | 
				
			||||||
 | 
							return _format->get_packet<T>(_clk.get_time(-_bp),
 | 
				
			||||||
 | 
							                              _clk.correction(), _timingQuality);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void queue_packet(MSEEDEncoderPacket<T> &pckt) {
 | 
				
			||||||
 | 
							_format->updateBuffer(pckt.record, _sampleCount, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Packet *packet = new Packet(DataRecordPtr(pckt.record), _format->networkCode, _format->stationCode,
 | 
				
			||||||
 | 
							                            _format->locationCode, _format->channelCode);
 | 
				
			||||||
 | 
							_packetQueue.push_back(PacketPtr(packet));
 | 
				
			||||||
 | 
							pckt.reset();
 | 
				
			||||||
 | 
							reset();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							UncompressedMSEED(MSEEDFormat *format, int freqn, int freqd)
 | 
				
			||||||
 | 
							    : Encoder(freqn, freqd),
 | 
				
			||||||
 | 
							      _format(format), _bp(0) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual ~UncompressedMSEED() { if ( _format ) delete _format; }
 | 
				
			||||||
 | 
							virtual void flush() {
 | 
				
			||||||
 | 
								if ( _current_packet.valid() ) {
 | 
				
			||||||
 | 
									queue_packet(_current_packet);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual void push(void *value) {
 | 
				
			||||||
 | 
								if ( !_current_packet.valid() )
 | 
				
			||||||
 | 
									_current_packet = get_packet();
 | 
				
			||||||
 | 
								else if ( _sampleCount * sizeof(T) >= _current_packet.datalen ) {
 | 
				
			||||||
 | 
									flush();
 | 
				
			||||||
 | 
									_current_packet = get_packet();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								_current_packet.data[_sampleCount] =
 | 
				
			||||||
 | 
								    Gempa::CAPS::Endianess::Converter::ToBigEndian<T>(*(T*)value);
 | 
				
			||||||
 | 
								++_sampleCount;
 | 
				
			||||||
 | 
								++_bp;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual int type() const { return _format->packType; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							MSEEDFormat               *_format;
 | 
				
			||||||
 | 
							MSEEDEncoderPacket<T>      _current_packet;
 | 
				
			||||||
 | 
							int                        _bp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __STEIM1_H__
 | 
				
			||||||
							
								
								
									
										491
									
								
								libs/gempa/caps/mseedpacket.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										491
									
								
								libs/gempa/caps/mseedpacket.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,491 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/mseedpacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					#include <streambuf>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <libmseed.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_SID(FUNC, format,...)\
 | 
				
			||||||
 | 
					do {\
 | 
				
			||||||
 | 
						char n[6];\
 | 
				
			||||||
 | 
						char s[6];\
 | 
				
			||||||
 | 
						char c[6];\
 | 
				
			||||||
 | 
						char l[6];\
 | 
				
			||||||
 | 
						ms_strncpclean(n, head.network, 2);\
 | 
				
			||||||
 | 
						ms_strncpclean(s, head.station, 5);\
 | 
				
			||||||
 | 
						ms_strncpclean(l, head.location, 2);\
 | 
				
			||||||
 | 
						ms_strncpclean(c, head.channel, 3);\
 | 
				
			||||||
 | 
						FUNC("[%s.%s.%s.%s] " format, n, s, l, c, ##__VA_ARGS__);\
 | 
				
			||||||
 | 
					} while(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MSEEDDataRecord::MSEEDDataRecord() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *MSEEDDataRecord::formatName() const {
 | 
				
			||||||
 | 
						return "MSEED";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MSEEDDataRecord::readMetaData(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
					                                   Header &header,
 | 
				
			||||||
 | 
					                                   Time &startTime,
 | 
				
			||||||
 | 
					                                   Time &endTime) {
 | 
				
			||||||
 | 
					#if 1 // Set this to 1 to enable no-malloc fast MSeed meta parser
 | 
				
			||||||
 | 
						fsdh_s head;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( size <= 0 ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("read metadata: invalid size of record: %d", size);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( size < MINRECLEN || size > MAXRECLEN ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("read metadata: invalid MSEED record size: %d", size);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read first 32 byte
 | 
				
			||||||
 | 
						size_t read = buf.sgetn((char*)&head, sizeof(head));
 | 
				
			||||||
 | 
						if ( read < sizeof(head) ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("read metadata: input buffer underflow: only %d/%d bytes read",
 | 
				
			||||||
 | 
							             (int)read, (int)sizeof(head));
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !MS_ISVALIDHEADER(((char*)&head)) ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("read metadata: invalid MSEED header");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool headerswapflag = false;
 | 
				
			||||||
 | 
						if ( !MS_ISVALIDYEARDAY(head.start_time.year, head.start_time.day) )
 | 
				
			||||||
 | 
							headerswapflag = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Swap byte order? */
 | 
				
			||||||
 | 
						if ( headerswapflag ) {
 | 
				
			||||||
 | 
							MS_SWAPBTIME(&head.start_time);
 | 
				
			||||||
 | 
							ms_gswap2a(&head.numsamples);
 | 
				
			||||||
 | 
							ms_gswap2a(&head.samprate_fact);
 | 
				
			||||||
 | 
							ms_gswap2a(&head.samprate_mult);
 | 
				
			||||||
 | 
							ms_gswap4a(&head.time_correct);
 | 
				
			||||||
 | 
							ms_gswap2a(&head.data_offset);
 | 
				
			||||||
 | 
							ms_gswap2a(&head.blockette_offset);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						header.dataType = DT_Unknown;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hptime_t hptime = ms_btime2hptime(&head.start_time);
 | 
				
			||||||
 | 
						if ( hptime == HPTERROR ) {
 | 
				
			||||||
 | 
							LOG_SID(CAPS_DEBUG, "read metadata: invalid start time");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						header.quality.ID = 0;
 | 
				
			||||||
 | 
						header.quality.str[0] = head.dataquality;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( head.time_correct != 0 && !(head.act_flags & 0x02) )
 | 
				
			||||||
 | 
							hptime += (hptime_t)head.time_correct * (HPTMODULUS / 10000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Parse blockettes
 | 
				
			||||||
 | 
						uint32_t blkt_offset = head.blockette_offset;
 | 
				
			||||||
 | 
						uint32_t blkt_length;
 | 
				
			||||||
 | 
						uint16_t blkt_type;
 | 
				
			||||||
 | 
						uint16_t next_blkt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( blkt_offset < sizeof(head) ) {
 | 
				
			||||||
 | 
							LOG_SID(CAPS_DEBUG, "read metadata: blockette "
 | 
				
			||||||
 | 
							        "offset points into header");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint32_t coffs = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ( (blkt_offset != 0) && ((int)blkt_offset < size) &&
 | 
				
			||||||
 | 
						        (blkt_offset < MAXRECLEN) ) {
 | 
				
			||||||
 | 
							char bhead[6];
 | 
				
			||||||
 | 
							int seek_ofs = blkt_offset-sizeof(head)-coffs;
 | 
				
			||||||
 | 
							buf.pubseekoff(seek_ofs, std::ios_base::cur, std::ios_base::in);
 | 
				
			||||||
 | 
							coffs += seek_ofs;
 | 
				
			||||||
 | 
							if ( buf.sgetn(bhead, 6) != 6 ) {
 | 
				
			||||||
 | 
								LOG_SID(CAPS_DEBUG, "read metadata: "
 | 
				
			||||||
 | 
								        "failed to read blockette header");
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							coffs += 6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							memcpy(&blkt_type, bhead, 2);
 | 
				
			||||||
 | 
							memcpy(&next_blkt, bhead+2, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( headerswapflag ) {
 | 
				
			||||||
 | 
								ms_gswap2(&blkt_type);
 | 
				
			||||||
 | 
								ms_gswap2(&next_blkt);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							blkt_length = ms_blktlen(blkt_type, bhead, headerswapflag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( blkt_length == 0 ) {
 | 
				
			||||||
 | 
								LOG_SID(CAPS_DEBUG, "read metadata: "
 | 
				
			||||||
 | 
								        "unknown blockette length for type %d",
 | 
				
			||||||
 | 
								        blkt_type);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Make sure blockette is contained within the msrecord buffer */
 | 
				
			||||||
 | 
							if ( (int)(blkt_offset - 4 + blkt_length) > size ) {
 | 
				
			||||||
 | 
								LOG_SID(CAPS_DEBUG, "read metadata: blockette "
 | 
				
			||||||
 | 
								        "%d extends beyond record size, truncated?",
 | 
				
			||||||
 | 
								        blkt_type);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( blkt_type == 1000 ) {
 | 
				
			||||||
 | 
								switch ( (int)bhead[4] ) {
 | 
				
			||||||
 | 
									case DE_ASCII:
 | 
				
			||||||
 | 
										header.dataType = DT_INT8;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									case DE_INT16:
 | 
				
			||||||
 | 
										header.dataType = DT_INT16;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									case DE_INT32:
 | 
				
			||||||
 | 
									case DE_STEIM1:
 | 
				
			||||||
 | 
									case DE_STEIM2:
 | 
				
			||||||
 | 
									case DE_CDSN:
 | 
				
			||||||
 | 
									case DE_DWWSSN:
 | 
				
			||||||
 | 
									case DE_SRO:
 | 
				
			||||||
 | 
										header.dataType = DT_INT32;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									case DE_FLOAT32:
 | 
				
			||||||
 | 
										header.dataType = DT_FLOAT;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									case DE_FLOAT64:
 | 
				
			||||||
 | 
										header.dataType = DT_DOUBLE;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									case DE_GEOSCOPE24:
 | 
				
			||||||
 | 
									case DE_GEOSCOPE163:
 | 
				
			||||||
 | 
									case DE_GEOSCOPE164:
 | 
				
			||||||
 | 
										header.dataType = DT_FLOAT;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									default:
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if ( blkt_type == 1001 ) {
 | 
				
			||||||
 | 
								// Add usec correction
 | 
				
			||||||
 | 
								hptime += ((hptime_t)bhead[5]) * (HPTMODULUS / 1000000);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Check that the next blockette offset is beyond the current blockette */
 | 
				
			||||||
 | 
							if ( next_blkt && next_blkt < (blkt_offset + blkt_length - 4) ) {
 | 
				
			||||||
 | 
								LOG_SID(CAPS_DEBUG, "read metadata: offset to "
 | 
				
			||||||
 | 
								        "next blockette (%d) is within current blockette "
 | 
				
			||||||
 | 
								        "ending at byte %d",
 | 
				
			||||||
 | 
								        blkt_type, (blkt_offset + blkt_length - 4));
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							/* Check that the offset is within record length */
 | 
				
			||||||
 | 
							else if ( next_blkt && next_blkt > size ) {
 | 
				
			||||||
 | 
								LOG_SID(CAPS_DEBUG, "read metadata: offset to "
 | 
				
			||||||
 | 
								        "next blockette (%d) from type %d is beyond record "
 | 
				
			||||||
 | 
								        "length", next_blkt, blkt_type);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								blkt_offset = next_blkt;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						startTime = Time((hptime_t)hptime/HPTMODULUS,(hptime_t)hptime%HPTMODULUS);
 | 
				
			||||||
 | 
						endTime = startTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( head.samprate_fact > 0 ) {
 | 
				
			||||||
 | 
							header.samplingFrequencyNumerator = head.samprate_fact;
 | 
				
			||||||
 | 
							header.samplingFrequencyDenominator = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							header.samplingFrequencyNumerator = 1;
 | 
				
			||||||
 | 
							header.samplingFrequencyDenominator = -head.samprate_fact;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( head.samprate_mult > 0 )
 | 
				
			||||||
 | 
							header.samplingFrequencyNumerator *= head.samprate_mult;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							header.samplingFrequencyDenominator *= -head.samprate_mult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( header.samplingFrequencyNumerator > 0.0 && head.numsamples > 0 ) {
 | 
				
			||||||
 | 
							hptime = (hptime_t)head.numsamples * HPTMODULUS * header.samplingFrequencyDenominator / header.samplingFrequencyNumerator;
 | 
				
			||||||
 | 
							endTime += TimeSpan((hptime_t)hptime/HPTMODULUS,(hptime_t)hptime%HPTMODULUS);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						timeToTimestamp(_header.samplingTime, startTime);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						std::vector<char> data(size);
 | 
				
			||||||
 | 
						size_t read = buf.sgetn(&data[0], data.size());
 | 
				
			||||||
 | 
						if ( read != data.size() ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("read metadata: input buffer underflow: only %d/%d bytes read",
 | 
				
			||||||
 | 
							                 (int)read, (int)data.size());
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unpackHeader(&data[0], data.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						header = _header;
 | 
				
			||||||
 | 
						startTime = _startTime;
 | 
				
			||||||
 | 
						endTime = _endTime;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DataRecord::Header *MSEEDDataRecord::header() const {
 | 
				
			||||||
 | 
						return &_header;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Time MSEEDDataRecord::startTime() const {
 | 
				
			||||||
 | 
						return _startTime;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Time MSEEDDataRecord::endTime() const {
 | 
				
			||||||
 | 
						return _endTime;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MSEEDDataRecord::canTrim() const {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MSEEDDataRecord::canMerge() const {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MSEEDDataRecord::trim(const Time &start,
 | 
				
			||||||
 | 
					                           const Time &end) const {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t MSEEDDataRecord::dataSize(bool /*withHeader*/) const {
 | 
				
			||||||
 | 
						return _data.size();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DataRecord::ReadStatus MSEEDDataRecord::get(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
					                                            const Time &start,
 | 
				
			||||||
 | 
					                                            const Time &end,
 | 
				
			||||||
 | 
					                                            int) {
 | 
				
			||||||
 | 
						//MSRecord *ms_rec = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( size <= 0 ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("get: invalid size of record: %d", size);
 | 
				
			||||||
 | 
							return RS_Error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_data.resize(size);
 | 
				
			||||||
 | 
						size_t read = buf.sgetn(&_data[0], _data.size());
 | 
				
			||||||
 | 
						if ( read != _data.size() ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("get: input buffer underflow: only %d/%d bytes read",
 | 
				
			||||||
 | 
							             (int)read, (int)_data.size());
 | 
				
			||||||
 | 
							return RS_Error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						arraybuf tmp(&_data[0], size);
 | 
				
			||||||
 | 
						readMetaData(tmp, size, _header, _startTime, _endTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( start.valid() || end.valid() ) {
 | 
				
			||||||
 | 
							// Out of scope?
 | 
				
			||||||
 | 
							if ( end.valid() && (end <= _startTime) )
 | 
				
			||||||
 | 
								return RS_AfterTimeWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( start.valid() && (start >= _endTime) )
 | 
				
			||||||
 | 
								return RS_BeforeTimeWindow;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return RS_Complete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						// Only unpack the header structure
 | 
				
			||||||
 | 
						int state = msr_unpack(&_data[0], _data.size(), &ms_rec, 0, 0);
 | 
				
			||||||
 | 
						if ( state != MS_NOERROR ) {
 | 
				
			||||||
 | 
							switch ( state ) {
 | 
				
			||||||
 | 
								case MS_GENERROR:
 | 
				
			||||||
 | 
									CAPS_WARNING("get: generic libmseed error");
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case MS_NOTSEED:
 | 
				
			||||||
 | 
									CAPS_WARNING("get: input data is not seed");
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case MS_WRONGLENGTH:
 | 
				
			||||||
 | 
									CAPS_WARNING("get: length of data read was not correct");
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case MS_OUTOFRANGE:
 | 
				
			||||||
 | 
									CAPS_WARNING("get: SEED record length out of range");
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case MS_UNKNOWNFORMAT:
 | 
				
			||||||
 | 
									CAPS_WARNING("get: unknown data encoding format");
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case MS_STBADCOMPFLAG:
 | 
				
			||||||
 | 
									CAPS_WARNING("get: invalid Steim compression flag(s)");
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ( ms_rec != NULL )
 | 
				
			||||||
 | 
								msr_free(&ms_rec);
 | 
				
			||||||
 | 
							return RS_Error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hptime_t hptime = msr_starttime(ms_rec);
 | 
				
			||||||
 | 
						_startTime = Time((hptime_t)hptime/HPTMODULUS,(hptime_t)hptime%HPTMODULUS);
 | 
				
			||||||
 | 
						_endTime = _startTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( ms_rec->samprate > 0.0 && ms_rec->samplecnt > 0 ) {
 | 
				
			||||||
 | 
							hptime = (hptime_t)(((double)(ms_rec->samplecnt) / ms_rec->samprate * HPTMODULUS) + 0.5);
 | 
				
			||||||
 | 
							_endTime += TimeSpan((hptime_t)hptime/HPTMODULUS,(hptime_t)hptime%HPTMODULUS);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_header.dataType = DT_Unknown;
 | 
				
			||||||
 | 
						timeToTimestamp(_header.samplingTime, _startTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( ms_rec->fsdh->samprate_fact > 0 ) {
 | 
				
			||||||
 | 
							_header.samplingFrequencyNumerator = ms_rec->fsdh->samprate_fact;
 | 
				
			||||||
 | 
							_header.samplingFrequencyDenominator = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							_header.samplingFrequencyNumerator = 1;
 | 
				
			||||||
 | 
							_header.samplingFrequencyDenominator = -ms_rec->fsdh->samprate_fact;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( ms_rec->fsdh->samprate_mult > 0 )
 | 
				
			||||||
 | 
							_header.samplingFrequencyNumerator *= ms_rec->fsdh->samprate_mult;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							_header.samplingFrequencyDenominator *= -ms_rec->fsdh->samprate_mult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch ( ms_rec->sampletype ) {
 | 
				
			||||||
 | 
							case 'a':
 | 
				
			||||||
 | 
								_header.dataType = DT_INT8;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'i':
 | 
				
			||||||
 | 
								_header.dataType = DT_INT32;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'f':
 | 
				
			||||||
 | 
								_header.dataType = DT_FLOAT;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'd':
 | 
				
			||||||
 | 
								_header.dataType = DT_DOUBLE;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								_header.dataType = DT_Unknown;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msr_free(&ms_rec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( start.valid() || end.valid() ) {
 | 
				
			||||||
 | 
							// Out of scope?
 | 
				
			||||||
 | 
							if ( end.valid() && (end <= _startTime) )
 | 
				
			||||||
 | 
								return RS_AfterTimeWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( start.valid() && (start >= _endTime) )
 | 
				
			||||||
 | 
								return RS_BeforeTimeWindow;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return RS_Complete;
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MSEEDDataRecord::put(std::streambuf &buf, bool /*withHeader*/) const {
 | 
				
			||||||
 | 
						return buf.sputn(&_data[0], _data.size()) == (int)_data.size();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MSEEDDataRecord::setData(const void *data, size_t size) {
 | 
				
			||||||
 | 
						_data.resize(size);
 | 
				
			||||||
 | 
						memcpy(_data.data(), data, size);
 | 
				
			||||||
 | 
						unpackHeader();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MSEEDDataRecord::unpackHeader(char *data, size_t size) {
 | 
				
			||||||
 | 
						// Only unpack the header structure
 | 
				
			||||||
 | 
						MSRecord *ms_rec = NULL;
 | 
				
			||||||
 | 
						int state = msr_unpack(data, size, &ms_rec, 0, 0);
 | 
				
			||||||
 | 
						if ( state != MS_NOERROR ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("read metadata: read error: %d", state);
 | 
				
			||||||
 | 
							if ( ms_rec != NULL )
 | 
				
			||||||
 | 
								msr_free(&ms_rec);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hptime_t hptime = msr_starttime(ms_rec);
 | 
				
			||||||
 | 
						_startTime = Time((hptime_t)hptime/HPTMODULUS,(hptime_t)hptime%HPTMODULUS);
 | 
				
			||||||
 | 
						_endTime = _startTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( ms_rec->samprate > 0.0 && ms_rec->samplecnt > 0 ) {
 | 
				
			||||||
 | 
							hptime = (hptime_t)(((double)(ms_rec->samplecnt) / ms_rec->samprate * HPTMODULUS) + 0.5);
 | 
				
			||||||
 | 
							_endTime += TimeSpan((hptime_t)hptime/HPTMODULUS,(hptime_t)hptime%HPTMODULUS);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_header.dataType = DT_Unknown;
 | 
				
			||||||
 | 
						timeToTimestamp(_header.samplingTime, _startTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( ms_rec->fsdh->samprate_fact > 0 ) {
 | 
				
			||||||
 | 
							_header.samplingFrequencyNumerator = ms_rec->fsdh->samprate_fact;
 | 
				
			||||||
 | 
							_header.samplingFrequencyDenominator = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							_header.samplingFrequencyNumerator = 1;
 | 
				
			||||||
 | 
							_header.samplingFrequencyDenominator = -ms_rec->fsdh->samprate_fact;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( ms_rec->fsdh->samprate_mult > 0 )
 | 
				
			||||||
 | 
							_header.samplingFrequencyNumerator *= ms_rec->fsdh->samprate_mult;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							_header.samplingFrequencyDenominator *= -ms_rec->fsdh->samprate_mult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch ( ms_rec->sampletype ) {
 | 
				
			||||||
 | 
							case 'a':
 | 
				
			||||||
 | 
								_header.dataType = DT_INT8;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'i':
 | 
				
			||||||
 | 
								_header.dataType = DT_INT32;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'f':
 | 
				
			||||||
 | 
								_header.dataType = DT_FLOAT;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'd':
 | 
				
			||||||
 | 
								_header.dataType = DT_DOUBLE;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								_header.dataType = DT_Unknown;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msr_free(&ms_rec);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										92
									
								
								libs/gempa/caps/mseedpacket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								libs/gempa/caps/mseedpacket.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_MSEEDPACKET_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_MSEEDPACKET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MSEEDDataRecord : public DataRecord {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							MSEEDDataRecord();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual const char *formatName() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool readMetaData(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                          Header &header,
 | 
				
			||||||
 | 
							                          Time &startTime,
 | 
				
			||||||
 | 
							                          Time &endTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual const Header *header() const;
 | 
				
			||||||
 | 
							virtual Time startTime() const;
 | 
				
			||||||
 | 
							virtual Time endTime() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool canTrim() const;
 | 
				
			||||||
 | 
							virtual bool canMerge() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool trim(const Time &start,
 | 
				
			||||||
 | 
							                  const Time &end) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual size_t dataSize(bool withHeader) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual ReadStatus get(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                       const Time &start = Time(),
 | 
				
			||||||
 | 
							                       const Time &end = Time(),
 | 
				
			||||||
 | 
							                       int maxSize = -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool put(std::streambuf &buf, bool withHeader) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns the packet type
 | 
				
			||||||
 | 
							 * @return The packet type
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							PacketType packetType() const { return MSEEDPacket; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Initializes the internal data vector from the given buffer
 | 
				
			||||||
 | 
							 * @param The buffer to read the data from
 | 
				
			||||||
 | 
							 * @param The buffer size
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual void setData(const void *data, size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void unpackHeader() { unpackHeader(_data.data(), _data.size()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							Header               _header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Time                 _startTime;
 | 
				
			||||||
 | 
							Time                 _endTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int                  _dataType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							void unpackHeader(char *data, size_t size);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										125
									
								
								libs/gempa/caps/packet.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								libs/gempa/caps/packet.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,125 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool PacketDataHeader::setUOM(const char *type) {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( type != NULL ) {
 | 
				
			||||||
 | 
							for ( i = 0; i < 4; ++i ) {
 | 
				
			||||||
 | 
								if ( type[i] == '\0' ) break;
 | 
				
			||||||
 | 
								unitOfMeasurement.str[i] = type[i];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Input type must not have more than 4 characters
 | 
				
			||||||
 | 
							if ( i == 3 && type[i] != '\0' && type[i+1] != '\0' ) {
 | 
				
			||||||
 | 
								memset(unitOfMeasurement.str, '\0', 4);
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Pad with null bytes
 | 
				
			||||||
 | 
						for ( ; i < 4; ++i )
 | 
				
			||||||
 | 
							unitOfMeasurement.str[i] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string PacketDataHeader::uom(char fill) const {
 | 
				
			||||||
 | 
						std::string s;
 | 
				
			||||||
 | 
						for ( int i = 0; i < 4; ++i ) {
 | 
				
			||||||
 | 
							if ( unitOfMeasurement.str[i] == '\0' ) break;
 | 
				
			||||||
 | 
							s += unitOfMeasurement.str[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( s.size() < 4 && fill != '\0' ) {
 | 
				
			||||||
 | 
							for ( int i = s.size(); i < 4; ++i )
 | 
				
			||||||
 | 
								s += fill;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool PacketDataHeader::operator!=(const PacketDataHeader &other) const {
 | 
				
			||||||
 | 
						return version != other.version ||
 | 
				
			||||||
 | 
						       packetType != other.packetType ||
 | 
				
			||||||
 | 
						       unitOfMeasurement.ID != other.unitOfMeasurement.ID;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool PacketDataHeaderV2::operator!=(const PacketDataHeaderV2 &other) const {
 | 
				
			||||||
 | 
						return PacketDataHeader::operator!=(other) ||
 | 
				
			||||||
 | 
						       samplingFrequencyNumerator != other.samplingFrequencyNumerator ||
 | 
				
			||||||
 | 
						       samplingFrequencyDenominator != other.samplingFrequencyDenominator ||
 | 
				
			||||||
 | 
						       quality.ID != other.quality.ID;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool DataRecord::Header::put(std::streambuf &buf) const {
 | 
				
			||||||
 | 
						Endianess::Writer put(buf);
 | 
				
			||||||
 | 
						char dt = (char)dataType;
 | 
				
			||||||
 | 
						put(dt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						put(samplingTime.year);
 | 
				
			||||||
 | 
						put(samplingTime.yday);
 | 
				
			||||||
 | 
						put(samplingTime.hour);
 | 
				
			||||||
 | 
						put(samplingTime.minute);
 | 
				
			||||||
 | 
						put(samplingTime.second);
 | 
				
			||||||
 | 
						put(samplingTime.usec);
 | 
				
			||||||
 | 
						put(samplingFrequencyNumerator);
 | 
				
			||||||
 | 
						put(samplingFrequencyDenominator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return put.good;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void DataRecord::Header::setSamplingTime(const Time &ts) {
 | 
				
			||||||
 | 
						int year, yday, hour, min, sec, usec;
 | 
				
			||||||
 | 
						ts.get2(&year, &yday, &hour, &min, &sec, &usec);
 | 
				
			||||||
 | 
						samplingTime.year = year;
 | 
				
			||||||
 | 
						samplingTime.yday = yday;
 | 
				
			||||||
 | 
						samplingTime.hour = hour;
 | 
				
			||||||
 | 
						samplingTime.minute = min;
 | 
				
			||||||
 | 
						samplingTime.second = sec;
 | 
				
			||||||
 | 
						samplingTime.usec = usec;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool DataRecord::Header::compatible(const Header &other) const {
 | 
				
			||||||
 | 
						return dataType == other.dataType &&
 | 
				
			||||||
 | 
						       samplingFrequencyNumerator == other.samplingFrequencyNumerator &&
 | 
				
			||||||
 | 
						       samplingFrequencyDenominator == other.samplingFrequencyDenominator;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool DataRecord::Header::operator!=(const Header &other) const {
 | 
				
			||||||
 | 
						return dataType != other.dataType ||
 | 
				
			||||||
 | 
						       samplingFrequencyNumerator != other.samplingFrequencyNumerator ||
 | 
				
			||||||
 | 
						       samplingFrequencyDenominator != other.samplingFrequencyDenominator;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DataRecord::~DataRecord() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										420
									
								
								libs/gempa/caps/packet.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										420
									
								
								libs/gempa/caps/packet.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,420 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_PACKET_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_PACKET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/api.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/endianess.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/datetime.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <boost/shared_ptr.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum PacketType {
 | 
				
			||||||
 | 
						UnknownPacket = 0,
 | 
				
			||||||
 | 
						RawDataPacket,
 | 
				
			||||||
 | 
						MSEEDPacket,
 | 
				
			||||||
 | 
						ANYPacket,
 | 
				
			||||||
 | 
						RTCM2Packet,
 | 
				
			||||||
 | 
						MetaDataPacket,
 | 
				
			||||||
 | 
						FixedRawDataPacket,
 | 
				
			||||||
 | 
						PacketTypeCount
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum DataType {
 | 
				
			||||||
 | 
						DT_Unknown = 0,
 | 
				
			||||||
 | 
						DT_DOUBLE  = 1,
 | 
				
			||||||
 | 
						DT_FLOAT   = 2,
 | 
				
			||||||
 | 
						DT_INT64   = 100,
 | 
				
			||||||
 | 
						DT_INT32   = 101,
 | 
				
			||||||
 | 
						DT_INT16   = 102,
 | 
				
			||||||
 | 
						DT_INT8    = 103
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					union UOM {
 | 
				
			||||||
 | 
						char    str[4];
 | 
				
			||||||
 | 
						int32_t ID;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					union Quality {
 | 
				
			||||||
 | 
						char    str[4];
 | 
				
			||||||
 | 
						int32_t ID;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API TimeStamp {
 | 
				
			||||||
 | 
						int16_t  year;   /* year, eg. 2003                   */
 | 
				
			||||||
 | 
						uint16_t yday;   /* day of year (1-366)              */
 | 
				
			||||||
 | 
						uint8_t  hour;   /* hour (0-23)                      */
 | 
				
			||||||
 | 
						uint8_t  minute; /* minute (0-59)                    */
 | 
				
			||||||
 | 
						uint8_t  second; /* second (0-59), 60 if leap second */
 | 
				
			||||||
 | 
						uint8_t  unused; /* unused byte */
 | 
				
			||||||
 | 
						int32_t  usec;   /* microsecond (0-999999)           */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API PacketDataHeader {
 | 
				
			||||||
 | 
						PacketDataHeader()
 | 
				
			||||||
 | 
						: version(1), packetType(UnknownPacket) {
 | 
				
			||||||
 | 
							unitOfMeasurement.ID = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PacketDataHeader(uint16_t version)
 | 
				
			||||||
 | 
						: version(version)
 | 
				
			||||||
 | 
						, packetType(UnknownPacket) {
 | 
				
			||||||
 | 
							unitOfMeasurement.ID = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint16_t   version;
 | 
				
			||||||
 | 
						PacketType packetType;
 | 
				
			||||||
 | 
						UOM        unitOfMeasurement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool setUOM(const char *type);
 | 
				
			||||||
 | 
						std::string uom(char fill = '\0') const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool operator!=(const PacketDataHeader &other) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int dataSize() const {
 | 
				
			||||||
 | 
							return sizeof(version) + sizeof((char)packetType) +
 | 
				
			||||||
 | 
							       sizeof(unitOfMeasurement.ID);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool put(std::streambuf &buf) const {
 | 
				
			||||||
 | 
							Endianess::Writer put(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							char type = char(packetType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							put(version);
 | 
				
			||||||
 | 
							put(type);
 | 
				
			||||||
 | 
							put(unitOfMeasurement.ID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return put.good;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool get(std::streambuf &buf) {
 | 
				
			||||||
 | 
							Endianess::Reader get(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							char type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							get(version);
 | 
				
			||||||
 | 
							get(type); packetType = PacketType(type);
 | 
				
			||||||
 | 
							get(unitOfMeasurement.ID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return get.good;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API PacketDataHeaderV2 : PacketDataHeader {
 | 
				
			||||||
 | 
						PacketDataHeaderV2()
 | 
				
			||||||
 | 
						: PacketDataHeader(2)
 | 
				
			||||||
 | 
						, samplingFrequencyNumerator(0)
 | 
				
			||||||
 | 
						, samplingFrequencyDenominator(0) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint16_t   samplingFrequencyNumerator;
 | 
				
			||||||
 | 
						uint16_t   samplingFrequencyDenominator;
 | 
				
			||||||
 | 
						Quality    quality;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool operator!=(const PacketDataHeaderV2 &other) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int dataSize() const {
 | 
				
			||||||
 | 
							return PacketDataHeader::dataSize() +
 | 
				
			||||||
 | 
							       sizeof(samplingFrequencyNumerator) +
 | 
				
			||||||
 | 
							       sizeof(samplingFrequencyDenominator) +
 | 
				
			||||||
 | 
							       sizeof(quality);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool put(std::streambuf &buf) const {
 | 
				
			||||||
 | 
							Endianess::Writer put(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PacketDataHeader::put(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							put(samplingFrequencyNumerator);
 | 
				
			||||||
 | 
							put(samplingFrequencyDenominator);
 | 
				
			||||||
 | 
							put(quality);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return put.good;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool get(std::streambuf &buf) {
 | 
				
			||||||
 | 
							Endianess::Reader get(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PacketDataHeader::get(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							get(samplingFrequencyNumerator);
 | 
				
			||||||
 | 
							get(samplingFrequencyDenominator);
 | 
				
			||||||
 | 
							get(quality);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return get.good;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum StreamIDComponent {
 | 
				
			||||||
 | 
						NetworkCode  = 0,
 | 
				
			||||||
 | 
						StationCode  = 1,
 | 
				
			||||||
 | 
						LocationCode = 2,
 | 
				
			||||||
 | 
						ChannelCode  = 3,
 | 
				
			||||||
 | 
						StreamIDComponentSize
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API PacketHeaderV1 {
 | 
				
			||||||
 | 
						uint8_t          SIDSize[4]; /* number of bytes of stream ID components */
 | 
				
			||||||
 | 
						uint16_t         size;   /* number of data bytes */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool put(std::streambuf &buf) {
 | 
				
			||||||
 | 
							Endianess::Writer put(buf);
 | 
				
			||||||
 | 
							for ( int i = 0; i < 4; ++i )
 | 
				
			||||||
 | 
								put(SIDSize[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							put(size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return put.good;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t dataSize() const {
 | 
				
			||||||
 | 
							return sizeof(uint8_t) * 4  + sizeof(size);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API PacketHeaderV2 {
 | 
				
			||||||
 | 
						uint8_t          SIDSize[4]; /* number of bytes of stream ID components */
 | 
				
			||||||
 | 
						uint32_t         size;   /* number of data bytes */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool put(std::streambuf &buf) {
 | 
				
			||||||
 | 
							Endianess::Writer put(buf);
 | 
				
			||||||
 | 
							for ( int i = 0; i < 4; ++i )
 | 
				
			||||||
 | 
								put(SIDSize[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							put(size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return put.good;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						size_t dataSize() const {
 | 
				
			||||||
 | 
							return sizeof(uint8_t) * 4  + sizeof(size);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API ResponseHeader {
 | 
				
			||||||
 | 
						uint16_t id;
 | 
				
			||||||
 | 
						int32_t  size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool get(std::streambuf &buf) {
 | 
				
			||||||
 | 
							Endianess::Reader get(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							get(id);
 | 
				
			||||||
 | 
							get(size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return get.good;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SC_GEMPA_CAPS_API DataRecord {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							typedef std::vector<char> Buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct Header {
 | 
				
			||||||
 | 
								DataType   dataType{DT_Unknown};
 | 
				
			||||||
 | 
								TimeStamp  samplingTime;
 | 
				
			||||||
 | 
								uint16_t   samplingFrequencyNumerator;
 | 
				
			||||||
 | 
								uint16_t   samplingFrequencyDenominator;
 | 
				
			||||||
 | 
								Quality    quality{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Header() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bool get(std::streambuf &buf) {
 | 
				
			||||||
 | 
									Endianess::Reader get(buf);
 | 
				
			||||||
 | 
									char dt;
 | 
				
			||||||
 | 
									get(dt);
 | 
				
			||||||
 | 
									dataType = (DataType)dt;
 | 
				
			||||||
 | 
									quality.ID = 0; // Quality is not yet part of the header stream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									get(samplingTime.year);
 | 
				
			||||||
 | 
									get(samplingTime.yday);
 | 
				
			||||||
 | 
									get(samplingTime.hour);
 | 
				
			||||||
 | 
									get(samplingTime.minute);
 | 
				
			||||||
 | 
									get(samplingTime.second);
 | 
				
			||||||
 | 
									get(samplingTime.usec);
 | 
				
			||||||
 | 
									get(samplingFrequencyNumerator);
 | 
				
			||||||
 | 
									get(samplingFrequencyDenominator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return get.good;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bool put(std::streambuf &buf) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								int dataSize() const {
 | 
				
			||||||
 | 
									return sizeof(samplingTime.year) +
 | 
				
			||||||
 | 
									       sizeof(samplingTime.yday) +
 | 
				
			||||||
 | 
									       sizeof(samplingTime.hour) +
 | 
				
			||||||
 | 
									       sizeof(samplingTime.minute) +
 | 
				
			||||||
 | 
									       sizeof(samplingTime.second) +
 | 
				
			||||||
 | 
									       sizeof(samplingTime.usec) +
 | 
				
			||||||
 | 
									       sizeof(samplingFrequencyNumerator) +
 | 
				
			||||||
 | 
									       sizeof(samplingFrequencyDenominator) +
 | 
				
			||||||
 | 
									       sizeof(char);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bool compatible(const Header &other) const;
 | 
				
			||||||
 | 
								bool operator!=(const Header &other) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								void setSamplingTime(const Time ×tamp);
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							enum ReadStatusCode {
 | 
				
			||||||
 | 
								RS_Error = 0,
 | 
				
			||||||
 | 
								RS_Complete = 1,
 | 
				
			||||||
 | 
								RS_Partial = 2,
 | 
				
			||||||
 | 
								RS_BeforeTimeWindow = 3,
 | 
				
			||||||
 | 
								RS_AfterTimeWindow = 4,
 | 
				
			||||||
 | 
								RS_Max
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							class ReadStatus {
 | 
				
			||||||
 | 
								public:
 | 
				
			||||||
 | 
									ReadStatus() {}
 | 
				
			||||||
 | 
									ReadStatus(ReadStatusCode code) : _code(code) {}
 | 
				
			||||||
 | 
									ReadStatus(const ReadStatus &other) : _code(other._code) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								public:
 | 
				
			||||||
 | 
									ReadStatus &operator=(const ReadStatus &other) { _code = other._code; return *this; }
 | 
				
			||||||
 | 
									operator ReadStatusCode() const { return _code; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								private:
 | 
				
			||||||
 | 
									operator bool() { return _code != RS_Error; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								private:
 | 
				
			||||||
 | 
									ReadStatusCode _code;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							virtual ~DataRecord();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual const char *formatName() const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool readMetaData(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                          Header &header,
 | 
				
			||||||
 | 
							                          Time &startTime, Time &endTime) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns if data trimming is supported
 | 
				
			||||||
 | 
							virtual bool canTrim() const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns if data merging is possible without modifying
 | 
				
			||||||
 | 
							//! preceding data
 | 
				
			||||||
 | 
							virtual bool canMerge() const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Trims a record to start and end time. Trimming
 | 
				
			||||||
 | 
							//! should not modify any data but give access to trimmed
 | 
				
			||||||
 | 
							//! start and end times and the resulting data size. The trimming
 | 
				
			||||||
 | 
							//! also influences writing the record to a stream.
 | 
				
			||||||
 | 
							//! Trimming requires the resulting start time being greater
 | 
				
			||||||
 | 
							//! or equal than the requested start time.
 | 
				
			||||||
 | 
							//! (Un)Trimming to the original record is semantically
 | 
				
			||||||
 | 
							//! equal to passing an invalid start and end time.
 | 
				
			||||||
 | 
							//! It returns true if trimming has been done or false
 | 
				
			||||||
 | 
							//! if an error occured or trimming is not supported.
 | 
				
			||||||
 | 
							virtual bool trim(const Time &start, const Time &end) const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the data size in bytes if the current state would
 | 
				
			||||||
 | 
							//! be written to a stream. Trimming has also to be taken into
 | 
				
			||||||
 | 
							//! account while calculating the size.
 | 
				
			||||||
 | 
							virtual size_t dataSize(bool withHeader = true) const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Reads the packet from a streambuf and trims the data
 | 
				
			||||||
 | 
							//! if possible to start and end. If maxBytes is greater
 | 
				
			||||||
 | 
							//! than 0 then the record should not use more than this
 | 
				
			||||||
 | 
							//! size of memory (in bytes). If not the complete record
 | 
				
			||||||
 | 
							//! has been read, RS_Partial must be returned, RS_Complete
 | 
				
			||||||
 | 
							//! otherwise.
 | 
				
			||||||
 | 
							virtual ReadStatus get(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                       const Time &start = Time(), const Time &end = Time(),
 | 
				
			||||||
 | 
							                       int maxBytes = -1) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! writes the packet to a streambuf and trims the data
 | 
				
			||||||
 | 
							//! if possible to start and end
 | 
				
			||||||
 | 
							virtual bool put(std::streambuf &buf, bool withHeader = true) const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the meta information of the data if supported
 | 
				
			||||||
 | 
							virtual const Header *header() const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the start time of the record
 | 
				
			||||||
 | 
							virtual Time startTime() const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the end time of the record
 | 
				
			||||||
 | 
							virtual Time endTime() const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the packet type of the record
 | 
				
			||||||
 | 
							virtual PacketType packetType() const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns the data vector to be filled by the caller
 | 
				
			||||||
 | 
							 * @return The pointer to the internal buffer
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual Buffer *buffer() { return &_data; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns pointer to raw data. If the record
 | 
				
			||||||
 | 
							 * is compressed it will be uncompressed
 | 
				
			||||||
 | 
							 * @return The pointer to the raw data
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual Buffer *data() { return &_data; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							Buffer _data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef boost::shared_ptr<DataRecord> DataRecordPtr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct RawPacket {
 | 
				
			||||||
 | 
						PacketDataHeader  header;
 | 
				
			||||||
 | 
						std::string       SID[4];
 | 
				
			||||||
 | 
						std::vector<char> data;
 | 
				
			||||||
 | 
						DataRecord       *record;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct MetaPacket {
 | 
				
			||||||
 | 
						std::string        SID[4];
 | 
				
			||||||
 | 
						PacketDataHeader   packetDataHeader;
 | 
				
			||||||
 | 
						DataRecord        *record;
 | 
				
			||||||
 | 
						DataRecord::Header recordHeader;
 | 
				
			||||||
 | 
						Time               startTime;
 | 
				
			||||||
 | 
						Time               endTime;
 | 
				
			||||||
 | 
						Time               timestamp;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										1120
									
								
								libs/gempa/caps/plugin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1120
									
								
								libs/gempa/caps/plugin.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										324
									
								
								libs/gempa/caps/plugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										324
									
								
								libs/gempa/caps/plugin.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,324 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_PLUGIN_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_PLUGIN_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					// Enable/disable journal 
 | 
				
			||||||
 | 
					#define CAPS_FEATURES_JOURNAL     1
 | 
				
			||||||
 | 
					// Enable/disable backfilling of packets
 | 
				
			||||||
 | 
					#define CAPS_FEATURES_BACKFILLING 1
 | 
				
			||||||
 | 
					#define CAPS_FEATURES_SSL         1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Supportted CAPS packets
 | 
				
			||||||
 | 
					#define CAPS_FEATURES_ANY         1
 | 
				
			||||||
 | 
					#define CAPS_FEATURES_MSEED       1
 | 
				
			||||||
 | 
					#define CAPS_FEATURES_RAW         1
 | 
				
			||||||
 | 
					#define CAPS_FEATURES_RTCM2       1
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "encoderfactory.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/socket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/version.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/pluginpacket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <boost/function.hpp>
 | 
				
			||||||
 | 
					#include <boost/shared_ptr.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <deque>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SC_GEMPA_CAPS_API Plugin {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							enum Status {
 | 
				
			||||||
 | 
								Success,
 | 
				
			||||||
 | 
								PacketSize,        /* Packet is bigger than the buffer size */
 | 
				
			||||||
 | 
								PacketLoss,        /* The other end didn't acknowledge
 | 
				
			||||||
 | 
								                      transmitted data after some time */
 | 
				
			||||||
 | 
								PacketNotValid,    /* Read meta data failed*/
 | 
				
			||||||
 | 
								PacketNotSupported,
 | 
				
			||||||
 | 
								MaxFutureEndTimeExceeded
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct Stats {
 | 
				
			||||||
 | 
								Stats() : maxBytesBuffered(0) {}
 | 
				
			||||||
 | 
								size_t maxBytesBuffered;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							typedef std::vector<char>                       Buffer;
 | 
				
			||||||
 | 
							typedef boost::shared_ptr<Buffer>               BufferPtr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_BACKFILLING) || CAPS_FEATURES_BACKFILLING
 | 
				
			||||||
 | 
							typedef std::list<PacketPtr>                    BackfillingBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							struct StreamState {
 | 
				
			||||||
 | 
								Time              lastEndTime;
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_BACKFILLING) || CAPS_FEATURES_BACKFILLING
 | 
				
			||||||
 | 
								Time              lastCommitEndTime;
 | 
				
			||||||
 | 
								BackfillingBuffer backfillingBuffer;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							typedef std::map<std::string, StreamState>      StreamStates;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							typedef boost::function<void (const std::string &, const CAPS::Time &,
 | 
				
			||||||
 | 
							                              const CAPS::Time &)> PacketAckFunc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Plugin(const std::string &name, const std::string &options = "",
 | 
				
			||||||
 | 
							       const std::string &description = "");
 | 
				
			||||||
 | 
							~Plugin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void close();
 | 
				
			||||||
 | 
							void quit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void enableLogging();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_BACKFILLING) || CAPS_FEATURES_BACKFILLING
 | 
				
			||||||
 | 
							void setBackfillingBufferSize(int secs) { _backfillingBufferSize = secs; }
 | 
				
			||||||
 | 
							int backfillingBufferSize() const { return _backfillingBufferSize; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns whether the plugin has been
 | 
				
			||||||
 | 
							 *  requested to quit or not.
 | 
				
			||||||
 | 
							 * @return True, if the plugin has been requested to quit.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							bool isExitRequested() {
 | 
				
			||||||
 | 
								return _isExitRequested;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns the stat object
 | 
				
			||||||
 | 
							 * @return The stat object
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							const Stats& stats() const {
 | 
				
			||||||
 | 
								return _stats;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Resets the max bytes buffered counter
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							void resetMaxBytesBuffered() {
 | 
				
			||||||
 | 
								_stats.maxBytesBuffered = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Sets the encoder factory used to created encoders for packet
 | 
				
			||||||
 | 
							 *        encoding, e.g. miniSEED.
 | 
				
			||||||
 | 
							 * @param factory The ownership of the factory goes to the plugin and
 | 
				
			||||||
 | 
							 *        will be deleted if necessary.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							void setEncoderFactory(EncoderFactory *factory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setHost(const std::string &host) { _host = host; }
 | 
				
			||||||
 | 
							const std::string &host() const { return _host; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setPort(unsigned short port) { _port = port; }
 | 
				
			||||||
 | 
							unsigned short port() const { return _port; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setBufferSize(size_t bufferSize) { _bufferSize = bufferSize; }
 | 
				
			||||||
 | 
							size_t bufferSize() const { return _bufferSize; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Enables SSL feature
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_SSL) || CAPS_FEATURES_SSL
 | 
				
			||||||
 | 
							void setSSLEnabled(bool enable) { _useSSL = enable; }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Sets username and password
 | 
				
			||||||
 | 
							 * @param user The username
 | 
				
			||||||
 | 
							 * @param password The password
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							void setCredentials(const std::string &user, const std::string &password) {
 | 
				
			||||||
 | 
								_user = user;
 | 
				
			||||||
 | 
								_password = password;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Sets the maximum allowed relative end time for packets. If
 | 
				
			||||||
 | 
							 * the packet end time is greater than the current time plus this
 | 
				
			||||||
 | 
							 * value the packet will be discarded. By default this value is
 | 
				
			||||||
 | 
							 * set to 120 seconds.
 | 
				
			||||||
 | 
							 * @param time The time span
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							void setMaxFutureEndTime(const TimeSpan &span) {
 | 
				
			||||||
 | 
								_maxFutureEndTime = span;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setPacketAckFunc(const PacketAckFunc &func) { _packetAckFunc = func; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setSendTimeout(int timeout) {
 | 
				
			||||||
 | 
								_sendTimeout = timeout;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setTimeouts(int ack, int lastAck) {
 | 
				
			||||||
 | 
								_ackTimeout = ack;
 | 
				
			||||||
 | 
								_lastAckTimeout = lastAck;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setTimeouts(int ack, int lastAck, int send) {
 | 
				
			||||||
 | 
								_ackTimeout = ack;
 | 
				
			||||||
 | 
								_lastAckTimeout = lastAck;
 | 
				
			||||||
 | 
								_sendTimeout = send;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_JOURNAL) || CAPS_FEATURES_JOURNAL
 | 
				
			||||||
 | 
							bool readJournal();
 | 
				
			||||||
 | 
							void setJournal(const std::string &filename) { _journalFile = filename; }
 | 
				
			||||||
 | 
							void setFlushInterval(int interval) { _flushInterval = interval; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const StreamStates &streamStates() const { return _states; }
 | 
				
			||||||
 | 
							bool writeJournal();
 | 
				
			||||||
 | 
							bool writeJournal(std::ostream &ostream);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							Status push(const std::string &net, const std::string &sta,
 | 
				
			||||||
 | 
							            const std::string &loc, const std::string &cha,
 | 
				
			||||||
 | 
							            DataRecordPtr rec, const std::string &uom,
 | 
				
			||||||
 | 
							            int timingQuality = -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Status push(const std::string &net, const std::string &sta,
 | 
				
			||||||
 | 
							            const std::string &loc, const std::string &cha,
 | 
				
			||||||
 | 
							            const Time &stime,
 | 
				
			||||||
 | 
							            uint16_t numerator, uint16_t denominator,
 | 
				
			||||||
 | 
							            const std::string &uom,
 | 
				
			||||||
 | 
							            void *data, size_t count,
 | 
				
			||||||
 | 
							            DataType dt, int timingQuality = -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Sends given data as any packet. Before sending the data will be 
 | 
				
			||||||
 | 
							 * copied into an internal buffer. We introduced this method
 | 
				
			||||||
 | 
							 * to simplify the creation of the python wrappers.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_ANY) || CAPS_FEATURES_ANY
 | 
				
			||||||
 | 
							Status push(const std::string &net, const std::string &sta,
 | 
				
			||||||
 | 
							            const std::string &loc, const std::string &cha,
 | 
				
			||||||
 | 
							            const Time &stime, uint16_t numerator,
 | 
				
			||||||
 | 
							            uint16_t denominator, const std::string &format,
 | 
				
			||||||
 | 
							            char *data, size_t count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Status push(const std::string &net, const std::string &sta,
 | 
				
			||||||
 | 
							            const std::string &loc, const std::string &cha,
 | 
				
			||||||
 | 
							            const Time &stime, uint16_t numerator,
 | 
				
			||||||
 | 
							            uint16_t denominator, const std::string &format,
 | 
				
			||||||
 | 
							            const std::string &data);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const char *version() {
 | 
				
			||||||
 | 
								return LIB_CAPS_VERSION_NAME;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							typedef std::deque<PacketPtr> PacketBuffer;
 | 
				
			||||||
 | 
							typedef boost::shared_ptr<Encoder> EncoderPtr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct EncoderItem {
 | 
				
			||||||
 | 
								EncoderItem() : dataType(DT_Unknown) {}
 | 
				
			||||||
 | 
								EncoderPtr        encoder;
 | 
				
			||||||
 | 
								DataType          dataType;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							typedef std::map<std::string, EncoderItem> EncoderItems;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							bool connect();
 | 
				
			||||||
 | 
							void disconnect();
 | 
				
			||||||
 | 
							bool isConnected() const;
 | 
				
			||||||
 | 
							Encoder* getEncoder(PacketPtr packet);
 | 
				
			||||||
 | 
							bool readResponse(unsigned int sec = 0);
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_JOURNAL) || CAPS_FEATURES_JOURNAL
 | 
				
			||||||
 | 
							bool readJournal(std::istream &istream);
 | 
				
			||||||
 | 
							void updateJournal();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							void sendBye();
 | 
				
			||||||
 | 
							bool commitPacket(PacketPtr packet);
 | 
				
			||||||
 | 
							bool encodePacket(PacketPtr packet);
 | 
				
			||||||
 | 
							bool sendPacket(Packet *packet);
 | 
				
			||||||
 | 
							void serializePacket(Packet *packet);
 | 
				
			||||||
 | 
							void tryFlushBackfillingBuffer(StreamState &state);
 | 
				
			||||||
 | 
							void trimBackfillingBuffer(StreamState &state);
 | 
				
			||||||
 | 
							bool flush();
 | 
				
			||||||
 | 
							void flushEncoders();
 | 
				
			||||||
 | 
							bool send(char *data, int len, int timeout = 60);
 | 
				
			||||||
 | 
							void wait();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							SocketPtr                 _socket;
 | 
				
			||||||
 | 
							std::string               _name;
 | 
				
			||||||
 | 
							std::string               _options;
 | 
				
			||||||
 | 
							std::string               _description;
 | 
				
			||||||
 | 
							size_t                    _bufferSize;
 | 
				
			||||||
 | 
							StreamStates              _states;
 | 
				
			||||||
 | 
							PacketBuffer              _packetBuffer;
 | 
				
			||||||
 | 
							bool                      _packetBufferDirty;
 | 
				
			||||||
 | 
							size_t                    _bytesBuffered;
 | 
				
			||||||
 | 
							std::string               _host;
 | 
				
			||||||
 | 
							unsigned short            _port;
 | 
				
			||||||
 | 
							char                      _responseBuf[512];
 | 
				
			||||||
 | 
							int                       _responseBufIdx;
 | 
				
			||||||
 | 
							fd_set                    _readFDs;
 | 
				
			||||||
 | 
							fd_set                    _writeFDs;
 | 
				
			||||||
 | 
							int                       _sendTimeout;
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_JOURNAL) || CAPS_FEATURES_JOURNAL
 | 
				
			||||||
 | 
							std::string               _journalFile;
 | 
				
			||||||
 | 
							bool                      _journalDirty;
 | 
				
			||||||
 | 
							Time                      _lastWrite;
 | 
				
			||||||
 | 
							int                       _flushInterval;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							bool                      _isExitRequested;
 | 
				
			||||||
 | 
							bool                      _closed;
 | 
				
			||||||
 | 
							bool                      _wasConnected;
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_BACKFILLING) || CAPS_FEATURES_BACKFILLING
 | 
				
			||||||
 | 
							int                       _backfillingBufferSize;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							int                       _ackTimeout;
 | 
				
			||||||
 | 
							int                       _lastAckTimeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							EncoderFactory           *_encoderFactory;
 | 
				
			||||||
 | 
							EncoderItems              _encoderItems;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PacketAckFunc             _packetAckFunc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string               _user;
 | 
				
			||||||
 | 
							std::string               _password;
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_SSL) || CAPS_FEATURES_SSL
 | 
				
			||||||
 | 
							bool                      _useSSL;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							Stats                     _stats;
 | 
				
			||||||
 | 
							TimeSpan                  _maxFutureEndTime;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef boost::shared_ptr<Plugin> PluginPtr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										383
									
								
								libs/gempa/caps/pluginapplication.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										383
									
								
								libs/gempa/caps/pluginapplication.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,383 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SEISCOMP_COMPONENT PluginApplication
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/pluginapplication.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/encoderfactory.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <seiscomp3/core/system.h>
 | 
				
			||||||
 | 
					#include <seiscomp3/logging/log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <boost/algorithm/string.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef SC_GEMPA_SEATTLE
 | 
				
			||||||
 | 
					#include <seiscomp3/system/environment.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#include <seiscomp3/config/environment.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace sc = Seiscomp::Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef SEISCOMP_LOG_VA
 | 
				
			||||||
 | 
					#define LOG_CAPS_CHANNEL(out, fmt) \
 | 
				
			||||||
 | 
						va_list ap;\
 | 
				
			||||||
 | 
						va_start(ap, fmt);\
 | 
				
			||||||
 | 
						out(fmt, ap);\
 | 
				
			||||||
 | 
						va_end(ap)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define LOG_CAPS_CHANNEL(out, fmt) \
 | 
				
			||||||
 | 
						va_list ap;\
 | 
				
			||||||
 | 
						va_start(ap, fmt);\
 | 
				
			||||||
 | 
						fprintf(stderr, #out"  "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n");\
 | 
				
			||||||
 | 
						va_end(ap)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LogError(const char *fmt, ...) {
 | 
				
			||||||
 | 
						LOG_CAPS_CHANNEL(SEISCOMP_VERROR, fmt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LogWarning(const char *fmt, ...) {
 | 
				
			||||||
 | 
						LOG_CAPS_CHANNEL(SEISCOMP_VWARNING, fmt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LogNotice(const char *fmt, ...) {
 | 
				
			||||||
 | 
						LOG_CAPS_CHANNEL(SEISCOMP_VNOTICE, fmt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LogInfo(const char *fmt, ...) {
 | 
				
			||||||
 | 
						LOG_CAPS_CHANNEL(SEISCOMP_VINFO, fmt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LogDebug(const char *fmt, ...) {
 | 
				
			||||||
 | 
						LOG_CAPS_CHANNEL(SEISCOMP_VDEBUG, fmt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const size_t MIN_BUFFER_SIZE = 1024*16;
 | 
				
			||||||
 | 
					const uint16_t DEFAULT_PORT = 18003;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PluginApplication::PluginApplication(int argc, char **argv, const string &desc)
 | 
				
			||||||
 | 
					: Seiscomp::Client::StreamApplication(argc, argv)
 | 
				
			||||||
 | 
					, _plugin(Plugin(desc)) {
 | 
				
			||||||
 | 
						_bufferSize = 1 << 20;
 | 
				
			||||||
 | 
						_backfillingBufferSize = 180;
 | 
				
			||||||
 | 
						_flushInterval = 10;
 | 
				
			||||||
 | 
						_ackTimeout = 60;
 | 
				
			||||||
 | 
						_lastAckTimeout = 5;
 | 
				
			||||||
 | 
						_sendTimeout = 60;
 | 
				
			||||||
 | 
						_logStatus = false;
 | 
				
			||||||
 | 
						_statusFlushInterval = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_host = "localhost";
 | 
				
			||||||
 | 
						_port = DEFAULT_PORT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_strAddr = "localhost:" + sc::toString(DEFAULT_PORT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SC_FS_DECLARE_PATH(path, "@ROOTDIR@/var/run/" + SCCoreApp->name() + "/journal");
 | 
				
			||||||
 | 
						_journalFile = path.string();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_mseedEnabled = false;
 | 
				
			||||||
 | 
						_mseedEncoding = Steim2;
 | 
				
			||||||
 | 
						_mseedRecordLength = 9;
 | 
				
			||||||
 | 
						_strMseedEncoding = "Steim2";
 | 
				
			||||||
 | 
						_maxFutureEndTime = 120;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// By default we disable the acquisition autostart because not all plugins
 | 
				
			||||||
 | 
						// require this feature. It must be enabled explicitly if required.
 | 
				
			||||||
 | 
						setAutoAcquisitionStart(false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void PluginApplication::createCommandLineDescription() {
 | 
				
			||||||
 | 
						Seiscomp::Client::StreamApplication::createCommandLineDescription();
 | 
				
			||||||
 | 
						commandline().addGroup("Output");
 | 
				
			||||||
 | 
						commandline().addOption("Output", "addr,a", "Data output address, format is [HOST:PORT]", &_strAddr);
 | 
				
			||||||
 | 
						commandline().addOption("Output", "buffer-size,b", "Size (bytes) of the packet buffer", &_bufferSize);
 | 
				
			||||||
 | 
						commandline().addOption("Output", "backfilling",
 | 
				
			||||||
 | 
						                        "Enable backfilling for out-of-order records. The backfilling buffer size is "
 | 
				
			||||||
 | 
						                        "in seconds", &_backfillingBufferSize);
 | 
				
			||||||
 | 
						commandline().addOption("Output", "mseed", "Enable on-the-fly MiniSeed "
 | 
				
			||||||
 | 
						                        "encoding. If the encoder does not support the input"
 | 
				
			||||||
 | 
						                        "type of a packet it will be forwarded. Re encoding of"
 | 
				
			||||||
 | 
						                        "MiniSEED packets is not supported.");
 | 
				
			||||||
 | 
						commandline().addOption("Output", "encoding", "MiniSEED encoding to use. (Uncompressed, Steim1 or Steim2)",
 | 
				
			||||||
 | 
						                        &_strMseedEncoding);
 | 
				
			||||||
 | 
						commandline().addOption("Output", "rec-len", "MiniSEED record length expressed as a power of 2."
 | 
				
			||||||
 | 
						                                             "A 512 byte record would be 9.",
 | 
				
			||||||
 | 
						                        &_mseedRecordLength);
 | 
				
			||||||
 | 
						commandline().addOption("Output", "max-future-endtime", "Maximum allowed relative end time for packets. If "
 | 
				
			||||||
 | 
						                        "the packet end time is greater than the current time plus this "
 | 
				
			||||||
 | 
						                        "value the packet will be discarded. By default this value is set to 120 seconds.",
 | 
				
			||||||
 | 
						                        &_maxFutureEndTime);
 | 
				
			||||||
 | 
						commandline().addGroup("Journal");
 | 
				
			||||||
 | 
						commandline().addOption("Journal", "journal,j",
 | 
				
			||||||
 | 
						                        "File to store stream states. Use an empty string to disable this feature.", &_journalFile);
 | 
				
			||||||
 | 
						commandline().addOption("Journal", "flush",
 | 
				
			||||||
 | 
						                        "Flush stream states every n seconds to disk", &_flushInterval);
 | 
				
			||||||
 | 
						commandline().addOption("Journal", "wait-for-ack",
 | 
				
			||||||
 | 
						                        "Wait when a sync has been forced, up to n seconds", &_ackTimeout);
 | 
				
			||||||
 | 
						commandline().addOption("Journal", "wait-for-last-ack,w",
 | 
				
			||||||
 | 
						                        "Wait on shutdown to receive acknownledgement messages, up to n seconds", &_lastAckTimeout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						commandline().addGroup("Status");
 | 
				
			||||||
 | 
						commandline().addOption("Status", "status-log", "Log information status "
 | 
				
			||||||
 | 
						                        "information e.g. max bytes buffered");
 | 
				
			||||||
 | 
						commandline().addOption("Status", "status-flush", "Flush status every n "
 | 
				
			||||||
 | 
						                        "seconds to disk",
 | 
				
			||||||
 | 
						                        &_statusFlushInterval);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void PluginApplication::done() {
 | 
				
			||||||
 | 
						LogInfo("Statistics of transmitted data:\n"
 | 
				
			||||||
 | 
						        "  records   : %d\n"
 | 
				
			||||||
 | 
						        "  samples   : %d\n"
 | 
				
			||||||
 | 
						        "  gaps      : %d\n"
 | 
				
			||||||
 | 
						        "  start time: %s\n"
 | 
				
			||||||
 | 
						        "  end time  : %s\n"
 | 
				
			||||||
 | 
						        "  files     : %d",
 | 
				
			||||||
 | 
						        _stats.records, _stats.samples, _stats.gaps,
 | 
				
			||||||
 | 
						        _stats.startTime.valid()?_stats.startTime.iso().c_str():"",
 | 
				
			||||||
 | 
						        _stats.endTime.valid()?_stats.endTime.iso().c_str():"",
 | 
				
			||||||
 | 
						        _stats.files);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Seiscomp::Client::StreamApplication::done();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void PluginApplication::exit(int returnCode) {
 | 
				
			||||||
 | 
						Seiscomp::Client::StreamApplication::exit(returnCode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_plugin.quit();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void PluginApplication::handleTimeout() {
 | 
				
			||||||
 | 
						sc::Time time = sc::Time::GMT().toLocalTime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Plugin::Stats stats = _plugin.stats();
 | 
				
			||||||
 | 
						_statusFile.stream() << time.toString("%Y/%m/%d %T") << " " << stats.maxBytesBuffered << endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_plugin.resetMaxBytesBuffered();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool PluginApplication::init() {
 | 
				
			||||||
 | 
						if ( !Seiscomp::Client::StreamApplication::init() ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Setup log handlers
 | 
				
			||||||
 | 
						Gempa::CAPS::SetLogHandler(Gempa::CAPS::LL_ERROR, LogError);
 | 
				
			||||||
 | 
						Gempa::CAPS::SetLogHandler(Gempa::CAPS::LL_WARNING, LogWarning);
 | 
				
			||||||
 | 
						Gempa::CAPS::SetLogHandler(Gempa::CAPS::LL_NOTICE, LogNotice);
 | 
				
			||||||
 | 
						Gempa::CAPS::SetLogHandler(Gempa::CAPS::LL_INFO, LogInfo);
 | 
				
			||||||
 | 
						Gempa::CAPS::SetLogHandler(Gempa::CAPS::LL_DEBUG, LogDebug);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_plugin.setHost(_host);
 | 
				
			||||||
 | 
						_plugin.setPort(_port);
 | 
				
			||||||
 | 
						_plugin.setBufferSize(_bufferSize);
 | 
				
			||||||
 | 
						_plugin.setFlushInterval(_flushInterval);
 | 
				
			||||||
 | 
						_plugin.setTimeouts(_ackTimeout, _lastAckTimeout, _sendTimeout);
 | 
				
			||||||
 | 
						_plugin.setMaxFutureEndTime(_maxFutureEndTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _mseedEnabled ) {
 | 
				
			||||||
 | 
							MSEEDEncoderFactory *factory = nullptr;
 | 
				
			||||||
 | 
							if ( _mseedEncoding == Uncompressed ) {
 | 
				
			||||||
 | 
								SEISCOMP_INFO("Output stream encoding set to MiniSEED/Uncompressed");
 | 
				
			||||||
 | 
								factory = new IdentityEncoderFactory();
 | 
				
			||||||
 | 
								_plugin.setEncoderFactory(factory);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if ( _mseedEncoding == Steim1 ) {
 | 
				
			||||||
 | 
								SEISCOMP_INFO("Output stream encoding set to MiniSEED/Steim1");
 | 
				
			||||||
 | 
								factory = new Steim1EncoderFactory();
 | 
				
			||||||
 | 
								_plugin.setEncoderFactory(factory);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ( _mseedEncoding == Steim2 ) {
 | 
				
			||||||
 | 
								SEISCOMP_INFO("Output stream encoding set to MiniSEED/Steim2");
 | 
				
			||||||
 | 
								factory = new Steim2EncoderFactory();
 | 
				
			||||||
 | 
								_plugin.setEncoderFactory(factory);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								SEISCOMP_ERROR("Unsupported MiniSEED encoding");
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( !factory->setRecordLength(_mseedRecordLength) ) {
 | 
				
			||||||
 | 
								SEISCOMP_ERROR("%s", factory->errorString().c_str());
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							SEISCOMP_INFO("MiniSEED encoding is disabled.");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _backfillingBufferSize > 0 ) {
 | 
				
			||||||
 | 
							_plugin.setBackfillingBufferSize(_backfillingBufferSize);
 | 
				
			||||||
 | 
							LogInfo("Backfilling buffer size set to %d", _backfillingBufferSize);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !_journalFile.empty() ) {
 | 
				
			||||||
 | 
							_journalFile = Seiscomp::Environment::Instance()->absolutePath(_journalFile);
 | 
				
			||||||
 | 
							// Recover states
 | 
				
			||||||
 | 
							LogInfo("Reading journal from %s", _journalFile.c_str());
 | 
				
			||||||
 | 
							_plugin.setJournal(_journalFile);
 | 
				
			||||||
 | 
							_plugin.readJournal();
 | 
				
			||||||
 | 
							LogInfo("Recovered %d streams", (int)_plugin.streamStates().size());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _logStatus ) {
 | 
				
			||||||
 | 
							string filename =  Seiscomp::Environment::Instance()->logDir() + "/" + SCCoreApp->name() + "-stats.log";
 | 
				
			||||||
 | 
							if ( !_statusFile.open(filename.c_str()) ) {
 | 
				
			||||||
 | 
								LogError("Could not open status file %s.", filename.c_str());
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							enableTimer(_statusFlushInterval);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool PluginApplication::initConfiguration() {
 | 
				
			||||||
 | 
						if ( !Seiscomp::Client::StreamApplication::initConfiguration() ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _host = configGetString("output.host"); }
 | 
				
			||||||
 | 
						catch ( ... ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _port = configGetInt("output.port"); }
 | 
				
			||||||
 | 
						catch ( ... ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _sendTimeout = configGetInt("output.timeout"); }
 | 
				
			||||||
 | 
						catch ( ... ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							string addr = configGetString("output.addr");
 | 
				
			||||||
 | 
							if ( !splitAddress(_host, _port, addr, DEFAULT_PORT) ) {
 | 
				
			||||||
 | 
								SEISCOMP_ERROR("%s: Invalid CAPS address, format is [HOST:PORT]",
 | 
				
			||||||
 | 
								               addr.c_str());
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						catch ( ... ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							_mseedEnabled = configGetBool("output.mseed.enable");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						catch ( ... ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							int length = configGetInt("output.mseed.recordLength");
 | 
				
			||||||
 | 
							if ( length < 0 ) {
 | 
				
			||||||
 | 
								SEISCOMP_ERROR("'output.mseed.recordLength' must be a positive integer");
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							_mseedRecordLength = uint(length);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						catch ( ... ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							string str = configGetString("output.mseed.encoding");
 | 
				
			||||||
 | 
							if ( !fromString(_mseedEncoding, str)) return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						catch ( ... ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _bufferSize = configGetInt("output.bufferSize"); }
 | 
				
			||||||
 | 
						catch ( ... ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _backfillingBufferSize = configGetInt("output.backfillingBufferSize"); }
 | 
				
			||||||
 | 
						catch ( ... ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _journalFile = configGetString("journal.file"); }
 | 
				
			||||||
 | 
						catch ( ... ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _flushInterval = configGetInt("journal.flush"); }
 | 
				
			||||||
 | 
						catch ( ... ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _ackTimeout = configGetInt("journal.waitForAck"); }
 | 
				
			||||||
 | 
						catch ( ... ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _lastAckTimeout = configGetInt("journal.waitForLastAck"); }
 | 
				
			||||||
 | 
						catch ( ... ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _logStatus = configGetBool("statusLog.enable"); }
 | 
				
			||||||
 | 
						catch ( ... ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _statusFlushInterval = configGetInt("statusLog.flush"); }
 | 
				
			||||||
 | 
						catch ( ... ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try { _maxFutureEndTime= configGetInt("output.maxFutureEndTime"); }
 | 
				
			||||||
 | 
						catch ( ... ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool PluginApplication::validateParameters() {
 | 
				
			||||||
 | 
						if ( !Seiscomp::Client::StreamApplication::validateParameters() ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( commandline().hasOption("mseed") ) {
 | 
				
			||||||
 | 
							_mseedEnabled = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( commandline().hasOption("status-log") ) {
 | 
				
			||||||
 | 
							_logStatus = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( commandline().hasOption("encoding") ) {
 | 
				
			||||||
 | 
							if ( !fromString(_mseedEncoding, _strMseedEncoding)) return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _bufferSize < MIN_BUFFER_SIZE ) {
 | 
				
			||||||
 | 
							SEISCOMP_ERROR("The plugin buffer size must be at least %ld bytes.",
 | 
				
			||||||
 | 
							               MIN_BUFFER_SIZE);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( commandline().hasOption("addr") ) {
 | 
				
			||||||
 | 
							if ( !splitAddress(_host, _port, _strAddr, DEFAULT_PORT) ) {
 | 
				
			||||||
 | 
								SEISCOMP_ERROR("%s: Invalid CAPS address, format is [HOST:PORT]",
 | 
				
			||||||
 | 
								               _strAddr.c_str());
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool PluginApplication::fromString(MseedEncoding &enc, string str) {
 | 
				
			||||||
 | 
						boost::to_lower(str);
 | 
				
			||||||
 | 
						if( str == "uncompressed" )
 | 
				
			||||||
 | 
							enc = Uncompressed;
 | 
				
			||||||
 | 
						else if ( str == "steim1" )
 | 
				
			||||||
 | 
							enc = Steim1;
 | 
				
			||||||
 | 
						else if ( str == "steim2" )
 | 
				
			||||||
 | 
							enc = Steim2;
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							SEISCOMP_ERROR("Unsupported encoding %s", str.c_str());
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										114
									
								
								libs/gempa/caps/pluginapplication.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								libs/gempa/caps/pluginapplication.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_PLUGINAPPLICATION_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_PLUGINAPPLICATION_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/api.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/plugin.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <seiscomp3/client/streamapplication.h>
 | 
				
			||||||
 | 
					#include <seiscomp3/logging/filerotator.h>
 | 
				
			||||||
 | 
					#include <seiscomp3/utils/timer.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SC_GEMPA_CAPS_API PluginApplication : public Seiscomp::Client::StreamApplication {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							PluginApplication(int argc, char **argv,
 | 
				
			||||||
 | 
							                  const std::string &desc = "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Adds common plugin commandline options.
 | 
				
			||||||
 | 
							*/
 | 
				
			||||||
 | 
							virtual void createCommandLineDescription();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual void done();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual void exit(int returnCode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual void handleRecord(Seiscomp::Record *record) {}
 | 
				
			||||||
 | 
							virtual void handleTimeout();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Initialization method.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual bool init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Reads common plugin configuration options.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual bool initConfiguration();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Validates command line parameters.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							virtual bool validateParameters();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							struct Statistics {
 | 
				
			||||||
 | 
								uint32_t records;
 | 
				
			||||||
 | 
								uint32_t samples;
 | 
				
			||||||
 | 
								Time     startTime;
 | 
				
			||||||
 | 
								Time     endTime;
 | 
				
			||||||
 | 
								uint32_t gaps;
 | 
				
			||||||
 | 
								uint32_t files;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Statistics() : records(0), samples(0), gaps(0), files(0) {}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							enum MseedEncoding {Uncompressed, Steim1, Steim2};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool fromString(MseedEncoding &enc, std::string str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							class FileRotator : public Seiscomp::Logging::FileRotatorOutput {
 | 
				
			||||||
 | 
								public:
 | 
				
			||||||
 | 
									std::ofstream& stream() { return _stream; }
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							Plugin                    _plugin;
 | 
				
			||||||
 | 
							std::string               _host;
 | 
				
			||||||
 | 
							ushort                    _port;
 | 
				
			||||||
 | 
							std::string               _strAddr;
 | 
				
			||||||
 | 
							size_t                    _bufferSize;
 | 
				
			||||||
 | 
							size_t                    _backfillingBufferSize;
 | 
				
			||||||
 | 
							bool                      _mseed;
 | 
				
			||||||
 | 
							std::string               _journalFile;
 | 
				
			||||||
 | 
							int                       _flushInterval;
 | 
				
			||||||
 | 
							int                       _ackTimeout;
 | 
				
			||||||
 | 
							int                       _lastAckTimeout;
 | 
				
			||||||
 | 
							int                       _sendTimeout;
 | 
				
			||||||
 | 
							int                       _maxFutureEndTime;
 | 
				
			||||||
 | 
							Statistics                _stats;
 | 
				
			||||||
 | 
							bool                      _mseedEnabled;
 | 
				
			||||||
 | 
							MseedEncoding             _mseedEncoding;
 | 
				
			||||||
 | 
							uint                      _mseedRecordLength;
 | 
				
			||||||
 | 
							std::string               _strMseedEncoding;
 | 
				
			||||||
 | 
							std::string               _strPacketType;
 | 
				
			||||||
 | 
							Seiscomp::Util::Timer     _timer;
 | 
				
			||||||
 | 
							FileRotator               _statusFile;
 | 
				
			||||||
 | 
							bool                      _logStatus;
 | 
				
			||||||
 | 
							uint                      _statusFlushInterval;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										69
									
								
								libs/gempa/caps/pluginpacket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								libs/gempa/caps/pluginpacket.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2016 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_PLUGINPACKET_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_PLUGINPACKET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mseed/encoder.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Packet {
 | 
				
			||||||
 | 
						Packet() : timingQuality(-1) {}
 | 
				
			||||||
 | 
						Packet(DataRecordPtr rec,
 | 
				
			||||||
 | 
						       const std::string &networkCode, const std::string &stationCode,
 | 
				
			||||||
 | 
						       const std::string &locationCode, const std::string &channelCode)
 | 
				
			||||||
 | 
						: record(rec), networkCode(networkCode), stationCode(stationCode),
 | 
				
			||||||
 | 
						  locationCode(locationCode), channelCode(channelCode), timingQuality(-1) {
 | 
				
			||||||
 | 
							streamID = networkCode + "." + stationCode + "." +
 | 
				
			||||||
 | 
							           locationCode + "." + channelCode;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Packet* clone() {
 | 
				
			||||||
 | 
							Packet *packet = new Packet(record, networkCode, stationCode,
 | 
				
			||||||
 | 
							                            locationCode, channelCode);
 | 
				
			||||||
 | 
							packet->buffer = buffer;
 | 
				
			||||||
 | 
							packet->dt_us = dt_us;
 | 
				
			||||||
 | 
							packet->streamID = streamID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return packet;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typedef std::vector<char>                       Buffer;
 | 
				
			||||||
 | 
						typedef boost::shared_ptr<Buffer>               BufferPtr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BufferPtr            buffer;    // PacketDataHeader, PacketHeader[V1|V2], Data
 | 
				
			||||||
 | 
						DataRecordPtr        record;
 | 
				
			||||||
 | 
						std::string          networkCode;
 | 
				
			||||||
 | 
						std::string          stationCode;
 | 
				
			||||||
 | 
						std::string          locationCode;
 | 
				
			||||||
 | 
						std::string          channelCode;
 | 
				
			||||||
 | 
						std::string          streamID;
 | 
				
			||||||
 | 
						DataType             dataType;
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_BACKFILLING) || CAPS_FEATURES_BACKFILLING
 | 
				
			||||||
 | 
						int64_t              dt_us;     // Length of one sample in microseconds
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						std::string          uom;
 | 
				
			||||||
 | 
						int                  timingQuality;
 | 
				
			||||||
 | 
						size_t size() const { return buffer->size(); }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef boost::shared_ptr<Packet>   PacketPtr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										418
									
								
								libs/gempa/caps/rawpacket.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										418
									
								
								libs/gempa/caps/rawpacket.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,418 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/rawpacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/riff.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DT2STR(prefix, dt)             \
 | 
				
			||||||
 | 
						do {                               \
 | 
				
			||||||
 | 
							switch ( dt ) {                \
 | 
				
			||||||
 | 
								case DT_DOUBLE:            \
 | 
				
			||||||
 | 
									return prefix"DOUBLE"; \
 | 
				
			||||||
 | 
								case DT_FLOAT:             \
 | 
				
			||||||
 | 
									return prefix"FLOAT";  \
 | 
				
			||||||
 | 
								case DT_INT64:             \
 | 
				
			||||||
 | 
									return prefix"INT64";  \
 | 
				
			||||||
 | 
								case DT_INT32:             \
 | 
				
			||||||
 | 
									return prefix"INT32";  \
 | 
				
			||||||
 | 
								case DT_INT16:             \
 | 
				
			||||||
 | 
									return prefix"INT16";  \
 | 
				
			||||||
 | 
								case DT_INT8:              \
 | 
				
			||||||
 | 
									return prefix"INT8";   \
 | 
				
			||||||
 | 
								default:                   \
 | 
				
			||||||
 | 
									break;                 \
 | 
				
			||||||
 | 
							}                              \
 | 
				
			||||||
 | 
						}                                  \
 | 
				
			||||||
 | 
						while (0);                         \
 | 
				
			||||||
 | 
						return prefix"UNKWN";              \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline int sizeOf(DataType dt) {
 | 
				
			||||||
 | 
						switch ( dt ) {
 | 
				
			||||||
 | 
							case DT_DOUBLE:
 | 
				
			||||||
 | 
								return sizeof(double);
 | 
				
			||||||
 | 
							case DT_FLOAT:
 | 
				
			||||||
 | 
								return sizeof(float);
 | 
				
			||||||
 | 
							case DT_INT64:
 | 
				
			||||||
 | 
								return sizeof(int64_t);
 | 
				
			||||||
 | 
							case DT_INT32:
 | 
				
			||||||
 | 
								return sizeof(int32_t);
 | 
				
			||||||
 | 
							case DT_INT16:
 | 
				
			||||||
 | 
								return sizeof(int16_t);
 | 
				
			||||||
 | 
							case DT_INT8:
 | 
				
			||||||
 | 
								return sizeof(int8_t);
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline Time getEndTime(const Time &stime, size_t count, const DataRecord::Header &header) {
 | 
				
			||||||
 | 
						if ( header.samplingFrequencyNumerator == 0 ||
 | 
				
			||||||
 | 
						     header.samplingFrequencyDenominator == 0 ) return stime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stime + samplesToTimeSpan(header, count);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RawDataRecord::RawDataRecord() : _dataOfs(0), _dataSize(0), _dirty(false) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *RawDataRecord::formatName() const {
 | 
				
			||||||
 | 
						DT2STR("RAW/", _currentHeader.dataType)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RawDataRecord::readMetaData(std::streambuf &buf, int size, Header &header,
 | 
				
			||||||
 | 
					                                 Time &startTime, Time &endTime) {
 | 
				
			||||||
 | 
						if ( !header.get(buf) ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_currentHeader.dataType = header.dataType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size -= header.dataSize();
 | 
				
			||||||
 | 
						int dtsize = sizeOf(header.dataType);
 | 
				
			||||||
 | 
						if ( dtsize == 0 ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("unknown data type: %d", header.dataType);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int count = size / dtsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						startTime = timestampToTime(header.samplingTime);
 | 
				
			||||||
 | 
						endTime = getEndTime(startTime, count, header);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void RawDataRecord::setHeader(const Header &header) {
 | 
				
			||||||
 | 
						_header = header;
 | 
				
			||||||
 | 
						_currentHeader = _header;
 | 
				
			||||||
 | 
						_startTime = timestampToTime(_header.samplingTime);
 | 
				
			||||||
 | 
						_dirty = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DataRecord::Header *RawDataRecord::header() const {
 | 
				
			||||||
 | 
						return &_header;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void RawDataRecord::setDataType(DataType dt) {
 | 
				
			||||||
 | 
						_header.dataType = dt;
 | 
				
			||||||
 | 
						_currentHeader = _header;
 | 
				
			||||||
 | 
						_dirty = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void RawDataRecord::setStartTime(const Time &time) {
 | 
				
			||||||
 | 
						_header.setSamplingTime(time);
 | 
				
			||||||
 | 
						_currentHeader = _header;
 | 
				
			||||||
 | 
						_startTime = time;
 | 
				
			||||||
 | 
						_dirty = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void RawDataRecord::setSamplingFrequency(uint16_t numerator, uint16_t denominator) {
 | 
				
			||||||
 | 
						_header.samplingFrequencyNumerator = numerator;
 | 
				
			||||||
 | 
						_header.samplingFrequencyDenominator = denominator;
 | 
				
			||||||
 | 
						_currentHeader = _header;
 | 
				
			||||||
 | 
						_dirty = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Time RawDataRecord::startTime() const {
 | 
				
			||||||
 | 
						return _startTime;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Time RawDataRecord::endTime() const {
 | 
				
			||||||
 | 
						if ( _dirty ) {
 | 
				
			||||||
 | 
							_endTime = getEndTime(_startTime, _data.size() / sizeOf(_header.dataType), _header);
 | 
				
			||||||
 | 
							_dirty = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return _endTime;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RawDataRecord::canTrim() const {
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RawDataRecord::canMerge() const {
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RawDataRecord::trim(const Time &start, const Time &end) const {
 | 
				
			||||||
 | 
						if ( _header.samplingFrequencyNumerator <= 0 || _header.samplingFrequencyDenominator <= 0 )
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If the start time is behind the end time return false
 | 
				
			||||||
 | 
						if ( start > end ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Initialize original values
 | 
				
			||||||
 | 
						int dataTypeSize = sizeOf(_header.dataType);
 | 
				
			||||||
 | 
						_dataSize = _data.size();
 | 
				
			||||||
 | 
						if ( dataTypeSize == 0 ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("unknown data type: %d", _header.dataType);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_startTime = timestampToTime(_header.samplingTime);
 | 
				
			||||||
 | 
						_endTime = _startTime + samplesToTimeSpan(_header, _dataSize / dataTypeSize);
 | 
				
			||||||
 | 
						_dirty = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Trim front
 | 
				
			||||||
 | 
						if ( start > _startTime ) {
 | 
				
			||||||
 | 
							TimeSpan ofs = start - _startTime;
 | 
				
			||||||
 | 
							int sampleOfs = timeSpanToSamplesCeil(_header, ofs);
 | 
				
			||||||
 | 
							_dataOfs = sampleOfs * dataTypeSize;
 | 
				
			||||||
 | 
							if ( _dataSize > _dataOfs )
 | 
				
			||||||
 | 
								_dataSize -= _dataOfs;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								_dataSize = 0;
 | 
				
			||||||
 | 
							_startTime += samplesToTimeSpan(_header, sampleOfs);
 | 
				
			||||||
 | 
							timeToTimestamp(_currentHeader.samplingTime, _startTime);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							_currentHeader.samplingTime = _header.samplingTime;
 | 
				
			||||||
 | 
							_dataOfs = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Trim back
 | 
				
			||||||
 | 
						if ( end.valid() && (end < _endTime) ) {
 | 
				
			||||||
 | 
							TimeSpan ofs = _endTime - end;
 | 
				
			||||||
 | 
							int sampleOfs = timeSpanToSamplesFloor(_header, ofs);
 | 
				
			||||||
 | 
							_dataSize -= sampleOfs * dataTypeSize;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t sampleCount = _dataSize / dataTypeSize;
 | 
				
			||||||
 | 
						_endTime = _startTime + samplesToTimeSpan(_currentHeader, sampleCount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CAPS_DEBUG("trimmed: %s ~ %s: %d samples",
 | 
				
			||||||
 | 
						            _startTime.iso().c_str(),
 | 
				
			||||||
 | 
						            _endTime.iso().c_str(), (int)sampleCount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t RawDataRecord::dataSize(bool withHeader) const {
 | 
				
			||||||
 | 
						if ( withHeader )
 | 
				
			||||||
 | 
							return _dataSize + _header.dataSize();
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return _dataSize;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DataRecord::ReadStatus RawDataRecord::get(streambuf &buf, int size,
 | 
				
			||||||
 | 
					                                          const Time &start, const Time &end,
 | 
				
			||||||
 | 
					                                          int maxBytes) {
 | 
				
			||||||
 | 
						size -= _header.dataSize();
 | 
				
			||||||
 | 
						if ( size < 0 ) return RS_Error;
 | 
				
			||||||
 | 
						if ( !_header.get(buf) ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("invalid raw header");
 | 
				
			||||||
 | 
							return RS_Error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return getData(buf, size, start, end, maxBytes);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DataRecord::ReadStatus RawDataRecord::getData(streambuf &buf, int size,
 | 
				
			||||||
 | 
					                                              const Time &start, const Time &end,
 | 
				
			||||||
 | 
					                                              int maxBytes) {
 | 
				
			||||||
 | 
						bool partial = false;
 | 
				
			||||||
 | 
						int sampleOfs;
 | 
				
			||||||
 | 
						int sampleCount;
 | 
				
			||||||
 | 
						int dataTypeSize = sizeOf(_header.dataType);
 | 
				
			||||||
 | 
						if ( dataTypeSize == 0 ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("unknown data type: %d", _header.dataType);
 | 
				
			||||||
 | 
							return RS_Error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sampleCount = size / dataTypeSize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_startTime = timestampToTime(_header.samplingTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _header.samplingFrequencyDenominator > 0 &&
 | 
				
			||||||
 | 
						     _header.samplingFrequencyNumerator > 0 )
 | 
				
			||||||
 | 
							_endTime = _startTime + samplesToTimeSpan(_header, sampleCount);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							_endTime = Time();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( (start.valid() || end.valid()) && _endTime.valid() ) {
 | 
				
			||||||
 | 
							// Out of bounds?
 | 
				
			||||||
 | 
							if ( end.valid() && (end <= _startTime) )
 | 
				
			||||||
 | 
								return RS_AfterTimeWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( start.valid() && (start >= _endTime) )
 | 
				
			||||||
 | 
								return RS_BeforeTimeWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Trim packet front
 | 
				
			||||||
 | 
							if ( _startTime < start ) {
 | 
				
			||||||
 | 
								TimeSpan ofs = start - _startTime;
 | 
				
			||||||
 | 
								sampleOfs = timeSpanToSamplesCeil(_header, ofs);
 | 
				
			||||||
 | 
								sampleCount -= sampleOfs;
 | 
				
			||||||
 | 
								CAPS_DEBUG("Triming packet start: added offset of %d samples", sampleOfs);
 | 
				
			||||||
 | 
								_startTime += samplesToTimeSpan(_header, sampleOfs);
 | 
				
			||||||
 | 
								// Update header timespan
 | 
				
			||||||
 | 
								timeToTimestamp(_header.samplingTime, _startTime);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								sampleOfs = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( maxBytes > 0 ) {
 | 
				
			||||||
 | 
								int maxSamples = maxBytes / dataTypeSize;
 | 
				
			||||||
 | 
								// Here we need to clip the complete dataset and only
 | 
				
			||||||
 | 
								// return a partial record
 | 
				
			||||||
 | 
								if ( maxSamples < sampleCount ) {
 | 
				
			||||||
 | 
									CAPS_DEBUG("Clip %d available samples to %d", sampleCount, maxSamples);
 | 
				
			||||||
 | 
									_endTime -= samplesToTimeSpan(_header, sampleCount-maxSamples);
 | 
				
			||||||
 | 
									sampleCount = maxSamples;
 | 
				
			||||||
 | 
									partial = true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Trim back
 | 
				
			||||||
 | 
							if ( end.valid() && (end < _endTime) ) {
 | 
				
			||||||
 | 
								TimeSpan ofs = _endTime - end;
 | 
				
			||||||
 | 
								int trimEnd = timeSpanToSamplesFloor(_header, ofs);
 | 
				
			||||||
 | 
								sampleCount -= trimEnd;
 | 
				
			||||||
 | 
								_endTime = _startTime + samplesToTimeSpan(_header, sampleCount);
 | 
				
			||||||
 | 
								CAPS_DEBUG("Triming packet end: added offset of %d samples", trimEnd);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							sampleOfs = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( sampleCount == 0 ) return RS_Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_currentHeader = _header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch ( _header.dataType ) {
 | 
				
			||||||
 | 
							case DT_INT8:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Stay with little endian data
 | 
				
			||||||
 | 
								RIFF::VectorChunk<1,false> dataChunk(_data, sampleOfs, sampleCount);
 | 
				
			||||||
 | 
								if ( !dataChunk.get(buf, size) ) return RS_Error;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case DT_INT16:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Stay with little endian data
 | 
				
			||||||
 | 
								RIFF::VectorChunk<2,false> dataChunk(_data, sampleOfs, sampleCount);
 | 
				
			||||||
 | 
								if ( !dataChunk.get(buf, size) ) return RS_Error;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case DT_INT32:
 | 
				
			||||||
 | 
							case DT_FLOAT:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Stay with little endian data
 | 
				
			||||||
 | 
								RIFF::VectorChunk<4,false> dataChunk(_data, sampleOfs, sampleCount);
 | 
				
			||||||
 | 
								if ( !dataChunk.get(buf, size) ) return RS_Error;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case DT_INT64:
 | 
				
			||||||
 | 
							case DT_DOUBLE:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Stay with little endian data
 | 
				
			||||||
 | 
								RIFF::VectorChunk<8,false> dataChunk(_data, sampleOfs, sampleCount);
 | 
				
			||||||
 | 
								if ( !dataChunk.get(buf, size) ) return RS_Error;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								CAPS_ERROR("THIS SHOULD NEVER HAPPEN: ignored invalid data with type %d",
 | 
				
			||||||
 | 
								           _header.dataType);
 | 
				
			||||||
 | 
								return RS_Error;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Initialize indicies
 | 
				
			||||||
 | 
						_dataOfs = 0;
 | 
				
			||||||
 | 
						_dataSize = _data.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return partial?RS_Partial:RS_Complete;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RawDataRecord::put(std::streambuf &buf, bool withHeader) const {
 | 
				
			||||||
 | 
						if ( withHeader && !_currentHeader.put(buf) ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch ( _header.dataType ) {
 | 
				
			||||||
 | 
							case DT_INT8:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Data is already in little endian
 | 
				
			||||||
 | 
								RIFF::CPtrChunk<1,false> dataChunk(&_data[_dataOfs], _dataSize);
 | 
				
			||||||
 | 
								if ( !dataChunk.put(buf) )
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case DT_INT16:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Data is already in little endian
 | 
				
			||||||
 | 
								RIFF::CPtrChunk<2,false> dataChunk(&_data[_dataOfs], _dataSize);
 | 
				
			||||||
 | 
								if ( !dataChunk.put(buf) )
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case DT_INT32:
 | 
				
			||||||
 | 
							case DT_FLOAT:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Data is already in little endian
 | 
				
			||||||
 | 
								RIFF::CPtrChunk<4,false> dataChunk(&_data[_dataOfs], _dataSize);
 | 
				
			||||||
 | 
								if ( !dataChunk.put(buf) )
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case DT_INT64:
 | 
				
			||||||
 | 
							case DT_DOUBLE:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Data is already in little endian
 | 
				
			||||||
 | 
								RIFF::CPtrChunk<8,false> dataChunk(&_data[_dataOfs], _dataSize);
 | 
				
			||||||
 | 
								if ( !dataChunk.put(buf) )
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								CAPS_ERROR("THIS SHOULD NEVER HAPPEN: ignored invalid data with type %d",
 | 
				
			||||||
 | 
								           _header.dataType);
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void RawDataRecord::setBuffer(const void *data, size_t size) {
 | 
				
			||||||
 | 
						_data.resize(size);
 | 
				
			||||||
 | 
						_dataSize = size;
 | 
				
			||||||
 | 
						_dataOfs = 0;
 | 
				
			||||||
 | 
						memcpy(_data.data(), data, size);
 | 
				
			||||||
 | 
						_dirty = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *FixedRawDataRecord::formatName() const {
 | 
				
			||||||
 | 
						DT2STR("FIXEDRAW/", _currentHeader.dataType)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										237
									
								
								libs/gempa/caps/rawpacket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								libs/gempa/caps/rawpacket.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,237 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_RAWPACKET_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_RAWPACKET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API RawResponseHeader {
 | 
				
			||||||
 | 
						int64_t timeSeconds;
 | 
				
			||||||
 | 
						int32_t timeMicroSeconds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool get(std::streambuf &buf) {
 | 
				
			||||||
 | 
							Endianess::Reader get(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							get(timeSeconds);
 | 
				
			||||||
 | 
							get(timeMicroSeconds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return get.good;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int dataSize() const {
 | 
				
			||||||
 | 
							return sizeof(timeSeconds) + sizeof(timeMicroSeconds);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RawDataRecord : public DataRecord {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							RawDataRecord();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const char *formatName() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Reads metadata from data record header
 | 
				
			||||||
 | 
							 * @param The streambuf object
 | 
				
			||||||
 | 
							 * @param The size of the data record in bytes
 | 
				
			||||||
 | 
							 * @param The data record header object
 | 
				
			||||||
 | 
							 * @param The startTime
 | 
				
			||||||
 | 
							 * @param The endTime
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							bool readMetaData(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                  Header &header,
 | 
				
			||||||
 | 
							                  Time &startTime, Time &endTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setHeader(const Header &header);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns the meta information of the data if supported
 | 
				
			||||||
 | 
							 * @return The data record header
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							const Header *header() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns the start time of the record
 | 
				
			||||||
 | 
							 * @return The start time
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							Time startTime() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns the end time of the record
 | 
				
			||||||
 | 
							 * @return The end time
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							Time endTime() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief canTrim checks if data trimming is possible
 | 
				
			||||||
 | 
							 * without modifying preceding data
 | 
				
			||||||
 | 
							 * @return True, if data trimming is possible
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							bool canTrim() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief canMerge checks if data merging is possible
 | 
				
			||||||
 | 
							 * without modifying preceding data
 | 
				
			||||||
 | 
							 * @return True, if data merging is possible
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							bool canMerge() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief  Trims a record to start and end time. Trimming
 | 
				
			||||||
 | 
							 * should not modify any data but give access to trimmed
 | 
				
			||||||
 | 
							 * start and end times and the resulting data size. The trimming
 | 
				
			||||||
 | 
							 * also influences writing the record to a stream.
 | 
				
			||||||
 | 
							 * Trimming requires the resulting start time being greater
 | 
				
			||||||
 | 
							 * or equal than the requested start time.
 | 
				
			||||||
 | 
							 * (Un)Trimming to the original record is semantically
 | 
				
			||||||
 | 
							 * equal to passing an invalid start and end time.
 | 
				
			||||||
 | 
							 * @param start The requested start time
 | 
				
			||||||
 | 
							 * @param end The requested end time
 | 
				
			||||||
 | 
							 * @return  It returns true if trimming has been done or false
 | 
				
			||||||
 | 
							 * if an error occured or trimming is not supported.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							bool trim(const Time &start, const Time &end) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns the data size in bytes if the current state would
 | 
				
			||||||
 | 
							 * be written to a stream. Trimming has also to be taken into
 | 
				
			||||||
 | 
							 * account while calculating the size.
 | 
				
			||||||
 | 
							 * @param withHeader Take header into account
 | 
				
			||||||
 | 
							 * @return Returns the data size in bytes
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							size_t dataSize(bool withHeader) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Reads the packet data including header from a streambuf
 | 
				
			||||||
 | 
							 * and trims the data if possible to start and end.
 | 
				
			||||||
 | 
							 * If maxBytes is greater than 0 then the record should
 | 
				
			||||||
 | 
							 * not use more than this size of memory (in bytes).
 | 
				
			||||||
 | 
							 *
 | 
				
			||||||
 | 
							 * @param The streambuf object
 | 
				
			||||||
 | 
							 * @param The buffer size
 | 
				
			||||||
 | 
							 * @param The requested start time
 | 
				
			||||||
 | 
							 * @param The requested end time
 | 
				
			||||||
 | 
							 * @param The Max bytes to use
 | 
				
			||||||
 | 
							 * @return If not the complete record has been read, RS_Partial
 | 
				
			||||||
 | 
							 * must be returned, RS_Complete otherwise.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							ReadStatus get(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							               const Time &start = Time(),
 | 
				
			||||||
 | 
							               const Time &end = Time(),
 | 
				
			||||||
 | 
							               int maxBytes = -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Reads the packet data without header from a streambuf
 | 
				
			||||||
 | 
							 * and trims the data if possible to start and end.
 | 
				
			||||||
 | 
							 * If maxBytes is greater than 0 then the record should
 | 
				
			||||||
 | 
							 * not use more than this size of memory (in bytes).
 | 
				
			||||||
 | 
							 *
 | 
				
			||||||
 | 
							 * @param The streambuf object
 | 
				
			||||||
 | 
							 * @param The buffer size
 | 
				
			||||||
 | 
							 * @param The requested start time
 | 
				
			||||||
 | 
							 * @param The requested end time
 | 
				
			||||||
 | 
							 * @param The Max bytes to use
 | 
				
			||||||
 | 
							 * @return If not the complete record has been read, RS_Partial
 | 
				
			||||||
 | 
							 * must be returned, RS_Complete otherwise.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							ReadStatus getData(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                   const Time &start = Time(),
 | 
				
			||||||
 | 
							                   const Time &end = Time(),
 | 
				
			||||||
 | 
							                   int maxBytes = -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! writes the packet to a streambuf and trims the data
 | 
				
			||||||
 | 
							//! if possible to start and end
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Writes the packet to a streambuf and trims the data
 | 
				
			||||||
 | 
							 * if possible to start and end
 | 
				
			||||||
 | 
							 * @param The streambuf object
 | 
				
			||||||
 | 
							 * @param Take header into account
 | 
				
			||||||
 | 
							 * @return True, if the data has been written
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							bool put(std::streambuf &buf, bool withHeader) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Returns the packet type
 | 
				
			||||||
 | 
							 * @return The packet type
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							PacketType packetType() const { return RawDataPacket; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Sets the start time of the record
 | 
				
			||||||
 | 
							 * @param The start time
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							void setStartTime(const Time &time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Sets the sampling frequency of the record
 | 
				
			||||||
 | 
							 * @param numerator The numerator
 | 
				
			||||||
 | 
							 * @param denominator The denomintor
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							void setSamplingFrequency(uint16_t numerator, uint16_t denominator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Sets the data type of the record
 | 
				
			||||||
 | 
							 * @param The datatype to use
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							void setDataType(DataType dt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * @brief Initializes the internal data vector from the given buffer
 | 
				
			||||||
 | 
							 * @param The buffer to read the data from
 | 
				
			||||||
 | 
							 * @param The buffer size
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							void setBuffer(const void *data, size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							Header  _header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mutable Header  _currentHeader;
 | 
				
			||||||
 | 
							mutable size_t  _dataOfs;
 | 
				
			||||||
 | 
							mutable size_t  _dataSize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mutable Time    _startTime;
 | 
				
			||||||
 | 
							mutable Time    _endTime;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
							mutable bool    _dirty;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FixedRawDataRecord : public RawDataRecord {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							virtual bool canTrim() const { return false; }
 | 
				
			||||||
 | 
							virtual bool canMerge() const { return false; }
 | 
				
			||||||
 | 
							virtual bool trim(const Time &start, const Time &end) const { return false; }
 | 
				
			||||||
 | 
							virtual const char *formatName() const;
 | 
				
			||||||
 | 
							virtual ReadStatus get(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                       const Time &/*start*/, const Time &/*end*/,
 | 
				
			||||||
 | 
							                       int maxBytes) {
 | 
				
			||||||
 | 
								return RawDataRecord::get(buf, size, Time(), Time(), maxBytes);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							PacketType packetType() const { return FixedRawDataPacket; }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										137
									
								
								libs/gempa/caps/recordbuilder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								libs/gempa/caps/recordbuilder.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,137 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_RECORD_SAMPLER_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_RECORD_SAMPLER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/datetime.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <boost/shared_ptr.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> class RecordBuilder {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							struct Record {
 | 
				
			||||||
 | 
								Record() : samplingInterval(0.0), sampleCount(0), userData(NULL) {}
 | 
				
			||||||
 | 
								std::string    netcode;
 | 
				
			||||||
 | 
								std::string    stacode;
 | 
				
			||||||
 | 
								std::string    loccode;
 | 
				
			||||||
 | 
								std::string    chacode;
 | 
				
			||||||
 | 
								Time           startTime;
 | 
				
			||||||
 | 
								double         samplingInterval;
 | 
				
			||||||
 | 
								size_t         sampleCount;
 | 
				
			||||||
 | 
								std::vector<T> data;
 | 
				
			||||||
 | 
								void          *userData;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							typedef boost::shared_ptr<Record> RecordPtr;
 | 
				
			||||||
 | 
							typedef boost::function<void (Record *rec, void*)> FlushCallback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							RecordBuilder() : _bufSize(64) {}
 | 
				
			||||||
 | 
							RecordBuilder(const std::string &netcode, const std::string &stacode,
 | 
				
			||||||
 | 
							              const std::string &loccode, const std::string &chacode,
 | 
				
			||||||
 | 
							              void *userData = NULL, size_t bufSize = 64) {
 | 
				
			||||||
 | 
								_networkCode = netcode;
 | 
				
			||||||
 | 
								_stationCode = stacode;
 | 
				
			||||||
 | 
								_locationCode = loccode;
 | 
				
			||||||
 | 
								_channelCode = chacode;
 | 
				
			||||||
 | 
								_userData = userData;
 | 
				
			||||||
 | 
								_bufSize = bufSize > 0? bufSize:1;
 | 
				
			||||||
 | 
								_record = NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void flush(bool lastSample = false) {
 | 
				
			||||||
 | 
								if ( _record != 0 ) {
 | 
				
			||||||
 | 
									 if ( lastSample ) push();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									_flushCallback(_record, _userData);
 | 
				
			||||||
 | 
									_record = NULL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void push(T value, const Time &time) {
 | 
				
			||||||
 | 
								if ( _time.valid() ) {
 | 
				
			||||||
 | 
									double interval = time - _time;
 | 
				
			||||||
 | 
									if ( interval <= 0.0 ) {
 | 
				
			||||||
 | 
										_time = Time();
 | 
				
			||||||
 | 
										flush(true);
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										if ( _record == NULL) {
 | 
				
			||||||
 | 
											_record = new Record;
 | 
				
			||||||
 | 
											if ( _record ) {
 | 
				
			||||||
 | 
												_record->netcode = _networkCode;
 | 
				
			||||||
 | 
												_record->stacode = _stationCode;
 | 
				
			||||||
 | 
												_record->loccode = _locationCode;
 | 
				
			||||||
 | 
												_record->chacode = _channelCode;
 | 
				
			||||||
 | 
												_record->startTime = _time;
 | 
				
			||||||
 | 
												_record->samplingInterval = interval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												_record->data.reserve(_bufSize);
 | 
				
			||||||
 | 
												_record->data[_record->sampleCount] = _value;
 | 
				
			||||||
 | 
												++_record->sampleCount;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else if ( interval != _record->samplingInterval ) {
 | 
				
			||||||
 | 
											flush(true);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else {
 | 
				
			||||||
 | 
											push();
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								_time = time;
 | 
				
			||||||
 | 
								_value = value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setFlushCallback(const FlushCallback &cb) { _flushCallback = cb; }
 | 
				
			||||||
 | 
							void setNetworkCode(const std::string &netcode) { _networkCode = netcode; }
 | 
				
			||||||
 | 
							void setStationCode(const std::string &stacode) { _stationCode = stacode; }
 | 
				
			||||||
 | 
							void setLocationCode(const std::string &loccode) { _locationCode = loccode; }
 | 
				
			||||||
 | 
							void setChannelCode(const std::string &chacode) { _channelCode = chacode; }
 | 
				
			||||||
 | 
							void setUserData(void *userData) { _userData = userData; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							void push() {
 | 
				
			||||||
 | 
								if ( _record->sampleCount % _bufSize == 0 )
 | 
				
			||||||
 | 
									_record->data.reserve(_record->sampleCount + _bufSize);
 | 
				
			||||||
 | 
								_record->data[_record->sampleCount] = _value;
 | 
				
			||||||
 | 
								++_record->sampleCount;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							T                       _value;
 | 
				
			||||||
 | 
							Time                    _time;
 | 
				
			||||||
 | 
							Record                 *_record;
 | 
				
			||||||
 | 
							FlushCallback           _flushCallback;
 | 
				
			||||||
 | 
							size_t                  _bufSize;
 | 
				
			||||||
 | 
							std::string             _networkCode;
 | 
				
			||||||
 | 
							std::string             _stationCode;
 | 
				
			||||||
 | 
							std::string             _locationCode;
 | 
				
			||||||
 | 
							std::string             _channelCode;
 | 
				
			||||||
 | 
							void                   *_userData;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										398
									
								
								libs/gempa/caps/riff.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										398
									
								
								libs/gempa/caps/riff.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,398 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/riff.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/endianess.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					namespace RIFF {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ChunkHeader::setChunkType(const char *t) {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( t != NULL ) {
 | 
				
			||||||
 | 
							for ( i = 0; i < 4; ++i ) {
 | 
				
			||||||
 | 
								if ( t[i] == '\0' ) break;
 | 
				
			||||||
 | 
								chunkType[i] = t[i];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Input type must not have more than 4 characters
 | 
				
			||||||
 | 
							if ( i == 3 && t[i] != '\0' && t[i+1] != '\0' ) {
 | 
				
			||||||
 | 
								memset(chunkType, ' ', 4);
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Pad with whitespaces
 | 
				
			||||||
 | 
						for ( ; i < 4; ++i )
 | 
				
			||||||
 | 
							chunkType[i] = ' ';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ChunkHeader::isChunkType(const char *t) const {
 | 
				
			||||||
 | 
						for ( int i = 0; i < 4; ++i ) {
 | 
				
			||||||
 | 
							if ( t[i] == '\0' && chunkType[i] == ' ' ) break;
 | 
				
			||||||
 | 
							if ( t[i] != chunkType[i] ) return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ChunkHeader::validChunkType() const {
 | 
				
			||||||
 | 
						for ( int i = 0; i < 4; ++i ) {
 | 
				
			||||||
 | 
							if ( chunkType[i] == '\0' ) continue;
 | 
				
			||||||
 | 
							if ( chunkType[i] >= 'a' && chunkType[i] <= 'z' ) continue;
 | 
				
			||||||
 | 
							if ( chunkType[i] >= 'A' && chunkType[i] <= 'Z' ) continue;
 | 
				
			||||||
 | 
							if ( chunkType[i] >= '0' && chunkType[i] <= '9' ) continue;
 | 
				
			||||||
 | 
							if ( chunkType[i] == '-' ) continue;
 | 
				
			||||||
 | 
							if ( chunkType[i] == '_' ) continue;
 | 
				
			||||||
 | 
							if ( chunkType[i] == ' ' ) continue;
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ChunkHeader::get(std::streambuf &input) {
 | 
				
			||||||
 | 
						Endianess::Reader get(input);
 | 
				
			||||||
 | 
						get(chunkType, 4);
 | 
				
			||||||
 | 
						get(chunkSize);
 | 
				
			||||||
 | 
						return get.good;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ChunkHeader::put(std::streambuf &output) const {
 | 
				
			||||||
 | 
						Endianess::Writer put(output);
 | 
				
			||||||
 | 
						put(chunkType, 4);
 | 
				
			||||||
 | 
						put(chunkSize);
 | 
				
			||||||
 | 
						return put.good;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ChunkIterator::ChunkIterator() : _stream(&_own) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ChunkIterator::ChunkIterator(const std::string &filename) {
 | 
				
			||||||
 | 
						begin(filename);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ChunkIterator::ChunkIterator(std::istream &input) {
 | 
				
			||||||
 | 
						begin(input);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ChunkIterator::begin(const std::string &filename) {
 | 
				
			||||||
 | 
						_stream = &_own;
 | 
				
			||||||
 | 
						_index = 0;
 | 
				
			||||||
 | 
						_own.open(filename.c_str());
 | 
				
			||||||
 | 
						memset(&_header, 0, sizeof(_header));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ChunkIterator::begin(std::istream &input) {
 | 
				
			||||||
 | 
						_stream = &input;
 | 
				
			||||||
 | 
						_index = input.tellg();
 | 
				
			||||||
 | 
						_header.chunkSize = 0;
 | 
				
			||||||
 | 
						memset(&_header, 0, sizeof(_header));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ChunkIterator::next() {
 | 
				
			||||||
 | 
						while ( _stream->good() ) {
 | 
				
			||||||
 | 
							// Jump to next header
 | 
				
			||||||
 | 
							_stream->seekg(_index + _header.chunkSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( !_header.read(*_stream) )
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//std::cout << " - "; std::cout.write(_header.chunkType, 4); std::cout << " : " << _header.chunkSize << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							_index = _stream->tellg();
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChunkHeader &ChunkIterator::header() const {
 | 
				
			||||||
 | 
						return _header;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t ChunkIterator::headerPos() const {
 | 
				
			||||||
 | 
						return _index - _header.dataSize();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t ChunkIterator::contentPos() const {
 | 
				
			||||||
 | 
						return _index;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Chunk::~Chunk() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool HeadChunk::get(std::streambuf &input, int size) {
 | 
				
			||||||
 | 
						Endianess::Reader r(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r(data.version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char dt;
 | 
				
			||||||
 | 
						r(dt);
 | 
				
			||||||
 | 
						data.packetType = static_cast<PacketType>(dt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r(data.unitOfMeasurement.str, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return r.good;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool HeadChunk::put(std::streambuf &output) const {
 | 
				
			||||||
 | 
						Endianess::Writer w(output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						w(data.version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char dt = data.packetType;
 | 
				
			||||||
 | 
						w(dt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						w(data.unitOfMeasurement.str, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return w.good;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int HeadChunk::chunkSize() const {
 | 
				
			||||||
 | 
						return sizeof(data.version) +
 | 
				
			||||||
 | 
						       sizeof(data.unitOfMeasurement.str) +
 | 
				
			||||||
 | 
						       sizeof(char);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool SIDChunk::put(std::streambuf &output) const {
 | 
				
			||||||
 | 
						char null = '\0';
 | 
				
			||||||
 | 
						Endianess::Writer w(output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !networkCode.empty() )
 | 
				
			||||||
 | 
							w(networkCode.c_str(), networkCode.size());
 | 
				
			||||||
 | 
						w(&null, 1);
 | 
				
			||||||
 | 
						if ( !stationCode.empty() )
 | 
				
			||||||
 | 
							w(stationCode.c_str(), stationCode.size());
 | 
				
			||||||
 | 
						w(&null, 1);
 | 
				
			||||||
 | 
						if ( !locationCode.empty() )
 | 
				
			||||||
 | 
							w(locationCode.c_str(), locationCode.size());
 | 
				
			||||||
 | 
						w(&null, 1);
 | 
				
			||||||
 | 
						if ( !channelCode.empty() )
 | 
				
			||||||
 | 
							w(channelCode.c_str(), channelCode.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return w.good;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool SIDChunk::get(std::streambuf &input, int size) {
 | 
				
			||||||
 | 
						char tmp;
 | 
				
			||||||
 | 
						int  count = size;
 | 
				
			||||||
 | 
						Endianess::Reader r(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r(&tmp, 1);
 | 
				
			||||||
 | 
						networkCode.clear();
 | 
				
			||||||
 | 
						while ( r.good && count-- ) {
 | 
				
			||||||
 | 
							if ( tmp == '\0' ) break;
 | 
				
			||||||
 | 
							networkCode += tmp;
 | 
				
			||||||
 | 
							r(&tmp, 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !r.good ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r(&tmp, 1);
 | 
				
			||||||
 | 
						stationCode.clear();
 | 
				
			||||||
 | 
						while ( r.good && count-- ) {
 | 
				
			||||||
 | 
							if ( tmp == '\0' ) break;
 | 
				
			||||||
 | 
							stationCode += tmp;
 | 
				
			||||||
 | 
							r(&tmp, 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !r.good ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r(&tmp, 1);
 | 
				
			||||||
 | 
						locationCode.clear();
 | 
				
			||||||
 | 
						while ( r.good && count-- ) {
 | 
				
			||||||
 | 
							if ( tmp == '\0' ) break;
 | 
				
			||||||
 | 
							locationCode += tmp;
 | 
				
			||||||
 | 
							r(&tmp, 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( !r.good ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r(&tmp, 1);
 | 
				
			||||||
 | 
						channelCode.clear();
 | 
				
			||||||
 | 
						while ( r.good && count-- ) {
 | 
				
			||||||
 | 
							if ( tmp == '\0' ) break;
 | 
				
			||||||
 | 
							channelCode += tmp;
 | 
				
			||||||
 | 
							r(&tmp, 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int SIDChunk::chunkSize() const {
 | 
				
			||||||
 | 
						return networkCode.size() + 1 +
 | 
				
			||||||
 | 
						       stationCode.size() + 1 +
 | 
				
			||||||
 | 
						       locationCode.size() + 1 +
 | 
				
			||||||
 | 
						       channelCode.size();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					CPtrChunk<SIZE_T,BigEndian>::CPtrChunk(const char* d, int len) : data(d), size(len) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					int CPtrChunk<SIZE_T,BigEndian>::chunkSize() const {
 | 
				
			||||||
 | 
						return size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					bool CPtrChunk<SIZE_T,BigEndian>::get(std::streambuf &, int) {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T, int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					struct CPtrWriter {
 | 
				
			||||||
 | 
						static bool Take(std::streambuf &output, const T*, int count);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// To little endian
 | 
				
			||||||
 | 
					template <typename T, int SIZE_T>
 | 
				
			||||||
 | 
					struct CPtrWriter<T,SIZE_T,true> {
 | 
				
			||||||
 | 
						static bool Take(std::streambuf &output, const T *data, int count) {
 | 
				
			||||||
 | 
							Endianess::Writer w(output);
 | 
				
			||||||
 | 
							for ( int i = 0; i < count; ++i ) {
 | 
				
			||||||
 | 
								T tmp = Endianess::Swapper<T,true,SIZE_T>::Take(data[i]);
 | 
				
			||||||
 | 
								w((const char*)&tmp, SIZE_T);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return w.good;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T, int SIZE_T>
 | 
				
			||||||
 | 
					struct CPtrWriter<T,SIZE_T,false> {
 | 
				
			||||||
 | 
						static bool Take(std::streambuf &output, const T *data, int count) {
 | 
				
			||||||
 | 
							return (int)output.sputn((const char*)data, SIZE_T*count) == SIZE_T*count;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					bool CPtrChunk<SIZE_T,BigEndian>::put(std::streambuf &output) const {
 | 
				
			||||||
 | 
						typedef typename Endianess::TypeMap<SIZE_T>::ValueType T;
 | 
				
			||||||
 | 
						return CPtrWriter<T,SIZE_T,BigEndian>::Take(output, (const T*)data, size/SIZE_T);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					VectorChunk<SIZE_T,BigEndian>::VectorChunk(std::vector<char> &d)
 | 
				
			||||||
 | 
					: data(d), startOfs(-1), len(-1) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					VectorChunk<SIZE_T,BigEndian>::VectorChunk(std::vector<char> &d, int ofs, int count)
 | 
				
			||||||
 | 
					: data(d), startOfs(ofs), len(count) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					int VectorChunk<SIZE_T,BigEndian>::chunkSize() const {
 | 
				
			||||||
 | 
						return data.size();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					bool VectorChunk<SIZE_T,BigEndian>::get(std::streambuf &input, int size) {
 | 
				
			||||||
 | 
						int count = size/SIZE_T;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( len >= 0 ) {
 | 
				
			||||||
 | 
							if ( len > count )
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							count = len;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Skip first samples (bytes = samples*sizeof(T))
 | 
				
			||||||
 | 
						if ( startOfs > 0 )
 | 
				
			||||||
 | 
							input.pubseekoff(startOfs*SIZE_T, std::ios_base::cur, std::ios_base::in);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Endianess::Reader r(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data.resize(count*SIZE_T);
 | 
				
			||||||
 | 
						r(&data[0], data.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Convert array to little endian
 | 
				
			||||||
 | 
						Endianess::ByteSwapper<BigEndian,SIZE_T>::Take(&data[0], count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Go the end of chunk
 | 
				
			||||||
 | 
						if ( (int)data.size() < size )
 | 
				
			||||||
 | 
							input.pubseekoff(size-data.size(), std::ios_base::cur, std::ios_base::in);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return r.good;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					bool VectorChunk<SIZE_T,BigEndian>::put(std::streambuf &output) const {
 | 
				
			||||||
 | 
						typedef typename Endianess::TypeMap<SIZE_T>::ValueType T;
 | 
				
			||||||
 | 
						return CPtrWriter<T,SIZE_T,BigEndian>::Take(output, (const T*)data.data(), data.size()/SIZE_T);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API CPtrChunk<1,false>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API CPtrChunk<1,true>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API CPtrChunk<2,false>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API CPtrChunk<2,true>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API CPtrChunk<4,false>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API CPtrChunk<4,true>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API CPtrChunk<8,false>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API CPtrChunk<8,true>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API VectorChunk<1,false>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API VectorChunk<1,true>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API VectorChunk<2,false>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API VectorChunk<2,true>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API VectorChunk<4,false>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API VectorChunk<4,true>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API VectorChunk<8,false>;
 | 
				
			||||||
 | 
					template struct SC_GEMPA_CAPS_API VectorChunk<8,true>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										193
									
								
								libs/gempa/caps/riff.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								libs/gempa/caps/riff.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,193 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2009 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CAPS_IO_RIFF_H
 | 
				
			||||||
 | 
					#define CAPS_IO_RIFF_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					namespace RIFF {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API ChunkHeader {
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							char     chunkType[4];
 | 
				
			||||||
 | 
							uint32_t chunkID;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int  chunkSize;    /* Chunk size in bytes */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool setChunkType(const char *type);
 | 
				
			||||||
 | 
						bool isChunkType(const char *type) const;
 | 
				
			||||||
 | 
						bool validChunkType() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int  dataSize() const { return 8; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool read(std::istream &input) { return get(*input.rdbuf()); }
 | 
				
			||||||
 | 
						bool write(std::ostream &output) const { return put(*output.rdbuf()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool get(std::streambuf &input);
 | 
				
			||||||
 | 
						bool put(std::streambuf &output) const;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const int ChunkHeaderSize = 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SC_GEMPA_CAPS_API ChunkIterator {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							ChunkIterator();
 | 
				
			||||||
 | 
							ChunkIterator(const std::string &filename);
 | 
				
			||||||
 | 
							ChunkIterator(std::istream &input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Starts iterating over a file or stream
 | 
				
			||||||
 | 
							void begin(const std::string &filename);
 | 
				
			||||||
 | 
							void begin(std::istream &input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Jumps to the next chunk. Returns false,
 | 
				
			||||||
 | 
							//! if no chunk is available
 | 
				
			||||||
 | 
							bool next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the current chunk header
 | 
				
			||||||
 | 
							const ChunkHeader &header() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the file position pointing
 | 
				
			||||||
 | 
							//! to the current chunk header
 | 
				
			||||||
 | 
							size_t headerPos() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the file position pointing
 | 
				
			||||||
 | 
							//! to the current chunk content
 | 
				
			||||||
 | 
							size_t contentPos() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Returns the current input stream
 | 
				
			||||||
 | 
							std::istream &istream() const { return *_stream; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							ChunkHeader    _header;
 | 
				
			||||||
 | 
							std::istream  *_stream;
 | 
				
			||||||
 | 
							size_t         _index;
 | 
				
			||||||
 | 
							std::ifstream  _own;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API Chunk {
 | 
				
			||||||
 | 
						virtual ~Chunk();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool read(std::istream &input, int size) { return get(*input.rdbuf(), size); }
 | 
				
			||||||
 | 
						bool write(std::ostream &output) const { return put(*output.rdbuf()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						virtual bool get(std::streambuf &input, int size) = 0;
 | 
				
			||||||
 | 
						virtual bool put(std::streambuf &output) const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						virtual int chunkSize() const = 0;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API HeadChunk : Chunk {
 | 
				
			||||||
 | 
						PacketDataHeader data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int chunkSize() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool get(std::streambuf &input, int size);
 | 
				
			||||||
 | 
						bool put(std::streambuf &output) const;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API SID {
 | 
				
			||||||
 | 
						std::string networkCode;
 | 
				
			||||||
 | 
						std::string stationCode;
 | 
				
			||||||
 | 
						std::string locationCode;
 | 
				
			||||||
 | 
						std::string channelCode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool operator==(const SID &other ) const {
 | 
				
			||||||
 | 
							return networkCode == other.networkCode &&
 | 
				
			||||||
 | 
							       stationCode == other.stationCode &&
 | 
				
			||||||
 | 
							       locationCode == other.locationCode &&
 | 
				
			||||||
 | 
							       channelCode == other.channelCode;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool operator!=(const SID &other ) const {
 | 
				
			||||||
 | 
							return networkCode != other.networkCode ||
 | 
				
			||||||
 | 
							       stationCode != other.stationCode ||
 | 
				
			||||||
 | 
							       locationCode != other.locationCode ||
 | 
				
			||||||
 | 
							       channelCode != other.channelCode;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::string toString() const {
 | 
				
			||||||
 | 
							return networkCode + "." + stationCode + "." +
 | 
				
			||||||
 | 
							       locationCode + "." + channelCode;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SC_GEMPA_CAPS_API SIDChunk : Chunk, SID {
 | 
				
			||||||
 | 
						int chunkSize() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool get(std::streambuf &input, int size);
 | 
				
			||||||
 | 
						bool put(std::streambuf &output) const;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					struct CPtrChunk : Chunk {
 | 
				
			||||||
 | 
						const char *data;
 | 
				
			||||||
 | 
						int size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CPtrChunk(const char* d, int len);
 | 
				
			||||||
 | 
						virtual ~CPtrChunk() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int chunkSize() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool get(std::streambuf &input, int size);
 | 
				
			||||||
 | 
						bool put(std::streambuf &output) const;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <int SIZE_T, bool BigEndian>
 | 
				
			||||||
 | 
					struct VectorChunk : Chunk {
 | 
				
			||||||
 | 
						std::vector<char> &data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VectorChunk(std::vector<char> &d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// sampleOfs and sampleCount are not byte offsets but elements of
 | 
				
			||||||
 | 
						// type T
 | 
				
			||||||
 | 
						VectorChunk(std::vector<char> &d, int sampleOfs, int sampleCount);
 | 
				
			||||||
 | 
						virtual ~VectorChunk() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int chunkSize() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool get(std::streambuf &input, int size);
 | 
				
			||||||
 | 
						bool put(std::streambuf &output) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int startOfs;
 | 
				
			||||||
 | 
						int len;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										174
									
								
								libs/gempa/caps/rtcm2packet.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								libs/gempa/caps/rtcm2packet.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,174 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/rtcm2packet.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/riff.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <streambuf>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RTCM2DataRecord::RTCM2Header::put(std::streambuf &buf) const {
 | 
				
			||||||
 | 
						Endianess::Writer put(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						put(samplingTime.year);
 | 
				
			||||||
 | 
						put(samplingTime.yday);
 | 
				
			||||||
 | 
						put(samplingTime.hour);
 | 
				
			||||||
 | 
						put(samplingTime.minute);
 | 
				
			||||||
 | 
						put(samplingTime.second);
 | 
				
			||||||
 | 
						put(samplingTime.usec);
 | 
				
			||||||
 | 
						put(samplingFrequencyNumerator);
 | 
				
			||||||
 | 
						put(samplingFrequencyDenominator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return put.good;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RTCM2DataRecord::RTCM2DataRecord() {
 | 
				
			||||||
 | 
						_header.samplingFrequencyDenominator = 0;
 | 
				
			||||||
 | 
						_header.samplingFrequencyNumerator = 0;
 | 
				
			||||||
 | 
						// Just a bunch of bytes
 | 
				
			||||||
 | 
						_header.dataType = DT_Unknown;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void RTCM2DataRecord::setTimeStamp(const Time &ts) {
 | 
				
			||||||
 | 
						 timeToTimestamp(_header.samplingTime, ts);
 | 
				
			||||||
 | 
						_startTime = ts;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void RTCM2DataRecord::setSamplingFrequency(uint16_t numerator, uint16_t denominator) {
 | 
				
			||||||
 | 
						_header.samplingFrequencyNumerator = numerator;
 | 
				
			||||||
 | 
						_header.samplingFrequencyDenominator = denominator;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *RTCM2DataRecord::formatName() const {
 | 
				
			||||||
 | 
						return "RTC2";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RTCM2DataRecord::readMetaData(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
					                                 Header &header,
 | 
				
			||||||
 | 
					                                 Time &startTime, Time &endTime) {
 | 
				
			||||||
 | 
						Endianess::Reader get(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						get(header.samplingTime.year);
 | 
				
			||||||
 | 
						get(header.samplingTime.yday);
 | 
				
			||||||
 | 
						get(header.samplingTime.hour);
 | 
				
			||||||
 | 
						get(header.samplingTime.minute);
 | 
				
			||||||
 | 
						get(header.samplingTime.second);
 | 
				
			||||||
 | 
						get(header.samplingTime.usec);
 | 
				
			||||||
 | 
						get(header.samplingFrequencyNumerator);
 | 
				
			||||||
 | 
						get(header.samplingFrequencyDenominator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						startTime = timestampToTime(header.samplingTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (  header.samplingFrequencyDenominator == 0 ||
 | 
				
			||||||
 | 
						       header.samplingFrequencyNumerator == 0 ) {
 | 
				
			||||||
 | 
							endTime = startTime;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							TimeSpan ts =
 | 
				
			||||||
 | 
							    header.samplingFrequencyDenominator / header.samplingFrequencyNumerator;
 | 
				
			||||||
 | 
							endTime = startTime + ts;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DataRecord::Header *RTCM2DataRecord::header() const {
 | 
				
			||||||
 | 
						return &_header;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Time RTCM2DataRecord::startTime() const {
 | 
				
			||||||
 | 
						return _startTime;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Time RTCM2DataRecord::endTime() const {
 | 
				
			||||||
 | 
						return _endTime;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RTCM2DataRecord::canTrim() const {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RTCM2DataRecord::canMerge() const {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RTCM2DataRecord::trim(const Time &start,
 | 
				
			||||||
 | 
					                           const Time &end) const {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t RTCM2DataRecord::dataSize(bool withHeader) const {
 | 
				
			||||||
 | 
						if ( withHeader )
 | 
				
			||||||
 | 
							return _data.size() + _header.dataSize();
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return _data.size();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DataRecord::ReadStatus RTCM2DataRecord::get(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
					                                            const Time &start, const Time &end,
 | 
				
			||||||
 | 
					                                            int) {
 | 
				
			||||||
 | 
						size -= _header.dataSize();
 | 
				
			||||||
 | 
						if ( size < 0 ) return RS_Error;
 | 
				
			||||||
 | 
						if ( !_header.get(buf) ) return RS_Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _header.samplingFrequencyNumerator == 0 ||
 | 
				
			||||||
 | 
						     _header.samplingFrequencyDenominator == 0 ) {
 | 
				
			||||||
 | 
							CAPS_ERROR("Sampling frequency not set");
 | 
				
			||||||
 | 
							return RS_Error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						TimeSpan ts =
 | 
				
			||||||
 | 
						    _header.samplingFrequencyDenominator / _header.samplingFrequencyNumerator;
 | 
				
			||||||
 | 
						_startTime = timestampToTime(_header.samplingTime);
 | 
				
			||||||
 | 
						_endTime = _startTime + ts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( end.valid() && (end <= _startTime) ) return RS_AfterTimeWindow;
 | 
				
			||||||
 | 
						if ( start.valid() && (start >= _endTime) ) return RS_BeforeTimeWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RIFF::VectorChunk<1,false> dataChunk(_data, 0, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return dataChunk.get(buf, size)?RS_Complete:RS_Error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool RTCM2DataRecord::put(std::streambuf &buf, bool withHeader) const {
 | 
				
			||||||
 | 
						if ( withHeader && !_header.put(buf) ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RIFF::CPtrChunk<1,false> dataChunk(&_data[0], _data.size());
 | 
				
			||||||
 | 
						return dataChunk.put(buf);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										109
									
								
								libs/gempa/caps/rtcm2packet.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								libs/gempa/caps/rtcm2packet.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_RTCM2PACKET_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_RTCM2PACKET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/endianess.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RTCM2DataRecord : public DataRecord {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							struct RTCM2Header : Header {
 | 
				
			||||||
 | 
								bool get(std::streambuf &buf) {
 | 
				
			||||||
 | 
									Endianess::Reader get(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									get(samplingTime.year);
 | 
				
			||||||
 | 
									get(samplingTime.yday);
 | 
				
			||||||
 | 
									get(samplingTime.hour);
 | 
				
			||||||
 | 
									get(samplingTime.minute);
 | 
				
			||||||
 | 
									get(samplingTime.second);
 | 
				
			||||||
 | 
									get(samplingTime.usec);
 | 
				
			||||||
 | 
									get(samplingFrequencyNumerator);
 | 
				
			||||||
 | 
									get(samplingFrequencyDenominator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return get.good;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bool put(std::streambuf &buf) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// size of data header
 | 
				
			||||||
 | 
								int dataSize() const {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
									       sizeof(samplingTime.year) +
 | 
				
			||||||
 | 
									       sizeof(samplingTime.yday) +
 | 
				
			||||||
 | 
									       sizeof(samplingTime.hour) +
 | 
				
			||||||
 | 
									       sizeof(samplingTime.minute) +
 | 
				
			||||||
 | 
									       sizeof(samplingTime.second) +
 | 
				
			||||||
 | 
									       sizeof(samplingTime.usec) +
 | 
				
			||||||
 | 
									       sizeof(samplingFrequencyNumerator) +
 | 
				
			||||||
 | 
									       sizeof(samplingFrequencyDenominator);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							RTCM2DataRecord();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const char* formatName() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setTimeStamp(const Time &ts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setSamplingFrequency(uint16_t numerator, uint16_t denominator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool readMetaData(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                          Header &header,
 | 
				
			||||||
 | 
							                          Time &startTime,
 | 
				
			||||||
 | 
							                          Time &endTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual const Header *header() const;
 | 
				
			||||||
 | 
							virtual Time startTime() const;
 | 
				
			||||||
 | 
							virtual Time endTime() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool canTrim() const;
 | 
				
			||||||
 | 
							virtual bool canMerge() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool trim(const Time &start,
 | 
				
			||||||
 | 
							                  const Time &end) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual size_t dataSize(bool withHeader) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual ReadStatus get(std::streambuf &buf, int size,
 | 
				
			||||||
 | 
							                       const Time &start,
 | 
				
			||||||
 | 
							                       const Time &end,
 | 
				
			||||||
 | 
							                       int maxSize = -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual bool put(std::streambuf &buf, bool withHeader) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PacketType packetType() const { return RTCM2Packet; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							RTCM2Header          _header;
 | 
				
			||||||
 | 
							Buffer               _data;
 | 
				
			||||||
 | 
							Time                 _startTime;
 | 
				
			||||||
 | 
							Time                 _endTime;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										404
									
								
								libs/gempa/caps/sessiontable.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										404
									
								
								libs/gempa/caps/sessiontable.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,404 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include  <gempa/caps/sessiontable.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace  CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setDataType(const char *data, int len, Gempa::CAPS::SessionTableItem &item) {
 | 
				
			||||||
 | 
						if ( CHECK_STRING(data, "FLOAT", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_FLOAT;
 | 
				
			||||||
 | 
							item.dataSize = 4;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 32bit floats", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( CHECK_STRING(data, "DOUBLE", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_DOUBLE;
 | 
				
			||||||
 | 
							item.dataSize = 8;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 64bit doubles", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( CHECK_STRING(data, "INT64", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_INT64;
 | 
				
			||||||
 | 
							item.dataSize = 8;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 64bit integers", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( CHECK_STRING(data, "INT32", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_INT32;
 | 
				
			||||||
 | 
							item.dataSize = 4;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 32bit integers", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( CHECK_STRING(data, "INT16", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_INT16;
 | 
				
			||||||
 | 
							item.dataSize = 2;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 16bit integers", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( CHECK_STRING(data, "INT8", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_INT8;
 | 
				
			||||||
 | 
							item.dataSize = 1;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 8bit integers", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							item.dataType = DT_Unknown;
 | 
				
			||||||
 | 
							CAPS_WARNING("Unknown raw data type '%s', all packages will be ignored",
 | 
				
			||||||
 | 
							            string(data, len).c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool SessionTableItem::splitStreamID() {
 | 
				
			||||||
 | 
						const char *tok;
 | 
				
			||||||
 | 
						int tok_len;
 | 
				
			||||||
 | 
						int tok_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char* str = streamID.c_str();
 | 
				
			||||||
 | 
						int len = strlen(str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						string *items[] = {&net, &sta, &loc, &cha};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for ( ; (tok = tokenize(str, ".", len, tok_len)) != NULL;
 | 
				
			||||||
 | 
						      ++tok_count ) {
 | 
				
			||||||
 | 
							if ( tok_count > 4 ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							items[tok_count]->assign(tok, tok_len);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( tok_count == 3 ) {
 | 
				
			||||||
 | 
							cha = loc;
 | 
				
			||||||
 | 
							loc = "";
 | 
				
			||||||
 | 
							tok_count = 4;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return tok_count == 4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SessionTable::SessionTable() : _state(Unspecific) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SessionTable::Status SessionTable::handleResponse(const char *src_data, int data_len) {
 | 
				
			||||||
 | 
						enum StreamHeaderToken {
 | 
				
			||||||
 | 
							REQ_ID = 0,
 | 
				
			||||||
 | 
							SID    = 1,
 | 
				
			||||||
 | 
							SF     = 2,
 | 
				
			||||||
 | 
							UOM    = 3,
 | 
				
			||||||
 | 
							FORMAT = 4,
 | 
				
			||||||
 | 
							COUNT  = 5
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int src_len = data_len;
 | 
				
			||||||
 | 
						const char *src = src_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int len;
 | 
				
			||||||
 | 
						const char *data;
 | 
				
			||||||
 | 
						if ( (data = tokenize(src_data, " ", data_len, len)) == NULL ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("server returned empty line, ignoring");
 | 
				
			||||||
 | 
							return Success;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch ( _state ) {
 | 
				
			||||||
 | 
							case Unspecific:
 | 
				
			||||||
 | 
								if ( CHECK_STRING(data, "STATUS", len) ) {
 | 
				
			||||||
 | 
									if ( (data = tokenize(src_data, " ", data_len, len)) != NULL ) {
 | 
				
			||||||
 | 
										if ( CHECK_STRING(data, "OK", len) ) {
 | 
				
			||||||
 | 
											CAPS_DEBUG("server responds OK");
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else {
 | 
				
			||||||
 | 
											CAPS_ERROR("received unknown status from server: %s", data);
 | 
				
			||||||
 | 
											return Error;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										CAPS_ERROR("received empty status from server");
 | 
				
			||||||
 | 
										return Error;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if ( CHECK_STRING(data, "REQUESTS", len) ) {
 | 
				
			||||||
 | 
									if ( (data = tokenize(src_data, " ", data_len, len)) != NULL ) {
 | 
				
			||||||
 | 
										CAPS_WARNING("received unknown REQUESTS parameter: %s", data);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									CAPS_DEBUG("stream table update started");
 | 
				
			||||||
 | 
									_state = Requests;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if ( CHECK_STRING(data, "EOD", len) ) {
 | 
				
			||||||
 | 
									CAPS_DEBUG("server sent EOD");
 | 
				
			||||||
 | 
									return EOD;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									CAPS_ERROR("received unknown response: %s", data);
 | 
				
			||||||
 | 
									return Error;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case Requests:
 | 
				
			||||||
 | 
								if ( CHECK_STRING(data, "END", len) ) {
 | 
				
			||||||
 | 
									if ( (data = tokenize(src_data, " ", data_len, len)) != NULL ) {
 | 
				
			||||||
 | 
										CAPS_WARNING("received unknown END parameter: %s", data);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									CAPS_DEBUG("stream table update complete");
 | 
				
			||||||
 | 
									_state = Unspecific;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								CAPS_DEBUG("request response data: %s", string(data, len).c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								typedef std::pair<const char *, int> Buffer;
 | 
				
			||||||
 | 
								const char *state = src;
 | 
				
			||||||
 | 
								Buffer toks[COUNT];
 | 
				
			||||||
 | 
								for ( int i = 0; i < COUNT; ++i )
 | 
				
			||||||
 | 
									toks[i].second = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Update request map
 | 
				
			||||||
 | 
								while ( (data = tokenize(src, ",", src_len, len)) != NULL ) {
 | 
				
			||||||
 | 
									trim(data, len);
 | 
				
			||||||
 | 
									if ( !strncasecmp(data, "ID:", 3) )
 | 
				
			||||||
 | 
										toks[REQ_ID] = Buffer(data+3, len-3);
 | 
				
			||||||
 | 
									else if ( !strncasecmp(data, "SID:", 4) )
 | 
				
			||||||
 | 
										toks[SID] = Buffer(data+4, len-4);
 | 
				
			||||||
 | 
									else if ( !strncasecmp(data, "SFREQ:", 6) )
 | 
				
			||||||
 | 
										toks[SF] = Buffer(data+6, len-6);
 | 
				
			||||||
 | 
									else if ( !strncasecmp(data, "UOM:", 4) )
 | 
				
			||||||
 | 
										toks[UOM] = Buffer(data+4, len-4);
 | 
				
			||||||
 | 
									else if ( !strncasecmp(data, "FMT:", 4) )
 | 
				
			||||||
 | 
										toks[FORMAT] = Buffer(data+4, len-4);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								SessionTableItem item;
 | 
				
			||||||
 | 
								char buffer[7];
 | 
				
			||||||
 | 
								if ( toks[REQ_ID].second > 6 ) {
 | 
				
			||||||
 | 
									CAPS_ERROR("request state ID too high: %s", state);
 | 
				
			||||||
 | 
									return Error;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								strncpy(buffer, toks[REQ_ID].first, toks[REQ_ID].second);
 | 
				
			||||||
 | 
								buffer[toks[REQ_ID].second] = '\0';
 | 
				
			||||||
 | 
								int req_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( (sscanf(buffer, "%d", &req_id) != 1) || req_id == 0 ) {
 | 
				
			||||||
 | 
									CAPS_ERROR("invalid request ID: %s", buffer);
 | 
				
			||||||
 | 
									return Error;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( toks[SID].second == 0 ) {
 | 
				
			||||||
 | 
									CAPS_ERROR("missing SID in request response");
 | 
				
			||||||
 | 
									return Error;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.streamID.assign(toks[SID].first, toks[SID].second);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( req_id < 0 ) {
 | 
				
			||||||
 | 
									removeStream(item.streamID);
 | 
				
			||||||
 | 
									CAPS_DEBUG("stream %s has finished", item.streamID.c_str());
 | 
				
			||||||
 | 
									return Success;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									CAPS_DEBUG("new request ID %d for stream %s received", req_id, item.streamID.c_str());
 | 
				
			||||||
 | 
									std::string tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ( (data = tokenize(toks[SF].first, "/", toks[SF].second, len)) != NULL ) {
 | 
				
			||||||
 | 
										trim(data, len);
 | 
				
			||||||
 | 
										tmp.assign(data, len);
 | 
				
			||||||
 | 
										if ( !str2int(item.samplingFrequency, tmp.c_str()) ) {
 | 
				
			||||||
 | 
											CAPS_ERROR("request state 'samplingFrequency' is not a number: %s", state);
 | 
				
			||||||
 | 
											item.samplingFrequency = 0;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else {
 | 
				
			||||||
 | 
											item.samplingFrequencyDivider = 1;
 | 
				
			||||||
 | 
											if ( (data = tokenize(toks[SF].first, "/", toks[SF].second, len)) != NULL ) {
 | 
				
			||||||
 | 
												trim(data, len);
 | 
				
			||||||
 | 
												tmp.assign(data, len);
 | 
				
			||||||
 | 
												if ( !str2int(item.samplingFrequencyDivider, tmp.c_str()) ) {
 | 
				
			||||||
 | 
													CAPS_ERROR("request state 'samplingFrequencyDivider' "
 | 
				
			||||||
 | 
													           "is not a number: %s", state);
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										item.samplingFrequency = 0;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ( toks[UOM].second > 4 ) {
 | 
				
			||||||
 | 
										CAPS_ERROR("request state 'unit of measurement' is invalid, "
 | 
				
			||||||
 | 
										           "too many characters: %s", state);
 | 
				
			||||||
 | 
										item.uom.ID = 0;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										memcpy(item.uom.str, toks[UOM].first, toks[UOM].second);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ( (data = tokenize(toks[FORMAT].first, "/", toks[FORMAT].second, len)) != NULL ) {
 | 
				
			||||||
 | 
										trim(data, len);
 | 
				
			||||||
 | 
										if ( CHECK_STRING(data, "RAW", len) ) {
 | 
				
			||||||
 | 
											item.type = RawDataPacket;
 | 
				
			||||||
 | 
											if ( (data = tokenize(toks[FORMAT].first, "/", toks[FORMAT].second, len)) != NULL ) {
 | 
				
			||||||
 | 
												setDataType(data, len, item);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											CAPS_DEBUG("%s: samplingFrequency=%d/%d",
 | 
				
			||||||
 | 
											           item.streamID.c_str(), item.samplingFrequency,
 | 
				
			||||||
 | 
											           item.samplingFrequencyDivider);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else if ( CHECK_STRING(data, "FIXEDRAW", len) ) {
 | 
				
			||||||
 | 
											item.type = FixedRawDataPacket;
 | 
				
			||||||
 | 
											if ( (data = tokenize(toks[FORMAT].first, "/", toks[FORMAT].second, len)) != NULL ) {
 | 
				
			||||||
 | 
												setDataType(data, len, item);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											CAPS_DEBUG("%s: samplingFrequency=%d/%d",
 | 
				
			||||||
 | 
											           item.streamID.c_str(), item.samplingFrequency,
 | 
				
			||||||
 | 
											           item.samplingFrequencyDivider);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else if ( CHECK_STRING(data, "MSEED", len) ) {
 | 
				
			||||||
 | 
											item.type = MSEEDPacket;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else if ( CHECK_STRING(data, "META", len ) ) {
 | 
				
			||||||
 | 
											item.type = MetaDataPacket;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else {
 | 
				
			||||||
 | 
											string tmp(data, len);
 | 
				
			||||||
 | 
											item.type = ANYPacket;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Register item
 | 
				
			||||||
 | 
									registerItem(req_id, item);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Success;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setDataType(const char *data, int len, Gempa::CAPS::SessionTableItem &item) {
 | 
				
			||||||
 | 
						if ( CHECK_STRING(data, "FLOAT", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_FLOAT;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 32bit floats", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( CHECK_STRING(data, "DOUBLE", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_DOUBLE;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 64bit doubles", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( CHECK_STRING(data, "INT64", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_INT64;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 64bit integers", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( CHECK_STRING(data, "INT32", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_INT32;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 32bit integers", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( CHECK_STRING(data, "INT16", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_INT16;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 16bit integers", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if ( CHECK_STRING(data, "INT8", len) ) {
 | 
				
			||||||
 | 
							item.dataType = DT_INT8;
 | 
				
			||||||
 | 
							//SEISCOMP_DEBUG("%s: raw format with 8bit integers", item.streamID.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							string tmp;
 | 
				
			||||||
 | 
							item.dataType = DT_Unknown;
 | 
				
			||||||
 | 
							tmp.assign(data, len);
 | 
				
			||||||
 | 
							CAPS_WARNING("Unknown raw data type '%s', all packages will be ignored",
 | 
				
			||||||
 | 
							             tmp.c_str());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void SessionTable::registerItem(int id, SessionTableItem &item) {
 | 
				
			||||||
 | 
						item.fSamplingFrequency = (double)item.samplingFrequency /
 | 
				
			||||||
 | 
						                          (double)item.samplingFrequencyDivider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SessionTable::iterator it = find(id);
 | 
				
			||||||
 | 
						if ( it == end() ) {
 | 
				
			||||||
 | 
							if ( !item.splitStreamID() ) {
 | 
				
			||||||
 | 
								CAPS_WARNING("invalid streamID received: %s", item.streamID.c_str());
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Copy the item
 | 
				
			||||||
 | 
							SessionTableItem &target = operator[](id);
 | 
				
			||||||
 | 
							target = item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							_streamIDLookup[item.streamID] = id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( _itemAddedFunc ) _itemAddedFunc(&target);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							bool res = item.splitStreamID();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// streamID changed for the same sessionID?
 | 
				
			||||||
 | 
							if ( it->second.streamID != item.streamID ) {
 | 
				
			||||||
 | 
								CAPS_WARNING("inconsistent state: streamID '%s' for id %d, "
 | 
				
			||||||
 | 
								             "but streamID '%s' has not been closed before",
 | 
				
			||||||
 | 
								             item.streamID.c_str(), id, it->second.streamID.c_str());
 | 
				
			||||||
 | 
								// Update lookup table
 | 
				
			||||||
 | 
								_streamIDLookup.erase(_streamIDLookup.find(it->second.streamID));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( !res ) {
 | 
				
			||||||
 | 
									CAPS_WARNING("invalid streamID received: %s", item.streamID.c_str());
 | 
				
			||||||
 | 
									erase(it);
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								_streamIDLookup[item.streamID] = id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// TODO: How to update the request list?
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							it->second = item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( _itemAddedFunc ) _itemAddedFunc(&it->second);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void SessionTable::removeStream(const std::string &streamID) {
 | 
				
			||||||
 | 
						StreamIDLookupTable::iterator it = _streamIDLookup.find(streamID);
 | 
				
			||||||
 | 
						if ( it == _streamIDLookup.end() ) {
 | 
				
			||||||
 | 
							CAPS_WARNING("internal: tried to remove unknown stream '%s'",
 | 
				
			||||||
 | 
							             streamID.c_str());
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SessionTable::iterator sessionIt = find(it->second);
 | 
				
			||||||
 | 
						if ( sessionIt != end() ) {
 | 
				
			||||||
 | 
							// Remove session table row
 | 
				
			||||||
 | 
							if ( _itemAboutToBeRemovedFunc )
 | 
				
			||||||
 | 
								_itemAboutToBeRemovedFunc(&sessionIt->second);
 | 
				
			||||||
 | 
							erase(sessionIt);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Remove lookup entry
 | 
				
			||||||
 | 
						_streamIDLookup.erase(it);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void SessionTable::reset() {
 | 
				
			||||||
 | 
						clear();
 | 
				
			||||||
 | 
						_streamIDLookup.clear();
 | 
				
			||||||
 | 
						_state = Unspecific;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										104
									
								
								libs/gempa/caps/sessiontable.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								libs/gempa/caps/sessiontable.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,104 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_SESSIONTABLE_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_SESSIONTABLE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "packet.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SessionTableItem {
 | 
				
			||||||
 | 
						SessionTableItem() : samplingFrequency(0), samplingFrequencyDivider(0),
 | 
				
			||||||
 | 
						                     fSamplingFrequency(0.0), dataType(DT_Unknown),
 | 
				
			||||||
 | 
						                     dataSize(0), userData(NULL) {}
 | 
				
			||||||
 | 
						std::string           streamID;
 | 
				
			||||||
 | 
						std::string           net;
 | 
				
			||||||
 | 
						std::string           sta;
 | 
				
			||||||
 | 
						std::string           loc;
 | 
				
			||||||
 | 
						std::string           cha;
 | 
				
			||||||
 | 
						uint16_t              samplingFrequency;
 | 
				
			||||||
 | 
						uint16_t              samplingFrequencyDivider;
 | 
				
			||||||
 | 
						double                fSamplingFrequency;
 | 
				
			||||||
 | 
						PacketType            type;
 | 
				
			||||||
 | 
						DataType              dataType;
 | 
				
			||||||
 | 
						int                   dataSize;
 | 
				
			||||||
 | 
						UOM                   uom;
 | 
				
			||||||
 | 
						Time                  startTime;
 | 
				
			||||||
 | 
						Time                  endTime;
 | 
				
			||||||
 | 
						void                 *userData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool splitStreamID();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SC_GEMPA_CAPS_API SessionTable : public std::map<int, SessionTableItem> {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							enum Status {Success, Error, EOD};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							typedef std::function<void (SessionTableItem*)> CallbackFunc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							//! Default constructor
 | 
				
			||||||
 | 
							SessionTable();
 | 
				
			||||||
 | 
							virtual ~SessionTable() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Resets state
 | 
				
			||||||
 | 
							void reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							SessionTableItem* getItem(int id) {
 | 
				
			||||||
 | 
								SessionTable::iterator it = find(id);
 | 
				
			||||||
 | 
								if ( it == end() ) return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return &it->second;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Status handleResponse(const char *src_data, int data_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setItemAddedFunc(const CallbackFunc &func) { _itemAddedFunc = func; }
 | 
				
			||||||
 | 
							void setItemAboutToBeRemovedFunc(const CallbackFunc &func) {
 | 
				
			||||||
 | 
								_itemAboutToBeRemovedFunc = func;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							enum ResponseState {
 | 
				
			||||||
 | 
								Unspecific,
 | 
				
			||||||
 | 
								Requests
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							typedef std::map<std::string, int> StreamIDLookupTable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							void registerItem(int id, SessionTableItem &item);
 | 
				
			||||||
 | 
							void removeStream(const std::string & streamID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							ResponseState        _state;
 | 
				
			||||||
 | 
							StreamIDLookupTable  _streamIDLookup;
 | 
				
			||||||
 | 
							CallbackFunc         _itemAddedFunc;
 | 
				
			||||||
 | 
							CallbackFunc         _itemAboutToBeRemovedFunc;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										545
									
								
								libs/gempa/caps/socket.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										545
									
								
								libs/gempa/caps/socket.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,545 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/socket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#ifndef WIN32
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <netdb.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#ifndef SHUT_RDWR
 | 
				
			||||||
 | 
					#define SHUT_RDWR SD_BOTH
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#define _WIN32_WINNT 0x0501  // Older versions does not support getaddrinfo
 | 
				
			||||||
 | 
					#include <io.h>
 | 
				
			||||||
 | 
					#include <winsock2.h>
 | 
				
			||||||
 | 
					#include <ws2tcpip.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cerrno>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline string toString(unsigned short value) {
 | 
				
			||||||
 | 
						stringstream ss;
 | 
				
			||||||
 | 
						ss << value;
 | 
				
			||||||
 | 
						return ss.str();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					Socket::Socket() {
 | 
				
			||||||
 | 
						_fd = -1;
 | 
				
			||||||
 | 
						_bytesSent = _bytesReceived = 0;
 | 
				
			||||||
 | 
						_timeOutSecs = _timeOutUsecs = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef WIN32
 | 
				
			||||||
 | 
						WSADATA wsa;
 | 
				
			||||||
 | 
						WSAStartup(MAKEWORD(2,0),&wsa);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					Socket::~Socket() {
 | 
				
			||||||
 | 
						close();
 | 
				
			||||||
 | 
					#ifdef WIN32
 | 
				
			||||||
 | 
						WSACleanup();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					const char *Socket::toString(Status stat) {
 | 
				
			||||||
 | 
						switch ( stat ) {
 | 
				
			||||||
 | 
							case Success:
 | 
				
			||||||
 | 
								return "success";
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
							case Error:
 | 
				
			||||||
 | 
								return "error";
 | 
				
			||||||
 | 
							case AllocationError:
 | 
				
			||||||
 | 
								return "allocation error";
 | 
				
			||||||
 | 
							case ReuseAdressError:
 | 
				
			||||||
 | 
								return "reusing address failed";
 | 
				
			||||||
 | 
							case BindError:
 | 
				
			||||||
 | 
								return "bind error";
 | 
				
			||||||
 | 
							case ListenError:
 | 
				
			||||||
 | 
								return "listen error";
 | 
				
			||||||
 | 
							case AcceptError:
 | 
				
			||||||
 | 
								return "accept error";
 | 
				
			||||||
 | 
							case ConnectError:
 | 
				
			||||||
 | 
								return "connect error";
 | 
				
			||||||
 | 
							case AddrInfoError:
 | 
				
			||||||
 | 
								return "address info error";
 | 
				
			||||||
 | 
							case Timeout:
 | 
				
			||||||
 | 
								return "timeout";
 | 
				
			||||||
 | 
							case InvalidSocket:
 | 
				
			||||||
 | 
								return "invalid socket";
 | 
				
			||||||
 | 
							case InvalidPort:
 | 
				
			||||||
 | 
								return "invalid port";
 | 
				
			||||||
 | 
							case InvalidAddressFamily:
 | 
				
			||||||
 | 
								return "invalid address family";
 | 
				
			||||||
 | 
							case InvalidAddress:
 | 
				
			||||||
 | 
								return "invalid address";
 | 
				
			||||||
 | 
							case InvalidHostname:
 | 
				
			||||||
 | 
								return "invalid hostname";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return "";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					void Socket::shutdown() {
 | 
				
			||||||
 | 
						if ( _fd == -1 ) return;
 | 
				
			||||||
 | 
						//CAPS_DEBUG("Socket::shutdown");
 | 
				
			||||||
 | 
						::shutdown(_fd, SHUT_RDWR);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					void Socket::close() {
 | 
				
			||||||
 | 
						if ( _fd != -1 ) {
 | 
				
			||||||
 | 
							//CAPS_DEBUG("[socket] close %lX with fd = %d", (long int)this, _fd);
 | 
				
			||||||
 | 
							int fd = _fd;
 | 
				
			||||||
 | 
							_fd = -1;
 | 
				
			||||||
 | 
							::close(fd);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					Socket::Status Socket::setSocketTimeout(int secs, int usecs) {
 | 
				
			||||||
 | 
						_timeOutSecs = secs;
 | 
				
			||||||
 | 
						_timeOutUsecs = usecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _fd != -1 )
 | 
				
			||||||
 | 
							return applySocketTimeout(_timeOutSecs, _timeOutUsecs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Success;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					Socket::Status Socket::applySocketTimeout(int secs, int usecs) {
 | 
				
			||||||
 | 
						if ( _fd != -1 ) {
 | 
				
			||||||
 | 
							struct timeval timeout;
 | 
				
			||||||
 | 
							void *opt;
 | 
				
			||||||
 | 
							int optlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( secs >= 0 ) {
 | 
				
			||||||
 | 
								timeout.tv_sec = secs;
 | 
				
			||||||
 | 
								timeout.tv_usec = usecs;
 | 
				
			||||||
 | 
								opt = &timeout;
 | 
				
			||||||
 | 
								optlen = sizeof(timeout);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								opt = NULL;
 | 
				
			||||||
 | 
								optlen = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CAPS_DEBUG("set socket timeout to %d.%ds", secs, usecs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( setsockopt(_fd, SOL_SOCKET, SO_RCVTIMEO, opt, optlen) )
 | 
				
			||||||
 | 
								return Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( setsockopt(_fd, SOL_SOCKET, SO_SNDTIMEO, opt, optlen) )
 | 
				
			||||||
 | 
								return Error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return InvalidSocket;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Success;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					Socket::Device::Status Socket::setNonBlocking(bool nb) {
 | 
				
			||||||
 | 
						if ( !isValid() )
 | 
				
			||||||
 | 
							return Device::InvalidDevice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef WIN32
 | 
				
			||||||
 | 
						int flags = fcntl(_fd, F_GETFL, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( nb )
 | 
				
			||||||
 | 
							flags |= O_NONBLOCK;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							flags &= ~O_NONBLOCK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( fcntl(_fd, F_SETFL, flags) == -1 )
 | 
				
			||||||
 | 
							return Device::Error;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						u_long arg = nb?1:0;
 | 
				
			||||||
 | 
						if ( ioctlsocket(_fd, FIONBIO, &arg) != 0 )
 | 
				
			||||||
 | 
							return Device::Error;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Device::Success;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					Socket::Status Socket::connect(const std::string &hostname, uint16_t port) {
 | 
				
			||||||
 | 
						if ( _fd != -1 ) {
 | 
				
			||||||
 | 
							//CAPS_WARNING("closing stale socket");
 | 
				
			||||||
 | 
							close();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct sockaddr addr;
 | 
				
			||||||
 | 
						size_t addrlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct addrinfo *res;
 | 
				
			||||||
 | 
						struct addrinfo hints;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset (&hints, 0, sizeof(hints));
 | 
				
			||||||
 | 
						hints.ai_family = PF_INET;
 | 
				
			||||||
 | 
						hints.ai_socktype = SOCK_STREAM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						string strPort = ::toString(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int ret = getaddrinfo(hostname.c_str(), strPort.c_str(), &hints, &res);
 | 
				
			||||||
 | 
						if ( ret ) {
 | 
				
			||||||
 | 
							CAPS_DEBUG("Test3 Socket::connect(%s:%d): %s",
 | 
				
			||||||
 | 
								       hostname.c_str(), port,
 | 
				
			||||||
 | 
					#ifndef WIN32
 | 
				
			||||||
 | 
							           strerror(errno));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
							           gai_strerror(ret));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							return AddrInfoError;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						addr = *(res->ai_addr);
 | 
				
			||||||
 | 
						addrlen = res->ai_addrlen;
 | 
				
			||||||
 | 
						freeaddrinfo(res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( (_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0 ) {
 | 
				
			||||||
 | 
							/*CAPS_DEBUG("Socket::connect(%s:%d): %s",
 | 
				
			||||||
 | 
							               hostname.c_str(), port, strerror(errno));*/
 | 
				
			||||||
 | 
							return AllocationError;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef WIN32
 | 
				
			||||||
 | 
						if ( ::connect(_fd, (struct sockaddr *)&addr, addrlen) == -1 ) {
 | 
				
			||||||
 | 
							if ( errno != EINPROGRESS ) {
 | 
				
			||||||
 | 
								/*CAPS_DEBUG("Socket::connect(%s:%d): %s",
 | 
				
			||||||
 | 
								               hostname.c_str(), port, strerror(errno));*/
 | 
				
			||||||
 | 
								close();
 | 
				
			||||||
 | 
								return errno == ETIMEDOUT?Timeout:ConnectError;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						if ( ::connect(_fd, (struct sockaddr *)&addr, addrlen) == SOCKET_ERROR ) {
 | 
				
			||||||
 | 
							int err = WSAGetLastError();
 | 
				
			||||||
 | 
							if (err != WSAEINPROGRESS && err != WSAEWOULDBLOCK) {
 | 
				
			||||||
 | 
								CAPS_DEBUG("Socket::connect(%s:%d): %s",
 | 
				
			||||||
 | 
								            hostname.c_str(), port, gai_strerror(err));
 | 
				
			||||||
 | 
								close();
 | 
				
			||||||
 | 
								return ConnectError;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Success;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					int Socket::send(const char *data) {
 | 
				
			||||||
 | 
						return write(data, strlen(data));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					int Socket::write(const char *data, int len) {
 | 
				
			||||||
 | 
					#if !defined(MACOSX) && !defined(WIN32)
 | 
				
			||||||
 | 
						int sent = (int)::send(_fd, data, len, MSG_NOSIGNAL);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						int sent = (int)::send(_fd, data, len, 0);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						if ( sent > 0 ) {
 | 
				
			||||||
 | 
							_bytesSent += sent;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return sent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					int Socket::read(char *data, int len) {
 | 
				
			||||||
 | 
						int recvd = (int)::recv(_fd, data, len, 0);
 | 
				
			||||||
 | 
						if ( recvd > 0 ) _bytesReceived += recvd;
 | 
				
			||||||
 | 
						return recvd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					int Socket::flush() { return 1; }
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					bool Socket::isValid() {
 | 
				
			||||||
 | 
						return _fd != -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_SSL) || CAPS_FEATURES_SSL
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					SSLSocket::SSLSocket() : _ssl(NULL), _ctx(NULL) {}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					SSLSocket::SSLSocket(SSL_CTX *ctx) : _ssl(NULL), _ctx(ctx) {}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					SSLSocket::~SSLSocket() {
 | 
				
			||||||
 | 
						close();
 | 
				
			||||||
 | 
						cleanUp();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					int SSLSocket::write(const char *data, int len) {
 | 
				
			||||||
 | 
						int ret = SSL_write(_ssl, data, len);
 | 
				
			||||||
 | 
						if ( ret > 0 ) {
 | 
				
			||||||
 | 
							_bytesSent += ret;
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int err = SSL_get_error(_ssl, ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch ( err ) {
 | 
				
			||||||
 | 
							case SSL_ERROR_WANT_X509_LOOKUP:
 | 
				
			||||||
 | 
								errno = EAGAIN;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							case SSL_ERROR_WANT_READ:
 | 
				
			||||||
 | 
								errno = EAGAIN;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							case SSL_ERROR_WANT_WRITE:
 | 
				
			||||||
 | 
								errno = EAGAIN;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							case SSL_ERROR_ZERO_RETURN:
 | 
				
			||||||
 | 
								errno = EINVAL;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					int SSLSocket::read(char *data, int len) {
 | 
				
			||||||
 | 
						int ret = SSL_read(_ssl, data, len);
 | 
				
			||||||
 | 
						if ( ret > 0 ) {
 | 
				
			||||||
 | 
							_bytesReceived += ret;
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int err = SSL_get_error(_ssl, ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch ( err ) {
 | 
				
			||||||
 | 
							case SSL_ERROR_WANT_X509_LOOKUP:
 | 
				
			||||||
 | 
								errno = EAGAIN;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							case SSL_ERROR_WANT_READ:
 | 
				
			||||||
 | 
								errno = EAGAIN;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							case SSL_ERROR_WANT_WRITE:
 | 
				
			||||||
 | 
								errno = EAGAIN;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							case SSL_ERROR_ZERO_RETURN:
 | 
				
			||||||
 | 
								errno = EINVAL;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					Socket::Status SSLSocket::connect(const std::string &hostname, uint16_t port) {
 | 
				
			||||||
 | 
						cleanUp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_ctx = SSL_CTX_new(SSLv23_client_method());
 | 
				
			||||||
 | 
						if ( _ctx == NULL ) {
 | 
				
			||||||
 | 
							CAPS_DEBUG("Invalid SSL context");
 | 
				
			||||||
 | 
							return ConnectError;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SSL_CTX_set_mode(_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Status s = Socket::connect(hostname, port);
 | 
				
			||||||
 | 
						if ( s != Success )
 | 
				
			||||||
 | 
							return s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_ssl = SSL_new(_ctx);
 | 
				
			||||||
 | 
						if ( _ssl == NULL ) {
 | 
				
			||||||
 | 
							CAPS_DEBUG("Failed to create SSL context");
 | 
				
			||||||
 | 
							return ConnectError;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SSL_set_fd(_ssl, _fd);
 | 
				
			||||||
 | 
						SSL_set_shutdown(_ssl, 0);
 | 
				
			||||||
 | 
						SSL_set_connect_state(_ssl);
 | 
				
			||||||
 | 
						int err = SSL_connect(_ssl);
 | 
				
			||||||
 | 
						if ( err < 0 ) {
 | 
				
			||||||
 | 
							CAPS_ERROR("Failed to connect with SSL, error %d",
 | 
				
			||||||
 | 
							           SSL_get_error(_ssl, err));
 | 
				
			||||||
 | 
							close();
 | 
				
			||||||
 | 
							return ConnectError;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Success;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					const unsigned char *SSLSocket::sessionID() const {
 | 
				
			||||||
 | 
					#if OPENSSL_VERSION_NUMBER < 0x10100000L
 | 
				
			||||||
 | 
						return _ssl?_ssl->session->session_id:NULL;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						return _ssl?SSL_SESSION_get0_id_context(SSL_get0_session(_ssl), NULL):NULL;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					unsigned int SSLSocket::sessionIDLength() const {
 | 
				
			||||||
 | 
					#if OPENSSL_VERSION_NUMBER < 0x10100000L
 | 
				
			||||||
 | 
						return _ssl?_ssl->session->session_id_length:0;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						unsigned int len;
 | 
				
			||||||
 | 
						if ( !_ssl ) return 0;
 | 
				
			||||||
 | 
						SSL_SESSION_get0_id_context(SSL_get0_session(_ssl), &len);
 | 
				
			||||||
 | 
						return len;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					X509 *SSLSocket::peerCertificate() {
 | 
				
			||||||
 | 
						if ( _ssl == NULL ) return NULL;
 | 
				
			||||||
 | 
						return SSL_get_peer_certificate(_ssl);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					void SSLSocket::cleanUp() {
 | 
				
			||||||
 | 
						if ( _ssl ) {
 | 
				
			||||||
 | 
							SSL_free(_ssl);
 | 
				
			||||||
 | 
							_ssl = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( _ctx ) {
 | 
				
			||||||
 | 
							SSL_CTX_free(_ctx);
 | 
				
			||||||
 | 
							_ctx = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										273
									
								
								libs/gempa/caps/socket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										273
									
								
								libs/gempa/caps/socket.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,273 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_SOCKET_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_SOCKET_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <boost/shared_ptr.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <openssl/ssl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <streambuf>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SC_GEMPA_CAPS_API Socket {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							typedef uint64_t count_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							enum Status {
 | 
				
			||||||
 | 
								Success = 0,
 | 
				
			||||||
 | 
								Error,
 | 
				
			||||||
 | 
								AllocationError,
 | 
				
			||||||
 | 
								ReuseAdressError,
 | 
				
			||||||
 | 
								BindError,
 | 
				
			||||||
 | 
								ListenError,
 | 
				
			||||||
 | 
								AcceptError,
 | 
				
			||||||
 | 
								ConnectError,
 | 
				
			||||||
 | 
								AddrInfoError,
 | 
				
			||||||
 | 
								Timeout,
 | 
				
			||||||
 | 
								InvalidSocket,
 | 
				
			||||||
 | 
								InvalidPort,
 | 
				
			||||||
 | 
								InvalidAddressFamily,
 | 
				
			||||||
 | 
								InvalidAddress,
 | 
				
			||||||
 | 
								InvalidHostname
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct Device {
 | 
				
			||||||
 | 
								enum Status {
 | 
				
			||||||
 | 
									Success = 0,
 | 
				
			||||||
 | 
									Error,
 | 
				
			||||||
 | 
									InvalidDevice,
 | 
				
			||||||
 | 
									AllocationError
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Socket();
 | 
				
			||||||
 | 
							virtual ~Socket();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							static const char *toString(Status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int fd() { return _fd; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool isValid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void shutdown();
 | 
				
			||||||
 | 
							void close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int send(const char *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual int write(const char *data, int len);
 | 
				
			||||||
 | 
							virtual int read(char *data, int len);
 | 
				
			||||||
 | 
							virtual int flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//! Sets the socket timeout. This utilizes setsockopt which does not
 | 
				
			||||||
 | 
							//! work in non blocking sockets.
 | 
				
			||||||
 | 
							Status setSocketTimeout(int secs, int usecs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Device::Status setNonBlocking(bool nb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual Status connect(const std::string &hostname, uint16_t port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							count_t rx() const { return _bytesReceived; }
 | 
				
			||||||
 | 
							count_t tx() const { return _bytesSent; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							Status applySocketTimeout(int secs, int usecs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							int         _fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							count_t     _bytesSent;
 | 
				
			||||||
 | 
							count_t     _bytesReceived;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int         _timeOutSecs;
 | 
				
			||||||
 | 
							int         _timeOutUsecs;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef boost::shared_ptr<Socket> SocketPtr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(CAPS_FEATURES_SSL) || CAPS_FEATURES_SSL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SSLSocket : public Socket {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							SSLSocket();
 | 
				
			||||||
 | 
							SSLSocket(SSL_CTX *ctx);
 | 
				
			||||||
 | 
							~SSLSocket();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							int write(const char *data, int len);
 | 
				
			||||||
 | 
							int read(char *data, int len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Status connect(const std::string &hostname, uint16_t port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual const unsigned char *sessionID() const;
 | 
				
			||||||
 | 
							virtual unsigned int sessionIDLength() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							X509 *peerCertificate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							void cleanUp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							SSL     *_ssl;
 | 
				
			||||||
 | 
							SSL_CTX *_ctx;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef boost::shared_ptr<SSLSocket> SSLSocketPtr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T, int N>
 | 
				
			||||||
 | 
					class socketbuf : public std::streambuf {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							socketbuf() {
 | 
				
			||||||
 | 
								setsocket(NULL);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							socketbuf(T *sock) {
 | 
				
			||||||
 | 
								setsocket(sock);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setsocket(T *sock) {
 | 
				
			||||||
 | 
								_allowed_reads = -1;
 | 
				
			||||||
 | 
								_real_buffer_size = 0;
 | 
				
			||||||
 | 
								_block_write = false;
 | 
				
			||||||
 | 
								setg(_in, _in, _in);
 | 
				
			||||||
 | 
								setp(_out, _out + N);
 | 
				
			||||||
 | 
								_sock = sock;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void settimeout(const struct timeval &tv) {
 | 
				
			||||||
 | 
								_timeout = tv;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void set_read_limit(int bytes) {
 | 
				
			||||||
 | 
								_allowed_reads = bytes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( _allowed_reads >= 0 ) {
 | 
				
			||||||
 | 
									if ( egptr() - gptr() > _allowed_reads )
 | 
				
			||||||
 | 
										setg(eback(), gptr(), gptr() + _allowed_reads);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Set the number of read bytes to the
 | 
				
			||||||
 | 
									// remaining bytes in the buffer
 | 
				
			||||||
 | 
									_allowed_reads -= egptr() - gptr();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									setg(eback(), gptr(), eback() + _real_buffer_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//std::cout << "[" << (void*)eback() << ", " << (void*)gptr() << ", " << (void*)egptr() << "]" << " = " << (egptr() - gptr()) << std::endl;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int read_limit() const {
 | 
				
			||||||
 | 
								if ( _allowed_reads < 0 ) return -1;
 | 
				
			||||||
 | 
								return egptr() - gptr() + _allowed_reads;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							virtual int underflow() {
 | 
				
			||||||
 | 
								// No more reads allowed?
 | 
				
			||||||
 | 
								if ( !_allowed_reads )
 | 
				
			||||||
 | 
									return traits_type::eof();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Read available data from socket
 | 
				
			||||||
 | 
								int res = _sock->read(_in, N);
 | 
				
			||||||
 | 
								if ( res <= 0 ) {
 | 
				
			||||||
 | 
									set_read_limit(0);
 | 
				
			||||||
 | 
									return traits_type::eof();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Set input sequence pointers
 | 
				
			||||||
 | 
								_real_buffer_size = res;
 | 
				
			||||||
 | 
								setg(_in, _in, _in + _real_buffer_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// clip to limit
 | 
				
			||||||
 | 
								set_read_limit(_allowed_reads);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return traits_type::to_int_type(*gptr());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual int overflow(int c) {
 | 
				
			||||||
 | 
								if ( _block_write ) return traits_type::eof();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( pptr() - pbase() == N ) {
 | 
				
			||||||
 | 
									if ( sync() != 0 ) return traits_type::eof();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( !traits_type::eq_int_type(traits_type::eof(), c)) {
 | 
				
			||||||
 | 
									   traits_type::assign(*pptr(), traits_type::to_char_type(c));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									   pbump(1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return traits_type::not_eof(c);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual int sync() {
 | 
				
			||||||
 | 
								if ( pbase() == pptr() ) return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								int res = _sock->write(pbase(), pptr() - pbase());
 | 
				
			||||||
 | 
								if ( res == pptr() - pbase() ) {
 | 
				
			||||||
 | 
									setp(_out, _out + N);
 | 
				
			||||||
 | 
									return 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Only forward seeking is supported
 | 
				
			||||||
 | 
							virtual std::streampos
 | 
				
			||||||
 | 
							seekoff(std::streamoff off, std::ios_base::seekdir way,
 | 
				
			||||||
 | 
							        std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) {
 | 
				
			||||||
 | 
								if ( way != std::ios_base::cur || which != std::ios_base::in || off < 0 )
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								while ( off > 0 ) {
 | 
				
			||||||
 | 
									int ch = sbumpc();
 | 
				
			||||||
 | 
									if ( ch == traits_type::eof() )
 | 
				
			||||||
 | 
										return -1;
 | 
				
			||||||
 | 
									--off;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							T       *_sock;
 | 
				
			||||||
 | 
							timeval  _timeout;
 | 
				
			||||||
 | 
							char     _in[N];
 | 
				
			||||||
 | 
							char     _out[N];
 | 
				
			||||||
 | 
							bool     _block_write;
 | 
				
			||||||
 | 
							int      _real_buffer_size;
 | 
				
			||||||
 | 
							int      _allowed_reads;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										1009
									
								
								libs/gempa/caps/strptime.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1009
									
								
								libs/gempa/caps/strptime.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										22
									
								
								libs/gempa/caps/strptime.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								libs/gempa/caps/strptime.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 *   Copyright (C) by GFZ Potsdam                                          *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 *   You can redistribute and/or modify this program under the             *
 | 
				
			||||||
 | 
					 *   terms of the SeisComP Public License.                                 *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 *   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         *
 | 
				
			||||||
 | 
					 *   SeisComP Public License for more details.                             *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef STRPTIME_H
 | 
				
			||||||
 | 
					#define STRPTIME_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Version of "strptime()", for the benefit of OSes that don't have it.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					extern char *strptime(const char *, const char *, struct tm *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										23
									
								
								libs/gempa/caps/test/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								libs/gempa/caps/test/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					SET(TESTS
 | 
				
			||||||
 | 
						datetime.cpp
 | 
				
			||||||
 | 
						rawpacket.cpp
 | 
				
			||||||
 | 
						packet.cpp
 | 
				
			||||||
 | 
						utils.cpp
 | 
				
			||||||
 | 
						datetime_time.cpp
 | 
				
			||||||
 | 
						endianess.cpp
 | 
				
			||||||
 | 
						mseedpacket.cpp
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FOREACH(testSrc ${TESTS})
 | 
				
			||||||
 | 
						GET_FILENAME_COMPONENT(testName ${testSrc} NAME_WE)
 | 
				
			||||||
 | 
						SET(testName test_caps_${testName})
 | 
				
			||||||
 | 
						ADD_EXECUTABLE(${testName} ${testSrc})
 | 
				
			||||||
 | 
						SC_LINK_LIBRARIES_INTERNAL(${testName} unittest)
 | 
				
			||||||
 | 
						SC_LINK_LIBRARIES(${testName} ${CURL_LIBRARIES} caps_client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ADD_TEST(
 | 
				
			||||||
 | 
							NAME ${testName}
 | 
				
			||||||
 | 
							WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
 | 
				
			||||||
 | 
							COMMAND ${testName}
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					ENDFOREACH(testSrc)
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								libs/gempa/caps/test/data/AM.RFE4F.00.SHZ.20180912.mseed
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								libs/gempa/caps/test/data/AM.RFE4F.00.SHZ.20180912.mseed
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										566
									
								
								libs/gempa/caps/test/datetime.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										566
									
								
								libs/gempa/caps/test/datetime.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,566 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * Author: Tracey Werner, Enrico Ellguth                                   *
 | 
				
			||||||
 | 
					 * Email: tracey.werner@gempa.de, enrico.ellguth@gempa.de                  *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SEISCOMP_TEST_MODULE gempa
 | 
				
			||||||
 | 
					#include <seiscomp3/unittest/unittests.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/datetime.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace gc = Gempa::CAPS;
 | 
				
			||||||
 | 
					namespace bu = boost::unit_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool isClose(gc::TimeSpan time, long sec, long micro, int offset = 1) {
 | 
				
			||||||
 | 
						long microSeconds = time.microseconds();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						long secDiff = time.seconds() - sec;
 | 
				
			||||||
 | 
						if ( secDiff > 0 )
 | 
				
			||||||
 | 
							microSeconds += secDiff * 1000000;
 | 
				
			||||||
 | 
						else if ( secDiff < 0 )
 | 
				
			||||||
 | 
							micro += abs(secDiff) * 1000000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( abs(microSeconds - micro) <= offset )
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE(gempa_common_caps_datetime)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(construction) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_warnings);
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_messages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct timeval tvPositive;
 | 
				
			||||||
 | 
						tvPositive.tv_sec = 60000;
 | 
				
			||||||
 | 
						tvPositive.tv_usec = 123456;
 | 
				
			||||||
 | 
						gc::TimeSpan k(tvPositive);
 | 
				
			||||||
 | 
						BOOST_CHECK(k.seconds() == tvPositive.tv_sec);
 | 
				
			||||||
 | 
						BOOST_CHECK(k.microseconds() == tvPositive.tv_usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct timeval tvNegativeUsec;
 | 
				
			||||||
 | 
						tvNegativeUsec.tv_sec = 300;
 | 
				
			||||||
 | 
						tvNegativeUsec.tv_usec = -13456;
 | 
				
			||||||
 | 
						gc::TimeSpan ki(tvNegativeUsec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ki.seconds() , tvNegativeUsec.tv_sec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ki.microseconds() , tvNegativeUsec.tv_usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct timeval tvNegativeSec;
 | 
				
			||||||
 | 
						tvNegativeSec.tv_sec = -300;
 | 
				
			||||||
 | 
						tvNegativeSec.tv_usec = 13456;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan kj(tvNegativeSec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(kj.seconds() , tvNegativeSec.tv_sec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(kj.microseconds() , tvNegativeSec.tv_usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct timeval tvNegative;
 | 
				
			||||||
 | 
						tvNegative.tv_sec = -3000;
 | 
				
			||||||
 | 
						tvNegative.tv_usec = -123456;
 | 
				
			||||||
 | 
						gc::TimeSpan kk(tvNegative);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(kk.seconds() , tvNegative.tv_sec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(kk.microseconds() , tvNegative.tv_usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct timeval tvNull;
 | 
				
			||||||
 | 
						gc::TimeSpan kl(tvNull);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(kl.seconds() , tvNull.tv_sec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(kl.microseconds() , tvNull.tv_usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// copy
 | 
				
			||||||
 | 
						gc::TimeSpan copyPositive(gc::TimeSpan(79743.123456));
 | 
				
			||||||
 | 
						BOOST_CHECK(copyPositive.seconds() == 79743);
 | 
				
			||||||
 | 
						BOOST_CHECK(copyPositive.microseconds() == 123456);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan copyNegative(gc::TimeSpan(-98765.123456));
 | 
				
			||||||
 | 
						long sec = -98765;
 | 
				
			||||||
 | 
						long micro = -123456;
 | 
				
			||||||
 | 
						BOOST_CHECK(isClose(copyNegative, sec, micro,20) == true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan copyNegativeTest(gc::TimeSpan(-98765.000070));
 | 
				
			||||||
 | 
						sec = -98765 ;
 | 
				
			||||||
 | 
						micro = 70;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(copyNegativeTest,sec, micro,500), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// long
 | 
				
			||||||
 | 
						gc::TimeSpan longPositive(765432, 456789);
 | 
				
			||||||
 | 
						BOOST_CHECK(longPositive.seconds() == 765432);
 | 
				
			||||||
 | 
						BOOST_CHECK(longPositive.microseconds() == 456789);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan longNegativeUsec(200, -732);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(longNegativeUsec.seconds(), 200);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(longNegativeUsec.microseconds(), -732);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan longNegativeSec(-800, 73265);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(longNegativeSec.seconds(), -800);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(longNegativeSec.microseconds(), 73265);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan longNegative(-500, -732650);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(longNegative.seconds(), -500);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(longNegative.microseconds(), -732650);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// double
 | 
				
			||||||
 | 
						double number = 123456.98765;
 | 
				
			||||||
 | 
						gc::TimeSpan doublePositive(number);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(doublePositive.seconds(), 123456);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(doublePositive.microseconds(), 987650);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						number = -98765.123470;
 | 
				
			||||||
 | 
						gc::TimeSpan doubleNegative(number);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(doubleNegative.seconds(), -98765);
 | 
				
			||||||
 | 
						BOOST_CHECK_CLOSE((double)doubleNegative.microseconds(), -123470, 0.01);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						number = -98765.000080;
 | 
				
			||||||
 | 
						gc::TimeSpan doubleNegativeTest(number);
 | 
				
			||||||
 | 
						sec = -98765;
 | 
				
			||||||
 | 
						micro = 80;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(doubleNegativeTest,sec, micro,500), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// pointer
 | 
				
			||||||
 | 
						timeval n;
 | 
				
			||||||
 | 
						n.tv_sec = 123;
 | 
				
			||||||
 | 
						n.tv_usec = 123456;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan pointerPositive(&n);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(pointerPositive.seconds(), 123);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(pointerPositive.microseconds(), 123456);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n.tv_sec = -123;
 | 
				
			||||||
 | 
						n.tv_usec = 123456;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan pointerNegativeSec(&n);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(pointerNegativeSec.seconds(), -123);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(pointerNegativeSec.microseconds(), 123456);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n.tv_sec = 123;
 | 
				
			||||||
 | 
						n.tv_usec = -123456;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan pointerNegativeUsec(&n);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(pointerNegativeUsec.seconds(), 123);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(pointerNegativeUsec.microseconds(), -123456);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n.tv_sec = -123;
 | 
				
			||||||
 | 
						n.tv_usec = -123456;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan pointerNegative(&n);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(pointerNegative.seconds(), -123);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(pointerNegative.microseconds(), -123456);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						timeval *nullPointer = NULL;
 | 
				
			||||||
 | 
						gc::TimeSpan pointerNull(nullPointer);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(pointerNull.seconds(), 0);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(pointerNull.microseconds(), 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(addition) {
 | 
				
			||||||
 | 
						gc::TimeSpan k = 5, l = 7;
 | 
				
			||||||
 | 
						BOOST_CHECK(k + l  == gc::TimeSpan(12));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan m = 320.5, n = 60.2;
 | 
				
			||||||
 | 
						BOOST_CHECK(m + n  == gc::TimeSpan(380.7));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan g = 55, d = -50;
 | 
				
			||||||
 | 
						BOOST_CHECK(d + g  == gc::TimeSpan(5));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan t = -80.0053, s = -70.0044;
 | 
				
			||||||
 | 
						gc::TimeSpan result = t + s;
 | 
				
			||||||
 | 
						long sec = t.seconds() + s.seconds();
 | 
				
			||||||
 | 
						long micro = t.microseconds() + s.microseconds();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(result, sec,micro),true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan u = -5.035, v = -60.044;
 | 
				
			||||||
 | 
						result = u + v;
 | 
				
			||||||
 | 
						sec = u.seconds() + v.seconds();
 | 
				
			||||||
 | 
						micro = u.microseconds() + v.microseconds();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(result,sec, micro), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan w = -5.0885, x = -6.01111;
 | 
				
			||||||
 | 
						result = w + x;
 | 
				
			||||||
 | 
						sec = w.seconds() + x.seconds();
 | 
				
			||||||
 | 
						micro = w.microseconds() + x.microseconds();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(result,sec, micro), true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(subtraction) {
 | 
				
			||||||
 | 
						gc::TimeSpan k = 5, l = 6;
 | 
				
			||||||
 | 
						BOOST_CHECK(k - l == gc::TimeSpan(-1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan t = 58, i = 68.05;
 | 
				
			||||||
 | 
						gc::TimeSpan result = t - i;
 | 
				
			||||||
 | 
						long sec = t.seconds() - i.seconds();
 | 
				
			||||||
 | 
						long micro = t.microseconds() - i.microseconds();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(result,sec, micro), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan e(30,4);
 | 
				
			||||||
 | 
						gc::TimeSpan o(45,3);
 | 
				
			||||||
 | 
						result = e - o;
 | 
				
			||||||
 | 
						sec = e.seconds() - o.seconds();
 | 
				
			||||||
 | 
						micro = e.microseconds() - o.microseconds();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(result,sec, micro), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan f = 30.00004, g = -45.00003;
 | 
				
			||||||
 | 
						result = f - g;
 | 
				
			||||||
 | 
						sec = f.seconds() - g.seconds();
 | 
				
			||||||
 | 
						micro = f.microseconds() - g.microseconds();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(result,sec, micro), true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(setSec) {
 | 
				
			||||||
 | 
						gc::TimeSpan h, k, l;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(h.set(4), gc::TimeSpan(4));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(k.set(2), gc::TimeSpan(2));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(l.set(1), gc::TimeSpan(1));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(l.set(-10), gc::TimeSpan(-10));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(k.set(-9876), gc::TimeSpan(-9876));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(l.set(0), gc::TimeSpan(0.));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(setMicro) {
 | 
				
			||||||
 | 
						gc::TimeSpan h, k, l, ts;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(h.setUSecs(9), gc::TimeSpan(0.000009));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(k.setUSecs(2), gc::TimeSpan(0.0000020));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(l.setUSecs(3), gc::TimeSpan(0.000003));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ts.setUSecs(4), gc::TimeSpan(0.000004));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(l.setUSecs(0), gc::TimeSpan(0.0));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(h.setUSecs(2000000), gc::TimeSpan(2.00));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(k.setUSecs(-3000000), gc::TimeSpan(-3.0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_warnings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan test = l.setUSecs(-7262);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(test.microseconds(), -7262);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan test2 = l.setUSecs(-98744);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(test2.microseconds(), -98744);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan test3 = l.setUSecs(-98);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(isClose(test3,0, -98), true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(secAndMicro) {
 | 
				
			||||||
 | 
						gc::TimeSpan ts(2.000002);
 | 
				
			||||||
 | 
						BOOST_CHECK(ts.seconds() == 2 && ts.microseconds() == 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan h(4.000009);
 | 
				
			||||||
 | 
						BOOST_CHECK(h.seconds() == 4 && h.microseconds()  == 9);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan t(0.000004);
 | 
				
			||||||
 | 
						BOOST_CHECK(t.seconds() == 0 && t.microseconds()  == 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan k(0.000000);
 | 
				
			||||||
 | 
						BOOST_CHECK(k.seconds() == 0 && k.microseconds()  == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan m(-8.123456);
 | 
				
			||||||
 | 
						long sec =  -8;
 | 
				
			||||||
 | 
						long micro = -123456;
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(isClose(m,sec, micro,20), true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(absolute) {
 | 
				
			||||||
 | 
						gc::TimeSpan k(-2.567);
 | 
				
			||||||
 | 
						gc::TimeSpan result = k.abs();
 | 
				
			||||||
 | 
						long sec = result.seconds();
 | 
				
			||||||
 | 
						long micro = result.microseconds();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(result,2, 567000,20), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan m(-2, -5);
 | 
				
			||||||
 | 
						gc::TimeSpan n(2, 5);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(m.abs(), n.abs());
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(m.abs(), n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan i(600, -700000);
 | 
				
			||||||
 | 
						result = i.abs();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.seconds(), 600);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.microseconds(),700000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan r(200, -5);
 | 
				
			||||||
 | 
						gc::TimeSpan s(200.000005);
 | 
				
			||||||
 | 
						gc::TimeSpan absR = r.abs();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(r.abs(), s.abs());
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(absR.seconds(), s.seconds());
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(absR.microseconds(), s.microseconds());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan l = (double)-1.000678;
 | 
				
			||||||
 | 
						result = l.abs();
 | 
				
			||||||
 | 
						sec = 1;
 | 
				
			||||||
 | 
						micro = 678;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(result,sec, micro), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan h = -4;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(h.abs(), gc::TimeSpan(4));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan ts;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ts.abs(), gc::TimeSpan(0.0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(length) {
 | 
				
			||||||
 | 
						gc::TimeSpan k = 2.000002;
 | 
				
			||||||
 | 
						BOOST_CHECK(k.length() == 2.000002);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan l = 1.000003;
 | 
				
			||||||
 | 
						BOOST_CHECK(l.length() == 1.000003);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan h = 4.000009;
 | 
				
			||||||
 | 
						BOOST_CHECK(h.length() == 4.000009);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(notEqual) {
 | 
				
			||||||
 | 
						gc::TimeSpan k = 2.000002, l = 1.000003;
 | 
				
			||||||
 | 
						BOOST_CHECK(k != l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan ts, t = 0.000007;
 | 
				
			||||||
 | 
						BOOST_CHECK(ts != t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan h = 4.000009, j = 2845687.000004;
 | 
				
			||||||
 | 
						BOOST_CHECK(h != j);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(assign) {
 | 
				
			||||||
 | 
						gc::TimeSpan k = 2.000002;
 | 
				
			||||||
 | 
						BOOST_CHECK(k == gc::TimeSpan(2.000002));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan t;
 | 
				
			||||||
 | 
						BOOST_CHECK(t  == gc::TimeSpan(0.0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan h = 4.000009;
 | 
				
			||||||
 | 
						BOOST_CHECK(h  == gc::TimeSpan(4.000009));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan ts = 0.000004;
 | 
				
			||||||
 | 
						BOOST_CHECK(ts == gc::TimeSpan(0.000004));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(plus) {
 | 
				
			||||||
 | 
						gc::TimeSpan k = 2.000002, l = 1.000003;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(k += l, gc::TimeSpan(3.000005));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan h = 4.000009, t;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(t += h, gc::TimeSpan(4.000009));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan ts = 0.000004, j = 80005.000004;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ts += j, gc::TimeSpan(80005.000008));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(minus) {
 | 
				
			||||||
 | 
						gc::TimeSpan k = 2.000002, l = 1.000003;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(k -= l, gc::TimeSpan(0.999999));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan t, j = 6897.098772;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(j -= t, gc::TimeSpan(6897.098772));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan h = 4.000009, ts = 0.000004;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(h -= ts, gc::TimeSpan(4.000005));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(lower) {
 | 
				
			||||||
 | 
						gc::TimeSpan k = 2.000002, t;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(t < k, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan h = 4.000009, j = 2.897665;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(j < h, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan ts = 0.000004, z = 7893648.987645;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(z < ts, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(greater) {
 | 
				
			||||||
 | 
						gc::TimeSpan k = 2.000002, t;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(k > t, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan h = 4.000009, j = 3.909888;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(h > j, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan ts = 0.000004, g = 0.000001;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(g > ts, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(lowerEqual) {
 | 
				
			||||||
 | 
						gc::TimeSpan k = 2.000002;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(k <= gc::TimeSpan(2.000002), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan t;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(t <= gc::TimeSpan(2), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan h = 4.000009;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(h <= gc::TimeSpan(2), false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(greaterEqual) {
 | 
				
			||||||
 | 
						gc::TimeSpan h = 4.000009;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(h >= gc::TimeSpan(2), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan ts = 0.000004;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ts >= gc::TimeSpan(0.000001), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan k = 2.000002;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(k >= gc::TimeSpan(2.000002), true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(inDouble) {
 | 
				
			||||||
 | 
						gc::TimeSpan k = 6.000003;
 | 
				
			||||||
 | 
						double kd = k.operator double();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(kd, 6.000003);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan t = 0.000008;
 | 
				
			||||||
 | 
						double td = t.operator double();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(td, 0.000008);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::TimeSpan ts = 2.000004;
 | 
				
			||||||
 | 
						double tsd = ts.operator double();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(tsd, 2.000004);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(toTimeval) {
 | 
				
			||||||
 | 
						const timeval tv = gc::Time(6.000003);
 | 
				
			||||||
 | 
						gc::TimeSpan k = 6.000003;
 | 
				
			||||||
 | 
						timeval kv = k.operator const timeval &();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(kv.tv_sec, tv.tv_sec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(kv.tv_usec, tv.tv_usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const timeval ti = gc::Time(0.000008);
 | 
				
			||||||
 | 
						gc::TimeSpan t = 0.000008;
 | 
				
			||||||
 | 
						timeval tvi = t.operator const timeval &();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(tvi.tv_sec, ti.tv_sec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(tvi.tv_usec, ti.tv_usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const timeval tl = gc::Time(2.000004);
 | 
				
			||||||
 | 
						gc::TimeSpan ts = 2.000004;
 | 
				
			||||||
 | 
						timeval tsv = ts.operator const timeval &();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(tsv.tv_sec, tl.tv_sec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(tsv.tv_usec, tl.tv_usec);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(fromString) {
 | 
				
			||||||
 | 
						gc::Time time = gc::Time::FromString("2019-01-01 10:01:59", "%F %T");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK(time.valid());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int year, month, day, hour, min, sec;
 | 
				
			||||||
 | 
						BOOST_CHECK(time.get(&year, &month, &day, &hour, &min, &sec));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(year, 2019);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(month, 1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(day, 1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(hour, 10);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(min, 01);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(sec, 59);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Buffer overflow test
 | 
				
			||||||
 | 
						std::string str;
 | 
				
			||||||
 | 
						str.resize(1024);
 | 
				
			||||||
 | 
						time = gc::Time::FromString(str.c_str(), "%F %T");
 | 
				
			||||||
 | 
						BOOST_CHECK(!time.valid());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE_END()
 | 
				
			||||||
							
								
								
									
										511
									
								
								libs/gempa/caps/test/datetime_time.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										511
									
								
								libs/gempa/caps/test/datetime_time.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,511 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * Author: Tracey Werner, Enrico Ellguth                                   *
 | 
				
			||||||
 | 
					 * Email: tracey.werner@gempa.de, enrico.ellguth@gempa.de                  *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SEISCOMP_TEST_MODULE gempa
 | 
				
			||||||
 | 
					#include <seiscomp3/unittest/unittests.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/datetime.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace gc = Gempa::CAPS;
 | 
				
			||||||
 | 
					namespace bu = boost::unit_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE(gempa_common_caps_datetime_time)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool isClose(gc::TimeSpan time, long sec, long micro, int offset = 1) {
 | 
				
			||||||
 | 
						long microSeconds = time.microseconds();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						long secDiff = time.seconds() - sec;
 | 
				
			||||||
 | 
						if ( secDiff > 0 )
 | 
				
			||||||
 | 
							microSeconds += secDiff * 1000000;
 | 
				
			||||||
 | 
						else if ( secDiff < 0 )
 | 
				
			||||||
 | 
							micro += abs(secDiff) * 1000000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( abs(microSeconds - micro) <= offset )
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(construction) {
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_warnings);
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_messages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time time;
 | 
				
			||||||
 | 
						BOOST_CHECK(time == gc::Time(0.0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// long
 | 
				
			||||||
 | 
						gc::Time tPositive(200, 600);
 | 
				
			||||||
 | 
						BOOST_CHECK(tPositive == gc::Time(200.000600));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time tNegativeUsec(3000, -789);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tNegativeUsec.seconds(), 3000);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tNegativeUsec.microseconds(), -789);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time tNegativeSec(-12, 12345);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tNegativeSec.seconds(), -12);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tNegativeSec.microseconds(), 12345);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time tNegative(-15,-9876);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tNegative.seconds(), -15);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tNegative.microseconds(), -9876);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TimeSpan
 | 
				
			||||||
 | 
						gc::Time tsPositive(gc::TimeSpan(5.345));
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tsPositive.seconds(), 5);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tsPositive.microseconds(), 345000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// timeval
 | 
				
			||||||
 | 
						timeval number;
 | 
				
			||||||
 | 
						number.tv_sec = 150;
 | 
				
			||||||
 | 
						number.tv_usec = 6000;
 | 
				
			||||||
 | 
						gc::Time tvPositive(number);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tvPositive.seconds(), 150);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tvPositive.microseconds(), 6000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						number.tv_sec = -150;
 | 
				
			||||||
 | 
						number.tv_usec = 9000;
 | 
				
			||||||
 | 
						gc::Time tvNegativeSec(number);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tvNegativeSec.seconds(), -150);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tvNegativeSec.microseconds(),9000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						number.tv_sec = 4000;
 | 
				
			||||||
 | 
						number.tv_usec = -98876;
 | 
				
			||||||
 | 
						gc::Time tvNegativeUsec(number);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tvNegativeUsec.seconds(), 4000);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tvNegativeUsec.microseconds(), -98876);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						number.tv_sec = -9877;
 | 
				
			||||||
 | 
						number.tv_usec = -874547;
 | 
				
			||||||
 | 
						gc::Time tvNegative(number);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tvNegative.seconds(), -9877);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tvNegative.microseconds(), -874547);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// double
 | 
				
			||||||
 | 
						double val = 5678.9864;
 | 
				
			||||||
 | 
						gc::Time tdPositive(val);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tdPositive.seconds(), 5678);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(tdPositive.microseconds(), 986400);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						val = -89765.745377;
 | 
				
			||||||
 | 
						gc::Time tdNegative(val);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(isClose(tdNegative, -89765, -745377), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// pointer
 | 
				
			||||||
 | 
						timeval pointer;
 | 
				
			||||||
 | 
						pointer.tv_sec = 76656;
 | 
				
			||||||
 | 
						pointer.tv_usec = 8900;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time tpPositive(&pointer);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tpPositive.seconds(), 76656);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tpPositive.microseconds(), 8900);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pointer.tv_sec = -76656;
 | 
				
			||||||
 | 
						pointer.tv_usec = 8900;
 | 
				
			||||||
 | 
						gc::Time tpNegativeSec(&pointer);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tpNegativeSec.seconds(), -76656);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tpNegativeSec.microseconds(), 8900);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pointer.tv_sec = 98744;
 | 
				
			||||||
 | 
						pointer.tv_usec = -8965;
 | 
				
			||||||
 | 
						gc::Time tpNegativeUsec(&pointer);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tpNegativeUsec.seconds(), 98744);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tpNegativeUsec.microseconds(), -8965);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pointer.tv_sec = -44;
 | 
				
			||||||
 | 
						pointer.tv_usec = -895;
 | 
				
			||||||
 | 
						gc::Time tpNegative(&pointer);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tpNegative.seconds(), -44);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(tpNegative.microseconds(), -895);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// copy
 | 
				
			||||||
 | 
						gc::Time copyPositive(gc::Time(758.9975));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(copyPositive.seconds(), 758);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(copyPositive.microseconds(), 997500);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time copyNegative(gc::Time(-877.963));
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(isClose(copyNegative, -877, -963000), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// date
 | 
				
			||||||
 | 
						gc::Time date(1971,1,3,1,1,4,6544);
 | 
				
			||||||
 | 
						double dayInSeconds = 86400;
 | 
				
			||||||
 | 
						double yearInSeconds = 31536000;
 | 
				
			||||||
 | 
						BOOST_WARN_CLOSE(double(date), dayInSeconds*2 + yearInSeconds,0.3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(addition) {
 | 
				
			||||||
 | 
						gc::Time a(7,5);
 | 
				
			||||||
 | 
						gc::TimeSpan b = 9.000004;
 | 
				
			||||||
 | 
						gc::TimeSpan result = a + b;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.microseconds(), 9);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.seconds(), 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time c(7,5);
 | 
				
			||||||
 | 
						gc::TimeSpan d = -3.000004;
 | 
				
			||||||
 | 
						result = c + d;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.microseconds(), 2);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.seconds(), 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time e(-7,5);
 | 
				
			||||||
 | 
						gc::TimeSpan f = 9.000004;
 | 
				
			||||||
 | 
						result = e + f;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.microseconds(),9);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.seconds(), 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time g(900,789);
 | 
				
			||||||
 | 
						gc::TimeSpan h;
 | 
				
			||||||
 | 
						result = h += g;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.microseconds(),789);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.seconds(), 900);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time i(455, -355);
 | 
				
			||||||
 | 
						gc::TimeSpan j = 80.000444;
 | 
				
			||||||
 | 
						i += j;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(i.microseconds(),89);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(i.seconds(), 535);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time k(-899, 22255);
 | 
				
			||||||
 | 
						gc::TimeSpan l = 773.992;
 | 
				
			||||||
 | 
						l += k;
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(l.seconds(), -125);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(l.microseconds(), 14255);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time m(500, 987);
 | 
				
			||||||
 | 
						gc::TimeSpan n(-30, 876);
 | 
				
			||||||
 | 
						int result2 = m.microseconds() + n.microseconds();
 | 
				
			||||||
 | 
						int result3 = m.seconds() + n.seconds();
 | 
				
			||||||
 | 
						m += n;
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(m.microseconds(),result2);
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(m.seconds(),result3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time o(-60, 47);
 | 
				
			||||||
 | 
						gc::TimeSpan p(-44,5);
 | 
				
			||||||
 | 
						long sec = o.seconds() + p.seconds();
 | 
				
			||||||
 | 
						long micro = o.microseconds() + p.microseconds();
 | 
				
			||||||
 | 
						o += p;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(o, sec, micro), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time q(9876, -6748);
 | 
				
			||||||
 | 
						gc::TimeSpan r = -876.987;
 | 
				
			||||||
 | 
						q += r;
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(q.microseconds(), 6253);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(q.seconds(),8999);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(subtraction) {
 | 
				
			||||||
 | 
						gc::Time a(7,5);
 | 
				
			||||||
 | 
						gc::TimeSpan b(9,000004);
 | 
				
			||||||
 | 
						gc::TimeSpan result = a - b;
 | 
				
			||||||
 | 
						long sec = a.seconds() - b.seconds();
 | 
				
			||||||
 | 
						long micro = a.microseconds() - b.microseconds();
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(isClose(result, sec, micro),true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time c(7,5);
 | 
				
			||||||
 | 
						gc::TimeSpan d = -3.000004;
 | 
				
			||||||
 | 
						result = c - d;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.microseconds(), 8);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.seconds(), 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time e(-7,5);
 | 
				
			||||||
 | 
						gc::TimeSpan f(9,000004);
 | 
				
			||||||
 | 
						result = e - f;
 | 
				
			||||||
 | 
						sec = e.seconds() - f.seconds();
 | 
				
			||||||
 | 
						micro = e.microseconds() -f.microseconds();
 | 
				
			||||||
 | 
						BOOST_WARN_EQUAL(isClose(result, sec, micro),true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time g(900,789);
 | 
				
			||||||
 | 
						gc::TimeSpan h;
 | 
				
			||||||
 | 
						sec = h.seconds() - g.seconds();
 | 
				
			||||||
 | 
						micro = h.microseconds() - g.microseconds();
 | 
				
			||||||
 | 
						h -= g;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(h, sec, micro), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time i(455, -355);
 | 
				
			||||||
 | 
						gc::TimeSpan j(80, 444);
 | 
				
			||||||
 | 
						sec = i.seconds() - j.seconds();
 | 
				
			||||||
 | 
						micro = i.microseconds() - j.microseconds();
 | 
				
			||||||
 | 
						i -= j;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(i, sec, micro), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time k(-899, 22255);
 | 
				
			||||||
 | 
						gc::TimeSpan l(773, 992);
 | 
				
			||||||
 | 
						sec = l.seconds() - k.seconds();
 | 
				
			||||||
 | 
						micro = l.microseconds() - k.microseconds();
 | 
				
			||||||
 | 
						l -= k;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(l, sec, micro), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time m(500,987);
 | 
				
			||||||
 | 
						gc::TimeSpan n = -30.876;
 | 
				
			||||||
 | 
						m -= n;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(m.microseconds(),876986);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(m.seconds(), 530);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time o(-60, 47);
 | 
				
			||||||
 | 
						gc::TimeSpan p = -44.05;
 | 
				
			||||||
 | 
						sec = o.seconds() - p.seconds();
 | 
				
			||||||
 | 
						micro = o.microseconds() - p.microseconds();
 | 
				
			||||||
 | 
						o -= p;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(o, sec, micro), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time q(9876, -6748);
 | 
				
			||||||
 | 
						gc::TimeSpan r = -876.987;
 | 
				
			||||||
 | 
						sec = q.seconds() -r.seconds();
 | 
				
			||||||
 | 
						micro = q.microseconds() - r.microseconds();
 | 
				
			||||||
 | 
						q -= r;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(q, sec, micro), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time s(50, 778), t(4, 221);
 | 
				
			||||||
 | 
						result = s - t;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.microseconds(), 557);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(result.seconds(), 46);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time u(-30,0),v(60,66);
 | 
				
			||||||
 | 
						result = u - v;
 | 
				
			||||||
 | 
						sec = u.seconds() -v.seconds();
 | 
				
			||||||
 | 
						micro = u.microseconds() - v.microseconds();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(result, sec, micro), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time w(798, -444),x(6, 0321);
 | 
				
			||||||
 | 
						sec = w.seconds() - x.seconds();
 | 
				
			||||||
 | 
						micro = w.microseconds() - x.microseconds();
 | 
				
			||||||
 | 
						result = w - x;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(isClose(result, sec, micro), true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(setAndGet) {
 | 
				
			||||||
 | 
						gc::Time date;
 | 
				
			||||||
 | 
						gc::TimeSpan oneDay (86400); // one day in seconds
 | 
				
			||||||
 | 
						gc::TimeSpan oneYear (31536000); // one year in seconds
 | 
				
			||||||
 | 
						gc::TimeSpan toNextYear (26524800); // seconds to the next year
 | 
				
			||||||
 | 
						int year = 1970, month = 8, day = 5,h = 7,min = 50,sec = 33,uSec= 80;
 | 
				
			||||||
 | 
						date.set(year,month,day,h,min,sec,uSec);
 | 
				
			||||||
 | 
						BOOST_CHECK(date.get(&year,&month,&day,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK(year == 1970);
 | 
				
			||||||
 | 
						BOOST_CHECK(month == 8);
 | 
				
			||||||
 | 
						BOOST_CHECK(day == 5);
 | 
				
			||||||
 | 
						BOOST_CHECK(h == 7);
 | 
				
			||||||
 | 
						BOOST_CHECK(min = 50);
 | 
				
			||||||
 | 
						BOOST_CHECK(sec = 33);
 | 
				
			||||||
 | 
						BOOST_CHECK(uSec = 80);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						date -= oneYear;
 | 
				
			||||||
 | 
						BOOST_CHECK(date.get(&year,&month,&day,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK(year == 1969);
 | 
				
			||||||
 | 
						BOOST_CHECK(month == 8);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(day , 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						year = 2017, month = 2, day = 28;
 | 
				
			||||||
 | 
						date.set(year,month,day,h,min,sec,uSec);
 | 
				
			||||||
 | 
						BOOST_CHECK(date.get(&year,&month,&day,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK(year == 2017);
 | 
				
			||||||
 | 
						BOOST_CHECK(month == 2);
 | 
				
			||||||
 | 
						BOOST_CHECK(day == 28);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						date += oneDay;
 | 
				
			||||||
 | 
						BOOST_CHECK(date.get(&year,&month,&day,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(month , 3);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(day , 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						year = 2018, month = 2, day = 28;
 | 
				
			||||||
 | 
						date.set(year,month,day,h,min,sec,uSec);
 | 
				
			||||||
 | 
						date += oneDay;
 | 
				
			||||||
 | 
						BOOST_CHECK(date.get(&year,&month,&day,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(month , 3);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(day, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						date += oneYear;
 | 
				
			||||||
 | 
						BOOST_CHECK(date.get(&year,&month,&day,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(year , 2019);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(day, 1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(month , 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time leapYear;
 | 
				
			||||||
 | 
						year = 1956, month = 2, day = 28;
 | 
				
			||||||
 | 
						leapYear.set(year,month,day,h,min,sec,uSec);
 | 
				
			||||||
 | 
						BOOST_CHECK(leapYear.get(&year,&month,&day,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK(year == 1956);
 | 
				
			||||||
 | 
						BOOST_CHECK(month == 2);
 | 
				
			||||||
 | 
						BOOST_CHECK(day == 28);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						leapYear += oneDay;
 | 
				
			||||||
 | 
						BOOST_CHECK(leapYear.get(&year,&month,&day,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK(month == 2);
 | 
				
			||||||
 | 
						BOOST_CHECK(day == 29);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						leapYear += oneDay;
 | 
				
			||||||
 | 
						BOOST_CHECK(leapYear.get(&year,&month,&day,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK(month == 3);
 | 
				
			||||||
 | 
						BOOST_CHECK(day == 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time time;
 | 
				
			||||||
 | 
						year = 2011, month = 2, day = 28;
 | 
				
			||||||
 | 
						int yday ;
 | 
				
			||||||
 | 
						time.set(year,month,day,h,min,sec,uSec);
 | 
				
			||||||
 | 
						BOOST_CHECK(time.get2(&year,&yday,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK(year == 2011);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(yday , 58);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						time += toNextYear;
 | 
				
			||||||
 | 
						BOOST_CHECK(time.get2(&year,&yday,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(year , 2012);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(yday , 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						year = 1964, month = 2, day = 29;
 | 
				
			||||||
 | 
						leapYear.set(year,month,day,h,min,sec,uSec);
 | 
				
			||||||
 | 
						BOOST_CHECK(leapYear.get2(&year,&yday,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(yday , 59);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						leapYear += toNextYear;
 | 
				
			||||||
 | 
						BOOST_CHECK(leapYear.get2(&year,&yday,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(year, 1965);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(yday , 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time before1900;
 | 
				
			||||||
 | 
						day = 28, month = 2, year = 1900;
 | 
				
			||||||
 | 
						before1900.set(year,month,day,h,min,sec,uSec);
 | 
				
			||||||
 | 
						BOOST_CHECK(before1900.get(&year,&month,&day,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(year , 1900);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(day , 28);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(month, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time pure;
 | 
				
			||||||
 | 
						pure.get(&year,&month,&day,&h,&min,&sec,&uSec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(year, 1970);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pure -= oneYear;
 | 
				
			||||||
 | 
						pure.get(&year,&month,&day,&h,&min,&sec,&uSec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(year, 1969);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						day = 50, month = 4, year = 1566;
 | 
				
			||||||
 | 
						before1900.set(year,month,day,h,min,sec,uSec);
 | 
				
			||||||
 | 
						BOOST_CHECK(before1900.get(&year,&month,&day,&h,&min,&sec,&uSec) == true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(year , 1566);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(day , 20);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(month, 5);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(localTime) {
 | 
				
			||||||
 | 
						gc::Time local;
 | 
				
			||||||
 | 
						local.set(1970,3,14,5,30,3,39);
 | 
				
			||||||
 | 
						gc::Time time(local);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(double(local), double(time));
 | 
				
			||||||
 | 
						std::string check1 = local.toString("%FT%T.%fZ");
 | 
				
			||||||
 | 
						std::string check2 = "1970-03-14T05:30:03.000039Z";
 | 
				
			||||||
 | 
						bool equal = boost::iequals(check1,check2);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(equal, true);
 | 
				
			||||||
 | 
						gc::Time localtest = local.LocalTime();
 | 
				
			||||||
 | 
						local = local.LocalTime();
 | 
				
			||||||
 | 
						localtest.setUSecs(0);
 | 
				
			||||||
 | 
						local.setUSecs(0);
 | 
				
			||||||
 | 
						check1 = local.iso();
 | 
				
			||||||
 | 
						check2 = localtest.iso();
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(check1, check2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local.set(1970,3,14,5,30,3,39);
 | 
				
			||||||
 | 
						check1 = "1970-03-14T05:30:03.000039Z";
 | 
				
			||||||
 | 
						check2 = local.toString("%FT%T.%fZ");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(check1, check2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local.set(1981,9,14,5,30,3,39);
 | 
				
			||||||
 | 
						check1 = "1981-09-14T05:30:03.000039Z";
 | 
				
			||||||
 | 
						check2 = local.toString("%FT%T.%fZ");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(check1, check2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local.set(2014,3,14,5,30,3,39);
 | 
				
			||||||
 | 
						check1 = "2014-03-14T05:30:03.000039Z";
 | 
				
			||||||
 | 
						check2 = local.toString("%FT%T.%fZ");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(check1, check2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local.set(2000,8,14,5,30,3,39);
 | 
				
			||||||
 | 
						check1 = local.toString("%FT%T.%fZ");
 | 
				
			||||||
 | 
						check2 = "2000-08-14T05:30:03.000039Z";
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(check1, check2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// before 1970
 | 
				
			||||||
 | 
						gc::Time before1970;
 | 
				
			||||||
 | 
						before1970.set(1950,6,4,15,8,66,11);
 | 
				
			||||||
 | 
						gc::Time t(before1970);
 | 
				
			||||||
 | 
						gc::Time time1 = local.LocalTime();
 | 
				
			||||||
 | 
						time1.setUSecs(0);
 | 
				
			||||||
 | 
						gc::Time time2 = before1970.LocalTime();
 | 
				
			||||||
 | 
						time2.setUSecs(0);
 | 
				
			||||||
 | 
						check1 = time1.toString("%FT%T.%fZ");
 | 
				
			||||||
 | 
						check2 = time2.toString("%FT%T.%fZ");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(check1, check2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						before1970.set(1914,9,4,7,8,66,11);
 | 
				
			||||||
 | 
						check1 = "1914-09-04T07:09:06.000011Z";
 | 
				
			||||||
 | 
						check2 = before1970.toString("%FT%T.%fZ");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(check1, check2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time yearDay = yearDay.FromYearDay(1971, 3);
 | 
				
			||||||
 | 
						double dayInSeconds = 86400;
 | 
				
			||||||
 | 
						double yearInSeconds = 31536000;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(double(yearDay),dayInSeconds*2 + yearInSeconds);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(validStrings) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time date(2016,8,26,15,44,9,644);
 | 
				
			||||||
 | 
						std::string test = date.toString("%FT%T.%fZ");
 | 
				
			||||||
 | 
						std::string check = "2016-08-26T15:44:09.000644Z";
 | 
				
			||||||
 | 
						bool equal = boost::iequals(test,check);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(equal, true);
 | 
				
			||||||
 | 
						BOOST_CHECK(date.FromString(test.c_str(),"%FT%T.%fZ") == date);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK(test == date.iso());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK(date.fromString(test.c_str(),"%FT%T.%fZ") == true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(date.valid(), true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE_END()
 | 
				
			||||||
							
								
								
									
										105
									
								
								libs/gempa/caps/test/endianess.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								libs/gempa/caps/test/endianess.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,105 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * Author: Tracey Werner, Enrico Ellguth                                   *
 | 
				
			||||||
 | 
					 * Email: tracey.werner@gempa.de, enrico.ellguth@gempa.de                  *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SEISCOMP_TEST_MODULE gempa
 | 
				
			||||||
 | 
					#include <seiscomp3/unittest/unittests.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/endianess.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/rawpacket.cpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace gce = Gempa::CAPS::Endianess;
 | 
				
			||||||
 | 
					namespace bu = boost::unit_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE(gempa_common_caps_endianess)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(converter) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_warnings);
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_messages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check little_endian int16_t.
 | 
				
			||||||
 | 
						const int16_t k16Value{0x0123};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(gce::Current::LittleEndian) {
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::ToLittleEndian(k16Value), k16Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromLittleEndian(k16Value), k16Value);
 | 
				
			||||||
 | 
							int16_t g16Value = gce::Converter::ToBigEndian(k16Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(g16Value, 8961);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromBigEndian(g16Value), k16Value);
 | 
				
			||||||
 | 
							gce::Converter::ToLittleEndian(&k16Value, 4);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(291, k16Value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::ToBigEndian(k16Value), k16Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromBigEndian(k16Value), k16Value);
 | 
				
			||||||
 | 
							int16_t g16Value = gce::Converter::ToLittleEndian(k16Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(g16Value, 291);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromLittleEndian(g16Value), k16Value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check little_endian int32_t.
 | 
				
			||||||
 | 
						const int32_t k32Value{0x01234567};
 | 
				
			||||||
 | 
						if(gce::Current::LittleEndian) {
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::ToLittleEndian(k32Value), k32Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromLittleEndian(k32Value), k32Value);
 | 
				
			||||||
 | 
							int32_t g32Value = gce::Converter::ToBigEndian(k32Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(g32Value, 1732584193);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromBigEndian(g32Value), k32Value);
 | 
				
			||||||
 | 
							gce::Converter::ToLittleEndian(&k32Value, 11);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(19088743, k32Value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::ToBigEndian(k32Value), k32Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromBigEndian(k32Value), k32Value);
 | 
				
			||||||
 | 
							int16_t g32Value = gce::Converter::ToLittleEndian(k32Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(g32Value, 19088743);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromLittleEndian(g32Value), k32Value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check little_endian int64_t.
 | 
				
			||||||
 | 
						const int64_t k64Value{0x0123456789abcdef};
 | 
				
			||||||
 | 
						if(gce::Current::LittleEndian) {
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::ToLittleEndian(k64Value), k64Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromLittleEndian(k64Value), k64Value);
 | 
				
			||||||
 | 
							int64_t g32Value = gce::Converter::ToBigEndian(k64Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(g32Value, -1167088121787636991);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromBigEndian(g32Value), k64Value);
 | 
				
			||||||
 | 
							gce::Converter::ToLittleEndian(&k64Value, 11);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(81985529216486895, k64Value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::ToBigEndian(k64Value), k64Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromBigEndian(k64Value), k64Value);
 | 
				
			||||||
 | 
							int16_t g64Value = gce::Converter::ToLittleEndian(k64Value);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(g64Value, 19088743);
 | 
				
			||||||
 | 
							BOOST_CHECK_EQUAL(gce::Converter::FromLittleEndian(g64Value), k64Value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE_END()
 | 
				
			||||||
							
								
								
									
										29
									
								
								libs/gempa/caps/test/errors_find
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								libs/gempa/caps/test/errors_find
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					Bei utils.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---------------------------------------------------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bei datetime.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---------------------------------------------------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bei rawpacket.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---------------------------------------------------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bei packet.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					---------------------------------------------------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bei endianess.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1) Bei reader ist der Pointer nicht an der ersten stelle des Streams. Siehe endianess.cpp (test) Zeile 114 und folgende.
 | 
				
			||||||
 | 
					---------------------------------------------------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bei mseedpacket.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1)
 | 
				
			||||||
 | 
					---------------------------------------------------------------------------------------------------------------------------
 | 
				
			||||||
							
								
								
									
										227
									
								
								libs/gempa/caps/test/mseedpacket.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								libs/gempa/caps/test/mseedpacket.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,227 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * Author: Tracey Werner, Enrico Ellguth                                   *
 | 
				
			||||||
 | 
					 * Email: tracey.werner@gempa.de, enrico.ellguth@gempa.de                  *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SEISCOMP_TEST_MODULE gempa
 | 
				
			||||||
 | 
					#include "test_utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <seiscomp3/unittest/unittests.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/mseedpacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/rawpacket.cpp>
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/datetime.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <streambuf>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace bu = boost::unit_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					using namespace Gempa::CAPS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Record {
 | 
				
			||||||
 | 
						Record() {
 | 
				
			||||||
 | 
							vector<char> mseed;
 | 
				
			||||||
 | 
							mseed.resize(512);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ifstream ifs("data/AM.RFE4F.00.SHZ.20180912.mseed");
 | 
				
			||||||
 | 
							if( ifs.is_open() ) {
 | 
				
			||||||
 | 
								ifs.read(mseed.data(), 512);
 | 
				
			||||||
 | 
								testRec.setData(mseed.data(), 512);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								BOOST_TEST_MESSAGE("unable to open test data file.");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						MSEEDDataRecord testRec;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE(gempa_common_caps_mseedpacket)
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(equal_functions) {
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_warnings);
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_messages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MSEEDDataRecord::Header header;
 | 
				
			||||||
 | 
						MSEEDDataRecord::Header otherHeader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						header.setSamplingTime(fromString("2018-01-01 00:00:01"));
 | 
				
			||||||
 | 
						header.samplingFrequencyNumerator = 30;
 | 
				
			||||||
 | 
						header.samplingFrequencyDenominator = 1;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(header != otherHeader, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool valid = header.compatible(otherHeader);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						otherHeader = header;
 | 
				
			||||||
 | 
						valid = header.compatible(otherHeader);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(header != otherHeader, false);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(header_functions) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MSEEDDataRecord::Header header;
 | 
				
			||||||
 | 
						header.dataType = DT_INT64;
 | 
				
			||||||
 | 
						header.samplingFrequencyNumerator = 1;
 | 
				
			||||||
 | 
						header.samplingFrequencyDenominator = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char buf[1024];
 | 
				
			||||||
 | 
						arraybuf abuf(buf, 1024);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(header.put(abuf), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MSEEDDataRecord::Header otherHeader;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(otherHeader.get(abuf), true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(otherHeader.samplingFrequencyNumerator, 1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(otherHeader.samplingFrequencyDenominator, 1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(otherHeader.dataType, DT_INT64);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(trim_function) {
 | 
				
			||||||
 | 
						// MSEEDs records can not be trimmed -> always false
 | 
				
			||||||
 | 
						MSEEDDataRecord testRec;
 | 
				
			||||||
 | 
						BOOST_CHECK(!testRec.canTrim());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(merge_function) {
 | 
				
			||||||
 | 
						// MSEEDs records can not be merged -> always false
 | 
				
			||||||
 | 
						MSEEDDataRecord testRec;
 | 
				
			||||||
 | 
						BOOST_CHECK(!testRec.canMerge());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE_END()
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_FIXTURE_TEST_CASE(getter_and_setter, Record) {
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL("MSEED", testRec.formatName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// get data size with and without header
 | 
				
			||||||
 | 
						size_t sizeWithout = testRec.dataSize(false);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(sizeWithout, 512);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t sizeWith = testRec.dataSize(true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(512, sizeWith);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// check start end end time
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(testRec.startTime().iso(), "2018-09-12T10:55:56.751Z");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(testRec.endTime().iso(), "2018-09-12T10:56:03.511Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// check sampling frequency
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(testRec.header()->samplingFrequencyNumerator, 50);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(testRec.header()->samplingFrequencyDenominator, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// check packet type
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(testRec.packetType(), MSEEDPacket);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_FIXTURE_TEST_CASE(read_header_from_buffer, Record) {
 | 
				
			||||||
 | 
						char data[512];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// write test record data into a buffer
 | 
				
			||||||
 | 
						arraybuf abuf(data, 512);
 | 
				
			||||||
 | 
						BOOST_CHECK(testRec.put(abuf, true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Time startTime, endTime;
 | 
				
			||||||
 | 
						MSEEDDataRecord::Header header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// read start, end time and further information from buffer
 | 
				
			||||||
 | 
						MSEEDDataRecord rec;
 | 
				
			||||||
 | 
						rec.readMetaData(abuf, 512, header, startTime, endTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(startTime.iso(), "2018-09-12T10:55:56.751Z");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(endTime.iso(), "2018-09-12T10:56:03.511Z");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(header.dataType, DT_INT32);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_FIXTURE_TEST_CASE(read_data_from_file, Record) {
 | 
				
			||||||
 | 
						ifstream ifs("data/AM.RFE4F.00.SHZ.20180912.mseed");
 | 
				
			||||||
 | 
						BOOST_CHECK(ifs.is_open());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vector<char> buf;
 | 
				
			||||||
 | 
						buf.resize(512);
 | 
				
			||||||
 | 
						ifs.read(buf.data(), 512);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MSEEDDataRecord rec;
 | 
				
			||||||
 | 
						rec.setData(buf.data(),512);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rec.header()->samplingFrequencyDenominator, 1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rec.header()->samplingFrequencyNumerator, 50);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						TimeSpan timeSpan = samplesToTimeSpan(*rec.header(), 338);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// check that the record start time + all samples is equal to
 | 
				
			||||||
 | 
						// the record end time
 | 
				
			||||||
 | 
						Time endTime = rec.startTime() + timeSpan;
 | 
				
			||||||
 | 
						BOOST_CHECK(endTime == rec.endTime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// check both header are equal
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rec.header()->compatible(*testRec.header()), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
							
								
								
									
										97
									
								
								libs/gempa/caps/test/packet.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								libs/gempa/caps/test/packet.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * Author: Tracey Werner, Enrico Ellguth                                   *
 | 
				
			||||||
 | 
					 * Email: tracey.werner@gempa.de, enrico.ellguth@gempa.de                  *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SEISCOMP_TEST_MODULE gempa
 | 
				
			||||||
 | 
					#include <seiscomp3/unittest/unittests.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/rawpacket.cpp>
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace gc = Gempa::CAPS;
 | 
				
			||||||
 | 
					namespace bu = boost::unit_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE(gempa_common_caps_packet)
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(equal_function) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_warnings);
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_messages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::DataRecord::Header header;
 | 
				
			||||||
 | 
						gc::DataRecord::Header other;
 | 
				
			||||||
 | 
						gc::Time t(1004791084,45368);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK_NO_THROW(header.setSamplingTime(t));
 | 
				
			||||||
 | 
						header.samplingFrequencyNumerator = 3;
 | 
				
			||||||
 | 
						header.samplingFrequencyDenominator = 7;
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(header != other, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool valid = header.compatible(other);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						other = header;
 | 
				
			||||||
 | 
						valid = header.compatible(other);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(header != other, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(getAndPut) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::DataRecord::Header header;
 | 
				
			||||||
 | 
						header.dataType = gc::DT_INT64;
 | 
				
			||||||
 | 
						header.samplingFrequencyNumerator = 1;
 | 
				
			||||||
 | 
						header.samplingFrequencyDenominator = 1;
 | 
				
			||||||
 | 
						char buf[1024];
 | 
				
			||||||
 | 
						gc::arraybuf abuf(buf, 1024);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(header.samplingFrequencyNumerator, 1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(header.samplingFrequencyDenominator, 1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(header.dataType, gc::DT_INT64);
 | 
				
			||||||
 | 
						bool valid = header.put(abuf);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::DataRecord::Header otherHeader;
 | 
				
			||||||
 | 
						valid = otherHeader.get(abuf);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid,true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(otherHeader.samplingFrequencyNumerator, 1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(otherHeader.samplingFrequencyDenominator, 1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(otherHeader.dataType, gc::DT_INT64);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE_END()
 | 
				
			||||||
							
								
								
									
										288
									
								
								libs/gempa/caps/test/rawpacket.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								libs/gempa/caps/test/rawpacket.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,288 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * Author: Tracey Werner, Enrico Ellguth                                   *
 | 
				
			||||||
 | 
					 * Email: tracey.werner@gempa.de, enrico.ellguth@gempa.de                  *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef M_PI
 | 
				
			||||||
 | 
					#define M_PI 3.14159265359
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SEISCOMP_TEST_MODULE gempa
 | 
				
			||||||
 | 
					#include "test_utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <seiscomp3/unittest/unittests.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/rawpacket.cpp>
 | 
				
			||||||
 | 
					#include <gempa/caps/mseedpacket.cpp>
 | 
				
			||||||
 | 
					#include <gempa/caps/datetime.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <streambuf>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace gc = Gempa::CAPS;
 | 
				
			||||||
 | 
					namespace bu = boost::unit_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Record {
 | 
				
			||||||
 | 
						Record() {
 | 
				
			||||||
 | 
							gc::DataRecord::Header header;
 | 
				
			||||||
 | 
							header.setSamplingTime(fromString("2018-01-01 00:00:01"));
 | 
				
			||||||
 | 
							header.dataType = gc::DT_INT32;
 | 
				
			||||||
 | 
							header.samplingFrequencyNumerator = 1;
 | 
				
			||||||
 | 
							header.samplingFrequencyDenominator = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rdr.setHeader(header);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::RawDataRecord rdr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> void fillRecord(T *data, size_t len , gc::Time stime, int sample_microsecs,
 | 
				
			||||||
 | 
					                                     double amplitude, double period) {
 | 
				
			||||||
 | 
						double periodScale = (2 * M_PI) / period;
 | 
				
			||||||
 | 
						double x = (double)stime * periodScale;
 | 
				
			||||||
 | 
						double xOffset = sample_microsecs * 1E-6 * periodScale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for ( size_t i = 0; i < len; ++i ) {
 | 
				
			||||||
 | 
							*data = amplitude * sin(x);
 | 
				
			||||||
 | 
							++data;
 | 
				
			||||||
 | 
							x += xOffset;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE(gempa_common_caps_rawpacket)
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_FIXTURE_TEST_CASE(getAndSet, Record) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_warnings);
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_messages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vector<int> data;
 | 
				
			||||||
 | 
						data.resize(256);
 | 
				
			||||||
 | 
						rdr.setBuffer(data.data(), 256);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set data type and get size of it
 | 
				
			||||||
 | 
						rdr.setDataType(gc::DT_FLOAT);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(sizeof(float), gc::sizeOf(rdr.header()->dataType));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL("RAW/FLOAT", rdr.formatName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdr.setDataType(gc::DT_INT64);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(sizeof(int64_t), gc::sizeOf(rdr.header()->dataType));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL("RAW/INT64", rdr.formatName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// get data size with and without header
 | 
				
			||||||
 | 
						size_t sizeWithout = rdr.dataSize(false);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(sizeWithout, 256);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t sizeWith = rdr.dataSize(true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(sizeWithout + rdr.header()->dataSize(), sizeWith);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data.resize(65536);
 | 
				
			||||||
 | 
						rdr.setBuffer(data.data(), 65536);
 | 
				
			||||||
 | 
						sizeWithout = rdr.dataSize(false);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(sizeWithout, 65536);
 | 
				
			||||||
 | 
						sizeWith = rdr.dataSize(true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(sizeWithout + rdr.header()->dataSize(), sizeWith);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set new FrequencyNumerator and FrequencyDenominator
 | 
				
			||||||
 | 
						rdr.setSamplingFrequency(100,1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.header()->samplingFrequencyNumerator, 100);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.header()->samplingFrequencyDenominator, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdr.setSamplingFrequency(20,1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.header()->samplingFrequencyNumerator, 20);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.header()->samplingFrequencyDenominator, 1);
 | 
				
			||||||
 | 
						gc::Time t = gc::getEndTime(rdr.startTime(),20, *rdr.header());
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(t.iso(), "2018-01-01T00:00:02.0000Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::DataRecord::Header otherHeader;
 | 
				
			||||||
 | 
						BOOST_CHECK_NO_THROW(rdr.setHeader(otherHeader));
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL("RAW/UNKWN", rdr.formatName());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_FIXTURE_TEST_CASE(checkTime, Record) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::Time t = gc::getEndTime(rdr.startTime(), 3, *rdr.header());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(t.iso(), "2018-01-01T00:00:04.0000Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdr.setStartTime(fromString("2018-02-01 00:00:03.0000"));
 | 
				
			||||||
 | 
						vector<int> data;
 | 
				
			||||||
 | 
						data.resize(1024);
 | 
				
			||||||
 | 
						rdr.setBuffer(data.data(), 1024);
 | 
				
			||||||
 | 
						t = gc::getEndTime(rdr.startTime(), 3, *rdr.header());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.startTime().iso(), "2018-02-01T00:00:03.0000Z");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(t.iso(), "2018-02-01T00:00:06.0000Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdr.setStartTime(fromString("1988-03-14 14:22:57.322"));
 | 
				
			||||||
 | 
						t = gc::getEndTime(rdr.startTime(), 2, *rdr.header());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(t.iso(), "1988-03-14T14:22:59.0000Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdr.setStartTime(fromString("1970-01-01 00:00:00.0000"));
 | 
				
			||||||
 | 
						rdr.setSamplingFrequency(20,1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.endTime().iso(), "1970-01-01T00:00:12.8Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdr.setDataType(gc::DT_FLOAT);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.endTime().iso(), "1970-01-01T00:00:12.8Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdr.setDataType(gc::DT_DOUBLE);
 | 
				
			||||||
 | 
						data.resize(2048);
 | 
				
			||||||
 | 
						rdr.setBuffer(data.data(), 2048);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.endTime().iso(), "1970-01-01T00:00:12.8Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdr.setDataType(gc::DT_INT64);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.endTime().iso(), "1970-01-01T00:00:12.8Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdr.setDataType(gc::DT_INT8);
 | 
				
			||||||
 | 
						data.resize(256);
 | 
				
			||||||
 | 
						rdr.setBuffer(data.data(), 256);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.endTime().iso(), "1970-01-01T00:00:12.8Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdr.setDataType(gc::DT_INT16);
 | 
				
			||||||
 | 
						data.resize(512);
 | 
				
			||||||
 | 
						rdr.setBuffer(data.data(),512);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.endTime().iso(), "1970-01-01T00:00:12.8Z");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_FIXTURE_TEST_CASE(trimTest, Record) {
 | 
				
			||||||
 | 
						// Raw records are trimable -> always true
 | 
				
			||||||
 | 
						BOOST_CHECK(rdr.canTrim());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const gc::Time endT = gc::getEndTime(rdr.startTime(), 1, *rdr.header());
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.canTrim(), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool trimTest = rdr.trim(rdr.startTime(), endT);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(trimTest, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.startTime().iso(), "2018-01-01T00:00:01.0000Z");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(endT.iso(), "2018-01-01T00:00:02.0000Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						trimTest = rdr.trim(endT, rdr.startTime());
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(trimTest, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdr.setSamplingFrequency(0,0);
 | 
				
			||||||
 | 
						trimTest = rdr.trim(rdr.startTime(), endT);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(trimTest, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdr.canMerge(), true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_FIXTURE_TEST_CASE(getAndPut, Record) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char data[500000];
 | 
				
			||||||
 | 
						uint64_t sample_microsecs = uint64_t(rdr.header()->samplingFrequencyDenominator) * 1000000 / rdr.header()->samplingFrequencyNumerator;
 | 
				
			||||||
 | 
						fillRecord<float>((float*)&data, 1024, rdr.startTime(), (int)sample_microsecs, 4.2, 2.1);
 | 
				
			||||||
 | 
						gc::arraybuf abuf(data, 1024);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vector<int> arr;
 | 
				
			||||||
 | 
						arr.resize(1024);
 | 
				
			||||||
 | 
						rdr.setBuffer(arr.data(), 1024);
 | 
				
			||||||
 | 
						bool check = rdr.put(abuf, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(check, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RS_PARTIAL = 2
 | 
				
			||||||
 | 
						gc::RawDataRecord rdrOther;
 | 
				
			||||||
 | 
						gc::DataRecord::ReadStatusCode ret = rdrOther.get(abuf, 1024, rdr.startTime(),rdr.endTime(), 10);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, gc::DataRecord::RS_Partial);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdrOther.startTime() == rdr.startTime(), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RS_COMPLETE = 1
 | 
				
			||||||
 | 
						gc::arraybuf abuf2(data, 1024);
 | 
				
			||||||
 | 
						check = rdrOther.put(abuf2, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(check, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::RawDataRecord rdrOther2;
 | 
				
			||||||
 | 
						ret = rdrOther2.get(abuf2, 1024, rdrOther2.startTime(),rdrOther2.endTime(), 10);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, gc::DataRecord::RS_Complete);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gc::DataRecord::Header header = *rdrOther2.header();
 | 
				
			||||||
 | 
						gc::Time start = rdrOther2.startTime();
 | 
				
			||||||
 | 
						gc::Time end = gc::getEndTime(rdrOther2.startTime(), 2, header);
 | 
				
			||||||
 | 
						rdrOther2.readMetaData(abuf, 1024, header, start, end);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdrOther2.startTime().iso(), "2018-01-01T00:00:01.0000Z");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(rdrOther2.endTime().iso(), "2018-01-01T00:04:13.0000Z");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RS_BEFORE_TIME_WINDOW = 3
 | 
				
			||||||
 | 
						gc::arraybuf abuf3(data, 1024);
 | 
				
			||||||
 | 
						gc::RawDataRecord rdrBefore;
 | 
				
			||||||
 | 
						header.setSamplingTime(fromString("2018-01-01 00:00:00"));
 | 
				
			||||||
 | 
						header.dataType = gc::DT_INT32;
 | 
				
			||||||
 | 
						header.samplingFrequencyNumerator = 1;
 | 
				
			||||||
 | 
						header.samplingFrequencyDenominator = 1;
 | 
				
			||||||
 | 
						rdrBefore.setHeader(header);
 | 
				
			||||||
 | 
						check = rdrBefore.put(abuf3, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(check, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = rdrOther.get(abuf3, 1024, rdr.endTime(),rdr.startTime(), 10);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, gc::DataRecord::RS_BeforeTimeWindow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RS_AFTER_TIME_WINDOW = 4
 | 
				
			||||||
 | 
						gc::arraybuf abuf4(data, 1024);
 | 
				
			||||||
 | 
						gc::RawDataRecord rdrAfter;
 | 
				
			||||||
 | 
						header.setSamplingTime(fromString("2020-01-01 00:00:00"));
 | 
				
			||||||
 | 
						header.dataType = gc::DT_INT32;
 | 
				
			||||||
 | 
						header.samplingFrequencyNumerator = 1;
 | 
				
			||||||
 | 
						header.samplingFrequencyDenominator = 1;
 | 
				
			||||||
 | 
						rdrAfter.setHeader(header);
 | 
				
			||||||
 | 
						check = rdrAfter.put(abuf4, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(check, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = rdrOther.get(abuf4, 1024, rdrBefore.startTime(),rdrBefore.endTime(), 10);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, gc::DataRecord::RS_AfterTimeWindow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// RS_ERROR = 0
 | 
				
			||||||
 | 
						gc::RawDataRecord rdrError;
 | 
				
			||||||
 | 
						ret = rdrError.get(abuf, 1248, rdr.startTime(),rdr.endTime(), 10);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, gc::DataRecord::RS_Error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE_END()
 | 
				
			||||||
							
								
								
									
										10
									
								
								libs/gempa/caps/test/test_utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								libs/gempa/caps/test/test_utils.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					#ifndef __TEST_UTILS_H__
 | 
				
			||||||
 | 
					#define __TEST_UTILS_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/datetime.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gempa::CAPS::Time fromString(const char *str) {
 | 
				
			||||||
 | 
						return Gempa::CAPS::Time::FromString(str, "%F %T");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										289
									
								
								libs/gempa/caps/test/utils.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								libs/gempa/caps/test/utils.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,289 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * Author: Tracey Werner, Enrico Ellguth                                   *
 | 
				
			||||||
 | 
					 * Email: tracey.werner@gempa.de, enrico.ellguth@gempa.de                  *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SEISCOMP_TEST_MODULE gempa
 | 
				
			||||||
 | 
					#include <seiscomp3/unittest/unittests.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace gc = Gempa::CAPS;
 | 
				
			||||||
 | 
					namespace bu = boost::unit_test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace gc;
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE(gempa_common_caps_utils)
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(split_address_function) {
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_warnings);
 | 
				
			||||||
 | 
						bu::unit_test_log.set_threshold_level(bu::log_messages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						string name;
 | 
				
			||||||
 | 
						unsigned short port;
 | 
				
			||||||
 | 
						int defaultPort = 18002;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						string hostname = "localhost";
 | 
				
			||||||
 | 
						bool valid = splitAddress(name, port, hostname,defaultPort);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(hostname, "localhost");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(port, 18002);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hostname = "data.gempa.de:18000";
 | 
				
			||||||
 | 
						valid = splitAddress(name, port, hostname, defaultPort);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(name, "data.gempa.de");
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(port, 18000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hostname = "";
 | 
				
			||||||
 | 
						valid = splitAddress(name, port, hostname, defaultPort);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hostname = "localhost:abcde";
 | 
				
			||||||
 | 
						valid = splitAddress(name, port, hostname, defaultPort);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// port range check. By definition allowed ports are 1 - 65535
 | 
				
			||||||
 | 
						hostname = "localhost:0";
 | 
				
			||||||
 | 
						valid = splitAddress(name, port, hostname, defaultPort);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hostname = "localhost:1";
 | 
				
			||||||
 | 
						valid = splitAddress(name, port, hostname, defaultPort);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hostname = "localhost:65536";
 | 
				
			||||||
 | 
						valid = splitAddress(name, port, hostname, defaultPort);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hostname = "localhost:-1";
 | 
				
			||||||
 | 
						valid = splitAddress(name, port, hostname, defaultPort);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hostname = "localhost:";
 | 
				
			||||||
 | 
						valid = splitAddress(name, port, hostname,defaultPort);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(valid, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(trim_function) {
 | 
				
			||||||
 | 
						// delete whitespaces before and after string
 | 
				
			||||||
 | 
						string text = " This is a test text 1";
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(trim(text), "This is a test text 1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char *str = text.c_str();
 | 
				
			||||||
 | 
						int len = text.length();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char *res = trim(str,len);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(string(res, len), "This is a test text 1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						text = "   This is a test text 2";
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(trim(text), "This is a test text 2");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = text.c_str();
 | 
				
			||||||
 | 
						len = text.length();
 | 
				
			||||||
 | 
						res = trim(str,len);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(string(res,len), "This is a test text 2");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						text = "This is a test text      ";
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(trim(text), "This is a test text");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = text.c_str();
 | 
				
			||||||
 | 
						len = text.length();
 | 
				
			||||||
 | 
						res = trim(str,len);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(string(res,len), "This is a test text");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						text = "   Hello World   ";
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(trim(text), "Hello World");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = text.c_str();
 | 
				
			||||||
 | 
						len = text.length();
 | 
				
			||||||
 | 
						res = trim(str,len);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(string(res,len), "Hello World");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						text = " Hello     :     world";
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(trim(text), "Hello     :     world");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = text.c_str();
 | 
				
			||||||
 | 
						len = text.length();
 | 
				
			||||||
 | 
						res = trim(str, len);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(string(res,len), "Hello     :     world");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(converts_time) {
 | 
				
			||||||
 | 
						// Converts  time object to timestamp
 | 
				
			||||||
 | 
						const Time t(2014,4,14,6,34,39,7389);
 | 
				
			||||||
 | 
						TimeStamp ts;
 | 
				
			||||||
 | 
						timeToTimestamp(ts, t);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ts.year, 2014);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ts.second, 39);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const Time t2(0,0);
 | 
				
			||||||
 | 
						timeToTimestamp(ts,t2);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ts.year, 1970);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ts.hour, 0);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ts.yday, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Converts timestamp to time object
 | 
				
			||||||
 | 
						Time t3 = timestampToTime(ts);
 | 
				
			||||||
 | 
						int year, yday, hour, min, sec, usec;
 | 
				
			||||||
 | 
						t3.get2(&year, &yday, &hour, &min, &sec, &usec);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(year, 1970);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(min, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(samples) {
 | 
				
			||||||
 | 
						DataRecord::Header head;
 | 
				
			||||||
 | 
						head.samplingFrequencyNumerator = 1;
 | 
				
			||||||
 | 
						head.samplingFrequencyDenominator = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Convert samples to timespan
 | 
				
			||||||
 | 
						TimeSpan ts = samplesToTimeSpan(head, 2);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ts, TimeSpan(2,0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Convert time span to samples
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(timeSpanToSamples(head, ts), 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Convert time span to samples and round up/down
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(timeSpanToSamplesCeil(head, TimeSpan(0, 500000)), 1);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(timeSpanToSamplesFloor(head, TimeSpan(0, 600000)), 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(str_to_int) {
 | 
				
			||||||
 | 
						// int tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char *str = "1352";
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						bool ret = str2int(i, str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(i, 1352);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = "";
 | 
				
			||||||
 | 
						ret = str2int(i, str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = "478a2";
 | 
				
			||||||
 | 
						ret = str2int(i, str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = " 57721";
 | 
				
			||||||
 | 
						ret = str2int(i, str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(i, 57721);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = "4876 9742";
 | 
				
			||||||
 | 
						ret = str2int(i, str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(i, 4876);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = "-98256";
 | 
				
			||||||
 | 
						ret = str2int(i,str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, true);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(i, -98256);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = "-2147483649";
 | 
				
			||||||
 | 
						ret = str2int(i,str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = "2147483648";
 | 
				
			||||||
 | 
						ret = str2int(i,str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// uint16_t tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = "1";
 | 
				
			||||||
 | 
						uint16_t value;
 | 
				
			||||||
 | 
						ret = str2int(value, str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = "-1";
 | 
				
			||||||
 | 
						ret = str2int(value, str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = "65535";
 | 
				
			||||||
 | 
						ret = str2int(value, str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = "65536";
 | 
				
			||||||
 | 
						ret = str2int(value, str);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(ret, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(tokenize_function) {
 | 
				
			||||||
 | 
						const char *text = "Hello, World!";
 | 
				
			||||||
 | 
						int len = strlen(text), tok_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char *tok = tokenize(text, ",", len, tok_len);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(string(tok, tok_len), "Hello");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tok = tokenize(text, ",", len, tok_len);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(string(tok,tok_len)," World!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						text = "This is a book";
 | 
				
			||||||
 | 
						len = strlen(text);
 | 
				
			||||||
 | 
						int tok_count = 0;
 | 
				
			||||||
 | 
						while ( (tok = tokenize(text, ",", len, tok_len)) != NULL ) {
 | 
				
			||||||
 | 
							if ( tok_count == 3 ) {
 | 
				
			||||||
 | 
								BOOST_CHECK_EQUAL(string(tok, tok_len), "book");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							++tok_count;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						text = "";
 | 
				
			||||||
 | 
						len = strlen(text);
 | 
				
			||||||
 | 
						tok = tokenize(text, ";", len,tok_len);
 | 
				
			||||||
 | 
						BOOST_CHECK_EQUAL(string(tok,tok_len), "");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_SUITE_END()
 | 
				
			||||||
							
								
								
									
										377
									
								
								libs/gempa/caps/utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										377
									
								
								libs/gempa/caps/utils.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,377 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 by gempa GmbH                                        *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * All Rights Reserved.                                                    *
 | 
				
			||||||
 | 
					 *                                                                         *
 | 
				
			||||||
 | 
					 * NOTICE: All information contained herein is, and remains                *
 | 
				
			||||||
 | 
					 * the property of gempa GmbH and its suppliers, if any. The intellectual  *
 | 
				
			||||||
 | 
					 * and technical concepts contained herein are proprietary to gempa GmbH   *
 | 
				
			||||||
 | 
					 * and its suppliers.                                                      *
 | 
				
			||||||
 | 
					 * Dissemination of this information or reproduction of this material      *
 | 
				
			||||||
 | 
					 * is strictly forbidden unless prior written permission is obtained       *
 | 
				
			||||||
 | 
					 * from gempa GmbH.                                                        *
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEMPA_CAPS_UTILS_H
 | 
				
			||||||
 | 
					#define GEMPA_CAPS_UTILS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cerrno>
 | 
				
			||||||
 | 
					#include <cstdlib>
 | 
				
			||||||
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <limits>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace  Gempa {
 | 
				
			||||||
 | 
					namespace CAPS {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class arraybuf : public std::streambuf {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							typedef std::streambuf::pos_type pos_type;
 | 
				
			||||||
 | 
							typedef std::streambuf::off_type off_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							arraybuf(const char *buf, int len) {
 | 
				
			||||||
 | 
								char *tmp = const_cast<char*>(buf);
 | 
				
			||||||
 | 
								setp(tmp, tmp + len);
 | 
				
			||||||
 | 
								setg(tmp, tmp, tmp + len);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							arraybuf(const std::string &buf) {
 | 
				
			||||||
 | 
								if ( buf.size() > 0 ) {
 | 
				
			||||||
 | 
									char *tmp = const_cast<char*>(&buf[0]);
 | 
				
			||||||
 | 
									setg(tmp, tmp, tmp + buf.size());
 | 
				
			||||||
 | 
									setp(tmp, tmp + buf.size());
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void reset(const char *buf, int len) {
 | 
				
			||||||
 | 
								char *tmp = const_cast<char*>(buf);
 | 
				
			||||||
 | 
								setp(tmp, tmp + len);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual pos_type seekoff(off_type ofs, std::ios_base::seekdir dir,
 | 
				
			||||||
 | 
							                         std::ios_base::openmode mode) {
 | 
				
			||||||
 | 
								if ( mode & std::ios_base::in ) {
 | 
				
			||||||
 | 
									char *next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									switch ( dir ) {
 | 
				
			||||||
 | 
										case std::ios_base::beg:
 | 
				
			||||||
 | 
											next = eback() + ofs;
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										case std::ios_base::cur:
 | 
				
			||||||
 | 
											next = gptr() + ofs;
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										case std::ios_base::end:
 | 
				
			||||||
 | 
											next = egptr() + ofs;
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										default:
 | 
				
			||||||
 | 
											return pos_type(off_type(-1));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ( next > egptr() || next < eback() )
 | 
				
			||||||
 | 
										return pos_type(off_type(-1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									gbump(next-gptr());
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( mode & std::ios_base::out ) {
 | 
				
			||||||
 | 
									return pos_type(off_type(-1));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return pos_type(off_type(-1));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode) {
 | 
				
			||||||
 | 
								if ( mode & std::ios_base::in ) {
 | 
				
			||||||
 | 
									char *next = eback() + pos;
 | 
				
			||||||
 | 
									if ( next > egptr() )
 | 
				
			||||||
 | 
										return pos_type(off_type(-1));
 | 
				
			||||||
 | 
									gbump(next-gptr());
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( mode & std::ios_base::out ) {
 | 
				
			||||||
 | 
									char *next = pbase() + pos;
 | 
				
			||||||
 | 
									if ( next > epptr() ) {
 | 
				
			||||||
 | 
										return pos_type(off_type(-1));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									pbump(pos);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return pos;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual std::streamsize xsgetn(char* s, std::streamsize n) {
 | 
				
			||||||
 | 
								char *next = gptr() + n;
 | 
				
			||||||
 | 
								if ( next >= egptr() )
 | 
				
			||||||
 | 
									n = n - (next - egptr());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( n == 0 ) return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								memcpy(s, gptr(), n);
 | 
				
			||||||
 | 
								setg(eback(), next, egptr());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return n;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::streampos tellg() {
 | 
				
			||||||
 | 
								return gptr() - eback();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::streampos tellp() {
 | 
				
			||||||
 | 
								return pptr() - pbase();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CHECK_STRING(data, str, len) \
 | 
				
			||||||
 | 
						((len == sizeof(str)-1) && (strncasecmp(data, str, len) == 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Splits an address string into hostname and port
 | 
				
			||||||
 | 
					 * @param host The host
 | 
				
			||||||
 | 
					 * @param port The port
 | 
				
			||||||
 | 
					 * @param address The address
 | 
				
			||||||
 | 
					 * @param default_port The default port which will be used
 | 
				
			||||||
 | 
					 * if the addrees contains no port
 | 
				
			||||||
 | 
					 * @return True, if the address is valid
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					inline bool splitAddress(std::string &host, unsigned short &port,
 | 
				
			||||||
 | 
					                         const std::string &address, unsigned short default_port) {
 | 
				
			||||||
 | 
						size_t pos = address.find(':');
 | 
				
			||||||
 | 
						if ( pos != std::string::npos ) {
 | 
				
			||||||
 | 
							int p = -1;
 | 
				
			||||||
 | 
							host = address.substr(0, pos);
 | 
				
			||||||
 | 
							std::stringstream ss(address.substr(pos+1));
 | 
				
			||||||
 | 
							ss >> p;
 | 
				
			||||||
 | 
							if ( p > 0 && p <= 65535 )
 | 
				
			||||||
 | 
								port = p;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							host = address;
 | 
				
			||||||
 | 
							port = default_port;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return !host.empty();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Returns substring that contains leftmost characters up to the delimiter
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					inline const char *tokenize(const char *&str, const char *delim,
 | 
				
			||||||
 | 
					                            int &len_source, int &len_tok) {
 | 
				
			||||||
 | 
						len_tok = 0;
 | 
				
			||||||
 | 
						for ( ; len_source; --len_source, ++str ) {
 | 
				
			||||||
 | 
							// Hit first non delimiter?
 | 
				
			||||||
 | 
							if ( strchr(delim, *str) == NULL ) {
 | 
				
			||||||
 | 
								const char *tok = str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								++str; --len_source;
 | 
				
			||||||
 | 
								len_tok = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Hit first delimiter?
 | 
				
			||||||
 | 
								for ( ; len_source; --len_source, ++str, ++len_tok ) {
 | 
				
			||||||
 | 
									if ( strchr(delim, *str) != NULL )
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return tok;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Removes whitespaces from start and end of string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					inline const char *trim(const char *&str, int &len) {
 | 
				
			||||||
 | 
						int i = len;
 | 
				
			||||||
 | 
						while ( i > 0 ) {
 | 
				
			||||||
 | 
							if ( isspace(*str) ) {
 | 
				
			||||||
 | 
								++str;
 | 
				
			||||||
 | 
								--len;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							++i;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						i = len-1;
 | 
				
			||||||
 | 
						while ( i > 0 ) {
 | 
				
			||||||
 | 
							if ( !isspace(str[i]) )
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							--len;
 | 
				
			||||||
 | 
							--i;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return str;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline std::string trim(const std::string &s) {
 | 
				
			||||||
 | 
						int l = (int)s.size();
 | 
				
			||||||
 | 
						const char *str = &s[0];
 | 
				
			||||||
 | 
						trim(str, l);
 | 
				
			||||||
 | 
						return std::string(str, l);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Converts  time object to timestamp
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					inline void timeToTimestamp(TimeStamp &ts, const Time &t) {
 | 
				
			||||||
 | 
						int year, yday, hour, min, sec, usec;
 | 
				
			||||||
 | 
						t.get2(&year, &yday, &hour, &min, &sec, &usec);
 | 
				
			||||||
 | 
						ts.year = year;
 | 
				
			||||||
 | 
						ts.yday = yday;
 | 
				
			||||||
 | 
						ts.hour = hour;
 | 
				
			||||||
 | 
						ts.minute = min;
 | 
				
			||||||
 | 
						ts.second = sec;
 | 
				
			||||||
 | 
						ts.usec = usec;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Converts string to integer value
 | 
				
			||||||
 | 
					 * @param v The integer value
 | 
				
			||||||
 | 
					 * @param s The input string
 | 
				
			||||||
 | 
					 * @param len The string length. If len is 0 the length
 | 
				
			||||||
 | 
					 *            is calculated from string
 | 
				
			||||||
 | 
					 * @param base The numeric base
 | 
				
			||||||
 | 
					 * @return True on success
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool str2int(T &v, char const *s, int len = 0, int base = 10) {
 | 
				
			||||||
 | 
						// Return false in case of empty string
 | 
				
			||||||
 | 
						if (*s == '\0' ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char *end;
 | 
				
			||||||
 | 
						long l;
 | 
				
			||||||
 | 
						errno = 0;
 | 
				
			||||||
 | 
						l = strtol(s, &end, base);
 | 
				
			||||||
 | 
						if ( errno == ERANGE ||
 | 
				
			||||||
 | 
						     l < std::numeric_limits<T>::min() ||
 | 
				
			||||||
 | 
						     l > std::numeric_limits<T>::max() ) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check if the string contains invalid chars
 | 
				
			||||||
 | 
						if ( len == 0 ) len = strlen(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int bytes_read = end - s;
 | 
				
			||||||
 | 
						if ( bytes_read < len && *end != ' ' ) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v = static_cast<T>(l);
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Converts string to integer value
 | 
				
			||||||
 | 
					 * @param v The integer value
 | 
				
			||||||
 | 
					 * @param s The input string
 | 
				
			||||||
 | 
					 * @param len The string length. If len is 0 the length
 | 
				
			||||||
 | 
					 *            is calculated from string
 | 
				
			||||||
 | 
					 * @param base The numeric base
 | 
				
			||||||
 | 
					 * @return True on success
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					inline bool str2int(int &v, char const *s, int len = 0, int base = 10) {
 | 
				
			||||||
 | 
						return str2int<int>(v, s, len, base);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Converts string to unsigned int16 value
 | 
				
			||||||
 | 
					 * @param v The integer value
 | 
				
			||||||
 | 
					 * @param s The input string
 | 
				
			||||||
 | 
					 * @param len The string length. If len is 0 the length
 | 
				
			||||||
 | 
					 *            is calculated from string
 | 
				
			||||||
 | 
					 * @param base The numeric base
 | 
				
			||||||
 | 
					 * @return True on success
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					inline bool str2int(uint16_t &v, char const *s, int len = 0, int base = 10) {
 | 
				
			||||||
 | 
						return str2int<uint16_t>(v, s, len, base);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Converts timestamp to time object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					inline Time
 | 
				
			||||||
 | 
					timestampToTime(const TimeStamp &ts) {
 | 
				
			||||||
 | 
						Time t;
 | 
				
			||||||
 | 
						t.set(ts.year, 1, 1, ts.hour, ts.minute, ts.second, ts.usec);
 | 
				
			||||||
 | 
						// Add the day of the year in seconds
 | 
				
			||||||
 | 
						t += TimeSpan(ts.yday*86400);
 | 
				
			||||||
 | 
						return t;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline TimeSpan
 | 
				
			||||||
 | 
					samplesToTimeSpan(const DataRecord::Header &head, int sampleCount) {
 | 
				
			||||||
 | 
						int64_t ms = ((int64_t)(sampleCount)) * 1000000 * head.samplingFrequencyDenominator / head.samplingFrequencyNumerator;
 | 
				
			||||||
 | 
						return TimeSpan(ms/1000000, ms%1000000);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline int
 | 
				
			||||||
 | 
					timeSpanToSamples(const DataRecord::Header &head, const TimeSpan &span) {
 | 
				
			||||||
 | 
						int64_t ms = ((int64_t)span.seconds())*1000000 + span.microseconds();
 | 
				
			||||||
 | 
						return ms * head.samplingFrequencyNumerator / head.samplingFrequencyDenominator / 1000000;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline int
 | 
				
			||||||
 | 
					timeSpanToSamplesCeil(const DataRecord::Header &head, const TimeSpan &span) {
 | 
				
			||||||
 | 
						int64_t ms = ((int64_t)span.seconds())*1000000 + span.microseconds();
 | 
				
			||||||
 | 
						return (ms * head.samplingFrequencyNumerator / head.samplingFrequencyDenominator + 999999) / 1000000;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline int
 | 
				
			||||||
 | 
					timeSpanToSamplesFloor(const DataRecord::Header &head, const TimeSpan &span) {
 | 
				
			||||||
 | 
						int64_t ms = ((int64_t)span.seconds())*1000000 + span.microseconds();
 | 
				
			||||||
 | 
						return ms * head.samplingFrequencyNumerator / head.samplingFrequencyDenominator / 1000000;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(WIN32)
 | 
				
			||||||
 | 
					inline void usleep(__int64 usec)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						HANDLE timer;
 | 
				
			||||||
 | 
						LARGE_INTEGER ft;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ft.QuadPart = -(10*usec); // Convert to 100 nanosecond interval, negative value indicates relative time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						timer = CreateWaitableTimer(NULL, TRUE, NULL);
 | 
				
			||||||
 | 
						SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
 | 
				
			||||||
 | 
						WaitForSingleObject(timer, INFINITE);
 | 
				
			||||||
 | 
						CloseHandle(timer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline uint8_t dataTypeSize(DataType dt) {
 | 
				
			||||||
 | 
						if ( dt == DT_INT8 )
 | 
				
			||||||
 | 
							return sizeof(int8_t);
 | 
				
			||||||
 | 
						if ( dt == DT_INT16 )
 | 
				
			||||||
 | 
							return sizeof(int16_t);
 | 
				
			||||||
 | 
						else if ( dt == DT_INT32 )
 | 
				
			||||||
 | 
							return sizeof(int32_t);
 | 
				
			||||||
 | 
						else if ( dt == DT_INT64 )
 | 
				
			||||||
 | 
							return sizeof(DT_INT64);
 | 
				
			||||||
 | 
						else if ( dt == DT_FLOAT )
 | 
				
			||||||
 | 
							return sizeof(float);
 | 
				
			||||||
 | 
						else if ( dt == DT_DOUBLE )
 | 
				
			||||||
 | 
							return sizeof(double);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										32
									
								
								libs/gempa/caps/version.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								libs/gempa/caps/version.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					/***************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 by gempa GmbH
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Stephan Herrnkind
 | 
				
			||||||
 | 
					 * Email: herrnkidn@gempa.de
 | 
				
			||||||
 | 
					 ***************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __GEMPA_CAPS_VERSION_H__
 | 
				
			||||||
 | 
					#define __GEMPA_CAPS_VERSION_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* #if (LIB_CAPS_VERSION >= LIB_CAPS_VERSION_CHECK(1, 0, 0)) */
 | 
				
			||||||
 | 
					#define LIB_CAPS_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LIB_CAPS_VERSION_MAJOR(v) (v >> 16)
 | 
				
			||||||
 | 
					#define LIB_CAPS_VERSION_MINOR(v) ((v >> 8) & 0xff)
 | 
				
			||||||
 | 
					#define LIB_CAPS_VERSION_PATCH(v) (v & 0xff)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* LIB_CAPS_VERSION is (major << 16) + (minor << 8) + patch. */
 | 
				
			||||||
 | 
					#define LIB_CAPS_VERSION 0x010000
 | 
				
			||||||
 | 
					#define LIB_CAPS_VERSION_NAME "1.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 API Changelog
 | 
				
			||||||
 | 
					 ******************************************************************************
 | 
				
			||||||
 | 
					 "1.0.0"   0x010000
 | 
				
			||||||
 | 
					   - Initial version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // __GEMPA_CAPS_VERSION_H__
 | 
				
			||||||
							
								
								
									
										1
									
								
								libs/swig/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								libs/swig/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					SUBDIRS(gempa)
 | 
				
			||||||
							
								
								
									
										125
									
								
								libs/swig/gempa/CAPS.i
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								libs/swig/gempa/CAPS.i
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,125 @@
 | 
				
			|||||||
 | 
					%feature("notabstract") Gempa::CAPS::AnyDataRecord;
 | 
				
			||||||
 | 
					%include "stdint.i"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%init
 | 
				
			||||||
 | 
					%{
 | 
				
			||||||
 | 
					import_array();
 | 
				
			||||||
 | 
					%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%module CAPS
 | 
				
			||||||
 | 
					%{
 | 
				
			||||||
 | 
					#define SWIG_FILE_WITH_INIT
 | 
				
			||||||
 | 
					#include <gempa/caps/utils.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/anypacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/datetime.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/log.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/mseedpacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/packet.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/plugin.h>
 | 
				
			||||||
 | 
					typedef Gempa::CAPS::Plugin::Buffer Buffer;
 | 
				
			||||||
 | 
					#include <gempa/caps/rawpacket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/riff.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/rtcm2packet.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/socket.h>
 | 
				
			||||||
 | 
					#include <gempa/caps/mseed/spclock.h>
 | 
				
			||||||
 | 
					#include <numpy/ndarrayobject.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%extend Gempa::CAPS::Plugin {
 | 
				
			||||||
 | 
					        Gempa::CAPS::Plugin::Status push(const std::string &net, const std::string &sta,
 | 
				
			||||||
 | 
					                              const std::string &loc, const std::string &cha,
 | 
				
			||||||
 | 
					                              const Time &stime, int16_t numerator, int16_t denominator,
 | 
				
			||||||
 | 
					                              const std::string &uom,
 | 
				
			||||||
 | 
					                              PyObject *obj, int type
 | 
				
			||||||
 | 
					                              ) {
 | 
				
			||||||
 | 
					                PyArrayObject *arr = NULL;
 | 
				
			||||||
 | 
					                Gempa::CAPS::DataType dataType = (Gempa::CAPS::DataType)type;
 | 
				
			||||||
 | 
					                Gempa::CAPS::Plugin::Status status = Gempa::CAPS::Plugin::PacketLoss;
 | 
				
			||||||
 | 
					                switch(type) {
 | 
				
			||||||
 | 
					                        case Gempa::CAPS::DT_INT8:
 | 
				
			||||||
 | 
					                                arr = (PyArrayObject*) PyArray_ContiguousFromObject(obj, PyArray_CHAR, 1, 1);
 | 
				
			||||||
 | 
					                                if ( arr == NULL )
 | 
				
			||||||
 | 
					                                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                status = self->push(net, sta, loc, cha, stime, numerator, denominator,
 | 
				
			||||||
 | 
					                                                    uom, (int8_t*)(arr->data), arr->dimensions[0], dataType);
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
 | 
					                        case Gempa::CAPS::DT_INT16:
 | 
				
			||||||
 | 
					                                arr = (PyArrayObject*) PyArray_ContiguousFromObject(obj, PyArray_INT16, 1, 1);
 | 
				
			||||||
 | 
					                                if ( arr == NULL )
 | 
				
			||||||
 | 
					                                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                status = self->push(net, sta, loc, cha, stime, numerator, denominator,
 | 
				
			||||||
 | 
					                                                    uom, (int16_t*)(arr->data), arr->dimensions[0], dataType);
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
 | 
					                        case Gempa::CAPS::DT_INT32:
 | 
				
			||||||
 | 
					                                arr = (PyArrayObject*) PyArray_ContiguousFromObject(obj, PyArray_INT32, 1, 1);
 | 
				
			||||||
 | 
					                                if ( arr == NULL )
 | 
				
			||||||
 | 
					                                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                status = self->push(net, sta, loc, cha, stime, numerator, denominator,
 | 
				
			||||||
 | 
					                                                    uom, (int32_t*)(arr->data), arr->dimensions[0], dataType);
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
 | 
					                        case Gempa::CAPS::DT_FLOAT:
 | 
				
			||||||
 | 
					                                arr = (PyArrayObject*) PyArray_ContiguousFromObject(obj, PyArray_FLOAT32, 1, 1);
 | 
				
			||||||
 | 
					                                if ( arr == NULL )
 | 
				
			||||||
 | 
					                                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                status = self->push(net, sta, loc, cha, stime, numerator, denominator,
 | 
				
			||||||
 | 
					                                                    uom, (float*)(arr->data), arr->dimensions[0], dataType);
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
 | 
					                        case Gempa::CAPS::DT_DOUBLE:
 | 
				
			||||||
 | 
					                                arr = (PyArrayObject*) PyArray_ContiguousFromObject(obj, PyArray_FLOAT64, 1, 1);
 | 
				
			||||||
 | 
					                                if ( arr == NULL )
 | 
				
			||||||
 | 
					                                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                status = self->push(net, sta, loc, cha, stime, numerator, denominator,
 | 
				
			||||||
 | 
					                                                    uom, (double*)(arr->data), arr->dimensions[0], dataType);
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
 | 
					                        default:
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Py_XDECREF(arr);
 | 
				
			||||||
 | 
					                return status;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Gempa::CAPS::Plugin::Status push(const std::string &net, const std::string &sta,
 | 
				
			||||||
 | 
					                                         const std::string &loc, const std::string &cha,
 | 
				
			||||||
 | 
					                                         const Time &stime, uint16_t numerator,
 | 
				
			||||||
 | 
					                                         uint16_t denominator, const std::string &format,
 | 
				
			||||||
 | 
					                                         PyObject *obj) {
 | 
				
			||||||
 | 
					                char *data;
 | 
				
			||||||
 | 
					                Py_ssize_t len;
 | 
				
			||||||
 | 
					                if ( PyBytes_AsStringAndSize(obj, &data, &len) == -1 )
 | 
				
			||||||
 | 
					                        return Gempa::CAPS::Plugin::PacketLoss;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return self->push(net, sta, loc, cha, stime, numerator,
 | 
				
			||||||
 | 
					                                  denominator, format, data, len);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%include "exception.i"
 | 
				
			||||||
 | 
					%include "std_string.i"
 | 
				
			||||||
 | 
					%include "numpy.i"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%include "gempa/caps/api.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/datetime.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/packet.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/pluginpacket.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/anypacket.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/log.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/mseed/spclock.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/mseed/encoder.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/encoderfactory.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/mseedpacket.h"
 | 
				
			||||||
 | 
					typedef Gempa::CAPS::Plugin::Buffer Buffer;
 | 
				
			||||||
 | 
					%include "gempa/caps/plugin.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/rawpacket.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/riff.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/rtcm2packet.h"
 | 
				
			||||||
 | 
					%include "gempa/caps/socket.h"
 | 
				
			||||||
 | 
					%include <carrays.i>
 | 
				
			||||||
 | 
					%array_class(char, charArray);
 | 
				
			||||||
 | 
					%include "gempa/caps/utils.h"
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user