init
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
PROJECT(openvibe-module-system)
|
||||
|
||||
SET(PROJECT_VERSION_MAJOR ${OV_GLOBAL_VERSION_MAJOR})
|
||||
SET(PROJECT_VERSION_MINOR ${OV_GLOBAL_VERSION_MINOR})
|
||||
SET(PROJECT_VERSION_PATCH ${OV_GLOBAL_VERSION_PATCH})
|
||||
SET(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
|
||||
|
||||
SET(SRC_FILES
|
||||
include/system/defines.h
|
||||
include/system/ovCChrono.h
|
||||
include/system/ovCMath.h
|
||||
include/system/ovCMemory.h
|
||||
include/system/ovCTime.h
|
||||
include/system/ovCDynamicModule.h
|
||||
src/ovCChrono.cpp
|
||||
src/ovCMath.cpp
|
||||
src/ovCMemory.cpp
|
||||
src/ovCTime.cpp
|
||||
src/ovCDynamicModule.cpp
|
||||
)
|
||||
|
||||
IF(WIN32)
|
||||
LIST(APPEND SRC_FILES
|
||||
"include/system/WindowsUtilities.h"
|
||||
"src/WindowsUtilities.cpp"
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
INCLUDE_DIRECTORIES(include)
|
||||
INCLUDE("FindSourceRCProperties")
|
||||
|
||||
ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRC_FILES})
|
||||
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
FOLDER ${MODULES_FOLDER}
|
||||
COMPILE_FLAGS "-DSystem_Shared -DSystem_Exports")
|
||||
|
||||
ADD_LIBRARY(${PROJECT_NAME}-static STATIC ${SRC_FILES})
|
||||
SET_TARGET_PROPERTIES(${PROJECT_NAME}-static PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
FOLDER ${MODULES_FOLDER}
|
||||
COMPILE_FLAGS "-DSystem_Static -DSystem_Exports")
|
||||
|
||||
IF(UNIX)
|
||||
SET_TARGET_PROPERTIES(${PROJECT_NAME}-static PROPERTIES COMPILE_FLAGS "-fPIC")
|
||||
ENDIF()
|
||||
|
||||
INCLUDE("FindOpenViBECommon")
|
||||
|
||||
IF(WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0")
|
||||
INCLUDE("FindThirdPartyBoost")
|
||||
OV_LINK_BOOST_LIB("system" ${OV_WIN32_BOOST_VERSION})
|
||||
OV_LINK_BOOST_LIB("thread" ${OV_WIN32_BOOST_VERSION})
|
||||
INCLUDE("FindThirdPartyBoost_Chrono")
|
||||
ENDIF()
|
||||
|
||||
|
||||
|
||||
# ---------------------------------
|
||||
# Finds standard library winmm
|
||||
# Adds library to target
|
||||
# Adds include path
|
||||
# ---------------------------------
|
||||
IF(WIN32)
|
||||
INCLUDE("OvSetWindowsSDKPath")
|
||||
|
||||
FIND_LIBRARY(LIB_STANDARD_MODULE_WINMM winmm ${OV_MS_SDK_PATH}/lib)
|
||||
|
||||
IF(LIB_STANDARD_MODULE_WINMM)
|
||||
MESSAGE(STATUS " Found winmm...")
|
||||
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIB_STANDARD_MODULE_WINMM})
|
||||
TARGET_LINK_LIBRARIES(${PROJECT_NAME}-static ${LIB_STANDARD_MODULE_WINMM})
|
||||
ELSE(LIB_STANDARD_MODULE_WINMM)
|
||||
MESSAGE(STATUS " FAILED to find winmm...")
|
||||
ENDIF(LIB_STANDARD_MODULE_WINMM)
|
||||
|
||||
FIND_LIBRARY(LIB_STANDARD_MODULE_DBGHELP dbghelp ${OV_MS_SDK_PATH}/lib)
|
||||
|
||||
IF(LIB_STANDARD_MODULE_DBGHELP)
|
||||
MESSAGE(STATUS " Found dbghelp...")
|
||||
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIB_STANDARD_MODULE_DBGHELP})
|
||||
TARGET_LINK_LIBRARIES(${PROJECT_NAME}-static ${LIB_STANDARD_MODULE_DBGHELP})
|
||||
ELSE(LIB_STANDARD_MODULE_DBGHELP)
|
||||
MESSAGE(STATUS " FAILED to find dbghelp...")
|
||||
ENDIF(LIB_STANDARD_MODULE_DBGHELP)
|
||||
ELSE()
|
||||
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${CMAKE_DL_LIBS})
|
||||
ENDIF()
|
||||
|
||||
# ---------------------------------
|
||||
# Target macros
|
||||
# Defines target operating system, architecture and compiler
|
||||
# ---------------------------------
|
||||
SET_BUILD_PLATFORM()
|
||||
|
||||
# -----------------------------
|
||||
# Install files
|
||||
# -----------------------------
|
||||
INSTALL(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
INSTALL(TARGETS ${PROJECT_NAME}-static
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
INSTALL(DIRECTORY include/ DESTINATION ${DIST_INCLUDEDIR} FILES_MATCHING PATTERN "*.h")
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
#if defined TARGET_OS_Windows
|
||||
#include <windows.h>
|
||||
|
||||
namespace System {
|
||||
class System_API WindowsUtilities
|
||||
{
|
||||
public:
|
||||
// Load a library in a matter compliant with non-ascii path
|
||||
// returns the eventual error code
|
||||
static void* utf16CompliantLoadLibrary(const char* path, HANDLE file = nullptr, DWORD flags = LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
|
||||
static BOOL utf16CompliantSetEnvironmentVariable(const char* name, const char* value);
|
||||
|
||||
// Load a library in a matter compliant with non-ascii path
|
||||
// returns the eventual error code
|
||||
static BOOL utf16CompliantCreateProcess(char* applicationName, char* commandLine, LPSECURITY_ATTRIBUTES processAttributes,
|
||||
LPSECURITY_ATTRIBUTES threadAttributes, BOOL inheritHandles, DWORD creationFlags, LPVOID environment,
|
||||
char* currentDirectory, LPSTARTUPINFO startupInfo, LPPROCESS_INFORMATION processInformation);
|
||||
|
||||
// Load a library in a matter compliant with non-ascii path
|
||||
// returns the eventual error code
|
||||
static HINSTANCE utf16CompliantShellExecute(HWND hwnd, LPCTSTR operation, LPCTSTR file, LPCTSTR parameters, LPCTSTR directory, INT nShowCmd);
|
||||
private:
|
||||
WindowsUtilities() = delete;
|
||||
};
|
||||
} // namespace System
|
||||
|
||||
#endif // TARGET_OS_Windows
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <ov_common_defines.h>
|
||||
|
||||
#if defined System_Shared
|
||||
# if defined TARGET_OS_Windows
|
||||
# define System_API_Export __declspec(dllexport)
|
||||
# define System_API_Import __declspec(dllimport)
|
||||
# elif defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
# define System_API_Export __attribute__((visibility("default")))
|
||||
# define System_API_Import __attribute__((visibility("default")))
|
||||
# else
|
||||
# define System_API_Export
|
||||
# define System_API_Import
|
||||
# endif
|
||||
#else
|
||||
# define System_API_Export
|
||||
# define System_API_Import
|
||||
#endif
|
||||
|
||||
#if defined System_Exports
|
||||
# define System_API System_API_Export
|
||||
#else
|
||||
# define System_API System_API_Import
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
#include <cstdlib> // fix Unix compatibility
|
||||
|
||||
namespace System {
|
||||
class System_API CChrono final
|
||||
{
|
||||
public:
|
||||
|
||||
CChrono() { }
|
||||
~CChrono();
|
||||
|
||||
bool reset(size_t nStep);
|
||||
|
||||
bool stepIn();
|
||||
bool stepOut();
|
||||
|
||||
uint64_t getTotalStepInDuration() const;
|
||||
uint64_t getTotalStepOutDuration() const;
|
||||
uint64_t getAverageStepInDuration() const;
|
||||
uint64_t getAverageStepOutDuration() const;
|
||||
double getStepInPercentage() const;
|
||||
double getStepOutPercentage() const;
|
||||
|
||||
bool hasNewEstimation() const { return m_hasNewEstimation; }
|
||||
|
||||
private:
|
||||
|
||||
uint64_t* m_stepInTime = nullptr;
|
||||
uint64_t* m_stepOutTime = nullptr;
|
||||
size_t m_nStep = 0;
|
||||
size_t m_stepIdx = 0;
|
||||
bool m_isInStep = false;
|
||||
bool m_hasNewEstimation = false;
|
||||
|
||||
uint64_t m_totalStepInTime = 0;
|
||||
uint64_t m_totalStepOutTime = 0;
|
||||
};
|
||||
} // namespace System
|
||||
@@ -0,0 +1,264 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
#include <shlobj.h>
|
||||
#include <Dbghelp.h>
|
||||
#elif defined TARGET_OS_Linux
|
||||
#include <linux/limits.h>
|
||||
#elif defined TARGET_OS_MacOS
|
||||
#include <sys/syslimits.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace System {
|
||||
class CDynamicModuleSymbolLoader; // forward declare to make function declaration possible
|
||||
|
||||
class System_API CDynamicModule final
|
||||
{
|
||||
public:
|
||||
enum ELogErrorCodes : size_t
|
||||
{
|
||||
LogErrorCodes_NoError = 0,
|
||||
LogErrorCodes_ModuleAlreadyLoaded = 1,
|
||||
LogErrorCodes_NoModuleLoaded = 2,
|
||||
LogErrorCodes_FilenameEmpty = 3,
|
||||
LogErrorCodes_FolderPathInvalid = 4,
|
||||
LogErrorCodes_RegistryQueryFailed = 5,
|
||||
LogErrorCodes_UnloadModuleFailed = 6,
|
||||
LogErrorCodes_FailToLoadModule = 7,
|
||||
LogErrorCodes_InvalidSymbol = 8,
|
||||
LogErrorCodes_EnvironmentVariableInvalid = 9,
|
||||
LogErrorCodes_ModuleNotFound = 10
|
||||
};
|
||||
|
||||
CDynamicModule();
|
||||
~CDynamicModule();
|
||||
|
||||
/**
|
||||
* \brief Load module from a path.
|
||||
*
|
||||
* \param modulePath
|
||||
* \param symbolNameCheck Symbol to check if it is present in the module. It is optionnal and is nullptr by default.
|
||||
*
|
||||
* \retval true If the module loaded successfully.
|
||||
* \retval false If module loading failed.
|
||||
*/
|
||||
bool loadFromPath(const char* modulePath, const char* symbolNameCheck = nullptr);
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
/**
|
||||
* \brief Load existing module that was already loaded by the process.
|
||||
*
|
||||
* \param modulePath The path to the module.
|
||||
* \param symbolNameCheck Symbol to check if it is present in the module. It is optionnal and is nullptr by default.
|
||||
*
|
||||
* \retval true If the module loaded successfully.
|
||||
* \retval false If module loading failed.
|
||||
*/
|
||||
bool loadFromExisting(const char* modulePath, const char* symbolNameCheck = nullptr);
|
||||
/**
|
||||
* \brief Load module from known path. Windows only.
|
||||
*
|
||||
* \param standardPath A CSIDL value that identifies the folder whose path is to be retrieved.
|
||||
* Only real folders are valid. If a virtual folder is specified, this function fails.
|
||||
* You can force creation of a folder by combining the folder's CSIDL with CSIDL_FLAG_CREATE.
|
||||
* \param modulePath Path of the module to load.
|
||||
* \param symbolNameCheck Symbol to check if it is present in the module. It is optional and is nullptr by default.
|
||||
*
|
||||
* \retval true If the module loaded successfully.
|
||||
* \retval false If module loading failed.
|
||||
*/
|
||||
bool loadFromKnownPath(int standardPath, const char* modulePath, const char* symbolNameCheck = nullptr);
|
||||
|
||||
/**
|
||||
* \brief Load module from Windows environment. Windows only.
|
||||
*
|
||||
* \param environmentPath Environment path.
|
||||
* \param modulePath Module file path.
|
||||
* \param symbolNameCheck Symbol to check if it is present in the module. It is optionnal and is nullptr by default.
|
||||
*
|
||||
* \retval true If the module loaded successfully.
|
||||
* \retval false If module loading failed.
|
||||
*/
|
||||
bool loadFromEnvironment(const char* environmentPath, const char* modulePath, const char* symbolNameCheck = nullptr);
|
||||
|
||||
/**
|
||||
* \brief Load module from the registry. Windows only.
|
||||
*
|
||||
* \param key Registry key. Check https://msdn.microsoft.com/en-us/library/windows/desktop/ms724836
|
||||
* \param registryPath Registry path.
|
||||
* \param registryKeyName Key name.
|
||||
* \param samDesired A mask that specifies the desired access rights to the key to be opened.
|
||||
* The function fails if the security descriptor of the key does not permit the requested access for the calling process
|
||||
* Check https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms724878
|
||||
* \param modulePath sModulePath Module path.
|
||||
* \param symbolNameCheck Symbol to check if it is present in the module. It is optionnal and is nullptr by default.
|
||||
*
|
||||
* \retval true If the module loaded successfully.
|
||||
* \retval false If module loading failed.
|
||||
*/
|
||||
bool loadFromRegistry(HKEY key, const char* registryPath, const char* registryKeyName, REGSAM samDesired, const char* modulePath,
|
||||
const char* symbolNameCheck = nullptr);
|
||||
|
||||
/**
|
||||
* \brief Check the module architecture. Windows only.
|
||||
* The architecture type of the computer. An image file can only be run on the specified computer or a system that emulates the specified computer.
|
||||
* This member can be one of the following values.
|
||||
* - x86: 0x014c
|
||||
* - x64: 0x8664
|
||||
* - ia64: 0x0200
|
||||
*
|
||||
* \param filePath Module file path
|
||||
* \param architecture Architecture code
|
||||
*
|
||||
* \retval true If the module architecture is equal to the architecture parameter.
|
||||
* \retval false If the module is unequal to the architecture parameter.
|
||||
*/
|
||||
static bool isModuleCompatible(const char* filePath, int architecture);
|
||||
#endif
|
||||
|
||||
// --------------------------------------
|
||||
|
||||
/**
|
||||
* \brief Unload the module. If setShouldFreeModule(false) is called, the unload() has no effect.
|
||||
*
|
||||
* \retval true In case of success.
|
||||
* \retval false In case of failure.
|
||||
*
|
||||
* \sa setShouldFreeModule
|
||||
* \sa isLoaded
|
||||
*/
|
||||
bool unload();
|
||||
|
||||
/**
|
||||
* \brief Check if the module is loaded.
|
||||
*
|
||||
* \retval true If the module is loaded.
|
||||
* \retval false If no module are loaded.
|
||||
*
|
||||
* \sa unload
|
||||
* \sa setShouldFreeModule
|
||||
*/
|
||||
bool isLoaded() const { return m_Handle != nullptr; }
|
||||
|
||||
/**
|
||||
* \brief Get the filename of the module.
|
||||
*
|
||||
* \return the file name of the module.
|
||||
*/
|
||||
const char* getFilename() const { return m_Filename; }
|
||||
|
||||
/**
|
||||
* \brief Should be used to avoid the warning "Missing dll" when loading acquisition server
|
||||
* This can happen when the loaded library needs a second library that is not detected.
|
||||
*
|
||||
* \param errorMode
|
||||
*/
|
||||
void setDynamicModuleErrorMode(const size_t errorMode) { m_ErrorMode = errorMode; }
|
||||
|
||||
/**
|
||||
* \brief Set if the module should, or not, be free. By default the module will be free.
|
||||
*
|
||||
* \param shouldFreeModule Set to true to free the module when unload is called. False otherwise.
|
||||
*
|
||||
* \sa unload
|
||||
*/
|
||||
void setShouldFreeModule(const bool shouldFreeModule) { m_ShouldFreeModule = shouldFreeModule; }
|
||||
|
||||
/**
|
||||
* \brief Get the last error code.
|
||||
*
|
||||
* \return The error code.
|
||||
*/
|
||||
size_t getLastError() const;
|
||||
|
||||
/**
|
||||
* \brief Get the error message corresponding to the error code.
|
||||
*
|
||||
* \param errorCode The error code.
|
||||
*
|
||||
* \return the message corresponding to the error code.
|
||||
*/
|
||||
static const char* getErrorString(size_t errorCode);
|
||||
|
||||
/**
|
||||
* \brief Get the detailed error
|
||||
*
|
||||
* \return A string with detailed information about the last error.
|
||||
*/
|
||||
const char* getErrorDetails() const;
|
||||
|
||||
private:
|
||||
void* m_Handle = nullptr;
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
char m_Filename[MAX_PATH];
|
||||
#elif defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
char m_Filename[PATH_MAX];
|
||||
#endif
|
||||
|
||||
size_t m_ErrorMode = 0;
|
||||
bool m_ShouldFreeModule = true;
|
||||
typedef void (*symbol_t)();
|
||||
|
||||
char m_ErrorDetails[1024];
|
||||
mutable ELogErrorCodes m_ErrorCode;
|
||||
|
||||
static const size_t m_ErrorModeNull = 0xffffffff;
|
||||
|
||||
friend class CDynamicModuleSymbolLoader;
|
||||
/**
|
||||
* \brief Set the error code and details.
|
||||
*
|
||||
* \param errorCode Error code.
|
||||
* \param details Detailed string error.
|
||||
*/
|
||||
void setError(ELogErrorCodes errorCode, const std::string& details = std::string());
|
||||
|
||||
/**
|
||||
* \brief Get a symbol from the module.
|
||||
*
|
||||
* \param symbolName Symbol name.
|
||||
*
|
||||
* \return The symbol.
|
||||
*/
|
||||
symbol_t getSymbolGeneric(const char* symbolName) const;
|
||||
|
||||
#ifdef TARGET_OS_Windows
|
||||
/**
|
||||
* \brief Get the image file headers. Windows only.
|
||||
*
|
||||
* \param filename The file path.
|
||||
* \param headers [out] The header.
|
||||
*
|
||||
* \retval true In case of success.
|
||||
* \retval false In case of failure.
|
||||
*/
|
||||
static bool getImageFileHeaders(const char* filename, IMAGE_NT_HEADERS& headers);
|
||||
#endif
|
||||
};
|
||||
|
||||
class CDynamicModuleSymbolLoader
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get a symbol from the module.
|
||||
*
|
||||
* \param dynamicModule
|
||||
* \param symbolName The symbol name.
|
||||
* \param symbol [out] The symbol.
|
||||
*
|
||||
* \retval true If the symbol exists.
|
||||
* \retval false If the symbol does not exist.
|
||||
*/
|
||||
template <typename T>
|
||||
static bool getSymbol(CDynamicModule& dynamicModule, const char* symbolName, T* symbol)
|
||||
{
|
||||
*symbol = reinterpret_cast<T>(dynamicModule.getSymbolGeneric(symbolName));
|
||||
return *symbol != nullptr;
|
||||
}
|
||||
};
|
||||
} // namespace System
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib> // fix Unix compatibility
|
||||
|
||||
namespace System {
|
||||
class System_API Math
|
||||
{
|
||||
public:
|
||||
|
||||
static bool initializeRandomMachine(size_t randomSeed);
|
||||
|
||||
static size_t randomI();
|
||||
// returns a value in [0,upperLimit( -- i.e. upperLimit not included in range
|
||||
static size_t randomWithCeiling(const size_t upperLimit);
|
||||
static double random0To1();
|
||||
static uint64_t random();
|
||||
|
||||
private:
|
||||
Math() = delete;
|
||||
};
|
||||
} // namespace System
|
||||
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
#include <cstdlib> // fix Unix compatibility
|
||||
|
||||
namespace System {
|
||||
class System_API Memory
|
||||
{
|
||||
public:
|
||||
|
||||
static bool hostToLittleEndian(uint16_t value, uint8_t* buffer);
|
||||
static bool hostToLittleEndian(uint32_t value, uint8_t* buffer);
|
||||
static bool hostToLittleEndian(uint64_t value, uint8_t* buffer);
|
||||
static bool hostToLittleEndian(int16_t value, uint8_t* buffer);
|
||||
static bool hostToLittleEndian(int value, uint8_t* buffer);
|
||||
static bool hostToLittleEndian(int64_t value, uint8_t* buffer);
|
||||
static bool hostToLittleEndian(float value, uint8_t* buffer);
|
||||
static bool hostToLittleEndian(double value, uint8_t* buffer);
|
||||
static bool hostToLittleEndian(long double value, uint8_t* buffer);
|
||||
static bool hostToBigEndian(uint16_t value, uint8_t* buffer);
|
||||
static bool hostToBigEndian(uint32_t value, uint8_t* buffer);
|
||||
static bool hostToBigEndian(uint64_t value, uint8_t* buffer);
|
||||
static bool hostToBigEndian(int16_t value, uint8_t* buffer);
|
||||
static bool hostToBigEndian(int value, uint8_t* buffer);
|
||||
static bool hostToBigEndian(int64_t value, uint8_t* buffer);
|
||||
static bool hostToBigEndian(float value, uint8_t* buffer);
|
||||
static bool hostToBigEndian(double value, uint8_t* buffer);
|
||||
static bool hostToBigEndian(long double value, uint8_t* buffer);
|
||||
|
||||
static bool littleEndianToHost(const uint8_t* buffer, uint16_t* value);
|
||||
static bool littleEndianToHost(const uint8_t* buffer, uint32_t* value);
|
||||
static bool littleEndianToHost(const uint8_t* buffer, uint64_t* value);
|
||||
static bool littleEndianToHost(const uint8_t* buffer, int16_t* value);
|
||||
static bool littleEndianToHost(const uint8_t* buffer, int* value);
|
||||
static bool littleEndianToHost(const uint8_t* buffer, int64_t* value);
|
||||
static bool littleEndianToHost(const uint8_t* buffer, float* value);
|
||||
static bool littleEndianToHost(const uint8_t* buffer, double* value);
|
||||
static bool littleEndianToHost(const uint8_t* buffer, long double* value);
|
||||
static bool bigEndianToHost(const uint8_t* buffer, uint16_t* value);
|
||||
static bool bigEndianToHost(const uint8_t* buffer, uint32_t* value);
|
||||
static bool bigEndianToHost(const uint8_t* buffer, uint64_t* value);
|
||||
static bool bigEndianToHost(const uint8_t* buffer, int16_t* value);
|
||||
static bool bigEndianToHost(const uint8_t* buffer, int* value);
|
||||
static bool bigEndianToHost(const uint8_t* buffer, int64_t* value);
|
||||
static bool bigEndianToHost(const uint8_t* buffer, float* value);
|
||||
static bool bigEndianToHost(const uint8_t* buffer, double* value);
|
||||
static bool bigEndianToHost(const uint8_t* buffer, long double* value);
|
||||
|
||||
private:
|
||||
Memory() = delete;
|
||||
};
|
||||
} // namespace System
|
||||
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
#include <cstdlib> // For Unix Compatibility
|
||||
|
||||
namespace System {
|
||||
/**
|
||||
* \class Time
|
||||
* \brief Static functions to handle time within the framework
|
||||
*
|
||||
*/
|
||||
class System_API Time
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief Make the calling thread sleep
|
||||
* \param milliSeconds : sleep duration in ms
|
||||
* \return Always true
|
||||
*/
|
||||
static bool sleep(const size_t milliSeconds);
|
||||
|
||||
/**
|
||||
* \brief Make the calling thread sleep
|
||||
* \param seconds : sleep duration in fixed point 32:32 seconds
|
||||
* \return Always true
|
||||
*/
|
||||
static bool zsleep(const uint64_t seconds);
|
||||
|
||||
/**
|
||||
* \brief Retrieve time in ms (turn the 32:32 fixed point seconds to milliseconds).
|
||||
* \return Elapsed time in ms since the first call to this function or zgetTime functions
|
||||
*/
|
||||
static uint32_t getTime() { return uint32_t((zgetTime() * 1000) >> 32); }
|
||||
|
||||
/**
|
||||
* \brief Retrieve time in fixed point 32:32 seconds
|
||||
* \return Elapsed time since the first call to the zgetTime functions or getTime.
|
||||
*/
|
||||
static uint64_t zgetTime() { return zgetTimeRaw(true); }
|
||||
|
||||
/**
|
||||
* \brief Retrieve time in fixed point 32:32 seconds
|
||||
* \param sinceFirstCall: If sinceFirstCall is true, returns the time since the first call to the zgetTime function or getTime.
|
||||
* Otherwise, returns time since epoch of the clock.
|
||||
* \return Elapsed time
|
||||
*/
|
||||
static uint64_t zgetTimeRaw(bool sinceFirstCall = true);
|
||||
|
||||
/**
|
||||
* \brief Check if the internal clock used by the framework is steady
|
||||
* \return True if the clock is steady, false otherwise
|
||||
* \note This is a theoretical check that queries the internal
|
||||
* clock implementation for available services
|
||||
*/
|
||||
static bool isClockSteady();
|
||||
|
||||
/**
|
||||
* \brief Check if the internal clock used by the framework has
|
||||
* a resolution higher than the required one
|
||||
* \param milliSeconds : Expected clock resolution (period between ticks) in ms (must be non-zero value)
|
||||
* \return True if the clock meets the requirements, false otherwise
|
||||
* \note This is a theoretical check that queries the internal
|
||||
* clock implementation for available services
|
||||
*/
|
||||
static bool checkResolution(const size_t milliSeconds);
|
||||
|
||||
private:
|
||||
|
||||
Time() = delete;
|
||||
};
|
||||
} // namespace System
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "system/WindowsUtilities.h"
|
||||
#if defined TARGET_OS_Windows
|
||||
#include "m_ConverterUtf8.h"
|
||||
#include <ShellAPI.h>
|
||||
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif
|
||||
|
||||
namespace System {
|
||||
|
||||
// Load a library in a matter compliant with non-ascii path
|
||||
// returns the eventual error code
|
||||
void* WindowsUtilities::utf16CompliantLoadLibrary(const char* path, const HANDLE file, const DWORD flags)
|
||||
{
|
||||
//const HMODULE hModule = ::LoadLibraryEx(path, file, flags); // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR|LOAD_LIBRARY_DEFAULT_DIRS);
|
||||
return ::LoadLibraryEx(path, file, flags); // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR|LOAD_LIBRARY_DEFAULT_DIRS);
|
||||
}
|
||||
|
||||
BOOL WindowsUtilities::utf16CompliantSetEnvironmentVariable(const char* name, const char* value) { return SetEnvironmentVariable(name, value); }
|
||||
|
||||
// Load a library in a matter compliant with non-ascii path
|
||||
// returns the eventual error code
|
||||
BOOL WindowsUtilities::utf16CompliantCreateProcess(char* applicationName, char* commandLine, LPSECURITY_ATTRIBUTES processAttributes,
|
||||
LPSECURITY_ATTRIBUTES threadAttributes, const BOOL inheritHandles, const DWORD creationFlags,
|
||||
LPVOID environment, char* currentDirectory, LPSTARTUPINFO startupInfo,
|
||||
LPPROCESS_INFORMATION processInformation)
|
||||
{
|
||||
return CreateProcess(applicationName, const_cast<char*>(commandLine), processAttributes, threadAttributes,
|
||||
inheritHandles, creationFlags, environment, currentDirectory, startupInfo, processInformation);
|
||||
}
|
||||
|
||||
// Load a library in a matter compliant with non-ascii path
|
||||
// returns the eventual error code
|
||||
HINSTANCE WindowsUtilities::utf16CompliantShellExecute(HWND hwnd, LPCTSTR operation, LPCTSTR file, LPCTSTR parameters, LPCTSTR directory, const INT nShowCmd)
|
||||
{
|
||||
return ShellExecute(hwnd, operation, file, parameters, directory, nShowCmd);
|
||||
}
|
||||
|
||||
} // namespace System
|
||||
#endif // TARGET_OS_Windows
|
||||
@@ -0,0 +1,101 @@
|
||||
#include "system/ovCChrono.h"
|
||||
#include "system/ovCTime.h"
|
||||
|
||||
namespace System {
|
||||
|
||||
CChrono::~CChrono()
|
||||
{
|
||||
delete [] m_stepInTime;
|
||||
delete [] m_stepOutTime;
|
||||
}
|
||||
|
||||
bool CChrono::reset(const size_t nStep)
|
||||
{
|
||||
if (!nStep) { return false; }
|
||||
|
||||
uint64_t* stepInTime = new uint64_t[nStep + 1];
|
||||
uint64_t* stepOutTime = new uint64_t[nStep + 1];
|
||||
if (!stepInTime || !stepOutTime)
|
||||
{
|
||||
delete [] stepInTime;
|
||||
delete [] stepOutTime;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i <= nStep; ++i)
|
||||
{
|
||||
stepInTime[i] = 0;
|
||||
stepOutTime[i] = 0;
|
||||
}
|
||||
|
||||
delete [] m_stepInTime;
|
||||
delete [] m_stepOutTime;
|
||||
m_stepInTime = stepInTime;
|
||||
m_stepOutTime = stepOutTime;
|
||||
|
||||
m_nStep = nStep;
|
||||
m_stepIdx = 0;
|
||||
m_isInStep = false;
|
||||
m_hasNewEstimation = false;
|
||||
|
||||
m_totalStepInTime = 0;
|
||||
m_totalStepOutTime = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CChrono::stepIn()
|
||||
{
|
||||
if (m_isInStep || !m_nStep) { return false; }
|
||||
|
||||
m_isInStep = !m_isInStep;
|
||||
|
||||
m_stepInTime[m_stepIdx] = Time::zgetTime();
|
||||
if (m_stepIdx == m_nStep)
|
||||
{
|
||||
m_totalStepInTime = 0;
|
||||
m_totalStepOutTime = 0;
|
||||
for (size_t i = 0; i < m_nStep; ++i)
|
||||
{
|
||||
m_totalStepInTime += m_stepOutTime[i] - m_stepInTime[i];
|
||||
m_totalStepOutTime += m_stepInTime[i + 1] - m_stepOutTime[i];
|
||||
}
|
||||
m_stepInTime[0] = m_stepInTime[m_nStep];
|
||||
m_stepIdx = 0;
|
||||
m_hasNewEstimation = true;
|
||||
}
|
||||
else { m_hasNewEstimation = false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CChrono::stepOut()
|
||||
{
|
||||
if (!m_isInStep || !m_nStep) { return false; }
|
||||
|
||||
m_isInStep = !m_isInStep;
|
||||
|
||||
m_stepOutTime[m_stepIdx] = Time::zgetTime();
|
||||
m_stepIdx++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t CChrono::getTotalStepInDuration() const { return m_totalStepInTime; }
|
||||
uint64_t CChrono::getTotalStepOutDuration() const { return m_totalStepOutTime; }
|
||||
uint64_t CChrono::getAverageStepInDuration() const { return m_nStep ? this->getTotalStepInDuration() / m_nStep : 0; }
|
||||
uint64_t CChrono::getAverageStepOutDuration() const { return m_nStep ? this->getTotalStepOutDuration() / m_nStep : 0; }
|
||||
|
||||
double CChrono::getStepInPercentage() const
|
||||
{
|
||||
const uint64_t totalStepDuration = (this->getTotalStepInDuration() + this->getTotalStepOutDuration());
|
||||
return totalStepDuration ? (this->getTotalStepInDuration() * 100.0) / totalStepDuration : 0;
|
||||
}
|
||||
|
||||
double CChrono::getStepOutPercentage() const
|
||||
{
|
||||
const uint64_t totalStepDuration = (this->getTotalStepOutDuration() + this->getTotalStepInDuration());
|
||||
return totalStepDuration ? (this->getTotalStepOutDuration() * 100.0) / totalStepDuration : 0;
|
||||
}
|
||||
|
||||
} // namespace System
|
||||
@@ -0,0 +1,396 @@
|
||||
#include "system/ovCDynamicModule.h"
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
#include <system/WindowsUtilities.h> // Allowed to use utf8_to_utf16 function for os that use utf16
|
||||
#elif defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
namespace System {
|
||||
|
||||
static const std::map<CDynamicModule::ELogErrorCodes, std::string> ERROR_MAP =
|
||||
{
|
||||
{ CDynamicModule::LogErrorCodes_ModuleAlreadyLoaded, "A module is already loaded." },
|
||||
{ CDynamicModule::LogErrorCodes_NoModuleLoaded, "No module loaded." },
|
||||
{ CDynamicModule::LogErrorCodes_FilenameEmpty, "The filename is empty." },
|
||||
{ CDynamicModule::LogErrorCodes_FolderPathInvalid, "The folder path is invalid." },
|
||||
{ CDynamicModule::LogErrorCodes_RegistryQueryFailed, "The registry query is invalid." },
|
||||
{ CDynamicModule::LogErrorCodes_UnloadModuleFailed, "Fail to unload the module." },
|
||||
{ CDynamicModule::LogErrorCodes_FailToLoadModule, "Fail to load the module." },
|
||||
{ CDynamicModule::LogErrorCodes_InvalidSymbol, "The symbol is invalid." },
|
||||
{ CDynamicModule::LogErrorCodes_ModuleNotFound, "Module not found." }
|
||||
};
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
static std::vector<std::string> split(char* str, const char* delim)
|
||||
{
|
||||
char* token = strtok(str, delim);
|
||||
|
||||
std::vector<std::string> result;
|
||||
|
||||
while (token != nullptr)
|
||||
{
|
||||
result.push_back(token);
|
||||
token = strtok(nullptr, delim);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string formatWindowsError(const DWORD code)
|
||||
{
|
||||
LPTSTR text;
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | // use system message tables to retrieve error text
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | // allocate buffer on local heap for error text
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS, // Important! will fail otherwise, since we're not (and CANNOT) pass insertion parameters
|
||||
nullptr, // unused with FORMAT_MESSAGE_FROM_SYSTEM
|
||||
code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
LPTSTR(&text), // output
|
||||
0, // minimum size for output buffer
|
||||
nullptr
|
||||
); // arguments - see note
|
||||
|
||||
return std::string(text);
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* CDynamicModule::getErrorString(size_t errorCode)
|
||||
{
|
||||
if (ERROR_MAP.count(ELogErrorCodes(errorCode)) == 0) { return "Invalid error code"; }
|
||||
return ERROR_MAP.at(ELogErrorCodes(errorCode)).c_str();
|
||||
}
|
||||
|
||||
const char* CDynamicModule::getErrorDetails() const { return &m_ErrorDetails[0]; }
|
||||
size_t CDynamicModule::getLastError() const { return m_ErrorCode; }
|
||||
|
||||
CDynamicModule::CDynamicModule()
|
||||
: m_ErrorMode(m_ErrorModeNull), m_ErrorCode(LogErrorCodes_NoError)
|
||||
{
|
||||
strcpy(m_ErrorDetails, "");
|
||||
strcpy(m_Filename, "");
|
||||
}
|
||||
|
||||
CDynamicModule::~CDynamicModule() {}
|
||||
|
||||
// --------------------------------------
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
bool CDynamicModule::loadFromExisting(const char* modulePath, const char* symbolNameCheck)
|
||||
{
|
||||
if (m_Handle)
|
||||
{
|
||||
this->setError(LogErrorCodes_ModuleAlreadyLoaded, "Module [" + std::string(m_Filename) + "] is already loaded");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Handle = ::GetModuleHandle(modulePath);
|
||||
|
||||
if (m_Handle == nullptr)
|
||||
{
|
||||
this->setError(LogErrorCodes_FailToLoadModule, "Windows error: " + formatWindowsError(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (symbolNameCheck != nullptr)
|
||||
{
|
||||
if (GetProcAddress(HMODULE(m_Handle), symbolNameCheck) == nullptr)
|
||||
{
|
||||
this->unload();
|
||||
this->setError(LogErrorCodes_InvalidSymbol, "Windows error: " + formatWindowsError(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
strcpy(m_Filename, modulePath);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CDynamicModule::loadFromPath(const char* modulePath, const char* symbolNameCheck)
|
||||
{
|
||||
if (m_Handle)
|
||||
{
|
||||
this->setError(LogErrorCodes_ModuleAlreadyLoaded, "Module [" + std::string(m_Filename) + "] is already loaded");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify empty filename
|
||||
if (modulePath == nullptr || (modulePath != nullptr && modulePath[0] == '\0'))
|
||||
{
|
||||
this->setError(LogErrorCodes_FilenameEmpty);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
|
||||
if (m_ErrorMode == m_ErrorModeNull)
|
||||
{
|
||||
const UINT mode = SetErrorMode(UINT(m_ErrorModeNull));
|
||||
SetErrorMode(mode);
|
||||
}
|
||||
else { SetErrorMode(UINT(m_ErrorMode)); }
|
||||
|
||||
m_Handle = WindowsUtilities::utf16CompliantLoadLibrary(modulePath, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
|
||||
if (m_Handle == nullptr)
|
||||
{
|
||||
this->setError(LogErrorCodes_FailToLoadModule, "Fail to load [" + std::string(modulePath) + "]. Windows error:" + formatWindowsError(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (symbolNameCheck != nullptr)
|
||||
{
|
||||
if (GetProcAddress(HMODULE(m_Handle), symbolNameCheck) == nullptr)
|
||||
{
|
||||
this->unload();
|
||||
this->setError(LogErrorCodes_InvalidSymbol,
|
||||
"Symbol invalid: [" + std::string(symbolNameCheck) + "]. Windows error: " + formatWindowsError(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#elif defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
m_Handle = ::dlopen(modulePath, RTLD_LAZY|RTLD_GLOBAL);
|
||||
|
||||
if (m_Handle == nullptr)
|
||||
{
|
||||
this->setError(LogErrorCodes_FailToLoadModule);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(symbolNameCheck != nullptr)
|
||||
{
|
||||
if(::dlsym(m_Handle, symbolNameCheck) == nullptr)
|
||||
{
|
||||
char* error = ::dlerror();
|
||||
|
||||
if(error) { this->setError(LogErrorCodes_InvalidSymbol, "Error: " + std::string(error)); }
|
||||
else { this->setError(LogErrorCodes_InvalidSymbol); }
|
||||
|
||||
::dlclose(m_Handle);
|
||||
m_Handle = NULL;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
strcpy(m_Filename, modulePath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
bool CDynamicModule::loadFromKnownPath(const int standardPath, const char* modulePath, const char* symbolNameCheck)
|
||||
{
|
||||
if (m_Handle)
|
||||
{
|
||||
this->setError(LogErrorCodes_ModuleAlreadyLoaded, "Module [" + std::string(m_Filename) + "] is already loaded");
|
||||
return false;
|
||||
}
|
||||
|
||||
char dllPath[MAX_PATH];
|
||||
|
||||
const HRESULT result = ::SHGetFolderPath(nullptr, standardPath, nullptr, SHGFP_TYPE_CURRENT, dllPath);
|
||||
|
||||
if (result != S_OK)
|
||||
{
|
||||
this->setError(LogErrorCodes_FolderPathInvalid, "Windows error code: " + std::to_string(result));
|
||||
return false;
|
||||
}
|
||||
|
||||
strcat(dllPath, "\\");
|
||||
strcat(dllPath, modulePath);
|
||||
return loadFromPath(dllPath, symbolNameCheck); // Error set in the loadFromPath function
|
||||
}
|
||||
|
||||
bool CDynamicModule::loadFromEnvironment(const char* environmentPath, const char* modulePath, const char* symbolNameCheck)
|
||||
{
|
||||
if (m_Handle)
|
||||
{
|
||||
this->setError(LogErrorCodes_ModuleAlreadyLoaded, "Module [" + std::string(m_Filename) + "] is already loaded");
|
||||
return false;
|
||||
}
|
||||
|
||||
char* str = getenv(environmentPath);
|
||||
|
||||
if (str == nullptr)
|
||||
{
|
||||
this->setError(LogErrorCodes_EnvironmentVariableInvalid);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> paths = split(str, ";");
|
||||
|
||||
for (const std::string& path : paths) { if (loadFromPath((path + "\\" + modulePath).c_str(), symbolNameCheck)) { return true; } }
|
||||
|
||||
this->setError(LogErrorCodes_ModuleNotFound);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CDynamicModule::loadFromRegistry(HKEY key, const char* registryPath, const char* registryKeyName, REGSAM samDesired, const char* modulePath,
|
||||
const char* symbolNameCheck)
|
||||
{
|
||||
char dllPath[MAX_PATH];
|
||||
DWORD size = sizeof(dllPath);
|
||||
dllPath[0] = '\0';
|
||||
|
||||
HKEY lKey = nullptr;
|
||||
|
||||
LONG result = RegOpenKeyEx(key, TEXT(registryPath), NULL, samDesired, &lKey);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
this->setError(LogErrorCodes_RegistryQueryFailed, "Fail to open registry key. Windows error code: " + std::to_string(result));
|
||||
RegCloseKey(lKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = ::RegQueryValueEx(lKey, registryKeyName, nullptr, nullptr, reinterpret_cast<unsigned char*>(dllPath), &size);
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
strcat(dllPath, modulePath);
|
||||
return loadFromPath(dllPath, symbolNameCheck); // Error set in the loadFromPath function
|
||||
}
|
||||
this->setError(LogErrorCodes_RegistryQueryFailed, "Fail to query registry value. Windows error code: " + std::to_string(result));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CDynamicModule::isModuleCompatible(const char* filePath, const int architecture)
|
||||
{
|
||||
IMAGE_NT_HEADERS headers;
|
||||
if (!getImageFileHeaders(filePath, headers)) { return false; } // Error set in the getImageFileHeaders function
|
||||
return headers.FileHeader.Machine == architecture;
|
||||
}
|
||||
#endif
|
||||
|
||||
// --------------------------------------
|
||||
|
||||
bool CDynamicModule::unload()
|
||||
{
|
||||
if (!m_Handle)
|
||||
{
|
||||
this->setError(LogErrorCodes_NoModuleLoaded);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the flag m_shouldFreeModule, set to true per default, is set to false,
|
||||
// the module is not unloaded.
|
||||
// This flag was first set for Enobio3G driver which dll freezes when unloaded
|
||||
if (!m_ShouldFreeModule) { return true; }
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
if (::FreeModule(reinterpret_cast<HMODULE>(m_Handle)) == 0)
|
||||
{
|
||||
this->setError(LogErrorCodes_UnloadModuleFailed, "Windows error code: " + formatWindowsError(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
#elif defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
if(::dlclose(m_Handle) != 0)
|
||||
{
|
||||
char* error = ::dlerror();
|
||||
if(error) { this->setError(LogErrorCodes_UnloadModuleFailed, "Error: " + std::string(error)); }
|
||||
else { this->setError(LogErrorCodes_UnloadModuleFailed); }
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
strcpy(m_Filename, "");
|
||||
m_Handle = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CDynamicModule::symbol_t CDynamicModule::getSymbolGeneric(const char* symbolName) const
|
||||
{
|
||||
symbol_t res = nullptr;
|
||||
|
||||
if (!m_Handle)
|
||||
{
|
||||
m_ErrorCode = LogErrorCodes_NoModuleLoaded;
|
||||
return res;
|
||||
}
|
||||
|
||||
if (m_Handle)
|
||||
{
|
||||
#if defined TARGET_OS_Windows
|
||||
res = symbol_t(GetProcAddress(reinterpret_cast<HMODULE>(m_Handle), symbolName));
|
||||
|
||||
if (!res)
|
||||
{
|
||||
m_ErrorCode = LogErrorCodes_InvalidSymbol;
|
||||
return res;
|
||||
}
|
||||
|
||||
#elif defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
res = (CDynamicModule::symbol_t)::dlsym(m_Handle, symbolName);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
m_ErrorCode = LogErrorCodes_InvalidSymbol;
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef TARGET_OS_Windows
|
||||
bool CDynamicModule::getImageFileHeaders(const char* filename, IMAGE_NT_HEADERS& headers)
|
||||
{
|
||||
const HANDLE fileHandle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
|
||||
if (fileHandle == INVALID_HANDLE_VALUE) { return false; }
|
||||
|
||||
const HANDLE imageHandle = CreateFileMapping(fileHandle, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
||||
|
||||
if (imageHandle == nullptr)
|
||||
{
|
||||
CloseHandle(fileHandle);
|
||||
return false;
|
||||
}
|
||||
|
||||
void* imagePtr = MapViewOfFile(imageHandle, FILE_MAP_READ, 0, 0, 0);
|
||||
|
||||
if (imagePtr == nullptr)
|
||||
{
|
||||
CloseHandle(imageHandle);
|
||||
CloseHandle(fileHandle);
|
||||
return false;
|
||||
}
|
||||
|
||||
const PIMAGE_NT_HEADERS headersPtr = ImageNtHeader(imagePtr);
|
||||
|
||||
if (headersPtr == nullptr)
|
||||
{
|
||||
UnmapViewOfFile(imagePtr);
|
||||
CloseHandle(imageHandle);
|
||||
CloseHandle(fileHandle);
|
||||
return false;
|
||||
}
|
||||
|
||||
headers = *headersPtr;
|
||||
|
||||
UnmapViewOfFile(imagePtr);
|
||||
CloseHandle(imageHandle);
|
||||
CloseHandle(fileHandle);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CDynamicModule::setError(const ELogErrorCodes errorCode, const std::string& details)
|
||||
{
|
||||
m_ErrorCode = errorCode;
|
||||
strcpy(m_ErrorDetails, details.c_str());
|
||||
}
|
||||
} // namespace System
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
*
|
||||
* @fixme This class could benefit from a serious overhaul, e.g. using randomness from some established library or C11.
|
||||
*
|
||||
* - Here Linear Congruential Generator is re-implemented to avoid third-party dependencies messing the up the rand() state.
|
||||
* This happened before when we used the global srand() / rand(). It made hard to make repeatable experiments on some
|
||||
* platforms. The generated randomness from the introduced home-made class is not super but it should be sufficient for
|
||||
* OpenViBE's present use-cases.
|
||||
*
|
||||
* Other notes
|
||||
*
|
||||
* - Due to generative process, values generated above L_RAND_MAX may not be dense (verify)
|
||||
* - randomIWithCeiling() may not be dense either
|
||||
*
|
||||
*/
|
||||
#include "system/ovCMath.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace System {
|
||||
|
||||
class RandomGenerator
|
||||
{
|
||||
size_t m_nextValue = 0;
|
||||
|
||||
public:
|
||||
static const size_t L_RAND_MAX = 2147483647; // (2^32)/2-1 == 2147483647 (0x7FFFFFFF)
|
||||
|
||||
explicit RandomGenerator(const size_t seed = 1) : m_nextValue(seed) {}
|
||||
|
||||
int rand()
|
||||
{
|
||||
// Pretty much C99 convention and parameters for a Linear Congruential Generator
|
||||
m_nextValue = (m_nextValue * 1103515245 + 12345) & L_RAND_MAX;
|
||||
return int(m_nextValue);
|
||||
}
|
||||
|
||||
void setSeed(const size_t seed) { m_nextValue = seed; }
|
||||
|
||||
size_t getSeed() const { return m_nextValue; }
|
||||
};
|
||||
|
||||
// Should be only accessed via Math:: calls defined below
|
||||
static RandomGenerator randomGenerator;
|
||||
|
||||
bool Math::initializeRandomMachine(const size_t randomSeed)
|
||||
{
|
||||
randomGenerator.setSeed(size_t(randomSeed));
|
||||
|
||||
// For safety, we install also the C++ basic random engine (it might be useg by dependencies, old code, etc)
|
||||
srand(uint32_t(randomSeed));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t Math::randomI() { return size_t(random()); }
|
||||
size_t Math::randomWithCeiling(const size_t upperLimit) { return size_t(random0To1() * double(upperLimit)); }
|
||||
double Math::random0To1() { return double(randomGenerator.rand()) / double(RandomGenerator::L_RAND_MAX); }
|
||||
|
||||
uint64_t Math::random()
|
||||
{
|
||||
const uint64_t r1 = randomGenerator.rand();
|
||||
const uint64_t r2 = randomGenerator.rand();
|
||||
const uint64_t r3 = randomGenerator.rand();
|
||||
const uint64_t r4 = randomGenerator.rand();
|
||||
return (r1 << 24) ^ (r2 << 16) ^ (r3 << 8) ^ (r4);
|
||||
}
|
||||
|
||||
} // namespace System
|
||||
@@ -0,0 +1,169 @@
|
||||
#include "system/ovCMemory.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace System {
|
||||
|
||||
// ________________________________________________________________________________________________________________
|
||||
//
|
||||
template <typename T>
|
||||
bool BigEndianToHost(const uint8_t* buffer, T* value)
|
||||
{
|
||||
if (!buffer || !value) { return false; }
|
||||
memset(value, 0, sizeof(T));
|
||||
for (size_t i = 0; i < sizeof(T); ++i) { ((uint8_t*)value)[i] = buffer[sizeof(T) - 1 - i]; }
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool LittleEndianToHost(const uint8_t* buffer, T* value)
|
||||
{
|
||||
if (!buffer || !value) { return false; }
|
||||
memset(value, 0, sizeof(T));
|
||||
for (size_t i = 0; i < sizeof(T); ++i) { ((uint8_t*)value)[i] = buffer[i]; }
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool HostToBigEndian(const T& value, uint8_t* buffer)
|
||||
{
|
||||
if (!buffer) { return false; }
|
||||
memset(buffer, 0, sizeof(T));
|
||||
for (size_t i = 0; i < sizeof(T); ++i) { buffer[i] = ((uint8_t*)&value)[sizeof(T) - 1 - i]; }
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool HostToLittleEndian(const T& value, uint8_t* buffer)
|
||||
{
|
||||
if (!buffer) { return false; }
|
||||
for (size_t i = 0; i < sizeof(T); ++i) { buffer[i] = uint8_t((value >> (i * 8)) & 0xff); }
|
||||
return true;
|
||||
}
|
||||
|
||||
// ________________________________________________________________________________________________________________
|
||||
//
|
||||
|
||||
bool Memory::hostToLittleEndian(const uint16_t value, uint8_t* buffer) { return HostToLittleEndian<uint16_t>(value, buffer); }
|
||||
bool Memory::hostToLittleEndian(const uint32_t value, uint8_t* buffer) { return HostToLittleEndian<uint32_t>(value, buffer); }
|
||||
bool Memory::hostToLittleEndian(const uint64_t value, uint8_t* buffer) { return HostToLittleEndian<uint64_t>(value, buffer); }
|
||||
bool Memory::hostToLittleEndian(const int16_t value, uint8_t* buffer) { return HostToLittleEndian<int16_t>(value, buffer); }
|
||||
bool Memory::hostToLittleEndian(const int value, uint8_t* buffer) { return HostToLittleEndian<int>(value, buffer); }
|
||||
bool Memory::hostToLittleEndian(const int64_t value, uint8_t* buffer) { return HostToLittleEndian<int64_t>(value, buffer); }
|
||||
|
||||
bool Memory::hostToLittleEndian(const float value, uint8_t* buffer)
|
||||
{
|
||||
uint32_t tmp;
|
||||
memcpy(&tmp, &value, sizeof(tmp));
|
||||
return hostToLittleEndian(tmp, buffer);
|
||||
}
|
||||
|
||||
bool Memory::hostToLittleEndian(const double value, uint8_t* buffer)
|
||||
{
|
||||
uint64_t tmp;
|
||||
memcpy(&tmp, &value, sizeof(tmp));
|
||||
return hostToLittleEndian(tmp, buffer);
|
||||
}
|
||||
|
||||
bool Memory::hostToLittleEndian(const long double /*value*/, uint8_t* /*buffer*/)
|
||||
{
|
||||
// $$$ TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ________________________________________________________________________________________________________________
|
||||
//
|
||||
|
||||
bool Memory::hostToBigEndian(const uint16_t value, uint8_t* buffer) { return HostToBigEndian<uint16_t>(value, buffer); }
|
||||
bool Memory::hostToBigEndian(const uint32_t value, uint8_t* buffer) { return HostToBigEndian<uint32_t>(value, buffer); }
|
||||
bool Memory::hostToBigEndian(const uint64_t value, uint8_t* buffer) { return HostToBigEndian<uint64_t>(value, buffer); }
|
||||
bool Memory::hostToBigEndian(const int16_t value, uint8_t* buffer) { return HostToBigEndian<int16_t>(value, buffer); }
|
||||
bool Memory::hostToBigEndian(const int value, uint8_t* buffer) { return HostToBigEndian<int>(value, buffer); }
|
||||
bool Memory::hostToBigEndian(const int64_t value, uint8_t* buffer) { return HostToBigEndian<int64_t>(value, buffer); }
|
||||
|
||||
bool Memory::hostToBigEndian(const float value, uint8_t* buffer)
|
||||
{
|
||||
uint32_t tmp;
|
||||
memcpy(&tmp, &value, sizeof(tmp));
|
||||
return hostToBigEndian(tmp, buffer);
|
||||
}
|
||||
|
||||
bool Memory::hostToBigEndian(const double value, uint8_t* buffer)
|
||||
{
|
||||
uint64_t tmp;
|
||||
memcpy(&tmp, &value, sizeof(tmp));
|
||||
return hostToBigEndian(tmp, buffer);
|
||||
}
|
||||
|
||||
bool Memory::hostToBigEndian(const long double /*value*/, uint8_t* /*buffer*/)
|
||||
{
|
||||
// $$$ TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
// ________________________________________________________________________________________________________________
|
||||
//
|
||||
|
||||
bool Memory::littleEndianToHost(const uint8_t* buffer, uint16_t* value) { return LittleEndianToHost<uint16_t>(buffer, value); }
|
||||
bool Memory::littleEndianToHost(const uint8_t* buffer, uint32_t* value) { return LittleEndianToHost<uint32_t>(buffer, value); }
|
||||
bool Memory::littleEndianToHost(const uint8_t* buffer, uint64_t* value) { return LittleEndianToHost<uint64_t>(buffer, value); }
|
||||
bool Memory::littleEndianToHost(const uint8_t* buffer, int16_t* value) { return LittleEndianToHost<int16_t>(buffer, value); }
|
||||
bool Memory::littleEndianToHost(const uint8_t* buffer, int* value) { return LittleEndianToHost<int>(buffer, value); }
|
||||
bool Memory::littleEndianToHost(const uint8_t* buffer, int64_t* value) { return LittleEndianToHost<int64_t>(buffer, value); }
|
||||
|
||||
bool Memory::littleEndianToHost(const uint8_t* buffer, float* value)
|
||||
{
|
||||
uint32_t tmp;
|
||||
const bool b = LittleEndianToHost<uint32_t>(buffer, &tmp);
|
||||
memcpy(value, &tmp, sizeof(float));
|
||||
return b;
|
||||
}
|
||||
|
||||
bool Memory::littleEndianToHost(const uint8_t* buffer, double* value)
|
||||
{
|
||||
uint64_t tmp;
|
||||
const bool b = LittleEndianToHost<uint64_t>(buffer, &tmp);
|
||||
memcpy(value, &tmp, sizeof(double));
|
||||
return b;
|
||||
}
|
||||
|
||||
bool Memory::littleEndianToHost(const uint8_t* /*buffer*/, long double* /*value*/)
|
||||
{
|
||||
// $$$ TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
// ________________________________________________________________________________________________________________
|
||||
//
|
||||
|
||||
bool Memory::bigEndianToHost(const uint8_t* buffer, uint16_t* value) { return BigEndianToHost<uint16_t>(buffer, value); }
|
||||
bool Memory::bigEndianToHost(const uint8_t* buffer, uint32_t* value) { return BigEndianToHost<uint32_t>(buffer, value); }
|
||||
bool Memory::bigEndianToHost(const uint8_t* buffer, uint64_t* value) { return BigEndianToHost<uint64_t>(buffer, value); }
|
||||
bool Memory::bigEndianToHost(const uint8_t* buffer, int16_t* value) { return BigEndianToHost<int16_t>(buffer, value); }
|
||||
bool Memory::bigEndianToHost(const uint8_t* buffer, int* value) { return BigEndianToHost<int>(buffer, value); }
|
||||
bool Memory::bigEndianToHost(const uint8_t* buffer, int64_t* value) { return BigEndianToHost<int64_t>(buffer, value); }
|
||||
|
||||
bool Memory::bigEndianToHost(const uint8_t* buffer, float* value)
|
||||
{
|
||||
uint32_t tmp;
|
||||
const bool b = BigEndianToHost<uint32_t>(buffer, &tmp);
|
||||
memcpy(value, &tmp, sizeof(float));
|
||||
return b;
|
||||
}
|
||||
|
||||
bool Memory::bigEndianToHost(const uint8_t* buffer, double* value)
|
||||
{
|
||||
uint64_t tmp;
|
||||
const bool b = BigEndianToHost<uint64_t>(buffer, &tmp);
|
||||
memcpy(value, &tmp, sizeof(double));
|
||||
return b;
|
||||
}
|
||||
|
||||
bool Memory::bigEndianToHost(const uint8_t* /*buffer*/, long double* /*value*/)
|
||||
{
|
||||
// $$$ TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace System
|
||||
@@ -0,0 +1,92 @@
|
||||
#include "system/ovCTime.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
|
||||
// \warning On Windows, avoid "using namespace System;" here as it may cause confusion with stuff coming from windows/boost
|
||||
// \note Support of C++11 steady clock:
|
||||
// - From GCC 4.8.1
|
||||
// - From Visual Studio 2015 (therefore a strategy is needed to handle Visual Studio 2013 version)
|
||||
|
||||
// time handling strategy selection
|
||||
// \note With officialy supported compilers and required boost version
|
||||
// it should never fallback in a OV_USE_SYSTEM case
|
||||
#if (defined(_MSC_VER) && _MSC_VER <= 1800 && defined(TARGET_HAS_Boost_Chrono))
|
||||
|
||||
#include <boost/chrono/config.hpp>
|
||||
|
||||
#ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
|
||||
|
||||
#include <boost/chrono.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
namespace Timelib = boost;
|
||||
|
||||
#else
|
||||
#error "Please use OpenViBE recommended version of Boost"
|
||||
#endif // BOOST_CHRONO_HAS_CLOCK_STEADY
|
||||
|
||||
#else // defined(_MSC_VER) && _MSC_VER <= 1800 && defined(TARGET_HAS_Boost_Chrono)
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
namespace Timelib = std;
|
||||
|
||||
#endif // defined(_MSC_VER) && _MSC_VER <= 1800 && defined(TARGET_HAS_Boost_Chrono)
|
||||
|
||||
using internal_clock = Timelib::chrono::steady_clock;
|
||||
// using internal_clock = chrono::high_resolution_clock;
|
||||
|
||||
namespace System {
|
||||
|
||||
bool Time::sleep(const size_t milliSeconds)
|
||||
{
|
||||
Timelib::this_thread::sleep_for(Timelib::chrono::milliseconds(milliSeconds));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Time::zsleep(const uint64_t seconds)
|
||||
{
|
||||
const uint32_t s = uint32_t(seconds >> 32);
|
||||
// zero the seconds with 0xFFFFFFFF, multiply to get the rest as fixed point microsec, then grab them (now in the 32 msbs)
|
||||
const uint64_t ms = ((seconds & 0xFFFFFFFFLL) * 1000000LL) >> 32;
|
||||
|
||||
const Timelib::chrono::microseconds duration = Timelib::chrono::seconds(s) + Timelib::chrono::microseconds(ms);
|
||||
Timelib::this_thread::sleep_for(duration);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t Time::zgetTimeRaw(const bool sinceFirstCall)
|
||||
{
|
||||
static bool initialized = false;
|
||||
static internal_clock::time_point start;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
start = internal_clock::now();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
const internal_clock::time_point now = internal_clock::now();
|
||||
const internal_clock::duration elapsed = (sinceFirstCall ? now - start : now.time_since_epoch());
|
||||
const Timelib::chrono::microseconds elapsedMs = Timelib::chrono::duration_cast<Timelib::chrono::microseconds>(elapsed);
|
||||
|
||||
const uint64_t microsPerSecond = 1000ULL * 1000ULL;
|
||||
const uint64_t seconds = uint64_t(elapsedMs.count() / microsPerSecond);
|
||||
const uint64_t fraction = uint64_t(elapsedMs.count() % microsPerSecond);
|
||||
|
||||
// below in fraction part, scale [0,microsPerSecond-1] to 32bit integer range
|
||||
const uint64_t res = (seconds << 32) + fraction * (0xFFFFFFFFLL / (microsPerSecond - 1));
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Time::isClockSteady() { return internal_clock::is_steady; }
|
||||
|
||||
bool Time::checkResolution(const size_t milliSeconds)
|
||||
{
|
||||
assert(milliSeconds != 0);
|
||||
const auto resolution = double(internal_clock::period::num) / internal_clock::period::den;
|
||||
return (size_t(std::ceil(resolution * 1000)) <= milliSeconds);
|
||||
}
|
||||
|
||||
} // namespace System
|
||||
Reference in New Issue
Block a user