diff --git a/application/argumentparser.h b/application/argumentparser.h index afbfab0..4b7fd2d 100644 --- a/application/argumentparser.h +++ b/application/argumentparser.h @@ -1,7 +1,7 @@ #ifndef APPLICATION_UTILITIES_ARGUMENTPARSER_H #define APPLICATION_UTILITIES_ARGUMENTPARSER_H -#include "./global.h" +#include "../global.h" #include #include @@ -14,10 +14,10 @@ class ArgumentParserTests; namespace ApplicationUtilities { -LIB_EXPORT extern const char *applicationName; -LIB_EXPORT extern const char *applicationAuthor; -LIB_EXPORT extern const char *applicationVersion; -LIB_EXPORT extern const char *applicationUrl; +CPP_UTILITIES_EXPORT extern const char *applicationName; +CPP_UTILITIES_EXPORT extern const char *applicationAuthor; +CPP_UTILITIES_EXPORT extern const char *applicationVersion; +CPP_UTILITIES_EXPORT extern const char *applicationUrl; #define SET_APPLICATION_INFO \ ::ApplicationUtilities::applicationName = APP_NAME; \ @@ -68,12 +68,12 @@ constexpr bool operator&(ValueCompletionBehavior lhs, ValueCompletionBehavior rh } /// \endcond -Argument LIB_EXPORT *firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except); +Argument CPP_UTILITIES_EXPORT *firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except); /*! * \brief The ArgumentOccurrence struct holds argument values for an occurrence of an argument. */ -struct LIB_EXPORT ArgumentOccurrence +struct CPP_UTILITIES_EXPORT ArgumentOccurrence { ArgumentOccurrence(std::size_t index); ArgumentOccurrence(std::size_t index, const std::vector parentPath, Argument *parent); @@ -119,7 +119,7 @@ inline ArgumentOccurrence::ArgumentOccurrence(std::size_t index, const std::vect } } -class LIB_EXPORT Argument +class CPP_UTILITIES_EXPORT Argument { friend class ArgumentParser; @@ -200,7 +200,7 @@ private: const char *m_preDefinedCompletionValues; }; -class LIB_EXPORT ArgumentParser +class CPP_UTILITIES_EXPORT ArgumentParser { friend ArgumentParserTests; public: @@ -767,7 +767,7 @@ inline void ArgumentParser::setDefaultArgument(Argument *argument) m_defaultArg = argument; } -class LIB_EXPORT HelpArgument : public Argument +class CPP_UTILITIES_EXPORT HelpArgument : public Argument { public: HelpArgument(ArgumentParser &parser); diff --git a/application/commandlineutils.h b/application/commandlineutils.h index b7c6996..5439fc7 100644 --- a/application/commandlineutils.h +++ b/application/commandlineutils.h @@ -1,7 +1,7 @@ #ifndef APPLICATIONUTILITIES_COMMANDLINEUTILS_H #define APPLICATIONUTILITIES_COMMANDLINEUTILS_H -#include "./global.h" +#include "../global.h" namespace ApplicationUtilities { @@ -15,10 +15,10 @@ enum class Response No }; -bool LIB_EXPORT confirmPrompt(const char *message, Response defaultResponse = Response::None); +bool CPP_UTILITIES_EXPORT confirmPrompt(const char *message, Response defaultResponse = Response::None); #ifdef PLATFORM_WINDOWS -void LIB_EXPORT startConsole(); +void CPP_UTILITIES_EXPORT startConsole(); # define CMD_UTILS_START_CONSOLE ::ApplicationUtilities::startConsole(); #else # define CMD_UTILS_START_CONSOLE diff --git a/application/failure.h b/application/failure.h index b062a1b..4d443da 100644 --- a/application/failure.h +++ b/application/failure.h @@ -1,14 +1,14 @@ #ifndef APPLICATION_UTILITIES_FAILURE_H #define APPLICATION_UTILITIES_FAILURE_H -#include "./global.h" +#include "../global.h" #include #include namespace ApplicationUtilities { -class LIB_EXPORT Failure : public std::exception +class CPP_UTILITIES_EXPORT Failure : public std::exception { public: Failure(); diff --git a/application/fakeqtconfigarguments.h b/application/fakeqtconfigarguments.h index 1689f03..9f5adb1 100644 --- a/application/fakeqtconfigarguments.h +++ b/application/fakeqtconfigarguments.h @@ -5,7 +5,7 @@ namespace ApplicationUtilities { -class LIB_EXPORT FakeQtConfigArguments +class CPP_UTILITIES_EXPORT FakeQtConfigArguments { public: FakeQtConfigArguments(); diff --git a/application/global.h b/application/global.h index fe380d0..307e31e 100644 --- a/application/global.h +++ b/application/global.h @@ -1,113 +1,113 @@ -#ifndef APPLICATION_UTILITIES_GLOBAL_H -#define APPLICATION_UTILITIES_GLOBAL_H - -#ifdef _WIN32 -# ifndef PLATFORM_WINDOWS -/// \brief Defined when compiling for Windows. -# define PLATFORM_WINDOWS -# endif -# if defined(__MINGW32__) || defined(__MINGW64__) -# ifndef PLATFORM_MINGW -/// \brief Defined when compiling with mingw(-w64). -# define PLATFORM_MINGW -# endif -# endif -#elif __unix__ -# ifndef PLATFORM_UNIX -/// \brief Defined when compiling for any UNIX (like) system. -# define PLATFORM_UNIX -# endif -#endif -#ifdef __linux__ -# ifndef PLATFORM_LINUX -/// \brief Defined when compiling for Linux. -# define PLATFORM_LINUX -# endif -#endif - -/*! - * \def LIB_EXPORT - * \brief Marks a symbol for shared library export. - */ - -/*! - * \def LIB_IMPORT - * \brief Declares a symbol to be an import from a shared library. - */ - -/*! - * \def LIB_HIDDEN - * \brief Hidden visibility indicates that the symbol will not be placed into - * the dynamic symbol table, so no other module (executable or shared library) - * can reference it directly. - */ - -#ifdef PLATFORM_WINDOWS -# define LIB_EXPORT __declspec(dllexport) -# define LIB_IMPORT __declspec(dllimport) -# define LIB_HIDDEN -#else -# define LIB_EXPORT __attribute__((visibility("default"))) -# define LIB_IMPORT __attribute__((visibility("default"))) -# define LIB_HIDDEN __attribute__((visibility("hidden"))) -#endif - -/*! - * \def USE_NOTHROW - * \brief Marks a function as never throwing, under no circumstances. - * \remarks If the function does nevertheless throw, the behaviour is undefined. - */ - -#ifndef USE_NOTHROW -# if __cplusplus >= 201103L -# define USE_NOTHROW noexcept -# else -# define USE_NOTHROW throw() -# endif -#endif - -/*! - * \def DECLARE_ENUM - * \brief Declares an enum without preventing lupdate to parse the file correctly. - */ - -#define DECLARE_ENUM(name, base) enum name : base - -/*! - * \def DECLARE_ENUM_CLASS - * \brief Declares an enum without preventing lupdate to parse the file correctly. - */ - -#define DECLARE_ENUM_CLASS(name, base) enum class name : base - -/*! - * \def VAR_UNUSED - * \brief Prevents warnings about unused variables. - */ - -#define VAR_UNUSED(x) (void)x; - -/*! - * \def IF_DEBUG_BUILD - * \brief Wraps debug-only lines conveniently. - */ - -#ifdef DEBUG_BUILD -# define IF_DEBUG_BUILD(x) x -#else -# define IF_DEBUG_BUILD(x) -#endif - -/*! - * \def FALLTHROUGH - * \brief Prevents clang from warning about missing break in switch-case. - * \remarks Does nothing if another compiler is used. - */ - -#ifdef __clang__ -# define FALLTHROUGH [[clang::fallthrough]] -# else -# define FALLTHROUGH -#endif - -#endif // APPLICATION_UTILITIES_GLOBAL_H +#ifndef APPLICATION_UTILITIES_GLOBAL_H +#define APPLICATION_UTILITIES_GLOBAL_H + +#ifdef _WIN32 +# ifndef PLATFORM_WINDOWS +/// \brief Defined when compiling for Windows. +# define PLATFORM_WINDOWS +# endif +# if defined(__MINGW32__) || defined(__MINGW64__) +# ifndef PLATFORM_MINGW +/// \brief Defined when compiling with mingw(-w64). +# define PLATFORM_MINGW +# endif +# endif +#elif __unix__ +# ifndef PLATFORM_UNIX +/// \brief Defined when compiling for any UNIX (like) system. +# define PLATFORM_UNIX +# endif +#endif +#ifdef __linux__ +# ifndef PLATFORM_LINUX +/// \brief Defined when compiling for Linux. +# define PLATFORM_LINUX +# endif +#endif + +/*! + * \def LIB_EXPORT + * \brief Marks a symbol for shared library export. + */ + +/*! + * \def LIB_IMPORT + * \brief Declares a symbol to be an import from a shared library. + */ + +/*! + * \def LIB_HIDDEN + * \brief Hidden visibility indicates that the symbol will not be placed into + * the dynamic symbol table, so no other module (executable or shared library) + * can reference it directly. + */ + +#ifdef PLATFORM_WINDOWS +# define LIB_EXPORT __declspec(dllexport) +# define LIB_IMPORT __declspec(dllimport) +# define LIB_HIDDEN +#else +# define LIB_EXPORT __attribute__((visibility("default"))) +# define LIB_IMPORT __attribute__((visibility("default"))) +# define LIB_HIDDEN __attribute__((visibility("hidden"))) +#endif + +/*! + * \def USE_NOTHROW + * \brief Marks a function as never throwing, under no circumstances. + * \remarks If the function does nevertheless throw, the behaviour is undefined. + */ + +#ifndef USE_NOTHROW +# if __cplusplus >= 201103L +# define USE_NOTHROW noexcept +# else +# define USE_NOTHROW throw() +# endif +#endif + +/*! + * \def DECLARE_ENUM + * \brief Declares an enum without preventing lupdate to parse the file correctly. + */ + +#define DECLARE_ENUM(name, base) enum name : base + +/*! + * \def DECLARE_ENUM_CLASS + * \brief Declares an enum without preventing lupdate to parse the file correctly. + */ + +#define DECLARE_ENUM_CLASS(name, base) enum class name : base + +/*! + * \def VAR_UNUSED + * \brief Prevents warnings about unused variables. + */ + +#define VAR_UNUSED(x) (void)x; + +/*! + * \def IF_DEBUG_BUILD + * \brief Wraps debug-only lines conveniently. + */ + +#ifdef DEBUG_BUILD +# define IF_DEBUG_BUILD(x) x +#else +# define IF_DEBUG_BUILD(x) +#endif + +/*! + * \def FALLTHROUGH + * \brief Prevents clang from warning about missing break in switch-case. + * \remarks Does nothing if another compiler is used. + */ + +#ifdef __clang__ +# define FALLTHROUGH [[clang::fallthrough]] +# else +# define FALLTHROUGH +#endif + +#endif // APPLICATION_UTILITIES_GLOBAL_H diff --git a/chrono/datetime.h b/chrono/datetime.h index ac8b1ba..7c6a73c 100644 --- a/chrono/datetime.h +++ b/chrono/datetime.h @@ -52,7 +52,7 @@ enum class DatePart Day /**< day */ }; -class LIB_EXPORT DateTime +class CPP_UTILITIES_EXPORT DateTime { public: explicit constexpr DateTime(); diff --git a/chrono/period.h b/chrono/period.h index eb3f438..8ea594e 100644 --- a/chrono/period.h +++ b/chrono/period.h @@ -3,11 +3,9 @@ #include "./datetime.h" -#include "../application/global.h" - namespace ChronoUtilities { -class LIB_EXPORT Period +class CPP_UTILITIES_EXPORT Period { public: Period(const DateTime &beg, const DateTime &end); diff --git a/chrono/timespan.h b/chrono/timespan.h index 224062c..ef4ccde 100644 --- a/chrono/timespan.h +++ b/chrono/timespan.h @@ -1,7 +1,7 @@ #ifndef CHRONO_UTILITIES_TIMESPAN_H #define CHRONO_UTILITIES_TIMESPAN_H -#include "../application/global.h" +#include "../global.h" #include "../conversion/types.h" #include @@ -25,7 +25,7 @@ enum class TimeSpanOutputFormat WithMeasures /**< measures are used, eg.: 34 d 5 h 10 min 7 s 31 ms */ }; -class LIB_EXPORT TimeSpan +class CPP_UTILITIES_EXPORT TimeSpan { friend class DateTime; public: diff --git a/cmake/modules/AppTarget.cmake b/cmake/modules/AppTarget.cmake index 656ba45..a8fa0c1 100644 --- a/cmake/modules/AppTarget.cmake +++ b/cmake/modules/AppTarget.cmake @@ -18,6 +18,7 @@ else() set(ACTUAL_ADDITIONAL_LINK_FLAGS ${ADDITIONAL_LINK_FLAGS}) set(ACTUAL_ADDITIONAL_COMPILE_DEFINITIONS ${ADDITIONAL_COMPILE_DEFINITIONS}) endif() + # add target for building the application add_executable(${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} ${GUI_TYPE} ${HEADER_FILES} ${SRC_FILES} ${WIDGETS_FILES} ${QML_FILES} ${RES_FILES} ${QM_FILES} ${WINDOWS_ICON_PATH}) target_link_libraries(${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} ${ACTUAL_ADDITIONAL_LINK_FLAGS} ${LIBRARIES}) @@ -33,7 +34,6 @@ install(TARGETS ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} RUNTIME DESTINATION bin COMPONENT binary ) - if(NOT TARGET install-binary) add_custom_target(install-binary DEPENDS ${META_PROJECT_NAME} @@ -64,7 +64,6 @@ foreach(ICON_FILE ${ICON_FILES}) COMPONENT desktop ) endforeach() - if(NOT TARGET install-desktop) add_custom_target(install-desktop DEPENDS ${META_PROJECT_NAME} diff --git a/cmake/modules/BasicConfig.cmake b/cmake/modules/BasicConfig.cmake index 46242b2..5320c69 100644 --- a/cmake/modules/BasicConfig.cmake +++ b/cmake/modules/BasicConfig.cmake @@ -39,7 +39,7 @@ set(TARGET_EXECUTABLE "${CMAKE_INSTALL_PREFIX}/bin/${TARGET_PREFIX}${META_PROJEC option(FORCE_OLD_ABI "specifies whether usage of old ABI should be forced" OFF) if(FORCE_OLD_ABI) add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) - set(META_REQUIRED_CFLAGS "${META_REQUIRED_CFLAGS} -D-D_GLIBCXX_USE_CXX11_ABI=0") + set(META_REQUIRED_BUILD_FLAGS "${META_REQUIRED_BUILD_CFLAGS} -D_GLIBCXX_USE_CXX11_ABI=0") message(STATUS "Forcing usage of old CXX11 ABI.") else() message(STATUS "Using default CXX11 ABI (not forcing old CX11 ABI).") @@ -59,9 +59,14 @@ if(LOGGING_ENABLED) endif() # options for deciding whether to build static and/or shared libraries -if((NOT ${META_PROJECT_TYPE} STREQUAL "library") AND (NOT ${META_PROJECT_TYPE} STREQUAL "")) +if(("${META_PROJECT_TYPE}" STREQUAL "library") OR ("${META_PROJECT_TYPE}" STREQUAL "")) option(BUILD_STATIC_LIBS "whether to build static libraries (disabled by default)" OFF) - option(BUILD_SHARED_LIBS "whether to build dynamic libraries (enabled by default)" ON) + option(DISABLE_SHARED_LIBS "whether building dynamic libraries is disabled (prevents BUILD_SHARED_LIBS being re-enabled when using Qt Creator)" OFF) + if(DISABLE_SHARED_LIBS) + set(BUILD_SHARED_LIBS OFF) + else() + option(BUILD_SHARED_LIBS "whether to build dynamic libraries (enabled by default)" ON) + endif() endif() # options for forcing static linkage when building applications or dynamic libraries diff --git a/cmake/modules/LibraryTarget.cmake b/cmake/modules/LibraryTarget.cmake index f8b25fa..186234e 100644 --- a/cmake/modules/LibraryTarget.cmake +++ b/cmake/modules/LibraryTarget.cmake @@ -30,6 +30,7 @@ set(LIB_INSTALL_DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${SELECTED_LIB_SUFFIX}") set(CMAKE_MODULE_INSTALL_DESTINATION "${CMAKE_INSTALL_PREFIX}/share/${META_PROJECT_NAME}/cmake/modules") set(CMAKE_CONFIG_INSTALL_DESTINATION "${CMAKE_INSTALL_PREFIX}/share/${META_PROJECT_NAME}/cmake") + # remove library prefix when building with mingw-w64 (just for consistency with qmake) if(MINGW) set(CMAKE_SHARED_LIBRARY_PREFIX "") @@ -40,6 +41,29 @@ if(MINGW) set(WINDOWS_EXT "dll") endif(MINGW) +# create global header and define build flags +if(NOT META_SHARED_LIB_COMPILE_DEFINITIONS) + set(META_SHARED_LIB_COMPILE_DEFINITIONS ${META_COMPILE_DEFINITIONS}) +endif() +if(NOT META_STATIC_LIB_COMPILE_DEFINITIONS) + set(META_STATIC_LIB_COMPILE_DEFINITIONS ${META_COMPILE_DEFINITIONS} ${META_PROJECT_VARNAME_UPPER}_STATIC) +endif() + +# add global library-specific header +include(TemplateFinder) +find_template_file("global.h" CPP_UTILITIES GLOBAL_H_TEMPLATE_FILE) +if("${META_PROJECT_NAME}" STREQUAL "c++utilities") + set(GENERAL_GLOBAL_H_INCLUDE_PATH "\"./application/global.h\"") +else() + set(GENERAL_GLOBAL_H_INCLUDE_PATH "") +endif() +configure_file( + "${GLOBAL_H_TEMPLATE_FILE}" + "${CMAKE_CURRENT_SOURCE_DIR}/global.h" # simply add this to source to ease inclusion + NEWLINE_STYLE UNIX # since this goes to sources ensure consistency +) +list(APPEND HEADER_FILES global.h) + # add target for building the library if(BUILD_SHARED_LIBS) # use correct linker flags and compile definitions (depend on linkage) @@ -65,6 +89,8 @@ endif() # add target for building a static version of the library if(BUILD_STATIC_LIBS) + set(ACTUAL_ADDITIONAL_COMPILE_DEFINITIONS ${ADDITIONAL_STATIC_COMPILE_DEFINITIONS}) + list(APPEND ACTUAL_ADDITIONAL_COMPILE_DEFINITIONS ${META_STATIC_LIB_COMPILE_DEFINITIONS}) add_library(${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}_static STATIC ${HEADER_FILES} ${SRC_FILES} ${WIDGETS_FILES} ${QML_FILES} ${RES_FILES} ${QM_FILES} ${WINDOWS_ICON_PATH}) # add target link libraries for the static lib also because otherwise Qt header files can not be located target_link_libraries(${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}_static ${STATIC_LIBRARIES}) @@ -73,7 +99,7 @@ if(BUILD_STATIC_LIBS) SOVERSION ${META_VERSION_MAJOR} OUTPUT_NAME ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} CXX_STANDARD 11 - COMPILE_DEFINITIONS "${ADDITIONAL_STATIC_COMPILE_DEFINITIONS}" + COMPILE_DEFINITIONS "${ACTUAL_ADDITIONAL_COMPILE_DEFINITIONS}" ) set(META_STATIC_LIB_DEPENDS ${${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}_static_LIB_DEPENDS}) # used in config file endif() @@ -101,7 +127,6 @@ write_basic_package_version_file( # create pkg-config file from template # will (currently) not contain Libs.private if static libs haven't been built anyways -include(TemplateFinder) find_template_file("template.pc" CPP_UTILITIES PKGCONFIG_TEMPLATE_FILE) configure_file( "${PKGCONFIG_TEMPLATE_FILE}" @@ -119,7 +144,6 @@ install( COMPONENT cmake-config ) - if(NOT TARGET install-cmake-config) add_custom_target(install-cmake-config DEPENDS ${META_PROJECT_NAME} @@ -152,7 +176,6 @@ if(BUILD_SHARED_LIBS) COMPONENT binary ) endif() - if(NOT TARGET install-binary) add_custom_target(install-binary DEPENDS ${META_PROJECT_NAME} @@ -190,7 +213,6 @@ foreach(HEADER_FILE ${HEADER_FILES} ${ADDITIONAL_HEADER_FILES}) COMPONENT header ) endforeach() - if(NOT TARGET install-header) add_custom_target(install-header DEPENDS ${META_PROJECT_NAME} @@ -207,7 +229,6 @@ foreach(CMAKE_MODULE_FILE ${CMAKE_MODULE_FILES}) COMPONENT cmake-modules ) endforeach() - if(NOT TARGET install-cmake-modules) add_custom_target(install-cmake-modules DEPENDS ${META_PROJECT_NAME} @@ -224,7 +245,6 @@ foreach(CMAKE_TEMPLATE_FILE ${CMAKE_TEMPLATE_FILES}) COMPONENT cmake-templates ) endforeach() - if(NOT TARGET install-cmake-templates) add_custom_target(install-cmake-templates DEPENDS ${META_PROJECT_NAME} @@ -245,21 +265,18 @@ if(NOT TARGET install-mingw-w64) DEPENDS install-binary install-header install-cmake-stuff ${LOCALIZATION_TARGET} ) endif() - if(NOT TARGET install-mingw-w64-importlib-strip) add_custom_target(install-mingw-w64-importlib-strip DEPENDS install-binary-strip COMMAND "${CMAKE_FIND_ROOT_PATH}/bin/strip" --strip-unneeded "\$\{DESTDIR\}\$\{DESTDIR:+/\}${CMAKE_INSTALL_PREFIX}/lib/lib${META_PROJECT_NAME}.dll.a" ) endif() - if(NOT TARGET install-mingw-w64-staticlib-strip) add_custom_target(install-mingw-w64-staticlib-strip DEPENDS install-binary-strip COMMAND "${CMAKE_FIND_ROOT_PATH}/bin/strip" -g "\$\{DESTDIR\}\$\{DESTDIR:+/\}${CMAKE_INSTALL_PREFIX}/lib/lib${META_PROJECT_NAME}.a" ) endif() - if(NOT TARGET install-mingw-w64-strip) add_custom_target(install-mingw-w64-strip DEPENDS install-binary-strip install-mingw-w64-importlib-strip install-mingw-w64-staticlib-strip install-header install-cmake-stuff ${LOCALIZATION_TARGET} diff --git a/cmake/templates/Config.cmake.in b/cmake/templates/Config.cmake.in index 5d04f1d..d2c8b11 100644 --- a/cmake/templates/Config.cmake.in +++ b/cmake/templates/Config.cmake.in @@ -1,41 +1,44 @@ @PACKAGE_INIT@ -set(@META_PROJECT_VARNAME@_HAS_SHARED_LIB "@BUILD_SHARED_LIBS@") -set(@META_PROJECT_VARNAME@_SHARED_LIB "@META_PROJECT_NAME@") -set(@META_PROJECT_VARNAME@_HAS_STATIC_LIB "@BUILD_STATIC_LIBS@") -set(@META_PROJECT_VARNAME@_STATIC_LIB "@META_PROJECT_NAME@.a") -set(@META_PROJECT_VARNAME@_STATIC_LIB_DEPENDS @META_STATIC_LIB_DEPENDS@) -set(@META_PROJECT_VARNAME@_INCLUDE_DIRS "@PACKAGE_HEADER_INSTALL_DESTINATION@") -set(@META_PROJECT_VARNAME@_BIN_DIR "@PACKAGE_BIN_INSTALL_DESTINATION@") -set(@META_PROJECT_VARNAME@_LIB_DIR "@PACKAGE_LIB_INSTALL_DESTINATION@") -set(@META_PROJECT_VARNAME@_MODULE_DIRS "@PACKAGE_CMAKE_MODULE_INSTALL_DESTINATION@") -set(@META_PROJECT_VARNAME@_CONFIG_DIRS "@PACKAGE_CMAKE_CONFIG_INSTALL_DESTINATION@") -set(@META_PROJECT_VARNAME@_REQUIRED_CFLAGS "@META_REQUIRED_CFLAGS@") +set(@META_PROJECT_VARNAME_UPPER@_HAS_SHARED_LIB "@BUILD_SHARED_LIBS@") +set(@META_PROJECT_VARNAME_UPPER@_SHARED_LIB "@META_PROJECT_NAME@") +set(@META_PROJECT_VARNAME_UPPER@_SHARED_LIB_COMPILE_DEFINITIONS @META_SHARED_LIB_COMPILE_DEFINITIONS@) +set(@META_PROJECT_VARNAME_UPPER@_HAS_STATIC_LIB "@BUILD_STATIC_LIBS@") +set(@META_PROJECT_VARNAME_UPPER@_STATIC_LIB "@META_PROJECT_NAME@.a") +set(@META_PROJECT_VARNAME_UPPER@_STATIC_LIB_DEPENDS @META_STATIC_LIB_DEPENDS@) +set(@META_PROJECT_VARNAME_UPPER@_STATIC_LIB_COMPILE_DEFINITIONS @META_STATIC_LIB_COMPILE_DEFINITIONS@) +set(@META_PROJECT_VARNAME_UPPER@_INCLUDE_DIRS "@PACKAGE_HEADER_INSTALL_DESTINATION@") +set(@META_PROJECT_VARNAME_UPPER@_BIN_DIR "@PACKAGE_BIN_INSTALL_DESTINATION@") +set(@META_PROJECT_VARNAME_UPPER@_LIB_DIR "@PACKAGE_LIB_INSTALL_DESTINATION@") +set(@META_PROJECT_VARNAME_UPPER@_MODULE_DIRS "@PACKAGE_CMAKE_MODULE_INSTALL_DESTINATION@") +set(@META_PROJECT_VARNAME_UPPER@_CONFIG_DIRS "@PACKAGE_CMAKE_CONFIG_INSTALL_DESTINATION@") -if(@META_PROJECT_VARNAME@_HAS_SHARED_LIB) - set(@META_PROJECT_VARNAME@_LIB "${@META_PROJECT_VARNAME@_SHARED_LIB}") +if(@META_PROJECT_VARNAME_UPPER@_HAS_SHARED_LIB) + set(@META_PROJECT_VARNAME_UPPER@_LIB "${@META_PROJECT_VARNAME_UPPER@_SHARED_LIB}") else() - set(@META_PROJECT_VARNAME@_LIB "${@META_PROJECT_VARNAME@_STATIC_LIB}") + set(@META_PROJECT_VARNAME_UPPER@_LIB "${@META_PROJECT_VARNAME_UPPER@_STATIC_LIB}") endif() -macro(use_@META_PROJECT_VARNAME@) - include_directories(BEFORE SYSTEM ${@META_PROJECT_VARNAME@_INCLUDE_DIRS}) - link_directories(${@META_PROJECT_VARNAME@_LIB_DIR}) +macro(use_@META_PROJECT_VARNAME_UPPER@) + include_directories(BEFORE SYSTEM ${@META_PROJECT_VARNAME_UPPER@_INCLUDE_DIRS}) + link_directories(${@META_PROJECT_VARNAME_UPPER@_LIB_DIR}) # add library to list of libraries to link against when building dynamic libraries or applications - if(@META_PROJECT_VARNAME@_HAS_STATIC_LIB AND ((NOT ARGV0 AND ((STATIC_LINKAGE AND "${META_PROJECT_TYPE}" STREQUAL "application") OR (STATIC_LIBRARY_LINKAGE AND ("${META_PROJECT_TYPE}" STREQUAL "" OR "${META_PROJECT_TYPE}" STREQUAL "library")))) OR ("${ARGV0}" STREQUAL "STATIC") OR (NOT ARGV0 AND NOT @META_PROJECT_VARNAME@_HAS_SHARED_LIB))) - list(APPEND LIBRARIES ${@META_PROJECT_VARNAME@_STATIC_LIB} ${@META_PROJECT_VARNAME@_STATIC_LIB_DEPENDS}) - message(STATUS "Linking ${META_PROJECT_NAME} statically against @META_PROJECT_NAME@ (${@META_PROJECT_VARNAME@_STATIC_LIB} ${@META_PROJECT_VARNAME@_STATIC_LIB_DEPENDS}).") - elseif(@META_PROJECT_VARNAME@_HAS_SHARED_LIB AND (NOT ARGV0 OR ("${ARGV0}" STREQUAL "SHARED"))) - list(APPEND LIBRARIES ${@META_PROJECT_VARNAME@_SHARED_LIB}) - message(STATUS "Linking ${META_PROJECT_NAME} dynamically against @META_PROJECT_NAME@ (${@META_PROJECT_VARNAME@_SHARED_LIB}).") + if(@META_PROJECT_VARNAME_UPPER@_HAS_STATIC_LIB AND ((NOT ARGV0 AND ((STATIC_LINKAGE AND "${META_PROJECT_TYPE}" STREQUAL "application") OR (STATIC_LIBRARY_LINKAGE AND ("${META_PROJECT_TYPE}" STREQUAL "" OR "${META_PROJECT_TYPE}" STREQUAL "library")))) OR ("${ARGV0}" STREQUAL "STATIC") OR (NOT ARGV0 AND NOT @META_PROJECT_VARNAME_UPPER@_HAS_SHARED_LIB))) + list(APPEND LIBRARIES ${@META_PROJECT_VARNAME_UPPER@_STATIC_LIB} ${@META_PROJECT_VARNAME_UPPER@_STATIC_LIB_DEPENDS}) + message(STATUS "Linking ${META_PROJECT_NAME} statically against @META_PROJECT_NAME@ (${@META_PROJECT_VARNAME_UPPER@_STATIC_LIB} ${@META_PROJECT_VARNAME_UPPER@_STATIC_LIB_DEPENDS}).") + list(APPEND ADDITIONAL_STATIC_COMPILE_DEFINITIONS ${@META_PROJECT_VARNAME_UPPER@_STATIC_LIB_COMPILE_DEFINITIONS}) + elseif(@META_PROJECT_VARNAME_UPPER@_HAS_SHARED_LIB AND (NOT ARGV0 OR ("${ARGV0}" STREQUAL "SHARED"))) + list(APPEND LIBRARIES ${@META_PROJECT_VARNAME_UPPER@_SHARED_LIB}) + message(STATUS "Linking ${META_PROJECT_NAME} dynamically against @META_PROJECT_NAME@ (${@META_PROJECT_VARNAME_UPPER@_SHARED_LIB}).") + list(APPEND ADDITIONAL_SHARED_COMPILE_DEFINITIONS ${@META_PROJECT_VARNAME_UPPER@_SHARED_LIB_COMPILE_DEFINITIONS}) elseif(ARGV0) message(FATAL_ERROR "Can not link ${META_PROJECT_NAME} against @META_PROJECT_NAME@ with the specified linkage ${ARGV0}.") else() message(FATAL_ERROR "Can not link ${META_PROJECT_NAME} against @META_PROJECT_NAME@.") endif() # add library (including dependencies) to list of libraries to be provided as transitive dependencies when building static libraries - list(APPEND STATIC_LIBRARIES ${@META_PROJECT_VARNAME@_STATIC_LIB} ${@META_PROJECT_VARNAME@_STATIC_LIB_DEPENDS}) - message(STATUS "Adding ${@META_PROJECT_VARNAME@_STATIC_LIB} ${@META_PROJECT_VARNAME@_STATIC_LIB_DEPENDS} to static library dependencies of ${META_PROJECT_NAME}.") + list(APPEND STATIC_LIBRARIES ${@META_PROJECT_VARNAME_UPPER@_STATIC_LIB} ${@META_PROJECT_VARNAME_UPPER@_STATIC_LIB_DEPENDS}) + message(STATUS "Adding ${@META_PROJECT_VARNAME_UPPER@_STATIC_LIB} ${@META_PROJECT_VARNAME_UPPER@_STATIC_LIB_DEPENDS} to static library dependencies of ${META_PROJECT_NAME}.") # make CMake modules of the project available - list(APPEND CMAKE_MODULE_PATH ${@META_PROJECT_VARNAME@_MODULE_DIRS}) + list(APPEND CMAKE_MODULE_PATH ${@META_PROJECT_VARNAME_UPPER@_MODULE_DIRS}) endmacro() diff --git a/cmake/templates/config.h.in b/cmake/templates/config.h.in index 29dafe1..ad9d1ba 100644 --- a/cmake/templates/config.h.in +++ b/cmake/templates/config.h.in @@ -1,5 +1,8 @@ -#ifndef APP_METADATA_AVAIL -#define APP_METADATA_AVAIL +// Created via CMake from template config.h.in +// WARNING! Any changes to this file will be overwritten by the next CMake run! + +#ifndef APPLICATION_CONFIG +#define APPLICATION_CONFIG #define PROJECT_NAME @META_PROJECT_NAME_STR@ #define APP_NAME @META_APP_NAME_STR@ @@ -12,4 +15,4 @@ #cmakedefine SVG_SUPPORT #cmakedefine SVG_ICON_SUPPORT -#endif // APP_METADATA_AVAIL +#endif // APPLICATION_CONFIG diff --git a/cmake/templates/global.h.in b/cmake/templates/global.h.in new file mode 100644 index 0000000..1f4bafc --- /dev/null +++ b/cmake/templates/global.h.in @@ -0,0 +1,17 @@ +// Created via CMake from template global.h.in +// WARNING! Any changes to this file will be overwritten by the next CMake run! + +#ifndef @META_PROJECT_VARNAME_UPPER@_GLOBAL +#define @META_PROJECT_VARNAME_UPPER@_GLOBAL + +#include @GENERAL_GLOBAL_H_INCLUDE_PATH@ + +#ifdef @META_PROJECT_VARNAME_UPPER@_STATIC +# define @META_PROJECT_VARNAME_UPPER@_EXPORT +# define @META_PROJECT_VARNAME_UPPER@_IMPORT +#else +# define @META_PROJECT_VARNAME_UPPER@_EXPORT LIB_EXPORT +# define @META_PROJECT_VARNAME_UPPER@_IMPORT LIB_IMPORT +#endif + +#endif // @META_PROJECT_VARNAME_UPPER@_GLOBAL diff --git a/cmake/templates/template.pc.in b/cmake/templates/template.pc.in index 72513f0..4080574 100644 --- a/cmake/templates/template.pc.in +++ b/cmake/templates/template.pc.in @@ -10,4 +10,4 @@ URL: @META_APP_URL@ Libs: -L${libdir} -l@TARGET_PREFIX@@META_PROJECT_NAME@@TARGET_SUFFIX@ Libs.private: @META_STATIC_LIB_DEPENDS@ -Cflags: -I${includedir} @META_REQUIRED_CFLAGS@ +Cflags: -I${includedir} diff --git a/conversion/binaryconversion.h b/conversion/binaryconversion.h index 3762453..fa08384 100644 --- a/conversion/binaryconversion.h +++ b/conversion/binaryconversion.h @@ -1,200 +1,200 @@ -#ifndef CONVERSION_UTILITIES_BINARY_CONVERSION_H -#define CONVERSION_UTILITIES_BINARY_CONVERSION_H - -#include "./types.h" - -#include "../application/global.h" - -#ifdef __BYTE_ORDER__ -# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false -# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN true -# define CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN -# elif __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__ -# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false -# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false -# define CONVERSION_UTILITIES_BYTE_ORDER_MIDDLE_ENDIAN -# elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN true -# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false -# define CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN -# endif -#endif -#ifdef __FLOAT_WORD_ORDER__ -# if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__ -# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_BIG_ENDIAN -# elif __FLOAT_WORD_ORDER__ == __ORDER_PDP_ENDIAN__ -# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_MIDDLE_ENDIAN -# elif __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_LITTLE_ENDIAN -# endif -#endif -#if defined(__BYTE_ORDER__) && defined(__FLOAT_WORD_ORDER__) -#else -# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) || defined(__LITTLE_ENDIAN__) || defined(_little_endian__) || defined(_LITTLE_ENDIAN) || defined(_WIN32_WCE) || defined(WINAPI_FAMILY) -# ifndef __BYTE_ORDER__ -# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN true -# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false -# define CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN -# endif -# ifndef __FLOAT_WORD_ORDER__ -# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_LITTLE_ENDIAN -# endif -# elif defined(__MIPSEB__) || defined(__s390__) || defined(__BIG_ENDIAN__) || defined(_big_endian__) || defined(_BIG_ENDIAN) -# ifndef __BYTE_ORDER__ -# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false -# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN true -# define CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN -# endif -# ifndef __FLOAT_WORD_ORDER__ -# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_BIG_ENDIAN -# endif -# else -# error "Unable to determine byte order!" -# endif -#endif - -#if defined(CONVERSION_UTILITIES_BYTE_ORDER_MIDDLE_ENDIAN) -# error "Middle endian byte order is not supported!" -#endif -#if defined(CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_MIDDLE_ENDIAN) -# error "Middle endian byte order is not supported!" -#endif - -/*! - * \namespace ConversionUtilities - * \brief Contains several functions providing conversions between different data types. - * - * binaryconversion.h declares functions which convert base data types to an array of bytes and vice versa. - * stringconversion.h declares different functions around string conversion such as converting a number to a string and vice versa. - */ -namespace ConversionUtilities -{ - -/*! - * \brief Encapsulates binary conversion functions using the big endian byte order. - * \sa Endianness - Wikipedia - */ -namespace BE { - -#if defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN) -# define CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL 0 -#elif defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN) -# define CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL 1 -#endif -#include "./binaryconversionprivate.h" -#undef CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL - -} - -/*! - * \brief Encapsulates binary conversion functions using the little endian byte order. - * \sa Endianness - Wikipedia - */ -namespace LE { - -#if defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN) -# define CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL 1 -#elif defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN) -# define CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL 0 -#endif -#include "./binaryconversionprivate.h" -#undef CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL - -} - -/*! - * \brief Returns the 8.8 fixed point representation converted from the specified 32-bit floating point number. - */ -LIB_EXPORT constexpr uint16 toFixed8(float32 float32value) -{ - return static_cast(float32value * 256.0f); -} - -/*! - * \brief Returns a 32-bit floating point number converted from the specified 8.8 fixed point representation. - */ -LIB_EXPORT constexpr float32 toFloat32(uint16 fixed8value) -{ - return static_cast(fixed8value) / 256.0f; -} - -/*! - * \brief Returns the 16.16 fixed point representation converted from the specified 32-bit floating point number. - */ -LIB_EXPORT constexpr uint32 toFixed16(float32 float32value) -{ - return static_cast(float32value * 65536.0f); -} - -/*! - * \brief Returns a 32-bit floating point number converted from the specified 16.16 fixed point representation. - */ -LIB_EXPORT constexpr float32 toFloat32(uint32 fixed16value) -{ - return static_cast(fixed16value) / 65536.0f; -} - -/*! - * \brief Returns a 32-bit synchsafe integer converted from a normal 32-bit integer. - * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. - * \sa ID3 tag version 2.4.0 - Main Structure - */ -LIB_EXPORT constexpr uint32 toSynchsafeInt(uint32 normalInt) -{ - return ((normalInt & 0x0000007fu) ) - | ((normalInt & 0x00003f80u) << 1) - | ((normalInt & 0x001fc000u) << 2) - | ((normalInt & 0x0fe00000u) << 3); -} - -/*! - * \brief Returns a normal 32-bit integer converted from a 32-bit synchsafe integer. - * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. - * \sa ID3 tag version 2.4.0 - Main Structure - */ -LIB_EXPORT constexpr uint32 toNormalInt(uint32 synchsafeInt) -{ - return ((synchsafeInt & 0x0000007fu) ) - | ((synchsafeInt & 0x00007f00u) >> 1) - | ((synchsafeInt & 0x007f0000u) >> 2) - | ((synchsafeInt & 0x7f000000u) >> 3); -} - -/*! - * \brief Swaps the byte order of the specified 16-bit unsigned integer. - */ -LIB_EXPORT constexpr uint16 swapOrder(uint16 value) -{ - return (value >> 8) | (value << 8); -} - -/*! - * \brief Swaps the byte order of the specified 32-bit unsigned integer. - */ -LIB_EXPORT constexpr uint32 swapOrder(uint32 value) -{ - return (value >> 24) - | ((value & 0x00FF0000) >> 8) - | ((value & 0x0000FF00) << 8) - | (value << 24); -} - -/*! - * \brief Swaps the byte order of the specified 64-bit unsigned integer. - */ -LIB_EXPORT constexpr uint64 swapOrder(uint64 value) -{ - return(value >> (7 * 8)) - | ((value & 0x00FF000000000000) >> (5 * 8)) - | ((value & 0x0000FF0000000000) >> (3 * 8)) - | ((value & 0x000000FF00000000) >> (1 * 8)) - | ((value & 0x00000000FF000000) << (1 * 8)) - | ((value & 0x0000000000FF0000) << (3 * 8)) - | ((value & 0x000000000000FF00) << (5 * 8)) - | ((value) << (7 * 8)); -} - -} - -#endif // CONVERSION_UTILITIES_BINARY_CONVERSION_H +#ifndef CONVERSION_UTILITIES_BINARY_CONVERSION_H +#define CONVERSION_UTILITIES_BINARY_CONVERSION_H + +#include "./types.h" + +#include "../global.h" + +#ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN true +# define CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN +# elif __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__ +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false +# define CONVERSION_UTILITIES_BYTE_ORDER_MIDDLE_ENDIAN +# elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN true +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false +# define CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN +# endif +#endif +#ifdef __FLOAT_WORD_ORDER__ +# if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__ +# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_BIG_ENDIAN +# elif __FLOAT_WORD_ORDER__ == __ORDER_PDP_ENDIAN__ +# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_MIDDLE_ENDIAN +# elif __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_LITTLE_ENDIAN +# endif +#endif +#if defined(__BYTE_ORDER__) && defined(__FLOAT_WORD_ORDER__) +#else +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) || defined(__LITTLE_ENDIAN__) || defined(_little_endian__) || defined(_LITTLE_ENDIAN) || defined(_WIN32_WCE) || defined(WINAPI_FAMILY) +# ifndef __BYTE_ORDER__ +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN true +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false +# define CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN +# endif +# ifndef __FLOAT_WORD_ORDER__ +# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_LITTLE_ENDIAN +# endif +# elif defined(__MIPSEB__) || defined(__s390__) || defined(__BIG_ENDIAN__) || defined(_big_endian__) || defined(_BIG_ENDIAN) +# ifndef __BYTE_ORDER__ +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false +# define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN true +# define CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN +# endif +# ifndef __FLOAT_WORD_ORDER__ +# define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_BIG_ENDIAN +# endif +# else +# error "Unable to determine byte order!" +# endif +#endif + +#if defined(CONVERSION_UTILITIES_BYTE_ORDER_MIDDLE_ENDIAN) +# error "Middle endian byte order is not supported!" +#endif +#if defined(CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_MIDDLE_ENDIAN) +# error "Middle endian byte order is not supported!" +#endif + +/*! + * \namespace ConversionUtilities + * \brief Contains several functions providing conversions between different data types. + * + * binaryconversion.h declares functions which convert base data types to an array of bytes and vice versa. + * stringconversion.h declares different functions around string conversion such as converting a number to a string and vice versa. + */ +namespace ConversionUtilities +{ + +/*! + * \brief Encapsulates binary conversion functions using the big endian byte order. + * \sa Endianness - Wikipedia + */ +namespace BE { + +#if defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN) +# define CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL 0 +#elif defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN) +# define CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL 1 +#endif +#include "./binaryconversionprivate.h" +#undef CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL + +} + +/*! + * \brief Encapsulates binary conversion functions using the little endian byte order. + * \sa Endianness - Wikipedia + */ +namespace LE { + +#if defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN) +# define CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL 1 +#elif defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN) +# define CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL 0 +#endif +#include "./binaryconversionprivate.h" +#undef CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL + +} + +/*! + * \brief Returns the 8.8 fixed point representation converted from the specified 32-bit floating point number. + */ +CPP_UTILITIES_EXPORT constexpr uint16 toFixed8(float32 float32value) +{ + return static_cast(float32value * 256.0f); +} + +/*! + * \brief Returns a 32-bit floating point number converted from the specified 8.8 fixed point representation. + */ +CPP_UTILITIES_EXPORT constexpr float32 toFloat32(uint16 fixed8value) +{ + return static_cast(fixed8value) / 256.0f; +} + +/*! + * \brief Returns the 16.16 fixed point representation converted from the specified 32-bit floating point number. + */ +CPP_UTILITIES_EXPORT constexpr uint32 toFixed16(float32 float32value) +{ + return static_cast(float32value * 65536.0f); +} + +/*! + * \brief Returns a 32-bit floating point number converted from the specified 16.16 fixed point representation. + */ +CPP_UTILITIES_EXPORT constexpr float32 toFloat32(uint32 fixed16value) +{ + return static_cast(fixed16value) / 65536.0f; +} + +/*! + * \brief Returns a 32-bit synchsafe integer converted from a normal 32-bit integer. + * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. + * \sa ID3 tag version 2.4.0 - Main Structure + */ +CPP_UTILITIES_EXPORT constexpr uint32 toSynchsafeInt(uint32 normalInt) +{ + return ((normalInt & 0x0000007fu) ) + | ((normalInt & 0x00003f80u) << 1) + | ((normalInt & 0x001fc000u) << 2) + | ((normalInt & 0x0fe00000u) << 3); +} + +/*! + * \brief Returns a normal 32-bit integer converted from a 32-bit synchsafe integer. + * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. + * \sa ID3 tag version 2.4.0 - Main Structure + */ +CPP_UTILITIES_EXPORT constexpr uint32 toNormalInt(uint32 synchsafeInt) +{ + return ((synchsafeInt & 0x0000007fu) ) + | ((synchsafeInt & 0x00007f00u) >> 1) + | ((synchsafeInt & 0x007f0000u) >> 2) + | ((synchsafeInt & 0x7f000000u) >> 3); +} + +/*! + * \brief Swaps the byte order of the specified 16-bit unsigned integer. + */ +CPP_UTILITIES_EXPORT constexpr uint16 swapOrder(uint16 value) +{ + return (value >> 8) | (value << 8); +} + +/*! + * \brief Swaps the byte order of the specified 32-bit unsigned integer. + */ +CPP_UTILITIES_EXPORT constexpr uint32 swapOrder(uint32 value) +{ + return (value >> 24) + | ((value & 0x00FF0000) >> 8) + | ((value & 0x0000FF00) << 8) + | (value << 24); +} + +/*! + * \brief Swaps the byte order of the specified 64-bit unsigned integer. + */ +CPP_UTILITIES_EXPORT constexpr uint64 swapOrder(uint64 value) +{ + return(value >> (7 * 8)) + | ((value & 0x00FF000000000000) >> (5 * 8)) + | ((value & 0x0000FF0000000000) >> (3 * 8)) + | ((value & 0x000000FF00000000) >> (1 * 8)) + | ((value & 0x00000000FF000000) << (1 * 8)) + | ((value & 0x0000000000FF0000) << (3 * 8)) + | ((value & 0x000000000000FF00) << (5 * 8)) + | ((value) << (7 * 8)); +} + +} + +#endif // CONVERSION_UTILITIES_BINARY_CONVERSION_H diff --git a/conversion/binaryconversionprivate.h b/conversion/binaryconversionprivate.h index 6abef22..be7b03f 100644 --- a/conversion/binaryconversionprivate.h +++ b/conversion/binaryconversionprivate.h @@ -6,12 +6,12 @@ #include "./types.h" -#include "../application/global.h" +#include "../global.h" /*! * \brief Returns a 16-bit signed integer converted from two bytes at a specified position in a char array. */ -LIB_EXPORT inline int16 toInt16(const char *value) +CPP_UTILITIES_EXPORT inline int16 toInt16(const char *value) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 return (static_cast(value[0]) << 8 & 0xFF00) @@ -25,7 +25,7 @@ LIB_EXPORT inline int16 toInt16(const char *value) /*! * \brief Returns a 16-bit unsigned integer converted from two bytes at a specified position in a char array. */ -LIB_EXPORT inline uint16 toUInt16(const char *value) +CPP_UTILITIES_EXPORT inline uint16 toUInt16(const char *value) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 return (static_cast(value[0]) << 8 & 0xFF00) @@ -39,7 +39,7 @@ LIB_EXPORT inline uint16 toUInt16(const char *value) /*! * \brief Returns a 32-bit signed integer converted from four bytes at a specified position in a char array. */ -LIB_EXPORT inline int32 toInt32(const char *value) +CPP_UTILITIES_EXPORT inline int32 toInt32(const char *value) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 return (static_cast(value[0]) << 24 & 0xFF000000) @@ -57,7 +57,7 @@ LIB_EXPORT inline int32 toInt32(const char *value) /*! * \brief Returns a 32-bit unsigned integer converted from three bytes at a specified position in a char array. */ -LIB_EXPORT inline uint32 toUInt24(const char *value) +CPP_UTILITIES_EXPORT inline uint32 toUInt24(const char *value) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 return (static_cast(value[0]) << 16 & 0x00FF0000) @@ -73,7 +73,7 @@ LIB_EXPORT inline uint32 toUInt24(const char *value) /*! * \brief Returns a 32-bit unsigned integer converted from four bytes at a specified position in a char array. */ -LIB_EXPORT inline uint32 toUInt32(const char *value) +CPP_UTILITIES_EXPORT inline uint32 toUInt32(const char *value) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 return (static_cast(value[0]) << 24 & 0xFF000000) @@ -91,7 +91,7 @@ LIB_EXPORT inline uint32 toUInt32(const char *value) /*! * \brief Returns a 64-bit signed integer converted from eight bytes at a specified position in a char array. */ -LIB_EXPORT inline int64 toInt64(const char *value) +CPP_UTILITIES_EXPORT inline int64 toInt64(const char *value) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 return (static_cast(value[0]) << 56 & 0xFF00000000000000) @@ -117,7 +117,7 @@ LIB_EXPORT inline int64 toInt64(const char *value) /*! * \brief Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a char array. */ -LIB_EXPORT inline uint64 toUInt64(const char *value) +CPP_UTILITIES_EXPORT inline uint64 toUInt64(const char *value) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 return (static_cast(value[0]) << 56 & 0xFF00000000000000) @@ -143,7 +143,7 @@ LIB_EXPORT inline uint64 toUInt64(const char *value) /*! * \brief Returns a 32-bit floating point number converted from four bytes at a specified position in a char array. */ -LIB_EXPORT inline float32 toFloat32(const char *value) +CPP_UTILITIES_EXPORT inline float32 toFloat32(const char *value) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 int32 val = toInt32(value); @@ -159,7 +159,7 @@ LIB_EXPORT inline float32 toFloat32(const char *value) /*! * \brief Returns a 64-bit floating point number converted from eight bytes at a specified position in a char array. */ -LIB_EXPORT inline float64 toFloat64(const char *value) +CPP_UTILITIES_EXPORT inline float64 toFloat64(const char *value) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 int64 val = toInt64(value); @@ -175,7 +175,7 @@ LIB_EXPORT inline float64 toFloat64(const char *value) /*! * \brief Stores the specified 16-bit signed integer value at a specified position in a char array. */ -LIB_EXPORT inline void getBytes(int16 value, char *outputbuffer) +CPP_UTILITIES_EXPORT inline void getBytes(int16 value, char *outputbuffer) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 outputbuffer[0] = static_cast((value >> 8) & 0xFF); @@ -189,7 +189,7 @@ LIB_EXPORT inline void getBytes(int16 value, char *outputbuffer) /*! * \brief Stores the specified 16-bit unsigned integer value at a specified position in a char array. */ -LIB_EXPORT inline void getBytes(uint16 value, char *outputbuffer) +CPP_UTILITIES_EXPORT inline void getBytes(uint16 value, char *outputbuffer) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 outputbuffer[0] = static_cast((value >> 8) & 0xFF); @@ -204,7 +204,7 @@ LIB_EXPORT inline void getBytes(uint16 value, char *outputbuffer) * \brief Stores the specified 24-bit unsigned integer value at a specified position in a char array. * \remarks Ignores the most significant byte. */ -LIB_EXPORT inline void getBytes24(uint32 value, char *outputbuffer) +CPP_UTILITIES_EXPORT inline void getBytes24(uint32 value, char *outputbuffer) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 outputbuffer[0] = static_cast((value >> 16) & 0xFF); @@ -220,7 +220,7 @@ LIB_EXPORT inline void getBytes24(uint32 value, char *outputbuffer) /*! * \brief Stores the specified 32-bit signed integer value at a specified position in a char array. */ -LIB_EXPORT inline void getBytes(int32 value, char *outputbuffer) +CPP_UTILITIES_EXPORT inline void getBytes(int32 value, char *outputbuffer) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 outputbuffer[0] = static_cast((value >> 24) & 0xFF); @@ -238,7 +238,7 @@ LIB_EXPORT inline void getBytes(int32 value, char *outputbuffer) /*! * \brief Stores the specified 32-bit signed integer value at a specified position in a char array. */ -LIB_EXPORT inline void getBytes(uint32 value, char *outputbuffer) +CPP_UTILITIES_EXPORT inline void getBytes(uint32 value, char *outputbuffer) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 outputbuffer[0] = static_cast((value >> 24) & 0xFF); @@ -256,7 +256,7 @@ LIB_EXPORT inline void getBytes(uint32 value, char *outputbuffer) /*! * \brief Stores the specified 64-bit signed integer value at a specified position in a char array. */ -LIB_EXPORT inline void getBytes(int64 value, char *outputbuffer) +CPP_UTILITIES_EXPORT inline void getBytes(int64 value, char *outputbuffer) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 outputbuffer[0] = static_cast((value >> 56) & 0xFF); @@ -282,7 +282,7 @@ LIB_EXPORT inline void getBytes(int64 value, char *outputbuffer) /*! * \brief Stores the specified 64-bit unsigned integer value at a specified position in a char array. */ -LIB_EXPORT inline void getBytes(uint64 value, char *outputbuffer) +CPP_UTILITIES_EXPORT inline void getBytes(uint64 value, char *outputbuffer) { #if CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL == 0 outputbuffer[0] = static_cast((value >> 56) & 0xFF); @@ -308,7 +308,7 @@ LIB_EXPORT inline void getBytes(uint64 value, char *outputbuffer) /*! * \brief Stores the specified 32-bit floating point value at a specified position in a char array. */ -LIB_EXPORT inline void getBytes(float32 value, char *outputbuffer) +CPP_UTILITIES_EXPORT inline void getBytes(float32 value, char *outputbuffer) { char *c = reinterpret_cast(&value); int32 i = *reinterpret_cast(c); @@ -318,7 +318,7 @@ LIB_EXPORT inline void getBytes(float32 value, char *outputbuffer) /*! * \brief Stores the specified 64-bit floating point value at a specified position in a char array. */ -LIB_EXPORT inline void getBytes(float64 value, char *outputbuffer) +CPP_UTILITIES_EXPORT inline void getBytes(float64 value, char *outputbuffer) { char *c = reinterpret_cast(&value); int64 i = *reinterpret_cast(c); diff --git a/conversion/conversionexception.h b/conversion/conversionexception.h index 0b44fe8..7991daa 100644 --- a/conversion/conversionexception.h +++ b/conversion/conversionexception.h @@ -1,14 +1,14 @@ #ifndef CONVERSION_UTILITIES_CONVERSIONEXCEPTION_H #define CONVERSION_UTILITIES_CONVERSIONEXCEPTION_H -#include "../application/global.h" +#include "../global.h" #include #include namespace ConversionUtilities { -class LIB_EXPORT ConversionException : public std::runtime_error +class CPP_UTILITIES_EXPORT ConversionException : public std::runtime_error { public: ConversionException() USE_NOTHROW; diff --git a/conversion/stringconversion.h b/conversion/stringconversion.h index d1e42b2..0de64fa 100644 --- a/conversion/stringconversion.h +++ b/conversion/stringconversion.h @@ -19,7 +19,7 @@ namespace ConversionUtilities /*! * \brief The StringDataDeleter struct deletes the data of a StringData instance. */ -struct LIB_EXPORT StringDataDeleter { +struct CPP_UTILITIES_EXPORT StringDataDeleter { /*! * \brief Deletes the specified \a stringData with std::free(), because the memory has been * allocated using std::malloc()/std::realloc(). @@ -36,15 +36,15 @@ struct LIB_EXPORT StringDataDeleter { typedef std::pair, std::size_t> StringData; //typedef std::pair, std::size_t> StringData; // might work too -LIB_EXPORT StringData convertString(const char *fromCharset, const char *toCharset, const char *inputBuffer, std::size_t inputBufferSize, float outputBufferSizeFactor = 1.0f); -LIB_EXPORT StringData convertUtf8ToUtf16LE(const char *inputBuffer, std::size_t inputBufferSize); -LIB_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize); -LIB_EXPORT StringData convertUtf8ToUtf16BE(const char *inputBuffer, std::size_t inputBufferSize); -LIB_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize); -LIB_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize); -LIB_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize); +CPP_UTILITIES_EXPORT StringData convertString(const char *fromCharset, const char *toCharset, const char *inputBuffer, std::size_t inputBufferSize, float outputBufferSizeFactor = 1.0f); +CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16LE(const char *inputBuffer, std::size_t inputBufferSize); +CPP_UTILITIES_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize); +CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16BE(const char *inputBuffer, std::size_t inputBufferSize); +CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize); +CPP_UTILITIES_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize); +CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize); -LIB_EXPORT void truncateString(std::string &str, char terminationChar = '\0'); +CPP_UTILITIES_EXPORT void truncateString(std::string &str, char terminationChar = '\0'); /*! * \brief Joins the given \a strings using the specified \a delimiter. @@ -59,7 +59,7 @@ LIB_EXPORT void truncateString(std::string &str, char terminationChar = '\0'); * \tparam Container The STL-container used to provide the \a strings. * \returns Returns the joined string. */ -template > LIB_EXPORT +template > CPP_UTILITIES_EXPORT typename Container::value_type joinStrings(const Container &strings, const typename Container::value_type &delimiter = typename Container::value_type(), bool omitEmpty = false, const typename Container::value_type &leftClosure = typename Container::value_type(), const typename Container::value_type &rightClosure = typename Container::value_type()) { typename Container::value_type res; @@ -108,7 +108,7 @@ enum class EmptyPartsTreat * \tparam Container The STL-container used to return the parts. * \returns Returns the parts. */ -template > LIB_EXPORT +template > CPP_UTILITIES_EXPORT Container splitString(const typename Container::value_type &string, const typename Container::value_type &delimiter, EmptyPartsTreat emptyPartsRole = EmptyPartsTreat::Keep, int maxParts = -1) { --maxParts; @@ -148,7 +148,7 @@ Container splitString(const typename Container::value_type &string, const typena /*! * \brief Returns whether \a str starts with \a phrase. */ -template LIB_EXPORT bool startsWith(const StringType &str, const StringType &phrase) +template CPP_UTILITIES_EXPORT bool startsWith(const StringType &str, const StringType &phrase) { if(str.size() < phrase.size()) { return false; @@ -166,7 +166,7 @@ template LIB_EXPORT bool startsWith(const StringType &str, /*! * \brief Returns whether \a str starts with \a phrase. */ -template LIB_EXPORT bool startsWith(const StringType &str, const typename StringType::value_type *phrase) +template CPP_UTILITIES_EXPORT bool startsWith(const StringType &str, const typename StringType::value_type *phrase) { for(auto stri = str.cbegin(), strend = str.cend(); stri != strend; ++stri, ++phrase) { if(!*phrase) { @@ -182,7 +182,7 @@ template LIB_EXPORT bool startsWith(const StringType &str, * \brief Returns whether \a str contains the specified \a substrings. * \remarks The \a substrings must occur in the specified order. */ -template LIB_EXPORT bool containsSubstrings(const StringType &str, std::initializer_list substrings) +template CPP_UTILITIES_EXPORT bool containsSubstrings(const StringType &str, std::initializer_list substrings) { typename StringType::size_type currentPos = 0; for(const auto &substr : substrings) { @@ -198,7 +198,7 @@ template LIB_EXPORT bool containsSubstrings(const StringTy * \brief Returns whether \a str contains the specified \a substrings. * \remarks The \a substrings must occur in the specified order. */ -template LIB_EXPORT bool containsSubstrings(const StringType &str, std::initializer_list substrings) +template CPP_UTILITIES_EXPORT bool containsSubstrings(const StringType &str, std::initializer_list substrings) { typename StringType::size_type currentPos = 0; for(const auto *substr : substrings) { @@ -213,7 +213,7 @@ template LIB_EXPORT bool containsSubstrings(const StringTy /*! * \brief Replaces all occurences of \a find with \a relpace in the specified \a str. */ -template LIB_EXPORT void findAndReplace(StringType &str, const StringType &find, const StringType &replace) +template CPP_UTILITIES_EXPORT void findAndReplace(StringType &str, const StringType &find, const StringType &replace) { for(typename StringType::size_type i = 0; (i = str.find(find, i)) != StringType::npos; i += replace.size()) { str.replace(i, find.size(), replace); @@ -226,7 +226,7 @@ template LIB_EXPORT void findAndReplace(StringType &str, c * \tparam StringType The string type (should be an instantiation of the basic_string class template). * \sa stringToNumber() */ -template LIB_EXPORT StringType numberToString(NumberType number, int base = 10) +template CPP_UTILITIES_EXPORT StringType numberToString(NumberType number, int base = 10) { std::basic_stringstream ss; ss << std::setbase(base) << number; @@ -240,7 +240,7 @@ template LIB_EXPORT Str * \throws A ConversionException will be thrown if the provided string is not a valid number. * \sa numberToString() */ -template LIB_EXPORT NumberType stringToNumber(const StringType &string, int base = 10) +template CPP_UTILITIES_EXPORT NumberType stringToNumber(const StringType &string, int base = 10) { std::basic_stringstream ss; ss << std::setbase(base) << string; @@ -259,7 +259,7 @@ template LIB_EXPORT NumberType string * \throws A ConversionException will be thrown if the provided string is not a valid number. * \sa numberToString() */ -template LIB_EXPORT NumberType stringToNumber(const CharType *string, int base = 10) +template CPP_UTILITIES_EXPORT NumberType stringToNumber(const CharType *string, int base = 10) { std::basic_stringstream ss; ss << std::setbase(base) << string; @@ -280,17 +280,17 @@ template LIB_EXPORT NumberType stringTo * * \tparam T The data type of the integer to be interpreted. */ -template LIB_EXPORT std::string interpretIntegerAsString(T integer, int startOffset = 0) +template CPP_UTILITIES_EXPORT std::string interpretIntegerAsString(T integer, int startOffset = 0) { char buffer[sizeof(T)]; ConversionUtilities::BE::getBytes(integer, buffer); return std::string(buffer + startOffset, sizeof(T) - startOffset); } -LIB_EXPORT std::string dataSizeToString(uint64 sizeInByte, bool includeByte = false); -LIB_EXPORT std::string bitrateToString(double speedInKbitsPerSecond, bool useByteInsteadOfBits = false); -LIB_EXPORT std::string encodeBase64(const byte *data, uint32 dataSize); -LIB_EXPORT std::pair, uint32> decodeBase64(const char *encodedStr, const uint32 strSize); +CPP_UTILITIES_EXPORT std::string dataSizeToString(uint64 sizeInByte, bool includeByte = false); +CPP_UTILITIES_EXPORT std::string bitrateToString(double speedInKbitsPerSecond, bool useByteInsteadOfBits = false); +CPP_UTILITIES_EXPORT std::string encodeBase64(const byte *data, uint32 dataSize); +CPP_UTILITIES_EXPORT std::pair, uint32> decodeBase64(const char *encodedStr, const uint32 strSize); } diff --git a/conversion/types.h b/conversion/types.h index d78ecd2..ac62c32 100644 --- a/conversion/types.h +++ b/conversion/types.h @@ -1,74 +1,74 @@ -#ifndef CONVERSION_UTILITIES_TYPES_H -#define CONVERSION_UTILITIES_TYPES_H - -#include - -/*! - * \brief signed byte - */ -typedef std::int8_t sbyte; - -/*! - * \brief unsigned byte - */ -typedef std::uint8_t byte; - -/*! - * \brief signed 16-bit integer - */ -typedef std::int16_t int16; - -/*! - * \brief signed 32-bit integer - */ -typedef std::int32_t int32; - -/*! - * \brief signed 64-bit integer - */ -typedef std::int64_t int64; - -/*! - * \brief signed pointer - */ -typedef std::intptr_t intptr; - -/*! - * \brief unsigned 16-bit integer - */ -typedef std::uint16_t uint16; - -/*! - * \brief unsigned 32-bit integer - */ -typedef std::uint32_t uint32; - -/*! - * \brief unsigned 64-bit integer - */ -typedef std::uint64_t uint64; - -/*! - * \brief unsigned pointer - */ -typedef std::uintptr_t uintptr; - -#if __SIZEOF_FLOAT__ == 4 -/*! - * \brief 32-bit floating point - */ -typedef float float32; -#else -#error "Unable to define float32!" -#endif - -#if __SIZEOF_DOUBLE__ == 8 -/*! - * \brief 64-bit floating point - */ -typedef double float64; -#else -#error "Unable to define float64!" -#endif - -#endif // CONVERSION_UTILITIES_TYPES_H +#ifndef CONVERSION_UTILITIES_TYPES_H +#define CONVERSION_UTILITIES_TYPES_H + +#include + +/*! + * \brief signed byte + */ +typedef std::int8_t sbyte; + +/*! + * \brief unsigned byte + */ +typedef std::uint8_t byte; + +/*! + * \brief signed 16-bit integer + */ +typedef std::int16_t int16; + +/*! + * \brief signed 32-bit integer + */ +typedef std::int32_t int32; + +/*! + * \brief signed 64-bit integer + */ +typedef std::int64_t int64; + +/*! + * \brief signed pointer + */ +typedef std::intptr_t intptr; + +/*! + * \brief unsigned 16-bit integer + */ +typedef std::uint16_t uint16; + +/*! + * \brief unsigned 32-bit integer + */ +typedef std::uint32_t uint32; + +/*! + * \brief unsigned 64-bit integer + */ +typedef std::uint64_t uint64; + +/*! + * \brief unsigned pointer + */ +typedef std::uintptr_t uintptr; + +#if __SIZEOF_FLOAT__ == 4 +/*! + * \brief 32-bit floating point + */ +typedef float float32; +#else +# error "Unable to define float32!" +#endif + +#if __SIZEOF_DOUBLE__ == 8 +/*! + * \brief 64-bit floating point + */ +typedef double float64; +#else +# error "Unable to define float64!" +#endif + +#endif // CONVERSION_UTILITIES_TYPES_H diff --git a/conversion/widen.h b/conversion/widen.h index fa43382..301ee5a 100644 --- a/conversion/widen.h +++ b/conversion/widen.h @@ -1,52 +1,52 @@ -#ifndef CONVERSION_UTILITIES_WIDEN_H -#define CONVERSION_UTILITIES_WIDEN_H - -#include "../application/global.h" - -#include -#include -#include -#include -#include - -namespace ConversionUtilities -{ - -/*! - * \brief Converts a std::string to a wide string using the specified locale. - */ -template, class A = std::allocator > -class LIB_EXPORT Widen : public std::unary_function > -{ -public: - /*! - * \brief Constructs a new instance with the specified \a locale. - */ - Widen(const std::locale &locale = std::locale()) : - m_loc(locale), - m_pctype(&std::use_facet >(locale)) - {} - - Widen(const Widen &) = delete; - Widen& operator= (const Widen &) = delete; - - /*! - * \brief Performs the conversation for the provided \a string. - */ - std::basic_string operator() (const std::string &string) const - { - typename std::basic_string::size_type srcLen = string.length(); - const char *srcBeg = string.c_str(); - std::vector tmp(srcLen); - m_pctype->widen(srcBeg, srcBeg + srcLen, &tmp[0]); - return std::basic_string(&tmp[0], srcLen); - } - -private: - std::locale m_loc; - const std::ctype* m_pctype; -}; - -} - -#endif // CONVERSION_UTILITIES_WIDEN_H +#ifndef CONVERSION_UTILITIES_WIDEN_H +#define CONVERSION_UTILITIES_WIDEN_H + +#include "../global.h" + +#include +#include +#include +#include +#include + +namespace ConversionUtilities +{ + +/*! + * \brief Converts a std::string to a wide string using the specified locale. + */ +template, class A = std::allocator > +class CPP_UTILITIES_EXPORT Widen : public std::unary_function > +{ +public: + /*! + * \brief Constructs a new instance with the specified \a locale. + */ + Widen(const std::locale &locale = std::locale()) : + m_loc(locale), + m_pctype(&std::use_facet >(locale)) + {} + + Widen(const Widen &) = delete; + Widen& operator= (const Widen &) = delete; + + /*! + * \brief Performs the conversation for the provided \a string. + */ + std::basic_string operator() (const std::string &string) const + { + typename std::basic_string::size_type srcLen = string.length(); + const char *srcBeg = string.c_str(); + std::vector tmp(srcLen); + m_pctype->widen(srcBeg, srcBeg + srcLen, &tmp[0]); + return std::basic_string(&tmp[0], srcLen); + } + +private: + std::locale m_loc; + const std::ctype* m_pctype; +}; + +} + +#endif // CONVERSION_UTILITIES_WIDEN_H diff --git a/global.h b/global.h new file mode 100644 index 0000000..fb8e5fa --- /dev/null +++ b/global.h @@ -0,0 +1,17 @@ +// Created via CMake from template global.h.in +// WARNING! Any changes to this file will be overwritten by the next CMake run! + +#ifndef CPP_UTILITIES_GLOBAL +#define CPP_UTILITIES_GLOBAL + +#include "./application/global.h" + +#ifdef CPP_UTILITIES_STATIC +# define CPP_UTILITIES_EXPORT +# define CPP_UTILITIES_IMPORT +#else +# define CPP_UTILITIES_EXPORT LIB_EXPORT +# define CPP_UTILITIES_IMPORT LIB_IMPORT +#endif + +#endif // CPP_UTILITIES_GLOBAL diff --git a/io/ansiescapecodes.h b/io/ansiescapecodes.h index 67b1c44..70002cd 100644 --- a/io/ansiescapecodes.h +++ b/io/ansiescapecodes.h @@ -1,7 +1,7 @@ #ifndef IOUTILITIES_ANSIESCAPECODES #define IOUTILITIES_ANSIESCAPECODES -#include "../application/global.h" +#include "../global.h" #include diff --git a/io/binaryreader.cpp b/io/binaryreader.cpp index 7079ca9..6f3ac11 100644 --- a/io/binaryreader.cpp +++ b/io/binaryreader.cpp @@ -1,339 +1,339 @@ -#include "./binaryreader.h" - -#include "../misc/memory.h" -#include "../conversion/conversionexception.h" - -#include -#include - -using namespace std; -using namespace IoUtilities; -using namespace ConversionUtilities; - -/*! - * \namespace IoUtilities - * \brief Contains utility classes helping to read and write streams. - */ - -/*! - * \class IoUtilities::BinaryReader - * \brief Reads primitive data types from a std::istream. - * \remarks Supports both, little endian and big endian. - */ - -/*! - * \brief Constructs a new BinaryReader. - * \param stream Specifies the stream to read from. - */ -BinaryReader::BinaryReader(istream *stream) : - m_stream(stream), - m_ownership(false) -{} - -/*! - * \brief Copies the specified BinaryReader. - * \remarks The copy will not take ownership over the stream. - */ -BinaryReader::BinaryReader(const BinaryReader &other) : - m_stream(other.m_stream), - m_ownership(false) -{} - -/*! - * \brief Destroys the BinaryReader. - */ -BinaryReader::~BinaryReader() -{ - if(m_ownership) { - delete m_stream; - } -} - -/*! - * \brief Assigns the stream the reader will read from when calling one of the read-methods. - * - * You can assign a null pointer when ensuring that none of the read-methods is called - * until a stream is assigned. - * - * \param stream Specifies the stream to be assigned. - * \param giveOwnership Indicated whether the reader should take ownership (default is false). - * - * \sa setStream() - */ -void BinaryReader::setStream(istream *stream, bool giveOwnership) -{ - if(m_ownership) { - delete m_stream; - } - if(stream) { - m_stream = stream; - m_ownership = giveOwnership; - } else { - m_stream = nullptr; - m_ownership = false; - } -} - -/*! - * \brief Returns the size of the assigned stream. - * - * The size is determined by seeking to the end of the stream and returning this offset. - * - * \remarks The method will seek back to the previous offset before returning. - */ -istream::pos_type BinaryReader::readStreamsize() -{ - istream::pos_type cp = m_stream->tellg(); - m_stream->seekg(0, ios_base::end); - const auto streamsize = m_stream->tellg(); - m_stream->seekg(cp); - return streamsize; -} - -/*! - * \brief Reads a length prefixed string from the current stream. - * - * \remarks Reads the length prefix from the stream and then a string of the denoted length. - * Advances the current position of the stream by the denoted length of the string plus the prefix length. - */ -string BinaryReader::readLengthPrefixedString() -{ - static const int maxPrefixLength = 4; - int prefixLength = 1; - byte beg = m_stream->peek(); - byte mask = 0x80; - while(prefixLength <= maxPrefixLength && (beg & mask) == 0) { - ++prefixLength; - mask >>= 1; - } - if(prefixLength > maxPrefixLength) { - throw ConversionException("Length denotation of length-prefixed string exceeds maximum."); - } - memset(m_buffer, 0, maxPrefixLength); - m_stream->read(m_buffer + (maxPrefixLength - prefixLength), prefixLength); - *(m_buffer + (maxPrefixLength - prefixLength)) ^= mask; - uint32 prefix = BE::toUInt32(m_buffer); - return readString(prefix); -} - -/*! - * \brief Reads a string from the current stream of the given \a length from the stream and advances the current position of the stream by \a length byte. - */ -string BinaryReader::readString(size_t length) -{ - string res; - res.resize(length); - m_stream->read(&res[0], length); - return res; -} - -/*! - * \brief Reads a terminated string from the current stream. - * - * Advances the current position of the stream by the string length plus one byte. - * - * \param termination The byte to be recognized as termination value. - */ -string BinaryReader::readTerminatedString(byte termination) -{ - stringstream ss(ios_base::in | ios_base::out | ios_base::binary); - ss.exceptions(ios_base::badbit | ios_base::failbit); - m_stream->get(*ss.rdbuf(), termination); // delim byte is not extracted from the stream - m_stream->seekg(1, ios_base::cur); // "extract" delim byte manually - return ss.str(); -} - -/*! - * \brief Reads a terminated string from the current stream. - * - * Advances the current position of the stream by the string length plus one byte - * but maximal by \a maxBytesToRead. - * - * \param maxBytesToRead The maximal number of bytes to read. - * \param termination The value to be recognized as termination. - */ -string BinaryReader::readTerminatedString(size_t maxBytesToRead, byte termination) -{ - unique_ptr buff = make_unique(maxBytesToRead); - for(char *i = buff.get(), *end = i + maxBytesToRead; i < end; ++i) { - m_stream->get(*i); - if(*(reinterpret_cast(i)) == termination) { - return string(buff.get(), i - buff.get()); - } - } - return string(buff.get(), maxBytesToRead); -} - -/*! - * \brief Reads a multibyte-terminated string from the current stream. - * - * Advances the current position of the stream by the string length plus two bytes. - * - * \param termination Specifies the two byte sized big endian value to be recognized as termination. - */ -string BinaryReader::readMultibyteTerminatedStringBE(uint16 termination) -{ - stringstream ss(ios_base::in | ios_base::out | ios_base::binary); - ss.exceptions(ios_base::badbit | ios_base::failbit); - char *delimChars = m_buffer, *buff = m_buffer + 2; - ConversionUtilities::BE::getBytes(termination, delimChars); - do { - m_stream->get(buff[0]); - m_stream->get(buff[1]); - } while(!((buff[0] == delimChars[0]) && (buff[1] == delimChars[1]))); - return ss.str(); -} - -/*! - * \brief Reads a multibyte-terminated string from the current stream. - * - * Advances the current position of the stream by the string length plus two bytes. - * - * \param termination Specifies the two byte sized little endian value to be recognized as termination. - */ -string BinaryReader::readMultibyteTerminatedStringLE(uint16 termination) -{ - stringstream ss(ios_base::in | ios_base::out | ios_base::binary); - ss.exceptions(ios_base::badbit | ios_base::failbit); - char *delimChars = m_buffer, *buff = m_buffer + 2; - ConversionUtilities::LE::getBytes(termination, delimChars); - do { - m_stream->get(buff[0]); - m_stream->get(buff[1]); - } while(!((buff[0] == delimChars[0]) && (buff[1] == delimChars[1]))); - return ss.str(); -} - -/*! - * \brief Reads a terminated string from the current stream. - * - * Advances the current position of the stream by the string length plus two bytes - * but maximal by \a maxBytesToRead. - * - * \param maxBytesToRead The maximal number of bytes to read. - * \param termination The two byte sized big endian value to be recognized as termination. - */ -string BinaryReader::readMultibyteTerminatedStringBE(std::size_t maxBytesToRead, uint16 termination) -{ - unique_ptr buff = make_unique(maxBytesToRead); - char *delimChars = m_buffer; - ConversionUtilities::BE::getBytes(termination, delimChars); - for(char *i = buff.get(), *end = i + maxBytesToRead; (i + 1) < end; i += 2) { - m_stream->get(*i); - m_stream->get(*(i + 1)); - if((*i == delimChars[0]) && (*(i + 1) == delimChars[1])) { - return string(buff.get(), i - buff.get()); - } - } - return string(buff.get(), maxBytesToRead); -} - -/*! - * \brief Reads a terminated string from the current stream. - * - * Advances the current position of the stream by the string length plus two bytes - * but maximal by \a maxBytesToRead. - * - * \param maxBytesToRead The maximal number of bytes to read. - * \param termination The two byte sized little endian value to be recognized as termination. - */ -string BinaryReader::readMultibyteTerminatedStringLE(std::size_t maxBytesToRead, uint16 termination) -{ - unique_ptr buff = make_unique(maxBytesToRead); - char *delimChars = m_buffer; - ConversionUtilities::LE::getBytes(termination, delimChars); - for(char *i = buff.get(), *end = i + maxBytesToRead; (i + 1) < end; i += 2) { - m_stream->get(*i); - m_stream->get(*(i + 1)); - if((*i == delimChars[0]) && (*(i + 1) == delimChars[1])) { - return string(buff.get(), i - buff.get()); - } - } - return string(buff.get(), maxBytesToRead); -} - -/*! - * \brief Reads \a length bytes from the stream and computes the CRC-32 for that block of data. - * - * \remarks Cyclic redundancy check (CRC) is an error-detecting code commonly used in - * digital networks and storage devices to detect accidental changes to raw data. - * \remarks Ogg compatible version - * \sa Cyclic redundancy check - Wikipedia - */ -uint32 BinaryReader::readCrc32(size_t length) -{ - uint32 crc = 0x00; - for(uint32 i = 0; i < length; ++i) { - crc = (crc << 8) ^ crc32Table[((crc >> 24) & 0xff) ^ static_cast(m_stream->get())]; - } - return crc; -} - -/*! - * \brief Reads \a length bytes from the buffer and computes the CRC-32 for that block of data. - * - * \remarks Cyclic redundancy check (CRC) is an error-detecting code commonly used in - * digital networks and storage devices to detect accidental changes to raw data. - * \remarks Ogg compatible version - * \sa Cyclic redundancy check - Wikipedia - */ -uint32 BinaryReader::computeCrc32(const char *buffer, size_t length) -{ - uint32 crc = 0x00; - for(const char *i = buffer, *end = buffer + length; i != end; ++i) { - crc = (crc << 8) ^ crc32Table[((crc >> 24) & 0xff) ^ static_cast(*i)]; - } - return crc; -} - -/*! - * \brief CRC-32 table. - * \remarks Internally used by readCrc32() method. - * \sa readCrc32() - */ -const uint32 BinaryReader::crc32Table[] = { - 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, - 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, - 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, - 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, - 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, - 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, - 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, - 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, - 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, - 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, - 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, - 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, - 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, - 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, - 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, - 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, - 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, - 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, - 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, - 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, - 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, - 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, - 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, - 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, - 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, - 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, - 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, - 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, - 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, - 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, - 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 -}; - +#include "./binaryreader.h" + +#include "../misc/memory.h" +#include "../conversion/conversionexception.h" + +#include +#include + +using namespace std; +using namespace IoUtilities; +using namespace ConversionUtilities; + +/*! + * \namespace IoUtilities + * \brief Contains utility classes helping to read and write streams. + */ + +/*! + * \class IoUtilities::BinaryReader + * \brief Reads primitive data types from a std::istream. + * \remarks Supports both, little endian and big endian. + */ + +/*! + * \brief Constructs a new BinaryReader. + * \param stream Specifies the stream to read from. + */ +BinaryReader::BinaryReader(istream *stream) : + m_stream(stream), + m_ownership(false) +{} + +/*! + * \brief Copies the specified BinaryReader. + * \remarks The copy will not take ownership over the stream. + */ +BinaryReader::BinaryReader(const BinaryReader &other) : + m_stream(other.m_stream), + m_ownership(false) +{} + +/*! + * \brief Destroys the BinaryReader. + */ +BinaryReader::~BinaryReader() +{ + if(m_ownership) { + delete m_stream; + } +} + +/*! + * \brief Assigns the stream the reader will read from when calling one of the read-methods. + * + * You can assign a null pointer when ensuring that none of the read-methods is called + * until a stream is assigned. + * + * \param stream Specifies the stream to be assigned. + * \param giveOwnership Indicated whether the reader should take ownership (default is false). + * + * \sa setStream() + */ +void BinaryReader::setStream(istream *stream, bool giveOwnership) +{ + if(m_ownership) { + delete m_stream; + } + if(stream) { + m_stream = stream; + m_ownership = giveOwnership; + } else { + m_stream = nullptr; + m_ownership = false; + } +} + +/*! + * \brief Returns the size of the assigned stream. + * + * The size is determined by seeking to the end of the stream and returning this offset. + * + * \remarks The method will seek back to the previous offset before returning. + */ +istream::pos_type BinaryReader::readStreamsize() +{ + istream::pos_type cp = m_stream->tellg(); + m_stream->seekg(0, ios_base::end); + const auto streamsize = m_stream->tellg(); + m_stream->seekg(cp); + return streamsize; +} + +/*! + * \brief Reads a length prefixed string from the current stream. + * + * \remarks Reads the length prefix from the stream and then a string of the denoted length. + * Advances the current position of the stream by the denoted length of the string plus the prefix length. + */ +string BinaryReader::readLengthPrefixedString() +{ + static const int maxPrefixLength = 4; + int prefixLength = 1; + byte beg = m_stream->peek(); + byte mask = 0x80; + while(prefixLength <= maxPrefixLength && (beg & mask) == 0) { + ++prefixLength; + mask >>= 1; + } + if(prefixLength > maxPrefixLength) { + throw ConversionException("Length denotation of length-prefixed string exceeds maximum."); + } + memset(m_buffer, 0, maxPrefixLength); + m_stream->read(m_buffer + (maxPrefixLength - prefixLength), prefixLength); + *(m_buffer + (maxPrefixLength - prefixLength)) ^= mask; + uint32 prefix = BE::toUInt32(m_buffer); + return readString(prefix); +} + +/*! + * \brief Reads a string from the current stream of the given \a length from the stream and advances the current position of the stream by \a length byte. + */ +string BinaryReader::readString(size_t length) +{ + string res; + res.resize(length); + m_stream->read(&res[0], length); + return res; +} + +/*! + * \brief Reads a terminated string from the current stream. + * + * Advances the current position of the stream by the string length plus one byte. + * + * \param termination The byte to be recognized as termination value. + */ +string BinaryReader::readTerminatedString(byte termination) +{ + stringstream ss(ios_base::in | ios_base::out | ios_base::binary); + ss.exceptions(ios_base::badbit | ios_base::failbit); + m_stream->get(*ss.rdbuf(), termination); // delim byte is not extracted from the stream + m_stream->seekg(1, ios_base::cur); // "extract" delim byte manually + return ss.str(); +} + +/*! + * \brief Reads a terminated string from the current stream. + * + * Advances the current position of the stream by the string length plus one byte + * but maximal by \a maxBytesToRead. + * + * \param maxBytesToRead The maximal number of bytes to read. + * \param termination The value to be recognized as termination. + */ +string BinaryReader::readTerminatedString(size_t maxBytesToRead, byte termination) +{ + unique_ptr buff = make_unique(maxBytesToRead); + for(char *i = buff.get(), *end = i + maxBytesToRead; i < end; ++i) { + m_stream->get(*i); + if(*(reinterpret_cast(i)) == termination) { + return string(buff.get(), i - buff.get()); + } + } + return string(buff.get(), maxBytesToRead); +} + +/*! + * \brief Reads a multibyte-terminated string from the current stream. + * + * Advances the current position of the stream by the string length plus two bytes. + * + * \param termination Specifies the two byte sized big endian value to be recognized as termination. + */ +string BinaryReader::readMultibyteTerminatedStringBE(uint16 termination) +{ + stringstream ss(ios_base::in | ios_base::out | ios_base::binary); + ss.exceptions(ios_base::badbit | ios_base::failbit); + char *delimChars = m_buffer, *buff = m_buffer + 2; + ConversionUtilities::BE::getBytes(termination, delimChars); + do { + m_stream->get(buff[0]); + m_stream->get(buff[1]); + } while(!((buff[0] == delimChars[0]) && (buff[1] == delimChars[1]))); + return ss.str(); +} + +/*! + * \brief Reads a multibyte-terminated string from the current stream. + * + * Advances the current position of the stream by the string length plus two bytes. + * + * \param termination Specifies the two byte sized little endian value to be recognized as termination. + */ +string BinaryReader::readMultibyteTerminatedStringLE(uint16 termination) +{ + stringstream ss(ios_base::in | ios_base::out | ios_base::binary); + ss.exceptions(ios_base::badbit | ios_base::failbit); + char *delimChars = m_buffer, *buff = m_buffer + 2; + ConversionUtilities::LE::getBytes(termination, delimChars); + do { + m_stream->get(buff[0]); + m_stream->get(buff[1]); + } while(!((buff[0] == delimChars[0]) && (buff[1] == delimChars[1]))); + return ss.str(); +} + +/*! + * \brief Reads a terminated string from the current stream. + * + * Advances the current position of the stream by the string length plus two bytes + * but maximal by \a maxBytesToRead. + * + * \param maxBytesToRead The maximal number of bytes to read. + * \param termination The two byte sized big endian value to be recognized as termination. + */ +string BinaryReader::readMultibyteTerminatedStringBE(std::size_t maxBytesToRead, uint16 termination) +{ + unique_ptr buff = make_unique(maxBytesToRead); + char *delimChars = m_buffer; + ConversionUtilities::BE::getBytes(termination, delimChars); + for(char *i = buff.get(), *end = i + maxBytesToRead; (i + 1) < end; i += 2) { + m_stream->get(*i); + m_stream->get(*(i + 1)); + if((*i == delimChars[0]) && (*(i + 1) == delimChars[1])) { + return string(buff.get(), i - buff.get()); + } + } + return string(buff.get(), maxBytesToRead); +} + +/*! + * \brief Reads a terminated string from the current stream. + * + * Advances the current position of the stream by the string length plus two bytes + * but maximal by \a maxBytesToRead. + * + * \param maxBytesToRead The maximal number of bytes to read. + * \param termination The two byte sized little endian value to be recognized as termination. + */ +string BinaryReader::readMultibyteTerminatedStringLE(std::size_t maxBytesToRead, uint16 termination) +{ + unique_ptr buff = make_unique(maxBytesToRead); + char *delimChars = m_buffer; + ConversionUtilities::LE::getBytes(termination, delimChars); + for(char *i = buff.get(), *end = i + maxBytesToRead; (i + 1) < end; i += 2) { + m_stream->get(*i); + m_stream->get(*(i + 1)); + if((*i == delimChars[0]) && (*(i + 1) == delimChars[1])) { + return string(buff.get(), i - buff.get()); + } + } + return string(buff.get(), maxBytesToRead); +} + +/*! + * \brief Reads \a length bytes from the stream and computes the CRC-32 for that block of data. + * + * \remarks Cyclic redundancy check (CRC) is an error-detecting code commonly used in + * digital networks and storage devices to detect accidental changes to raw data. + * \remarks Ogg compatible version + * \sa Cyclic redundancy check - Wikipedia + */ +uint32 BinaryReader::readCrc32(size_t length) +{ + uint32 crc = 0x00; + for(uint32 i = 0; i < length; ++i) { + crc = (crc << 8) ^ crc32Table[((crc >> 24) & 0xff) ^ static_cast(m_stream->get())]; + } + return crc; +} + +/*! + * \brief Reads \a length bytes from the buffer and computes the CRC-32 for that block of data. + * + * \remarks Cyclic redundancy check (CRC) is an error-detecting code commonly used in + * digital networks and storage devices to detect accidental changes to raw data. + * \remarks Ogg compatible version + * \sa Cyclic redundancy check - Wikipedia + */ +uint32 BinaryReader::computeCrc32(const char *buffer, size_t length) +{ + uint32 crc = 0x00; + for(const char *i = buffer, *end = buffer + length; i != end; ++i) { + crc = (crc << 8) ^ crc32Table[((crc >> 24) & 0xff) ^ static_cast(*i)]; + } + return crc; +} + +/*! + * \brief CRC-32 table. + * \remarks Internally used by readCrc32() method. + * \sa readCrc32() + */ +const uint32 BinaryReader::crc32Table[] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + diff --git a/io/binaryreader.h b/io/binaryreader.h index 4f53184..ce85afe 100644 --- a/io/binaryreader.h +++ b/io/binaryreader.h @@ -1,567 +1,565 @@ -#ifndef IOUTILITIES_BINERYREADER_H -#define IOUTILITIES_BINERYREADER_H - -#include "../application/global.h" -#include "../conversion/types.h" -#include "../conversion/binaryconversion.h" - -#include -#include -#include - -namespace IoUtilities -{ -class LIB_EXPORT BinaryReader -{ - -public: - BinaryReader(std::istream *stream); - BinaryReader(const BinaryReader &other); - BinaryReader & operator=(const BinaryReader & rhs) = delete; - ~BinaryReader(); - - const std::istream *stream() const; - std::istream *stream(); - void setStream(std::istream *stream, bool giveOwnership = false); - bool hasOwnership() const; - void giveOwnership(); - void detatchOwnership(); - bool fail() const; - bool eof() const; - bool canRead() const; - std::istream::pos_type readStreamsize(); - void read(char *buffer, std::streamsize length); - void read(byte *buffer, std::streamsize length); - void read(std::vector &buffer, std::streamsize length); - int16 readInt16BE(); - uint16 readUInt16BE(); - int32 readInt24BE(); - uint32 readUInt24BE(); - int32 readInt32BE(); - uint32 readUInt32BE(); - int64 readInt40BE(); - uint64 readUInt40BE(); - int64 readInt56BE(); - uint64 readUInt56BE(); - int64 readInt64BE(); - uint64 readUInt64BE(); - float32 readFloat32BE(); - float64 readFloat64BE(); - int16 readInt16LE(); - uint16 readUInt16LE(); - int32 readInt24LE(); - uint32 readUInt24LE(); - int32 readInt32LE(); - uint32 readUInt32LE(); - int64 readInt40LE(); - uint64 readUInt40LE(); - int64 readInt56LE(); - uint64 readUInt56LE(); - int64 readInt64LE(); - uint64 readUInt64LE(); - float32 readFloat32LE(); - float64 readFloat64LE(); - char readChar(); - byte readByte(); - bool readBool(); - std::string readLengthPrefixedString(); - std::string readString(std::size_t length); - std::string readTerminatedString(byte termination = 0); - std::string readTerminatedString(size_t maxBytesToRead, byte termination = 0); - std::string readMultibyteTerminatedStringBE(uint16 termination = 0); - std::string readMultibyteTerminatedStringLE(uint16 termination = 0); - std::string readMultibyteTerminatedStringBE(std::size_t maxBytesToRead, uint16 termination = 0); - std::string readMultibyteTerminatedStringLE(std::size_t maxBytesToRead, uint16 termination = 0); - uint32 readSynchsafeUInt32BE(); - float32 readFixed8BE(); - float32 readFixed16BE(); - uint32 readSynchsafeUInt32LE(); - float32 readFixed8LE(); - float32 readFixed16LE(); - uint32 readCrc32(std::size_t length); - static uint32 computeCrc32(const char *buffer, std::size_t length); - static const uint32 crc32Table[]; - -private: - std::istream *m_stream; - bool m_ownership; - char m_buffer[8]; -}; - -/*! - * \brief Returns a pointer to the stream the reader will read from when calling one of the read-methods. - * - * \sa setStream() - */ -inline std::istream *BinaryReader::stream() -{ - return m_stream; -} - -/*! - * \brief Returns a pointer to the stream the reader will read from when calling one of the read-methods. - * - * \sa setStream() - */ -inline const std::istream *BinaryReader::stream() const -{ - return m_stream; -} - -/*! - * \brief Returns whether the reader takes ownership over the assigned stream. - * - * \sa setStream() - * \sa giveOwnership() - * \sa detatchOwnership() - */ -inline bool BinaryReader::hasOwnership() const -{ - return m_ownership; -} - -/*! - * \brief The reader will take ownership over the assigned stream. - * - * \sa setStream() - * \sa detatchOwnership() - * \sa hasOwnership() - */ -inline void BinaryReader::giveOwnership() -{ - if(m_stream) { - m_ownership = true; - } -} - -/*! - * \brief The reader will not take ownership over the assigned stream. - * - * \sa setStream() - * \sa giveOwnership() - * \sa hasOwnership() - */ -inline void BinaryReader::detatchOwnership() -{ - m_ownership = false; -} - -/*! - * \brief Returns an indication whether the fail bit of the assigned stream is set. - */ -inline bool BinaryReader::fail() const -{ - return m_stream ? m_stream->fail() : false; -} - -/*! - * \brief Returns an indication whether the end-of-stream bit of the assigned stream is set. - */ -inline bool BinaryReader::eof() const -{ - return m_stream && m_stream->eof(); -} - -/*! - * \brief Returns an indication whether a stream is assigned the reader can read from. - */ -inline bool BinaryReader::canRead() const -{ - return m_stream && m_stream->good(); -} - -/*! - * \brief Reads the specified number of characters from the stream in the character array. - */ -inline void BinaryReader::read(char *buffer, std::streamsize length) -{ - m_stream->read(buffer, length); -} - -/*! - * \brief Reads the specified number of bytes from the stream in the character array. - */ -inline void BinaryReader::read(byte *buffer, std::streamsize length) -{ - m_stream->read(reinterpret_cast(buffer), length); -} - -/*! - * \brief Reads the specified number of bytes from the stream in the specified \a buffer. - */ -inline void BinaryReader::read(std::vector &buffer, std::streamsize length) -{ - buffer.resize(length); - m_stream->read(buffer.data(), length); -} - -/*! - * \brief Reads a 16-bit big endian signed integer from the current stream and advances the current position of the stream by two bytes. - */ -inline int16 BinaryReader::readInt16BE() -{ - m_stream->read(m_buffer, sizeof(int16)); - return ConversionUtilities::BE::toInt16(m_buffer); -} - -/*! - * \brief Reads a 16-bit big endian unsigned integer from the current stream and advances the current position of the stream by two bytes. - */ -inline uint16 BinaryReader::readUInt16BE() -{ - m_stream->read(m_buffer, sizeof(uint16)); - return ConversionUtilities::BE::toUInt16(m_buffer); -} - -/*! - * \brief Reads a 24-bit big endian signed integer from the current stream and advances the current position of the stream by three bytes. - */ -inline int32 BinaryReader::readInt24BE() -{ - *m_buffer = 0; - m_stream->read(m_buffer + 1, 3); - auto val = ConversionUtilities::BE::toInt32(m_buffer); - if(val >= 0x800000) { - val = -(0x1000000 - val); - } - return val; -} - -/*! - * \brief Reads a 24-bit big endian unsigned integer from the current stream and advances the current position of the stream by three bytes. - */ -inline uint32 BinaryReader::readUInt24BE() -{ - *m_buffer = 0; - m_stream->read(m_buffer + 1, 3); - return ConversionUtilities::BE::toUInt32(m_buffer); -} - -/*! - * \brief Reads a 32-bit big endian signed integer from the current stream and advances the current position of the stream by four bytes. - */ -inline int32 BinaryReader::readInt32BE() -{ - m_stream->read(m_buffer, sizeof(int32)); - return ConversionUtilities::BE::toInt32(m_buffer); -} - -/*! - * \brief Reads a 32-bit big endian unsigned integer from the current stream and advances the current position of the stream by four bytes. - */ -inline uint32 BinaryReader::readUInt32BE() -{ - m_stream->read(m_buffer, sizeof(uint32)); - return ConversionUtilities::BE::toUInt32(m_buffer); -} - -/*! - * \brief Reads a 40-bit big endian signed integer from the current stream and advances the current position of the stream by five bytes. - */ -inline int64 BinaryReader::readInt40BE() -{ - *m_buffer = *(m_buffer + 1) = *(m_buffer + 2) = 0; - m_stream->read(m_buffer + 3, 5); - auto val = ConversionUtilities::BE::toInt64(m_buffer); - if(val >= 0x8000000000) { - val = -(0x10000000000 - val); - } - return val; -} - -/*! - * \brief Reads a 40-bit big endian unsigned integer from the current stream and advances the current position of the stream by five bytes. - */ -inline uint64 BinaryReader::readUInt40BE() -{ - *m_buffer = *(m_buffer + 1) = *(m_buffer + 2) = 0; - m_stream->read(m_buffer + 3, 5); - return ConversionUtilities::BE::toUInt64(m_buffer); -} - -/*! - * \brief Reads a 56-bit big endian signed integer from the current stream and advances the current position of the stream by seven bytes. - */ -inline int64 BinaryReader::readInt56BE() -{ - *m_buffer = 0; - m_stream->read(m_buffer + 1, 7); - auto val = ConversionUtilities::BE::toInt64(m_buffer); - if(val >= 0x80000000000000) { - val = -(0x100000000000000 - val); - } - return val; -} - -/*! - * \brief Reads a 56-bit big endian unsigned integer from the current stream and advances the current position of the stream by seven bytes. - */ -inline uint64 BinaryReader::readUInt56BE() -{ - *m_buffer = 0; - m_stream->read(m_buffer + 1, 7); - return ConversionUtilities::BE::toUInt64(m_buffer); -} - -/*! - * \brief Reads a 64-bit big endian signed integer from the current stream and advances the current position of the stream by eight bytes. - */ -inline int64 BinaryReader::readInt64BE() -{ - m_stream->read(m_buffer, sizeof(int64)); - return ConversionUtilities::BE::toInt64(m_buffer); -} - -/*! - * \brief Reads a 64-bit big endian unsigned integer from the current stream and advances the current position of the stream by eight bytes. - */ -inline uint64 BinaryReader::readUInt64BE() -{ - m_stream->read(m_buffer, sizeof(uint64)); - return ConversionUtilities::BE::toUInt64(m_buffer); -} - -/*! - * \brief Reads a 32-bit big endian floating point value from the current stream and advances the current position of the stream by four bytes. - */ -inline float32 BinaryReader::readFloat32BE() -{ - m_stream->read(m_buffer, sizeof(float32)); - return ConversionUtilities::BE::toFloat32(m_buffer); -} - -/*! - * \brief Reads a 64-bit big endian floating point value from the current stream and advances the current position of the stream by eight bytes. - */ -inline float64 BinaryReader::readFloat64BE() -{ - m_stream->read(m_buffer, sizeof(float64)); - return ConversionUtilities::BE::toFloat64(m_buffer); -} - -/*! - * \brief Reads a 16-bit little endian signed integer from the current stream and advances the current position of the stream by two bytes. - */ -inline int16 BinaryReader::readInt16LE() -{ - m_stream->read(m_buffer, sizeof(int16)); - return ConversionUtilities::LE::toInt16(m_buffer); -} - -/*! - * \brief Reads a 16-bit little endian unsigned integer from the current stream and advances the current position of the stream by two bytes. - */ -inline uint16 BinaryReader::readUInt16LE() -{ - m_stream->read(m_buffer, sizeof(uint16)); - return ConversionUtilities::LE::toUInt16(m_buffer); -} - -/*! - * \brief Reads a 24-bit little endian signed integer from the current stream and advances the current position of the stream by three bytes. - */ -inline int32 BinaryReader::readInt24LE() -{ - *(m_buffer + 3) = 0; - m_stream->read(m_buffer, 3); - auto val = ConversionUtilities::LE::toInt32(m_buffer); - if(val >= 0x800000) { - val = -(0x1000000 - val); - } - return val; -} - -/*! - * \brief Reads a 24-bit little endian unsigned integer from the current stream and advances the current position of the stream by three bytes. - */ -inline uint32 BinaryReader::readUInt24LE() -{ - *(m_buffer + 3) = 0; - m_stream->read(m_buffer, 3); - return ConversionUtilities::LE::toUInt32(m_buffer); -} - -/*! - * \brief Reads a 32-bit little endian signed integer from the current stream and advances the current position of the stream by four bytes. - */ -inline int32 BinaryReader::readInt32LE() -{ - m_stream->read(m_buffer, sizeof(int32)); - return ConversionUtilities::LE::toInt32(m_buffer); -} - -/*! - * \brief Reads a 32-bit little endian unsigned integer from the current stream and advances the current position of the stream by four bytes. - */ -inline uint32 BinaryReader::readUInt32LE() -{ - m_stream->read(m_buffer, sizeof(uint32)); - return ConversionUtilities::LE::toUInt32(m_buffer); -} - -/*! - * \brief Reads a 40-bit little endian signed integer from the current stream and advances the current position of the stream by five bytes. - */ -inline int64 BinaryReader::readInt40LE() -{ - *(m_buffer + 5) = *(m_buffer + 6) = *(m_buffer + 7) = 0; - m_stream->read(m_buffer, 5); - auto val = ConversionUtilities::LE::toInt64(m_buffer); - if(val >= 0x8000000000) { - val = -(0x10000000000 - val); - } - return val; -} - -/*! - * \brief Reads a 40-bit little endian unsigned integer from the current stream and advances the current position of the stream by five bytes. - */ -inline uint64 BinaryReader::readUInt40LE() -{ - *(m_buffer + 5) = *(m_buffer + 6) = *(m_buffer + 7) = 0; - m_stream->read(m_buffer, 5); - return ConversionUtilities::LE::toUInt64(m_buffer); -} - -/*! - * \brief Reads a 56-bit little endian signed integer from the current stream and advances the current position of the stream by seven bytes. - */ -inline int64 BinaryReader::readInt56LE() -{ - *(m_buffer + 7) = 0; - m_stream->read(m_buffer, 7); - auto val = ConversionUtilities::LE::toInt64(m_buffer); - if(val >= 0x80000000000000) { - val = -(0x100000000000000 - val); - } - return val; -} - -/*! - * \brief Reads a 56-bit little endian unsigned integer from the current stream and advances the current position of the stream by seven bytes. - */ -inline uint64 BinaryReader::readUInt56LE() -{ - *(m_buffer + 7) = 0; - m_stream->read(m_buffer, 7); - return ConversionUtilities::LE::toUInt64(m_buffer); -} - -/*! - * \brief Reads a 64-bit little endian signed integer from the current stream and advances the current position of the stream by eight bytes. - */ -inline int64 BinaryReader::readInt64LE() -{ - m_stream->read(m_buffer, sizeof(int64)); - return ConversionUtilities::LE::toInt64(m_buffer); -} - -/*! - * \brief Reads a 64-bit little endian unsigned integer from the current stream and advances the current position of the stream by eight bytes. - */ -inline uint64 BinaryReader::readUInt64LE() -{ - m_stream->read(m_buffer, sizeof(uint64)); - return ConversionUtilities::LE::toUInt64(m_buffer); -} - -/*! - * \brief Reads a 32-bit little endian floating point value from the current stream and advances the current position of the stream by four bytes. - */ -inline float32 BinaryReader::readFloat32LE() -{ - m_stream->read(m_buffer, sizeof(float32)); - return ConversionUtilities::LE::toFloat32(m_buffer); -} - -/*! - * \brief Reads a 64-bit little endian floating point value from the current stream and advances the current position of the stream by eight bytes. - */ -inline float64 BinaryReader::readFloat64LE() -{ - m_stream->read(m_buffer, sizeof(float64)); - return ConversionUtilities::LE::toFloat64(m_buffer); -} - -/*! - * \brief Reads a single character from the current stream and advances the current position of the stream by one byte. - */ -inline char BinaryReader::readChar() -{ - m_stream->read(m_buffer, sizeof(char)); - return m_buffer[0]; -} - -/*! - * \brief Reads a single byte/unsigned character from the current stream and advances the current position of the stream by one byte. - */ -inline byte BinaryReader::readByte() -{ - m_stream->read(m_buffer, sizeof(char)); - return static_cast(m_buffer[0]); -} - -/*! - * \brief Reads a boolean value from the current stream and advances the current position of the stream by one byte. - * \sa IoUtilities::BitReader - */ -inline bool BinaryReader::readBool() -{ - return readByte() != 0; -} - -/*! - * \brief Reads a 32-bit big endian synchsafe integer from the current stream and advances the current position of the stream by four bytes. - * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. - * \sa ID3 tag version 2.4.0 - Main Structure - */ -inline uint32 BinaryReader::readSynchsafeUInt32BE() -{ - return ConversionUtilities::toNormalInt(readUInt32BE()); -} - -/*! - * \brief Reads a 8.8 fixed point big endian representation from the current stream and returns it as 32-bit floating point value. - */ -inline float32 BinaryReader::readFixed8BE() -{ - return ConversionUtilities::toFloat32(readUInt16BE()); -} - -/*! - * \brief Reads a 16.16 fixed point big endian representation from the current stream and returns it as 32-bit floating point value. - */ -inline float32 BinaryReader::readFixed16BE() -{ - return ConversionUtilities::toFloat32(readUInt32BE()); -} - -/*! - * \brief Reads a 32-bit little endian synchsafe integer from the current stream and advances the current position of the stream by four bytes. - * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. - * \sa ID3 tag version 2.4.0 - Main Structure - */ -inline uint32 BinaryReader::readSynchsafeUInt32LE() -{ - return ConversionUtilities::toNormalInt(readUInt32LE()); -} - -/*! - * \brief Reads a 8.8 fixed point little endian representation from the current stream and returns it as 32-bit floating point value. - */ -inline float32 BinaryReader::readFixed8LE() -{ - return ConversionUtilities::toFloat32(readUInt16LE()); -} - -/*! - * \brief Reads a 16.16 fixed point little endian representation from the current stream and returns it as 32-bit floating point value. - */ -inline float32 BinaryReader::readFixed16LE() -{ - return ConversionUtilities::toFloat32(readUInt32LE()); -} - -} - -#endif // IOUTILITIES_BINERYREADER_H +#ifndef IOUTILITIES_BINERYREADER_H +#define IOUTILITIES_BINERYREADER_H + +#include "../conversion/binaryconversion.h" + +#include +#include +#include + +namespace IoUtilities +{ +class CPP_UTILITIES_EXPORT BinaryReader +{ + +public: + BinaryReader(std::istream *stream); + BinaryReader(const BinaryReader &other); + BinaryReader & operator=(const BinaryReader & rhs) = delete; + ~BinaryReader(); + + const std::istream *stream() const; + std::istream *stream(); + void setStream(std::istream *stream, bool giveOwnership = false); + bool hasOwnership() const; + void giveOwnership(); + void detatchOwnership(); + bool fail() const; + bool eof() const; + bool canRead() const; + std::istream::pos_type readStreamsize(); + void read(char *buffer, std::streamsize length); + void read(byte *buffer, std::streamsize length); + void read(std::vector &buffer, std::streamsize length); + int16 readInt16BE(); + uint16 readUInt16BE(); + int32 readInt24BE(); + uint32 readUInt24BE(); + int32 readInt32BE(); + uint32 readUInt32BE(); + int64 readInt40BE(); + uint64 readUInt40BE(); + int64 readInt56BE(); + uint64 readUInt56BE(); + int64 readInt64BE(); + uint64 readUInt64BE(); + float32 readFloat32BE(); + float64 readFloat64BE(); + int16 readInt16LE(); + uint16 readUInt16LE(); + int32 readInt24LE(); + uint32 readUInt24LE(); + int32 readInt32LE(); + uint32 readUInt32LE(); + int64 readInt40LE(); + uint64 readUInt40LE(); + int64 readInt56LE(); + uint64 readUInt56LE(); + int64 readInt64LE(); + uint64 readUInt64LE(); + float32 readFloat32LE(); + float64 readFloat64LE(); + char readChar(); + byte readByte(); + bool readBool(); + std::string readLengthPrefixedString(); + std::string readString(std::size_t length); + std::string readTerminatedString(byte termination = 0); + std::string readTerminatedString(size_t maxBytesToRead, byte termination = 0); + std::string readMultibyteTerminatedStringBE(uint16 termination = 0); + std::string readMultibyteTerminatedStringLE(uint16 termination = 0); + std::string readMultibyteTerminatedStringBE(std::size_t maxBytesToRead, uint16 termination = 0); + std::string readMultibyteTerminatedStringLE(std::size_t maxBytesToRead, uint16 termination = 0); + uint32 readSynchsafeUInt32BE(); + float32 readFixed8BE(); + float32 readFixed16BE(); + uint32 readSynchsafeUInt32LE(); + float32 readFixed8LE(); + float32 readFixed16LE(); + uint32 readCrc32(std::size_t length); + static uint32 computeCrc32(const char *buffer, std::size_t length); + static const uint32 crc32Table[]; + +private: + std::istream *m_stream; + bool m_ownership; + char m_buffer[8]; +}; + +/*! + * \brief Returns a pointer to the stream the reader will read from when calling one of the read-methods. + * + * \sa setStream() + */ +inline std::istream *BinaryReader::stream() +{ + return m_stream; +} + +/*! + * \brief Returns a pointer to the stream the reader will read from when calling one of the read-methods. + * + * \sa setStream() + */ +inline const std::istream *BinaryReader::stream() const +{ + return m_stream; +} + +/*! + * \brief Returns whether the reader takes ownership over the assigned stream. + * + * \sa setStream() + * \sa giveOwnership() + * \sa detatchOwnership() + */ +inline bool BinaryReader::hasOwnership() const +{ + return m_ownership; +} + +/*! + * \brief The reader will take ownership over the assigned stream. + * + * \sa setStream() + * \sa detatchOwnership() + * \sa hasOwnership() + */ +inline void BinaryReader::giveOwnership() +{ + if(m_stream) { + m_ownership = true; + } +} + +/*! + * \brief The reader will not take ownership over the assigned stream. + * + * \sa setStream() + * \sa giveOwnership() + * \sa hasOwnership() + */ +inline void BinaryReader::detatchOwnership() +{ + m_ownership = false; +} + +/*! + * \brief Returns an indication whether the fail bit of the assigned stream is set. + */ +inline bool BinaryReader::fail() const +{ + return m_stream ? m_stream->fail() : false; +} + +/*! + * \brief Returns an indication whether the end-of-stream bit of the assigned stream is set. + */ +inline bool BinaryReader::eof() const +{ + return m_stream && m_stream->eof(); +} + +/*! + * \brief Returns an indication whether a stream is assigned the reader can read from. + */ +inline bool BinaryReader::canRead() const +{ + return m_stream && m_stream->good(); +} + +/*! + * \brief Reads the specified number of characters from the stream in the character array. + */ +inline void BinaryReader::read(char *buffer, std::streamsize length) +{ + m_stream->read(buffer, length); +} + +/*! + * \brief Reads the specified number of bytes from the stream in the character array. + */ +inline void BinaryReader::read(byte *buffer, std::streamsize length) +{ + m_stream->read(reinterpret_cast(buffer), length); +} + +/*! + * \brief Reads the specified number of bytes from the stream in the specified \a buffer. + */ +inline void BinaryReader::read(std::vector &buffer, std::streamsize length) +{ + buffer.resize(length); + m_stream->read(buffer.data(), length); +} + +/*! + * \brief Reads a 16-bit big endian signed integer from the current stream and advances the current position of the stream by two bytes. + */ +inline int16 BinaryReader::readInt16BE() +{ + m_stream->read(m_buffer, sizeof(int16)); + return ConversionUtilities::BE::toInt16(m_buffer); +} + +/*! + * \brief Reads a 16-bit big endian unsigned integer from the current stream and advances the current position of the stream by two bytes. + */ +inline uint16 BinaryReader::readUInt16BE() +{ + m_stream->read(m_buffer, sizeof(uint16)); + return ConversionUtilities::BE::toUInt16(m_buffer); +} + +/*! + * \brief Reads a 24-bit big endian signed integer from the current stream and advances the current position of the stream by three bytes. + */ +inline int32 BinaryReader::readInt24BE() +{ + *m_buffer = 0; + m_stream->read(m_buffer + 1, 3); + auto val = ConversionUtilities::BE::toInt32(m_buffer); + if(val >= 0x800000) { + val = -(0x1000000 - val); + } + return val; +} + +/*! + * \brief Reads a 24-bit big endian unsigned integer from the current stream and advances the current position of the stream by three bytes. + */ +inline uint32 BinaryReader::readUInt24BE() +{ + *m_buffer = 0; + m_stream->read(m_buffer + 1, 3); + return ConversionUtilities::BE::toUInt32(m_buffer); +} + +/*! + * \brief Reads a 32-bit big endian signed integer from the current stream and advances the current position of the stream by four bytes. + */ +inline int32 BinaryReader::readInt32BE() +{ + m_stream->read(m_buffer, sizeof(int32)); + return ConversionUtilities::BE::toInt32(m_buffer); +} + +/*! + * \brief Reads a 32-bit big endian unsigned integer from the current stream and advances the current position of the stream by four bytes. + */ +inline uint32 BinaryReader::readUInt32BE() +{ + m_stream->read(m_buffer, sizeof(uint32)); + return ConversionUtilities::BE::toUInt32(m_buffer); +} + +/*! + * \brief Reads a 40-bit big endian signed integer from the current stream and advances the current position of the stream by five bytes. + */ +inline int64 BinaryReader::readInt40BE() +{ + *m_buffer = *(m_buffer + 1) = *(m_buffer + 2) = 0; + m_stream->read(m_buffer + 3, 5); + auto val = ConversionUtilities::BE::toInt64(m_buffer); + if(val >= 0x8000000000) { + val = -(0x10000000000 - val); + } + return val; +} + +/*! + * \brief Reads a 40-bit big endian unsigned integer from the current stream and advances the current position of the stream by five bytes. + */ +inline uint64 BinaryReader::readUInt40BE() +{ + *m_buffer = *(m_buffer + 1) = *(m_buffer + 2) = 0; + m_stream->read(m_buffer + 3, 5); + return ConversionUtilities::BE::toUInt64(m_buffer); +} + +/*! + * \brief Reads a 56-bit big endian signed integer from the current stream and advances the current position of the stream by seven bytes. + */ +inline int64 BinaryReader::readInt56BE() +{ + *m_buffer = 0; + m_stream->read(m_buffer + 1, 7); + auto val = ConversionUtilities::BE::toInt64(m_buffer); + if(val >= 0x80000000000000) { + val = -(0x100000000000000 - val); + } + return val; +} + +/*! + * \brief Reads a 56-bit big endian unsigned integer from the current stream and advances the current position of the stream by seven bytes. + */ +inline uint64 BinaryReader::readUInt56BE() +{ + *m_buffer = 0; + m_stream->read(m_buffer + 1, 7); + return ConversionUtilities::BE::toUInt64(m_buffer); +} + +/*! + * \brief Reads a 64-bit big endian signed integer from the current stream and advances the current position of the stream by eight bytes. + */ +inline int64 BinaryReader::readInt64BE() +{ + m_stream->read(m_buffer, sizeof(int64)); + return ConversionUtilities::BE::toInt64(m_buffer); +} + +/*! + * \brief Reads a 64-bit big endian unsigned integer from the current stream and advances the current position of the stream by eight bytes. + */ +inline uint64 BinaryReader::readUInt64BE() +{ + m_stream->read(m_buffer, sizeof(uint64)); + return ConversionUtilities::BE::toUInt64(m_buffer); +} + +/*! + * \brief Reads a 32-bit big endian floating point value from the current stream and advances the current position of the stream by four bytes. + */ +inline float32 BinaryReader::readFloat32BE() +{ + m_stream->read(m_buffer, sizeof(float32)); + return ConversionUtilities::BE::toFloat32(m_buffer); +} + +/*! + * \brief Reads a 64-bit big endian floating point value from the current stream and advances the current position of the stream by eight bytes. + */ +inline float64 BinaryReader::readFloat64BE() +{ + m_stream->read(m_buffer, sizeof(float64)); + return ConversionUtilities::BE::toFloat64(m_buffer); +} + +/*! + * \brief Reads a 16-bit little endian signed integer from the current stream and advances the current position of the stream by two bytes. + */ +inline int16 BinaryReader::readInt16LE() +{ + m_stream->read(m_buffer, sizeof(int16)); + return ConversionUtilities::LE::toInt16(m_buffer); +} + +/*! + * \brief Reads a 16-bit little endian unsigned integer from the current stream and advances the current position of the stream by two bytes. + */ +inline uint16 BinaryReader::readUInt16LE() +{ + m_stream->read(m_buffer, sizeof(uint16)); + return ConversionUtilities::LE::toUInt16(m_buffer); +} + +/*! + * \brief Reads a 24-bit little endian signed integer from the current stream and advances the current position of the stream by three bytes. + */ +inline int32 BinaryReader::readInt24LE() +{ + *(m_buffer + 3) = 0; + m_stream->read(m_buffer, 3); + auto val = ConversionUtilities::LE::toInt32(m_buffer); + if(val >= 0x800000) { + val = -(0x1000000 - val); + } + return val; +} + +/*! + * \brief Reads a 24-bit little endian unsigned integer from the current stream and advances the current position of the stream by three bytes. + */ +inline uint32 BinaryReader::readUInt24LE() +{ + *(m_buffer + 3) = 0; + m_stream->read(m_buffer, 3); + return ConversionUtilities::LE::toUInt32(m_buffer); +} + +/*! + * \brief Reads a 32-bit little endian signed integer from the current stream and advances the current position of the stream by four bytes. + */ +inline int32 BinaryReader::readInt32LE() +{ + m_stream->read(m_buffer, sizeof(int32)); + return ConversionUtilities::LE::toInt32(m_buffer); +} + +/*! + * \brief Reads a 32-bit little endian unsigned integer from the current stream and advances the current position of the stream by four bytes. + */ +inline uint32 BinaryReader::readUInt32LE() +{ + m_stream->read(m_buffer, sizeof(uint32)); + return ConversionUtilities::LE::toUInt32(m_buffer); +} + +/*! + * \brief Reads a 40-bit little endian signed integer from the current stream and advances the current position of the stream by five bytes. + */ +inline int64 BinaryReader::readInt40LE() +{ + *(m_buffer + 5) = *(m_buffer + 6) = *(m_buffer + 7) = 0; + m_stream->read(m_buffer, 5); + auto val = ConversionUtilities::LE::toInt64(m_buffer); + if(val >= 0x8000000000) { + val = -(0x10000000000 - val); + } + return val; +} + +/*! + * \brief Reads a 40-bit little endian unsigned integer from the current stream and advances the current position of the stream by five bytes. + */ +inline uint64 BinaryReader::readUInt40LE() +{ + *(m_buffer + 5) = *(m_buffer + 6) = *(m_buffer + 7) = 0; + m_stream->read(m_buffer, 5); + return ConversionUtilities::LE::toUInt64(m_buffer); +} + +/*! + * \brief Reads a 56-bit little endian signed integer from the current stream and advances the current position of the stream by seven bytes. + */ +inline int64 BinaryReader::readInt56LE() +{ + *(m_buffer + 7) = 0; + m_stream->read(m_buffer, 7); + auto val = ConversionUtilities::LE::toInt64(m_buffer); + if(val >= 0x80000000000000) { + val = -(0x100000000000000 - val); + } + return val; +} + +/*! + * \brief Reads a 56-bit little endian unsigned integer from the current stream and advances the current position of the stream by seven bytes. + */ +inline uint64 BinaryReader::readUInt56LE() +{ + *(m_buffer + 7) = 0; + m_stream->read(m_buffer, 7); + return ConversionUtilities::LE::toUInt64(m_buffer); +} + +/*! + * \brief Reads a 64-bit little endian signed integer from the current stream and advances the current position of the stream by eight bytes. + */ +inline int64 BinaryReader::readInt64LE() +{ + m_stream->read(m_buffer, sizeof(int64)); + return ConversionUtilities::LE::toInt64(m_buffer); +} + +/*! + * \brief Reads a 64-bit little endian unsigned integer from the current stream and advances the current position of the stream by eight bytes. + */ +inline uint64 BinaryReader::readUInt64LE() +{ + m_stream->read(m_buffer, sizeof(uint64)); + return ConversionUtilities::LE::toUInt64(m_buffer); +} + +/*! + * \brief Reads a 32-bit little endian floating point value from the current stream and advances the current position of the stream by four bytes. + */ +inline float32 BinaryReader::readFloat32LE() +{ + m_stream->read(m_buffer, sizeof(float32)); + return ConversionUtilities::LE::toFloat32(m_buffer); +} + +/*! + * \brief Reads a 64-bit little endian floating point value from the current stream and advances the current position of the stream by eight bytes. + */ +inline float64 BinaryReader::readFloat64LE() +{ + m_stream->read(m_buffer, sizeof(float64)); + return ConversionUtilities::LE::toFloat64(m_buffer); +} + +/*! + * \brief Reads a single character from the current stream and advances the current position of the stream by one byte. + */ +inline char BinaryReader::readChar() +{ + m_stream->read(m_buffer, sizeof(char)); + return m_buffer[0]; +} + +/*! + * \brief Reads a single byte/unsigned character from the current stream and advances the current position of the stream by one byte. + */ +inline byte BinaryReader::readByte() +{ + m_stream->read(m_buffer, sizeof(char)); + return static_cast(m_buffer[0]); +} + +/*! + * \brief Reads a boolean value from the current stream and advances the current position of the stream by one byte. + * \sa IoUtilities::BitReader + */ +inline bool BinaryReader::readBool() +{ + return readByte() != 0; +} + +/*! + * \brief Reads a 32-bit big endian synchsafe integer from the current stream and advances the current position of the stream by four bytes. + * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. + * \sa ID3 tag version 2.4.0 - Main Structure + */ +inline uint32 BinaryReader::readSynchsafeUInt32BE() +{ + return ConversionUtilities::toNormalInt(readUInt32BE()); +} + +/*! + * \brief Reads a 8.8 fixed point big endian representation from the current stream and returns it as 32-bit floating point value. + */ +inline float32 BinaryReader::readFixed8BE() +{ + return ConversionUtilities::toFloat32(readUInt16BE()); +} + +/*! + * \brief Reads a 16.16 fixed point big endian representation from the current stream and returns it as 32-bit floating point value. + */ +inline float32 BinaryReader::readFixed16BE() +{ + return ConversionUtilities::toFloat32(readUInt32BE()); +} + +/*! + * \brief Reads a 32-bit little endian synchsafe integer from the current stream and advances the current position of the stream by four bytes. + * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. + * \sa ID3 tag version 2.4.0 - Main Structure + */ +inline uint32 BinaryReader::readSynchsafeUInt32LE() +{ + return ConversionUtilities::toNormalInt(readUInt32LE()); +} + +/*! + * \brief Reads a 8.8 fixed point little endian representation from the current stream and returns it as 32-bit floating point value. + */ +inline float32 BinaryReader::readFixed8LE() +{ + return ConversionUtilities::toFloat32(readUInt16LE()); +} + +/*! + * \brief Reads a 16.16 fixed point little endian representation from the current stream and returns it as 32-bit floating point value. + */ +inline float32 BinaryReader::readFixed16LE() +{ + return ConversionUtilities::toFloat32(readUInt32LE()); +} + +} + +#endif // IOUTILITIES_BINERYREADER_H diff --git a/io/binarywriter.cpp b/io/binarywriter.cpp index 3105368..8acda42 100644 --- a/io/binarywriter.cpp +++ b/io/binarywriter.cpp @@ -1,95 +1,95 @@ -#include "./binarywriter.h" - -#include "../conversion/conversionexception.h" - -#include -#include - -using namespace std; -using namespace IoUtilities; -using namespace ConversionUtilities; - -/*! - * \class IoUtilities::BinaryWriter - * \brief Writes primitive data types to a std::ostream. - * \remarks Supports both, little endian and big endian. - */ - -/*! - * \brief Constructs a new BinaryWriter. - * \param stream Specifies the stream to write to. - */ -BinaryWriter::BinaryWriter(ostream *stream) : - m_stream(stream), - m_ownership(false) -{} - -/*! - * \brief Copies the specified BinaryWriter. - * \remarks The copy will not take ownership over the stream. - */ -BinaryWriter::BinaryWriter(const BinaryWriter &other) : - m_stream(other.m_stream), - m_ownership(false) -{} - -/*! - * \brief Destroys the BinaryWriter. - */ -BinaryWriter::~BinaryWriter() -{ - if(m_ownership) { - delete m_stream; - } -} - -/*! - * \brief Assigns the stream the writer will write to when calling one of the write-methods. - * - * You can assign a null pointer when ensuring that none of the write-methods is called - * until a stream is assigned. - * - * \param stream Specifies the stream to be assigned. - * \param giveOwnership Indicated whether the reader should take ownership (default is false). - * - * \sa setStream() - */ -void BinaryWriter::setStream(ostream *stream, bool giveOwnership) -{ - if(m_ownership) { - delete m_stream; - } - if(stream) { - m_stream = stream; - m_ownership = giveOwnership; - } else { - m_stream = nullptr; - m_ownership = false; - } -} - -/*! - * \brief Writes the length of a string and the string itself to the current stream. - * - * Advances the current position of the stream by the length of the string plus the size of the length prefix. - */ -void BinaryWriter::writeLengthPrefixedString(const string &value) -{ - size_t length = value.length(); - if(length < 0x80) { - m_buffer[0] = 0x80 | length; - m_stream->write(m_buffer, 1); - } else if(length < 0x4000) { - BE::getBytes(static_cast(0x4000 | length), m_buffer); - m_stream->write(m_buffer, 2); - } else if(length < 0x200000) { - BE::getBytes(static_cast(0x200000 | length), m_buffer); - m_stream->write(m_buffer + 1, 3); - } else if(length < 0x10000000) { - BE::getBytes(static_cast(0x10000000 | length), m_buffer); - m_stream->write(m_buffer, 4); - } else { - throw ConversionException("The size of the string exceeds the maximum."); - } - m_stream->write(value.c_str(), length); -} +#include "./binarywriter.h" + +#include "../conversion/conversionexception.h" + +#include +#include + +using namespace std; +using namespace IoUtilities; +using namespace ConversionUtilities; + +/*! + * \class IoUtilities::BinaryWriter + * \brief Writes primitive data types to a std::ostream. + * \remarks Supports both, little endian and big endian. + */ + +/*! + * \brief Constructs a new BinaryWriter. + * \param stream Specifies the stream to write to. + */ +BinaryWriter::BinaryWriter(ostream *stream) : + m_stream(stream), + m_ownership(false) +{} + +/*! + * \brief Copies the specified BinaryWriter. + * \remarks The copy will not take ownership over the stream. + */ +BinaryWriter::BinaryWriter(const BinaryWriter &other) : + m_stream(other.m_stream), + m_ownership(false) +{} + +/*! + * \brief Destroys the BinaryWriter. + */ +BinaryWriter::~BinaryWriter() +{ + if(m_ownership) { + delete m_stream; + } +} + +/*! + * \brief Assigns the stream the writer will write to when calling one of the write-methods. + * + * You can assign a null pointer when ensuring that none of the write-methods is called + * until a stream is assigned. + * + * \param stream Specifies the stream to be assigned. + * \param giveOwnership Indicated whether the reader should take ownership (default is false). + * + * \sa setStream() + */ +void BinaryWriter::setStream(ostream *stream, bool giveOwnership) +{ + if(m_ownership) { + delete m_stream; + } + if(stream) { + m_stream = stream; + m_ownership = giveOwnership; + } else { + m_stream = nullptr; + m_ownership = false; + } +} + +/*! + * \brief Writes the length of a string and the string itself to the current stream. + * + * Advances the current position of the stream by the length of the string plus the size of the length prefix. + */ +void BinaryWriter::writeLengthPrefixedString(const string &value) +{ + size_t length = value.length(); + if(length < 0x80) { + m_buffer[0] = 0x80 | length; + m_stream->write(m_buffer, 1); + } else if(length < 0x4000) { + BE::getBytes(static_cast(0x4000 | length), m_buffer); + m_stream->write(m_buffer, 2); + } else if(length < 0x200000) { + BE::getBytes(static_cast(0x200000 | length), m_buffer); + m_stream->write(m_buffer + 1, 3); + } else if(length < 0x10000000) { + BE::getBytes(static_cast(0x10000000 | length), m_buffer); + m_stream->write(m_buffer, 4); + } else { + throw ConversionException("The size of the string exceeds the maximum."); + } + m_stream->write(value.c_str(), length); +} diff --git a/io/binarywriter.h b/io/binarywriter.h index 6d5b6da..c53d57e 100644 --- a/io/binarywriter.h +++ b/io/binarywriter.h @@ -1,534 +1,533 @@ -#ifndef IOUTILITIES_BINARYWRITER_H -#define IOUTILITIES_BINARYWRITER_H - -#include "../application/global.h" -#include "../conversion/types.h" -#include "../conversion/binaryconversion.h" - -#include -#include -#include - -namespace IoUtilities -{ - -class LIB_EXPORT BinaryWriter -{ -public: - BinaryWriter(std::ostream *stream); - BinaryWriter(const BinaryWriter &other); - BinaryWriter & operator=(const BinaryWriter & rhs) = delete; - ~BinaryWriter(); - - const std::ostream *stream() const; - std::ostream *stream(); - void setStream(std::ostream *stream, bool giveOwnership = false); - bool hasOwnership() const; - void giveOwnership(); - void detatchOwnership(); - void flush(); - bool fail() const; - void write(const char *buffer, std::streamsize length); - void write(const std::vector &buffer, std::streamsize length); - void writeChar(char value); - void writeByte(byte value); - void writeInt16BE(int16 value); - void writeUInt16BE(uint16 value); - void writeInt24BE(int32 value); - void writeUInt24BE(uint32 value); - void writeInt32BE(int32 value); - void writeUInt32BE(uint32 value); - void writeInt40BE(int64 value); - void writeUInt40BE(uint64 value); - void writeInt56BE(int64 value); - void writeUInt56BE(uint64 value); - void writeInt64BE(int64 value); - void writeUInt64BE(uint64 value); - void writeFloat32BE(float32 value); - void writeFloat64BE(float64 value); - void writeInt16LE(int16 value); - void writeUInt16LE(uint16 value); - void writeInt24LE(int32 value); - void writeUInt24LE(uint32 value); - void writeInt32LE(int32 value); - void writeUInt32LE(uint32 value); - void writeInt40LE(int64 value); - void writeUInt40LE(uint64 value); - void writeInt56LE(int64 value); - void writeUInt56LE(uint64 value); - void writeInt64LE(int64 value); - void writeUInt64LE(uint64 value); - void writeFloat32LE(float32 value); - void writeFloat64LE(float64 value); - void writeString(const std::string &value); - void writeTerminatedString(const std::string &value); - void writeLengthPrefixedString(const std::string &value); - void writeBool(bool value); - void writeSynchsafeUInt32BE(uint32 valueToConvertAndWrite); - void writeFixed8BE(float32 valueToConvertAndWrite); - void writeFixed16BE(float32 valueToConvertAndWrite); - void writeSynchsafeUInt32LE(uint32 valueToConvertAndWrite); - void writeFixed8LE(float32 valueToConvertAndWrite); - void writeFixed16LE(float32 valueToConvertAndWrite); - -private: - std::ostream *m_stream; - bool m_ownership; - char m_buffer[8]; -}; - -/*! - * \brief Returns a pointer to the stream the writer will write to when calling one of the write-methods. - * - * \sa setStream() - */ -inline std::ostream *BinaryWriter::stream() -{ - return m_stream; -} - -/*! - * \brief Returns a pointer to the stream the writer will write to when calling one of the write-methods. - * - * \sa setStream() - */ -inline const std::ostream *BinaryWriter::stream() const -{ - return m_stream; -} - -/*! - * \brief Returns whether the writer takes ownership over the assigned stream. - * - * \sa setStream() - * \sa giveOwnership() - * \sa detatchOwnership() - */ -inline bool BinaryWriter::hasOwnership() const -{ - return m_ownership; -} - -/*! - * \brief The writer will take ownership over the assigned stream. - * - * \sa setStream() - * \sa detatchOwnership() - * \sa hasOwnership() - */ -inline void BinaryWriter::giveOwnership() -{ - if(m_stream) { - m_ownership = true; - } -} - -/*! - * \brief The writer will not take ownership over the assigned stream. - * - * \sa setStream() - * \sa giveOwnership() - * \sa hasOwnership() - */ -inline void BinaryWriter::detatchOwnership() -{ - m_ownership = false; -} - -/*! - * \brief Calls the flush() method of the assigned stream. - */ -inline void BinaryWriter::flush() -{ - m_stream->flush(); -} - -/*! - * \brief Returns an indication whether the fail bit of the assigned stream is set. - */ -inline bool BinaryWriter::fail() const -{ - return m_stream ? m_stream->fail() : false; -} - -/*! - * \brief Writes a character array to the current stream and advances the current position of the stream by the \a length of the array. - */ -inline void BinaryWriter::write(const char *buffer, std::streamsize length) -{ - m_stream->write(buffer, length); -} - -/*! - * \brief Writes the specified number of bytes from the \a buffer to the current stream and advances the current position of the stream by - * the specified \a length which must be less or equal to the \a buffer size. - */ -inline void BinaryWriter::write(const std::vector &buffer, std::streamsize length) -{ - m_stream->write(buffer.data(), length); -} - -/*! - * \brief Writes a single character to the current stream and advances the current position of the stream by one byte. - */ -inline void BinaryWriter::writeChar(char value) -{ - m_buffer[0] = value; - m_stream->write(m_buffer, 1); -} - -/*! - * \brief Writes a single byte to the current stream and advances the current position of the stream by one byte. - */ -inline void BinaryWriter::writeByte(byte value) -{ - m_buffer[0] = *reinterpret_cast(&value); - m_stream->write(m_buffer, 1); -} - -/*! - * \brief Writes a boolean value to the current stream and advances the current position of the stream by one byte. - */ -inline void BinaryWriter::writeBool(bool value) -{ - writeByte(value ? 1 : 0); -} - -/*! - * \brief Writes a 16-bit big endian signed integer to the current stream and advances the current position of the stream by two bytes. - */ -inline void BinaryWriter::writeInt16BE(int16 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(int16)); -} - -/*! - * \brief Writes a 16-bit big endian unsigned integer to the current stream and advances the current position of the stream by two bytes. - */ -inline void BinaryWriter::writeUInt16BE(uint16 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(uint16)); -} - -/*! - * \brief Writes a 24-bit big endian signed integer to the current stream and advances the current position of the stream by three bytes. - * \remarks The most significant byte of the specified 32-bit signed integer \a value will be discarded. - */ -inline void BinaryWriter::writeInt24BE(int32 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer + 1, 3); -} - -/*! - * \brief Writes a 24-bit big endian unsigned integer to the current stream and advances the current position of the stream by three bytes. - * \remarks The most significant byte of the specified 32-bit unsigned integer \a value will be discarded. - */ -inline void BinaryWriter::writeUInt24BE(uint32 value) -{ - // discard most significant byte - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer + 1, 3); -} - -/*! - * \brief Writes a 32-bit big endian signed integer to the current stream and advances the current position of the stream by four bytes. - */ -inline void BinaryWriter::writeInt32BE(int32 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(int32)); -} - -/*! - * \brief Writes a 32-bit big endian unsigned integer to the current stream and advances the current position of the stream by four bytes. - */ -inline void BinaryWriter::writeUInt32BE(uint32 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(uint32)); -} - -/*! - * \brief Writes a 40-bit big endian signed integer to the current stream and advances the current position of the stream by four bytes. - * \remarks The most significant bytes of the specified 64-bit unsigned integer \a value will be discarded. - */ -inline void BinaryWriter::writeInt40BE(int64 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer + 3, 5); -} - -/*! - * \brief Writes a 40-bit big endian unsigned integer to the current stream and advances the current position of the stream by four bytes. - * \remarks The most significant bytes of the specified 64-bit unsigned integer \a value will be discarded. - */ -inline void BinaryWriter::writeUInt40BE(uint64 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer + 3, 5); -} - -/*! - * \brief Writes a 56-bit big endian signed integer to the current stream and advances the current position of the stream by four bytes. - * \remarks The most significant byte of the specified 64-bit unsigned integer \a value will be discarded. - */ -inline void BinaryWriter::writeInt56BE(int64 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer + 1, 7); -} - -/*! - * \brief Writes a 56-bit big endian unsigned integer to the current stream and advances the current position of the stream by four bytes. - * \remarks The most significant byte of the specified 64-bit unsigned integer \a value will be discarded. - */ -inline void BinaryWriter::writeUInt56BE(uint64 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer + 1, 7); -} - -/*! - * \brief Writes a 64-bit big endian signed integer to the current stream and advances the current position of the stream by eight bytes. - */ -inline void BinaryWriter::writeInt64BE(int64 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(int64)); -} - -/*! - * \brief Writes a 64-bit big endian unsigned integer to the current stream and advances the current position of the stream by eight bytes. - */ -inline void BinaryWriter::writeUInt64BE(uint64 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(uint64)); -} - -/*! - * \brief Writes a 32-bit big endian floating point \a value to the current stream and advances the current position of the stream by four bytes. - */ -inline void BinaryWriter::writeFloat32BE(float32 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(float32)); -} - -/*! - * \brief Writes a 64-bit big endian floating point \a value to the current stream and advances the current position of the stream by eight bytes. - */ -inline void BinaryWriter::writeFloat64BE(float64 value) -{ - ConversionUtilities::BE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(float64)); -} - -/*! - * \brief Writes a 16-bit little endian signed integer to the current stream and advances the current position of the stream by two bytes. - */ -inline void BinaryWriter::writeInt16LE(int16 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(int16)); -} - -/*! - * \brief Writes a 16-bit little endian unsigned integer to the current stream and advances the current position of the stream by two bytes. - */ -inline void BinaryWriter::writeUInt16LE(uint16 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(uint16)); -} - -/*! - * \brief Writes a 24-bit little endian signed integer to the current stream and advances the current position of the stream by three bytes. - * \remarks The most significant byte of the specified 32-bit signed integer \a value will be discarded. - */ -inline void BinaryWriter::writeInt24LE(int32 value) -{ - // discard most significant byte - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, 3); -} - -/*! - * \brief Writes a 24-bit little endian unsigned integer to the current stream and advances the current position of the stream by three bytes. - * \remarks The most significant byte of the specified 32-bit unsigned integer \a value will be discarded. - */ -inline void BinaryWriter::writeUInt24LE(uint32 value) -{ - // discard most significant byte - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, 3); -} - -/*! - * \brief Writes a 32-bit little endian signed integer to the current stream and advances the current position of the stream by four bytes. - */ -inline void BinaryWriter::writeInt32LE(int32 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(int32)); -} - -/*! - * \brief Writes a 32-bit little endian unsigned integer to the current stream and advances the current position of the stream by four bytes. - */ -inline void BinaryWriter::writeUInt32LE(uint32 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(uint32)); -} - -/*! - * \brief Writes a 40-bit big endian signed integer to the current stream and advances the current position of the stream by four bytes. - * \remarks The most significant bytes of the specified 64-bit unsigned integer \a value will be discarded. - */ -inline void BinaryWriter::writeInt40LE(int64 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, 5); -} - -/*! - * \brief Writes a 40-bit big endian unsigned integer to the current stream and advances the current position of the stream by four bytes. - * \remarks The most significant bytes of the specified 64-bit unsigned integer \a value will be discarded. - */ -inline void BinaryWriter::writeUInt40LE(uint64 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, 5); -} - -/*! - * \brief Writes a 56-bit big endian signed integer to the current stream and advances the current position of the stream by four bytes. - * \remarks The most significant byte of the specified 64-bit unsigned integer \a value will be discarded. - */ -inline void BinaryWriter::writeInt56LE(int64 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, 7); -} - -/*! - * \brief Writes a 56-bit big endian unsigned integer to the current stream and advances the current position of the stream by four bytes. - * \remarks The most significant byte of the specified 64-bit unsigned integer \a value will be discarded. - */ -inline void BinaryWriter::writeUInt56LE(uint64 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, 7); -} - -/*! - * \brief Writes a 64-bit little endian signed integer to the current stream and advances the current position of the stream by eight bytes. - */ -inline void BinaryWriter::writeInt64LE(int64 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(int64)); -} - -/*! - * \brief Writes a 64-bit little endian unsigned integer to the current stream and advances the current position of the stream by eight bytes. - */ -inline void BinaryWriter::writeUInt64LE(uint64 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(uint64)); -} - -/*! - * \brief Writes a 32-bit little endian floating point \a value to the current stream and advances the current position of the stream by four bytes. - */ -inline void BinaryWriter::writeFloat32LE(float32 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(float32)); -} - -/*! - * \brief Writes a 64-bit little endian floating point \a value to the current stream and advances the current position of the stream by eight bytes. - */ -inline void BinaryWriter::writeFloat64LE(float64 value) -{ - ConversionUtilities::LE::getBytes(value, m_buffer); - m_stream->write(m_buffer, sizeof(float64)); -} - -/*! - * \brief Writes a string to the current stream and advances the current position of the stream by the length of the string. - */ -inline void BinaryWriter::writeString(const std::string &value) -{ - m_stream->write(value.c_str(), value.length()); -} - -/*! - * \brief Writes a terminated string to the current stream and advances the current position of the stream by the length of the string plus 1. - */ -inline void BinaryWriter::writeTerminatedString(const std::string &value) -{ - m_stream->write(value.c_str(), value.length() + 1); -} - -/*! - * \brief Writes a 32-bit big endian synchsafe integer to the current stream and advances the current position of the stream by four bytes. - * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. - * \sa ID3 tag version 2.4.0 - Main Structure - */ -inline void BinaryWriter::writeSynchsafeUInt32BE(uint32 valueToConvertAndWrite) -{ - writeUInt32BE(ConversionUtilities::toSynchsafeInt(valueToConvertAndWrite)); -} - -/*! - * \brief Writes the 8.8 fixed point big endian representation for the specified 32-bit floating point \a value to the current stream and advances the current position of the stream by two bytes. - */ -inline void BinaryWriter::writeFixed8BE(float32 valueToConvertAndWrite) -{ - writeUInt16BE(ConversionUtilities::toFixed8(valueToConvertAndWrite)); -} - -/*! - * \brief Writes the 16.16 fixed point big endian representation for the specified 32-bit floating point \a value to the current stream and advances the current position of the stream by four bytes. - */ -inline void BinaryWriter::writeFixed16BE(float32 valueToConvertAndWrite) -{ - writeUInt32BE(ConversionUtilities::toFixed16(valueToConvertAndWrite)); -} - -/*! - * \brief Writes a 32-bit little endian synchsafe integer to the current stream and advances the current position of the stream by four bytes. - * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. - * \sa ID3 tag version 2.4.0 - Main Structure - */ -inline void BinaryWriter::writeSynchsafeUInt32LE(uint32 valueToConvertAndWrite) -{ - writeUInt32LE(ConversionUtilities::toSynchsafeInt(valueToConvertAndWrite)); -} - -/*! - * \brief Writes the 8.8 fixed point little endian representation for the specified 32-bit floating point \a value to the current stream and advances the current position of the stream by two bytes. - */ -inline void BinaryWriter::writeFixed8LE(float32 valueToConvertAndWrite) -{ - writeUInt16LE(ConversionUtilities::toFixed8(valueToConvertAndWrite)); -} - -/*! - * \brief Writes the 16.16 fixed point little endian representation for the specified 32-bit floating point \a value to the current stream and advances the current position of the stream by four bytes. - */ -inline void BinaryWriter::writeFixed16LE(float32 valueToConvertAndWrite) -{ - writeUInt32LE(ConversionUtilities::toFixed16(valueToConvertAndWrite)); -} - -} - -#endif // IO_UTILITIES_BINARYWRITER_H +#ifndef IOUTILITIES_BINARYWRITER_H +#define IOUTILITIES_BINARYWRITER_H + +#include "../conversion/types.h" +#include "../conversion/binaryconversion.h" + +#include +#include +#include + +namespace IoUtilities +{ + +class CPP_UTILITIES_EXPORT BinaryWriter +{ +public: + BinaryWriter(std::ostream *stream); + BinaryWriter(const BinaryWriter &other); + BinaryWriter & operator=(const BinaryWriter & rhs) = delete; + ~BinaryWriter(); + + const std::ostream *stream() const; + std::ostream *stream(); + void setStream(std::ostream *stream, bool giveOwnership = false); + bool hasOwnership() const; + void giveOwnership(); + void detatchOwnership(); + void flush(); + bool fail() const; + void write(const char *buffer, std::streamsize length); + void write(const std::vector &buffer, std::streamsize length); + void writeChar(char value); + void writeByte(byte value); + void writeInt16BE(int16 value); + void writeUInt16BE(uint16 value); + void writeInt24BE(int32 value); + void writeUInt24BE(uint32 value); + void writeInt32BE(int32 value); + void writeUInt32BE(uint32 value); + void writeInt40BE(int64 value); + void writeUInt40BE(uint64 value); + void writeInt56BE(int64 value); + void writeUInt56BE(uint64 value); + void writeInt64BE(int64 value); + void writeUInt64BE(uint64 value); + void writeFloat32BE(float32 value); + void writeFloat64BE(float64 value); + void writeInt16LE(int16 value); + void writeUInt16LE(uint16 value); + void writeInt24LE(int32 value); + void writeUInt24LE(uint32 value); + void writeInt32LE(int32 value); + void writeUInt32LE(uint32 value); + void writeInt40LE(int64 value); + void writeUInt40LE(uint64 value); + void writeInt56LE(int64 value); + void writeUInt56LE(uint64 value); + void writeInt64LE(int64 value); + void writeUInt64LE(uint64 value); + void writeFloat32LE(float32 value); + void writeFloat64LE(float64 value); + void writeString(const std::string &value); + void writeTerminatedString(const std::string &value); + void writeLengthPrefixedString(const std::string &value); + void writeBool(bool value); + void writeSynchsafeUInt32BE(uint32 valueToConvertAndWrite); + void writeFixed8BE(float32 valueToConvertAndWrite); + void writeFixed16BE(float32 valueToConvertAndWrite); + void writeSynchsafeUInt32LE(uint32 valueToConvertAndWrite); + void writeFixed8LE(float32 valueToConvertAndWrite); + void writeFixed16LE(float32 valueToConvertAndWrite); + +private: + std::ostream *m_stream; + bool m_ownership; + char m_buffer[8]; +}; + +/*! + * \brief Returns a pointer to the stream the writer will write to when calling one of the write-methods. + * + * \sa setStream() + */ +inline std::ostream *BinaryWriter::stream() +{ + return m_stream; +} + +/*! + * \brief Returns a pointer to the stream the writer will write to when calling one of the write-methods. + * + * \sa setStream() + */ +inline const std::ostream *BinaryWriter::stream() const +{ + return m_stream; +} + +/*! + * \brief Returns whether the writer takes ownership over the assigned stream. + * + * \sa setStream() + * \sa giveOwnership() + * \sa detatchOwnership() + */ +inline bool BinaryWriter::hasOwnership() const +{ + return m_ownership; +} + +/*! + * \brief The writer will take ownership over the assigned stream. + * + * \sa setStream() + * \sa detatchOwnership() + * \sa hasOwnership() + */ +inline void BinaryWriter::giveOwnership() +{ + if(m_stream) { + m_ownership = true; + } +} + +/*! + * \brief The writer will not take ownership over the assigned stream. + * + * \sa setStream() + * \sa giveOwnership() + * \sa hasOwnership() + */ +inline void BinaryWriter::detatchOwnership() +{ + m_ownership = false; +} + +/*! + * \brief Calls the flush() method of the assigned stream. + */ +inline void BinaryWriter::flush() +{ + m_stream->flush(); +} + +/*! + * \brief Returns an indication whether the fail bit of the assigned stream is set. + */ +inline bool BinaryWriter::fail() const +{ + return m_stream ? m_stream->fail() : false; +} + +/*! + * \brief Writes a character array to the current stream and advances the current position of the stream by the \a length of the array. + */ +inline void BinaryWriter::write(const char *buffer, std::streamsize length) +{ + m_stream->write(buffer, length); +} + +/*! + * \brief Writes the specified number of bytes from the \a buffer to the current stream and advances the current position of the stream by + * the specified \a length which must be less or equal to the \a buffer size. + */ +inline void BinaryWriter::write(const std::vector &buffer, std::streamsize length) +{ + m_stream->write(buffer.data(), length); +} + +/*! + * \brief Writes a single character to the current stream and advances the current position of the stream by one byte. + */ +inline void BinaryWriter::writeChar(char value) +{ + m_buffer[0] = value; + m_stream->write(m_buffer, 1); +} + +/*! + * \brief Writes a single byte to the current stream and advances the current position of the stream by one byte. + */ +inline void BinaryWriter::writeByte(byte value) +{ + m_buffer[0] = *reinterpret_cast(&value); + m_stream->write(m_buffer, 1); +} + +/*! + * \brief Writes a boolean value to the current stream and advances the current position of the stream by one byte. + */ +inline void BinaryWriter::writeBool(bool value) +{ + writeByte(value ? 1 : 0); +} + +/*! + * \brief Writes a 16-bit big endian signed integer to the current stream and advances the current position of the stream by two bytes. + */ +inline void BinaryWriter::writeInt16BE(int16 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(int16)); +} + +/*! + * \brief Writes a 16-bit big endian unsigned integer to the current stream and advances the current position of the stream by two bytes. + */ +inline void BinaryWriter::writeUInt16BE(uint16 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(uint16)); +} + +/*! + * \brief Writes a 24-bit big endian signed integer to the current stream and advances the current position of the stream by three bytes. + * \remarks The most significant byte of the specified 32-bit signed integer \a value will be discarded. + */ +inline void BinaryWriter::writeInt24BE(int32 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer + 1, 3); +} + +/*! + * \brief Writes a 24-bit big endian unsigned integer to the current stream and advances the current position of the stream by three bytes. + * \remarks The most significant byte of the specified 32-bit unsigned integer \a value will be discarded. + */ +inline void BinaryWriter::writeUInt24BE(uint32 value) +{ + // discard most significant byte + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer + 1, 3); +} + +/*! + * \brief Writes a 32-bit big endian signed integer to the current stream and advances the current position of the stream by four bytes. + */ +inline void BinaryWriter::writeInt32BE(int32 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(int32)); +} + +/*! + * \brief Writes a 32-bit big endian unsigned integer to the current stream and advances the current position of the stream by four bytes. + */ +inline void BinaryWriter::writeUInt32BE(uint32 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(uint32)); +} + +/*! + * \brief Writes a 40-bit big endian signed integer to the current stream and advances the current position of the stream by four bytes. + * \remarks The most significant bytes of the specified 64-bit unsigned integer \a value will be discarded. + */ +inline void BinaryWriter::writeInt40BE(int64 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer + 3, 5); +} + +/*! + * \brief Writes a 40-bit big endian unsigned integer to the current stream and advances the current position of the stream by four bytes. + * \remarks The most significant bytes of the specified 64-bit unsigned integer \a value will be discarded. + */ +inline void BinaryWriter::writeUInt40BE(uint64 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer + 3, 5); +} + +/*! + * \brief Writes a 56-bit big endian signed integer to the current stream and advances the current position of the stream by four bytes. + * \remarks The most significant byte of the specified 64-bit unsigned integer \a value will be discarded. + */ +inline void BinaryWriter::writeInt56BE(int64 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer + 1, 7); +} + +/*! + * \brief Writes a 56-bit big endian unsigned integer to the current stream and advances the current position of the stream by four bytes. + * \remarks The most significant byte of the specified 64-bit unsigned integer \a value will be discarded. + */ +inline void BinaryWriter::writeUInt56BE(uint64 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer + 1, 7); +} + +/*! + * \brief Writes a 64-bit big endian signed integer to the current stream and advances the current position of the stream by eight bytes. + */ +inline void BinaryWriter::writeInt64BE(int64 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(int64)); +} + +/*! + * \brief Writes a 64-bit big endian unsigned integer to the current stream and advances the current position of the stream by eight bytes. + */ +inline void BinaryWriter::writeUInt64BE(uint64 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(uint64)); +} + +/*! + * \brief Writes a 32-bit big endian floating point \a value to the current stream and advances the current position of the stream by four bytes. + */ +inline void BinaryWriter::writeFloat32BE(float32 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(float32)); +} + +/*! + * \brief Writes a 64-bit big endian floating point \a value to the current stream and advances the current position of the stream by eight bytes. + */ +inline void BinaryWriter::writeFloat64BE(float64 value) +{ + ConversionUtilities::BE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(float64)); +} + +/*! + * \brief Writes a 16-bit little endian signed integer to the current stream and advances the current position of the stream by two bytes. + */ +inline void BinaryWriter::writeInt16LE(int16 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(int16)); +} + +/*! + * \brief Writes a 16-bit little endian unsigned integer to the current stream and advances the current position of the stream by two bytes. + */ +inline void BinaryWriter::writeUInt16LE(uint16 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(uint16)); +} + +/*! + * \brief Writes a 24-bit little endian signed integer to the current stream and advances the current position of the stream by three bytes. + * \remarks The most significant byte of the specified 32-bit signed integer \a value will be discarded. + */ +inline void BinaryWriter::writeInt24LE(int32 value) +{ + // discard most significant byte + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, 3); +} + +/*! + * \brief Writes a 24-bit little endian unsigned integer to the current stream and advances the current position of the stream by three bytes. + * \remarks The most significant byte of the specified 32-bit unsigned integer \a value will be discarded. + */ +inline void BinaryWriter::writeUInt24LE(uint32 value) +{ + // discard most significant byte + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, 3); +} + +/*! + * \brief Writes a 32-bit little endian signed integer to the current stream and advances the current position of the stream by four bytes. + */ +inline void BinaryWriter::writeInt32LE(int32 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(int32)); +} + +/*! + * \brief Writes a 32-bit little endian unsigned integer to the current stream and advances the current position of the stream by four bytes. + */ +inline void BinaryWriter::writeUInt32LE(uint32 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(uint32)); +} + +/*! + * \brief Writes a 40-bit big endian signed integer to the current stream and advances the current position of the stream by four bytes. + * \remarks The most significant bytes of the specified 64-bit unsigned integer \a value will be discarded. + */ +inline void BinaryWriter::writeInt40LE(int64 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, 5); +} + +/*! + * \brief Writes a 40-bit big endian unsigned integer to the current stream and advances the current position of the stream by four bytes. + * \remarks The most significant bytes of the specified 64-bit unsigned integer \a value will be discarded. + */ +inline void BinaryWriter::writeUInt40LE(uint64 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, 5); +} + +/*! + * \brief Writes a 56-bit big endian signed integer to the current stream and advances the current position of the stream by four bytes. + * \remarks The most significant byte of the specified 64-bit unsigned integer \a value will be discarded. + */ +inline void BinaryWriter::writeInt56LE(int64 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, 7); +} + +/*! + * \brief Writes a 56-bit big endian unsigned integer to the current stream and advances the current position of the stream by four bytes. + * \remarks The most significant byte of the specified 64-bit unsigned integer \a value will be discarded. + */ +inline void BinaryWriter::writeUInt56LE(uint64 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, 7); +} + +/*! + * \brief Writes a 64-bit little endian signed integer to the current stream and advances the current position of the stream by eight bytes. + */ +inline void BinaryWriter::writeInt64LE(int64 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(int64)); +} + +/*! + * \brief Writes a 64-bit little endian unsigned integer to the current stream and advances the current position of the stream by eight bytes. + */ +inline void BinaryWriter::writeUInt64LE(uint64 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(uint64)); +} + +/*! + * \brief Writes a 32-bit little endian floating point \a value to the current stream and advances the current position of the stream by four bytes. + */ +inline void BinaryWriter::writeFloat32LE(float32 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(float32)); +} + +/*! + * \brief Writes a 64-bit little endian floating point \a value to the current stream and advances the current position of the stream by eight bytes. + */ +inline void BinaryWriter::writeFloat64LE(float64 value) +{ + ConversionUtilities::LE::getBytes(value, m_buffer); + m_stream->write(m_buffer, sizeof(float64)); +} + +/*! + * \brief Writes a string to the current stream and advances the current position of the stream by the length of the string. + */ +inline void BinaryWriter::writeString(const std::string &value) +{ + m_stream->write(value.c_str(), value.length()); +} + +/*! + * \brief Writes a terminated string to the current stream and advances the current position of the stream by the length of the string plus 1. + */ +inline void BinaryWriter::writeTerminatedString(const std::string &value) +{ + m_stream->write(value.c_str(), value.length() + 1); +} + +/*! + * \brief Writes a 32-bit big endian synchsafe integer to the current stream and advances the current position of the stream by four bytes. + * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. + * \sa ID3 tag version 2.4.0 - Main Structure + */ +inline void BinaryWriter::writeSynchsafeUInt32BE(uint32 valueToConvertAndWrite) +{ + writeUInt32BE(ConversionUtilities::toSynchsafeInt(valueToConvertAndWrite)); +} + +/*! + * \brief Writes the 8.8 fixed point big endian representation for the specified 32-bit floating point \a value to the current stream and advances the current position of the stream by two bytes. + */ +inline void BinaryWriter::writeFixed8BE(float32 valueToConvertAndWrite) +{ + writeUInt16BE(ConversionUtilities::toFixed8(valueToConvertAndWrite)); +} + +/*! + * \brief Writes the 16.16 fixed point big endian representation for the specified 32-bit floating point \a value to the current stream and advances the current position of the stream by four bytes. + */ +inline void BinaryWriter::writeFixed16BE(float32 valueToConvertAndWrite) +{ + writeUInt32BE(ConversionUtilities::toFixed16(valueToConvertAndWrite)); +} + +/*! + * \brief Writes a 32-bit little endian synchsafe integer to the current stream and advances the current position of the stream by four bytes. + * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file. + * \sa ID3 tag version 2.4.0 - Main Structure + */ +inline void BinaryWriter::writeSynchsafeUInt32LE(uint32 valueToConvertAndWrite) +{ + writeUInt32LE(ConversionUtilities::toSynchsafeInt(valueToConvertAndWrite)); +} + +/*! + * \brief Writes the 8.8 fixed point little endian representation for the specified 32-bit floating point \a value to the current stream and advances the current position of the stream by two bytes. + */ +inline void BinaryWriter::writeFixed8LE(float32 valueToConvertAndWrite) +{ + writeUInt16LE(ConversionUtilities::toFixed8(valueToConvertAndWrite)); +} + +/*! + * \brief Writes the 16.16 fixed point little endian representation for the specified 32-bit floating point \a value to the current stream and advances the current position of the stream by four bytes. + */ +inline void BinaryWriter::writeFixed16LE(float32 valueToConvertAndWrite) +{ + writeUInt32LE(ConversionUtilities::toFixed16(valueToConvertAndWrite)); +} + +} + +#endif // IO_UTILITIES_BINARYWRITER_H diff --git a/io/bitreader.h b/io/bitreader.h index 290a5f2..036548a 100644 --- a/io/bitreader.h +++ b/io/bitreader.h @@ -2,8 +2,8 @@ #define IOUTILITIES_BITREADER_H #include "../conversion/types.h" -#include "../application/global.h" #include "../io/catchiofailure.h" +#include "../global.h" #include #include @@ -11,7 +11,7 @@ namespace IoUtilities { -class LIB_EXPORT BitReader +class CPP_UTILITIES_EXPORT BitReader { public: BitReader(const char *buffer, std::size_t bufferSize); diff --git a/io/catchiofailure.cpp b/io/catchiofailure.cpp index b7e593a..8b6910e 100644 --- a/io/catchiofailure.cpp +++ b/io/catchiofailure.cpp @@ -1,36 +1,36 @@ -// ensure the old ABI is used -// TODO: add condition for GCC version if GCC Bug 66145 is fixed -#define _GLIBCXX_USE_CXX11_ABI 0 - -#include "./catchiofailure.h" - -#include - -using namespace std; - -namespace IoUtilities { - -/*! - * \brief Provides a workaround for GCC Bug 66145. - * \returns Returns the error message. - * \throws Throws the current exception if it is not std::ios_base::failure. - */ -const char *catchIoFailure() -{ - try { - throw; - } catch(const ios_base::failure &e) { - return e.what(); - } -} - -/*! - * \brief Throws a std::ios_base::failure with the specified message. - */ -void throwIoFailure(const char *what) -{ - throw ios_base::failure(what); -} - -} - +// ensure the old ABI is used +// TODO: add condition for GCC version if GCC Bug 66145 is fixed +#define _GLIBCXX_USE_CXX11_ABI 0 + +#include "./catchiofailure.h" + +#include + +using namespace std; + +namespace IoUtilities { + +/*! + * \brief Provides a workaround for GCC Bug 66145. + * \returns Returns the error message. + * \throws Throws the current exception if it is not std::ios_base::failure. + */ +const char *catchIoFailure() +{ + try { + throw; + } catch(const ios_base::failure &e) { + return e.what(); + } +} + +/*! + * \brief Throws a std::ios_base::failure with the specified message. + */ +void throwIoFailure(const char *what) +{ + throw ios_base::failure(what); +} + +} + diff --git a/io/catchiofailure.h b/io/catchiofailure.h index e2f2522..e96d600 100644 --- a/io/catchiofailure.h +++ b/io/catchiofailure.h @@ -1,15 +1,15 @@ -#ifndef IOUTILITIES_CATCHIOFAILURE_H -#define IOUTILITIES_CATCHIOFAILURE_H - -#include "../application/global.h" - -#include - -namespace IoUtilities { - -LIB_EXPORT const char *catchIoFailure(); -LIB_EXPORT void throwIoFailure(const char *what); - -} - -#endif // IOUTILITIES_CATCHIOFAILURE_H +#ifndef IOUTILITIES_CATCHIOFAILURE_H +#define IOUTILITIES_CATCHIOFAILURE_H + +#include "../global.h" + +#include + +namespace IoUtilities { + +CPP_UTILITIES_EXPORT const char *catchIoFailure(); +CPP_UTILITIES_EXPORT void throwIoFailure(const char *what); + +} + +#endif // IOUTILITIES_CATCHIOFAILURE_H diff --git a/io/copy.h b/io/copy.h index 43aeb6b..80cf540 100644 --- a/io/copy.h +++ b/io/copy.h @@ -1,7 +1,7 @@ #ifndef IOUTILITIES_COPY_H #define IOUTILITIES_COPY_H -#include "../application/global.h" +#include "../global.h" #include #include @@ -14,7 +14,7 @@ namespace IoUtilities { * \tparam Specifies the buffer size. */ template -class LIB_EXPORT CopyHelper +class CPP_UTILITIES_EXPORT CopyHelper { public: CopyHelper(); diff --git a/io/inifile.h b/io/inifile.h index e135c04..df492f7 100644 --- a/io/inifile.h +++ b/io/inifile.h @@ -1,7 +1,7 @@ #ifndef IOUTILITIES_INIFILE_H #define IOUTILITIES_INIFILE_H -#include "../application/global.h" +#include "../global.h" #include #include @@ -9,7 +9,7 @@ namespace IoUtilities { -class LIB_EXPORT IniFile +class CPP_UTILITIES_EXPORT IniFile { public: IniFile(); diff --git a/io/path.cpp b/io/path.cpp index 92b0192..d5ac7bc 100644 --- a/io/path.cpp +++ b/io/path.cpp @@ -1,218 +1,217 @@ -#include "./path.h" - -#include "../application/global.h" -#include "../conversion/widen.h" - -#include -#include -#include -#include -#ifdef PLATFORM_UNIX -# include -# include -# include -# include -# include -#else -# ifdef PLATFORM_WINDOWS -# ifdef UNICODE -# undef UNICODE -# endif -# ifdef _UNICODE -# undef _UNICODE -# endif -# include -# endif -#endif - -using namespace std; -using namespace ConversionUtilities; - -namespace IoUtilities { - -/*! - * \brief Returns the file name and extension of the specified \a path string. - */ -string fileName(const string &path) -{ - size_t lastSlash = path.rfind('/'); - size_t lastBackSlash = path.rfind('\\'); - size_t lastSeparator; - if(lastSlash == string::npos && lastBackSlash == string::npos) { - return path; - } else if(lastSlash == string::npos) { - lastSeparator = lastBackSlash; - } else if(lastBackSlash == string::npos) { - lastSeparator = lastSlash; - } else { - lastSeparator = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; - } - return path.substr(lastSeparator + 1); -} - -/*! - * \brief Returns the directory of the specified \a path string (including trailing slash). - */ -string directory(const string &path) -{ - size_t lastSlash = path.rfind('/'); - size_t lastBackSlash = path.rfind('\\'); - size_t lastSeparator; - if(lastSlash == string::npos && lastBackSlash == string::npos) { - return string(); - } else if(lastSlash == string::npos) { - lastSeparator = lastBackSlash; - } else if(lastBackSlash == string::npos) { - lastSeparator = lastSlash; - } else { - lastSeparator = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; - } - return path.substr(0, lastSeparator + 1); -} - -/*! - * \brief Removes invalid characters from the specified \a fileName. - * - * The characters <, >, ?, !, *, |, /, :, \ and new lines are considered as invalid. - */ -void removeInvalidChars(std::string &fileName) -{ - size_t startPos = 0; - static const char invalidPathChars[] = {'\"', '<', '>', '?', '!', '*', '|', '/', ':', '\\', '\n'}; - for(const char *i = invalidPathChars, *end = invalidPathChars + sizeof(invalidPathChars); i != end; ++i) { - startPos = fileName.find(*i); - while(startPos != string::npos) { - fileName.replace(startPos, 1, string()); - startPos = fileName.find(*i, startPos); - } - } -} - -/*! - * \brief Locates a directory meant to store application settings. - * \param result Specifies a string to store the path in. - * \param applicationDirectoryName Specifies the name for the application subdirectory. - * \param createApplicationDirectory Indicates wheter the application subdirectory should be created if not present. - * \returns Returns if a settings directory could be located. - */ -bool settingsDirectory(std::string &result, std::string applicationDirectoryName, bool createApplicationDirectory) -{ - result.clear(); - fstream pathConfigFile("path.config", ios_base::in); - if(pathConfigFile.good()) { - for(string line; getline(pathConfigFile, line); ) { - string::size_type p = line.find('='); - if((p != string::npos) && (p + 1 < line.length())) { - string fieldName = line.substr(0, p); - if(fieldName == "settings") { - result.assign(line.substr(p + 1)); - } - } - } - } - if(!result.empty()) { -#ifdef PLATFORM_UNIX - struct stat sb; - return (stat(result.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)); -#else -# ifdef PLATFORM_WINDOWS - DWORD ftyp = GetFileAttributesA(result.c_str()); - return (ftyp != INVALID_FILE_ATTRIBUTES) && (ftyp & FILE_ATTRIBUTE_DIRECTORY); -# else -# error Platform not supported. -# endif -#endif - } else { - if(!applicationDirectoryName.empty()) { - removeInvalidChars(applicationDirectoryName); - } -#ifdef PLATFORM_UNIX - if(char *homeDir = getenv("HOME")) { - result = string(homeDir); - } else { - struct passwd *pw = getpwuid(getuid()); - result = string(pw->pw_dir); - } - struct stat sb; - result += "/.config"; - if(createApplicationDirectory && !(stat(result.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode))) { - if(mkdir(result.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) != 0) { - return false; - } - } - if(!applicationDirectoryName.empty()) { - result += "/" + applicationDirectoryName; - if(createApplicationDirectory && !(stat(result.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode))) { - if(mkdir(result.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) != 0) { - return false; - } - } - } -#else -# ifdef PLATFORM_WINDOWS - if(char *appData = getenv("appdata")) { - result = appData; - if(!applicationDirectoryName.empty()) { - result += "\\" + applicationDirectoryName; - if(createApplicationDirectory) { - DWORD ftyp = GetFileAttributesA(result.c_str()); - if(ftyp == INVALID_FILE_ATTRIBUTES) { - return false; - } else if(ftyp & FILE_ATTRIBUTE_DIRECTORY) { - return true; - } else { - if(CreateDirectory(result.c_str(), NULL) == 0) { - return false; - } else { - return true; - } - } - } - } - } else { - return false; - } -# else -# error Platform not supported. -# endif -#endif - } - return true; -} - -/*! - * \brief Returns the names of the directory entries in the specified \a path with the specified \a types. - */ -std::list directoryEntries(const char *path, DirectoryEntryType types) -{ -#ifdef PLATFORM_UNIX - list entries; - if(auto dir = opendir(path)) { - while(auto dirEntry = readdir(dir)) { - bool filter = false; - switch(dirEntry->d_type) { - case DT_REG: - filter = (types & DirectoryEntryType::File) != DirectoryEntryType::None; - break; - case DT_DIR: - filter = (types & DirectoryEntryType::Directory) != DirectoryEntryType::None; - break; - case DT_LNK: - filter = (types & DirectoryEntryType::Symlink) != DirectoryEntryType::None; - break; - default: - filter = (types & DirectoryEntryType::All) != DirectoryEntryType::None; - } - if(filter) { - entries.emplace_back(dirEntry->d_name); - } - } - closedir(dir); - } - return entries; -#else - return list(); // TODO -#endif -} - -} +#include "./path.h" + +#include "../conversion/widen.h" + +#include +#include +#include +#include +#ifdef PLATFORM_UNIX +# include +# include +# include +# include +# include +#else +# ifdef PLATFORM_WINDOWS +# ifdef UNICODE +# undef UNICODE +# endif +# ifdef _UNICODE +# undef _UNICODE +# endif +# include +# endif +#endif + +using namespace std; +using namespace ConversionUtilities; + +namespace IoUtilities { + +/*! + * \brief Returns the file name and extension of the specified \a path string. + */ +string fileName(const string &path) +{ + size_t lastSlash = path.rfind('/'); + size_t lastBackSlash = path.rfind('\\'); + size_t lastSeparator; + if(lastSlash == string::npos && lastBackSlash == string::npos) { + return path; + } else if(lastSlash == string::npos) { + lastSeparator = lastBackSlash; + } else if(lastBackSlash == string::npos) { + lastSeparator = lastSlash; + } else { + lastSeparator = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; + } + return path.substr(lastSeparator + 1); +} + +/*! + * \brief Returns the directory of the specified \a path string (including trailing slash). + */ +string directory(const string &path) +{ + size_t lastSlash = path.rfind('/'); + size_t lastBackSlash = path.rfind('\\'); + size_t lastSeparator; + if(lastSlash == string::npos && lastBackSlash == string::npos) { + return string(); + } else if(lastSlash == string::npos) { + lastSeparator = lastBackSlash; + } else if(lastBackSlash == string::npos) { + lastSeparator = lastSlash; + } else { + lastSeparator = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; + } + return path.substr(0, lastSeparator + 1); +} + +/*! + * \brief Removes invalid characters from the specified \a fileName. + * + * The characters <, >, ?, !, *, |, /, :, \ and new lines are considered as invalid. + */ +void removeInvalidChars(std::string &fileName) +{ + size_t startPos = 0; + static const char invalidPathChars[] = {'\"', '<', '>', '?', '!', '*', '|', '/', ':', '\\', '\n'}; + for(const char *i = invalidPathChars, *end = invalidPathChars + sizeof(invalidPathChars); i != end; ++i) { + startPos = fileName.find(*i); + while(startPos != string::npos) { + fileName.replace(startPos, 1, string()); + startPos = fileName.find(*i, startPos); + } + } +} + +/*! + * \brief Locates a directory meant to store application settings. + * \param result Specifies a string to store the path in. + * \param applicationDirectoryName Specifies the name for the application subdirectory. + * \param createApplicationDirectory Indicates wheter the application subdirectory should be created if not present. + * \returns Returns if a settings directory could be located. + */ +bool settingsDirectory(std::string &result, std::string applicationDirectoryName, bool createApplicationDirectory) +{ + result.clear(); + fstream pathConfigFile("path.config", ios_base::in); + if(pathConfigFile.good()) { + for(string line; getline(pathConfigFile, line); ) { + string::size_type p = line.find('='); + if((p != string::npos) && (p + 1 < line.length())) { + string fieldName = line.substr(0, p); + if(fieldName == "settings") { + result.assign(line.substr(p + 1)); + } + } + } + } + if(!result.empty()) { +#ifdef PLATFORM_UNIX + struct stat sb; + return (stat(result.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)); +#else +# ifdef PLATFORM_WINDOWS + DWORD ftyp = GetFileAttributesA(result.c_str()); + return (ftyp != INVALID_FILE_ATTRIBUTES) && (ftyp & FILE_ATTRIBUTE_DIRECTORY); +# else +# error Platform not supported. +# endif +#endif + } else { + if(!applicationDirectoryName.empty()) { + removeInvalidChars(applicationDirectoryName); + } +#ifdef PLATFORM_UNIX + if(char *homeDir = getenv("HOME")) { + result = string(homeDir); + } else { + struct passwd *pw = getpwuid(getuid()); + result = string(pw->pw_dir); + } + struct stat sb; + result += "/.config"; + if(createApplicationDirectory && !(stat(result.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode))) { + if(mkdir(result.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) != 0) { + return false; + } + } + if(!applicationDirectoryName.empty()) { + result += "/" + applicationDirectoryName; + if(createApplicationDirectory && !(stat(result.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode))) { + if(mkdir(result.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) != 0) { + return false; + } + } + } +#else +# ifdef PLATFORM_WINDOWS + if(char *appData = getenv("appdata")) { + result = appData; + if(!applicationDirectoryName.empty()) { + result += "\\" + applicationDirectoryName; + if(createApplicationDirectory) { + DWORD ftyp = GetFileAttributesA(result.c_str()); + if(ftyp == INVALID_FILE_ATTRIBUTES) { + return false; + } else if(ftyp & FILE_ATTRIBUTE_DIRECTORY) { + return true; + } else { + if(CreateDirectory(result.c_str(), NULL) == 0) { + return false; + } else { + return true; + } + } + } + } + } else { + return false; + } +# else +# error Platform not supported. +# endif +#endif + } + return true; +} + +/*! + * \brief Returns the names of the directory entries in the specified \a path with the specified \a types. + */ +std::list directoryEntries(const char *path, DirectoryEntryType types) +{ +#ifdef PLATFORM_UNIX + list entries; + if(auto dir = opendir(path)) { + while(auto dirEntry = readdir(dir)) { + bool filter = false; + switch(dirEntry->d_type) { + case DT_REG: + filter = (types & DirectoryEntryType::File) != DirectoryEntryType::None; + break; + case DT_DIR: + filter = (types & DirectoryEntryType::Directory) != DirectoryEntryType::None; + break; + case DT_LNK: + filter = (types & DirectoryEntryType::Symlink) != DirectoryEntryType::None; + break; + default: + filter = (types & DirectoryEntryType::All) != DirectoryEntryType::None; + } + if(filter) { + entries.emplace_back(dirEntry->d_name); + } + } + closedir(dir); + } + return entries; +#else + return list(); // TODO +#endif +} + +} diff --git a/io/path.h b/io/path.h index 3c95b49..8bde847 100644 --- a/io/path.h +++ b/io/path.h @@ -1,56 +1,54 @@ -#ifndef IOUTILITIES_PATHHELPER_H -#define IOUTILITIES_PATHHELPER_H - -#include "./binarywriter.h" -#include "./binaryreader.h" - -#include "../application/global.h" - -#include -#include - -#ifdef PLATFORM_WINDOWS -# define PATH_SEP_CHAR '\\' -# define SEARCH_PATH_SEP_CHAR ';' -# define PATH_SEP_STR "\\" -# define SEARCH_PATH_SEP_STR ";" -#else -# define PATH_SEP_CHAR '/' -# define SEARCH_PATH_SEP_CHAR ':' -# define PATH_SEP_STR "/" -# define SEARCH_PATH_SEP_STR ":" -#endif - -namespace IoUtilities { - -/*! - * \brief The DirectoryEntryType enum specifies the type of a directory entry (file, directory or symlink). - */ -enum class DirectoryEntryType : unsigned char -{ - None = 0, - File = 1, - Directory = 2, - Symlink = 4, - All = 0xFF -}; - -constexpr DirectoryEntryType operator|(DirectoryEntryType lhs, DirectoryEntryType rhs) -{ - return static_cast(static_cast(lhs) | static_cast(rhs)); -} - -constexpr DirectoryEntryType operator&(DirectoryEntryType lhs, DirectoryEntryType rhs) -{ - return static_cast(static_cast(lhs) & static_cast(rhs)); -} - -LIB_EXPORT std::string fileName(const std::string &path); -LIB_EXPORT std::string directory(const std::string &path); -LIB_EXPORT void removeInvalidChars(std::string &fileName); -LIB_EXPORT bool settingsDirectory(std::string &result, std::string applicationDirectoryName = std::string(), bool createApplicationDirectory = false); -LIB_EXPORT std::list directoryEntries(const char *path, DirectoryEntryType types = DirectoryEntryType::All); - -} - -#endif // IOUTILITIES_PATHHELPER_H +#ifndef IOUTILITIES_PATHHELPER_H +#define IOUTILITIES_PATHHELPER_H + +#include "./binarywriter.h" +#include "./binaryreader.h" + +#include +#include + +#ifdef PLATFORM_WINDOWS +# define PATH_SEP_CHAR '\\' +# define SEARCH_PATH_SEP_CHAR ';' +# define PATH_SEP_STR "\\" +# define SEARCH_PATH_SEP_STR ";" +#else +# define PATH_SEP_CHAR '/' +# define SEARCH_PATH_SEP_CHAR ':' +# define PATH_SEP_STR "/" +# define SEARCH_PATH_SEP_STR ":" +#endif + +namespace IoUtilities { + +/*! + * \brief The DirectoryEntryType enum specifies the type of a directory entry (file, directory or symlink). + */ +enum class DirectoryEntryType : unsigned char +{ + None = 0, + File = 1, + Directory = 2, + Symlink = 4, + All = 0xFF +}; + +constexpr DirectoryEntryType operator|(DirectoryEntryType lhs, DirectoryEntryType rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +constexpr DirectoryEntryType operator&(DirectoryEntryType lhs, DirectoryEntryType rhs) +{ + return static_cast(static_cast(lhs) & static_cast(rhs)); +} + +CPP_UTILITIES_EXPORT std::string fileName(const std::string &path); +CPP_UTILITIES_EXPORT std::string directory(const std::string &path); +CPP_UTILITIES_EXPORT void removeInvalidChars(std::string &fileName); +CPP_UTILITIES_EXPORT bool settingsDirectory(std::string &result, std::string applicationDirectoryName = std::string(), bool createApplicationDirectory = false); +CPP_UTILITIES_EXPORT std::list directoryEntries(const char *path, DirectoryEntryType types = DirectoryEntryType::All); + +} + +#endif // IOUTILITIES_PATHHELPER_H diff --git a/math/math.h b/math/math.h index 639110d..7ff7e0e 100644 --- a/math/math.h +++ b/math/math.h @@ -1,17 +1,17 @@ #ifndef MATHUTILITIES_H #define MATHUTILITIES_H -#include "../application/global.h" +#include "../global.h" #include "../conversion/types.h" namespace MathUtilities { -LIB_EXPORT int random(int lowerbounds, int upperbounds); -LIB_EXPORT int digitsum(int number, int base = 10); -LIB_EXPORT int factorial(int number); -LIB_EXPORT uint64 powerModulo(uint64 base, uint64 expontent, uint64 module); -LIB_EXPORT int64 inverseModulo(int64 number, int64 module); -LIB_EXPORT uint64 orderModulo(uint64 number, uint64 module); +CPP_UTILITIES_EXPORT int random(int lowerbounds, int upperbounds); +CPP_UTILITIES_EXPORT int digitsum(int number, int base = 10); +CPP_UTILITIES_EXPORT int factorial(int number); +CPP_UTILITIES_EXPORT uint64 powerModulo(uint64 base, uint64 expontent, uint64 module); +CPP_UTILITIES_EXPORT int64 inverseModulo(int64 number, int64 module); +CPP_UTILITIES_EXPORT uint64 orderModulo(uint64 number, uint64 module); } diff --git a/misc/random.cpp b/misc/random.cpp index b733746..957b27a 100644 --- a/misc/random.cpp +++ b/misc/random.cpp @@ -1,125 +1,125 @@ -#include "./random.h" - -#include -#include -#include -#include -#include -#include - -using namespace std; - -/*! - * \namespace RandomUtilities - * \brief Contains utility functions for generating random character sequences. - */ - -namespace RandomUtilities { - -//! @cond -const char letters[28] = "qwertzuiopasdfghjklyxcvbnm"; -const char capitalLetters[28] = "QWERTZUIOPASDFGHJKLYXCVBNM"; -const char numbers[11] = "1234567890"; -const char symbols[24] = "!\"$%&/()=?'#*+~-_><.:,;"; -//! @endcond - -/*! - * \brief Generates a random character sequence using the given \a randomizer. - * \remarks Might be removed because not used anymore. - */ -void generateRandomCharacterSequence(char *result, unsigned int length, std::function randomizer, int highestRandomNumber, bool useSmallLetters, bool useCapitalLetters, bool useNumbers, bool useSymbols, bool useAtLeastOneOfEachCategory) -{ - if(length) { - return; - } - signed char categoryCount = 0; - bool needSmallLetter = false; - bool needCapitalLetter = false; - bool needNumber = false; - bool needSymbol = false; - if(useSmallLetters) { - needSmallLetter = useAtLeastOneOfEachCategory; - ++categoryCount; - } - if(useCapitalLetters) { - needCapitalLetter = useAtLeastOneOfEachCategory; - ++categoryCount; - } - if(useNumbers) { - needNumber = useAtLeastOneOfEachCategory; - ++categoryCount; - } - if(useSymbols) { - needSymbol = useAtLeastOneOfEachCategory; - ++categoryCount; - } - signed char neededCharacters = useAtLeastOneOfEachCategory ? categoryCount : 0; - if(!categoryCount) { - *result = '\0'; - return; - } - for(char *i = result, *end = result + length; i < end; ++i) { - int category = -1; - if((neededCharacters > 0 && (randomizer() < (highestRandomNumber / 2.0))) || ((end - i) >= neededCharacters)) { - if(needSmallLetter) - category = 0; - if(needCapitalLetter && ((category == -1) || (randomizer() < (highestRandomNumber / 2.0)))) - category = 1; - if(needNumber && ((category == -1) || (randomizer() < (highestRandomNumber / 4.0)))) - category = 2; - if(needSymbol && ((category == -1) || (randomizer() < (highestRandomNumber / 8.0)))) - category = 3; - } else { - if(useSmallLetters) - category = 0; - if(useCapitalLetters && ((category == -1) || (randomizer() < (highestRandomNumber / 2.0)))) - category = 1; - if(useNumbers && ((category == -1) || (randomizer() < (highestRandomNumber / 4.0)))) - category = 2; - if(useSymbols && ((category == -1) || (randomizer() < (highestRandomNumber / 8.0)))) - category = 3; - } - switch(category) { - case 0: - *i = letters[rand() % 26]; - if(needSmallLetter) { - needSmallLetter = false; - --neededCharacters; - } - break; - case 1: - *i = capitalLetters[rand() % 26]; - if(needCapitalLetter) { - needCapitalLetter = false; - --neededCharacters; - } - break; - case 2: - *i = numbers[rand() % 9]; - if(needNumber) { - needNumber = false; - --neededCharacters; - } - break; - case 3: - *i = symbols[rand() % 22]; - if(needSymbol) { - needSymbol = false; - --neededCharacters; - } - break; - } - } -} - -/*! - * \brief Generates a random character sequence using std::rand(). - * \remarks Might be removed because not used anymore. - */ -void generateRandomCharacterSequence(char *result, unsigned int length, bool useSmallLetters, bool useCapitalLetters, bool useNumbers, bool useSymbols, bool useAtLeastOneOfEachCategory) -{ - generateRandomCharacterSequence(result, length, rand, RAND_MAX, useSmallLetters, useCapitalLetters, useNumbers, useSymbols, useAtLeastOneOfEachCategory); -} - -} - +#include "./random.h" + +#include +#include +#include +#include +#include +#include + +using namespace std; + +/*! + * \namespace RandomUtilities + * \brief Contains utility functions for generating random character sequences. + */ + +namespace RandomUtilities { + +//! @cond +const char letters[28] = "qwertzuiopasdfghjklyxcvbnm"; +const char capitalLetters[28] = "QWERTZUIOPASDFGHJKLYXCVBNM"; +const char numbers[11] = "1234567890"; +const char symbols[24] = "!\"$%&/()=?'#*+~-_><.:,;"; +//! @endcond + +/*! + * \brief Generates a random character sequence using the given \a randomizer. + * \remarks Might be removed because not used anymore. + */ +void generateRandomCharacterSequence(char *result, unsigned int length, std::function randomizer, int highestRandomNumber, bool useSmallLetters, bool useCapitalLetters, bool useNumbers, bool useSymbols, bool useAtLeastOneOfEachCategory) +{ + if(length) { + return; + } + signed char categoryCount = 0; + bool needSmallLetter = false; + bool needCapitalLetter = false; + bool needNumber = false; + bool needSymbol = false; + if(useSmallLetters) { + needSmallLetter = useAtLeastOneOfEachCategory; + ++categoryCount; + } + if(useCapitalLetters) { + needCapitalLetter = useAtLeastOneOfEachCategory; + ++categoryCount; + } + if(useNumbers) { + needNumber = useAtLeastOneOfEachCategory; + ++categoryCount; + } + if(useSymbols) { + needSymbol = useAtLeastOneOfEachCategory; + ++categoryCount; + } + signed char neededCharacters = useAtLeastOneOfEachCategory ? categoryCount : 0; + if(!categoryCount) { + *result = '\0'; + return; + } + for(char *i = result, *end = result + length; i < end; ++i) { + int category = -1; + if((neededCharacters > 0 && (randomizer() < (highestRandomNumber / 2.0))) || ((end - i) >= neededCharacters)) { + if(needSmallLetter) + category = 0; + if(needCapitalLetter && ((category == -1) || (randomizer() < (highestRandomNumber / 2.0)))) + category = 1; + if(needNumber && ((category == -1) || (randomizer() < (highestRandomNumber / 4.0)))) + category = 2; + if(needSymbol && ((category == -1) || (randomizer() < (highestRandomNumber / 8.0)))) + category = 3; + } else { + if(useSmallLetters) + category = 0; + if(useCapitalLetters && ((category == -1) || (randomizer() < (highestRandomNumber / 2.0)))) + category = 1; + if(useNumbers && ((category == -1) || (randomizer() < (highestRandomNumber / 4.0)))) + category = 2; + if(useSymbols && ((category == -1) || (randomizer() < (highestRandomNumber / 8.0)))) + category = 3; + } + switch(category) { + case 0: + *i = letters[rand() % 26]; + if(needSmallLetter) { + needSmallLetter = false; + --neededCharacters; + } + break; + case 1: + *i = capitalLetters[rand() % 26]; + if(needCapitalLetter) { + needCapitalLetter = false; + --neededCharacters; + } + break; + case 2: + *i = numbers[rand() % 9]; + if(needNumber) { + needNumber = false; + --neededCharacters; + } + break; + case 3: + *i = symbols[rand() % 22]; + if(needSymbol) { + needSymbol = false; + --neededCharacters; + } + break; + } + } +} + +/*! + * \brief Generates a random character sequence using std::rand(). + * \remarks Might be removed because not used anymore. + */ +void generateRandomCharacterSequence(char *result, unsigned int length, bool useSmallLetters, bool useCapitalLetters, bool useNumbers, bool useSymbols, bool useAtLeastOneOfEachCategory) +{ + generateRandomCharacterSequence(result, length, rand, RAND_MAX, useSmallLetters, useCapitalLetters, useNumbers, useSymbols, useAtLeastOneOfEachCategory); +} + +} + diff --git a/misc/random.h b/misc/random.h index 7d2b56c..9f50357 100644 --- a/misc/random.h +++ b/misc/random.h @@ -1,15 +1,15 @@ -#ifndef RANDOMUTILS_H -#define RANDOMUTILS_H - -#include "../application/global.h" - -#include - -namespace RandomUtilities { - -LIB_EXPORT void generateRandomCharacterSequence(char *result, unsigned int length, bool useSmallLetters = true, bool useCapitalLetters = true, bool useNumbers = true, bool useSymbols = true, bool useAtLeastOneOfEachCategory = true); -LIB_EXPORT void generateRandomCharacterSequence(char *result, unsigned int length, std::function randomizer, int maximalRandomNumber, bool useSmallLetters = true, bool useCapitalLetters = true, bool useNumbers = true, bool useSymbols = true, bool useAtLeastOneOfEachCategory = true); - -} - -#endif // RANDOMUTILS_H +#ifndef RANDOMUTILS_H +#define RANDOMUTILS_H + +#include "../global.h" + +#include + +namespace RandomUtilities { + +CPP_UTILITIES_EXPORT void generateRandomCharacterSequence(char *result, unsigned int length, bool useSmallLetters = true, bool useCapitalLetters = true, bool useNumbers = true, bool useSymbols = true, bool useAtLeastOneOfEachCategory = true); +CPP_UTILITIES_EXPORT void generateRandomCharacterSequence(char *result, unsigned int length, std::function randomizer, int maximalRandomNumber, bool useSmallLetters = true, bool useCapitalLetters = true, bool useNumbers = true, bool useSymbols = true, bool useAtLeastOneOfEachCategory = true); + +} + +#endif // RANDOMUTILS_H diff --git a/tests/testutils.h b/tests/testutils.h index ff272c8..7770b6d 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -8,7 +8,7 @@ namespace TestUtilities { -class LIB_EXPORT TestApplication +class CPP_UTILITIES_EXPORT TestApplication { public: TestApplication(int argc, char **argv); @@ -79,7 +79,7 @@ inline const std::vector &TestApplication::units() const * \remarks A TestApplication must be present. * \sa TestApplication::testFilePath() */ -inline LIB_EXPORT std::string testFilePath(const std::string &name) +inline CPP_UTILITIES_EXPORT std::string testFilePath(const std::string &name) { return TestApplication::instance()->testFilePath(name); } @@ -90,7 +90,7 @@ inline LIB_EXPORT std::string testFilePath(const std::string &name) * \remarks A TestApplication must be present. * \sa TestApplication::workingCopyPath() */ -inline LIB_EXPORT std::string workingCopyPath(const std::string &name) +inline CPP_UTILITIES_EXPORT std::string workingCopyPath(const std::string &name) { return TestApplication::instance()->workingCopyPath(name); } @@ -100,7 +100,7 @@ inline LIB_EXPORT std::string workingCopyPath(const std::string &name) * \remarks A TestApplication must be present. * \sa TestApplication::execApp() */ -inline LIB_EXPORT int execApp(const char *const *args, std::string &output, std::string &errors) +inline CPP_UTILITIES_EXPORT int execApp(const char *const *args, std::string &output, std::string &errors) { return TestApplication::instance()->execApp(args, output, errors); }