├── .github ├── FUNDING.yml └── workflows │ └── actions_build.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── CC_CommsExternal.cmake ├── CC_CommsPrefetch.cmake ├── CC_Compile.cmake ├── CC_CxxtestFuncs.cmake ├── CC_DocCleanupScript.cmake ├── CC_RunWithValgrindScript.cmake └── LibCommsConfig.cmake ├── doc ├── BUILD.md ├── CMake.md └── README.md ├── doxygen ├── comms.dox ├── dia │ ├── frame.dia │ ├── frame_layers.dia │ └── message_class_hierarchy.dia ├── doxygen.conf ├── layout.xml ├── main.dox ├── page_assert.dox ├── page_custom_checksum_layer.dox ├── page_custom_id_layer.dox ├── page_custom_size_layer.dox ├── page_custom_sync_prefix_layer.dox ├── page_custom_transport_value_layer.dox ├── page_define_prot.dox ├── page_dispatch.dox ├── page_field.dox ├── page_frame.dox └── page_use_prot.dox ├── include └── comms │ ├── Assert.h │ ├── CompileControl.h │ ├── EmptyHandler.h │ ├── ErrorStatus.h │ ├── Field.h │ ├── GenericHandler.h │ ├── GenericMessage.h │ ├── Message.h │ ├── MessageBase.h │ ├── MsgDispatcher.h │ ├── MsgFactory.h │ ├── MsgFactoryCreateFailureReason.h │ ├── cast.h │ ├── comms.h │ ├── details │ ├── DispatchMsgHelperType.h │ ├── DispatchMsgIdRetrieveHelper.h │ ├── DispatchMsgLinearSwitchHelper.h │ ├── DispatchMsgPolymorphicHelper.h │ ├── DispatchMsgStaticBinSearchHelper.h │ ├── FieldBase.h │ ├── FieldCastHelper.h │ ├── MessageIdTypeRetriever.h │ ├── MessageImplBases.h │ ├── MessageImplBuilder.h │ ├── MessageImplOptionsParser.h │ ├── MessageInterfaceBases.h │ ├── MessageInterfaceBuilder.h │ ├── MessageInterfaceOptionsParser.h │ ├── MsgDispatcherOptionsParser.h │ ├── MsgFactoryBase.h │ ├── MsgFactoryOptionsParser.h │ ├── ProcessHelper.h │ ├── ReadIteratorHelper.h │ ├── ValueAssignWrapper.h │ ├── WriteIteratorHelper.h │ ├── base_detection.h │ ├── bits_access.h │ ├── detect.h │ ├── dispatch_impl.h │ ├── field_alias.h │ ├── fields_access.h │ ├── gen_enum.h │ ├── macro_common.h │ ├── message_check.h │ ├── process.h │ ├── protocol_layers_access.h │ ├── reverse_macro_args.h │ ├── tag.h │ ├── transport_fields_access.h │ └── variant_access.h │ ├── dispatch.h │ ├── field │ ├── ArrayList.h │ ├── Bitfield.h │ ├── BitmaskValue.h │ ├── Bundle.h │ ├── EnumValue.h │ ├── FloatValue.h │ ├── IntValue.h │ ├── Optional.h │ ├── OptionalMode.h │ ├── String.h │ ├── Variant.h │ ├── adapter │ │ ├── AvailableLength.h │ │ ├── CustomReadWrap.h │ │ ├── CustomRefreshWrap.h │ │ ├── CustomValidator.h │ │ ├── CustomWriteWrap.h │ │ ├── DefaultValueInitialiser.h │ │ ├── DisplayOffset.h │ │ ├── EmptySerialization.h │ │ ├── ExistsBetweenVersions.h │ │ ├── FailOnInvalid.h │ │ ├── FieldType.h │ │ ├── FixedBitLength.h │ │ ├── FixedLength.h │ │ ├── FixedValue.h │ │ ├── IgnoreInvalid.h │ │ ├── InvalidByDefault.h │ │ ├── MissingOnInvalid.h │ │ ├── MissingOnReadFail.h │ │ ├── NumValueMultiRangeValidator.h │ │ ├── RemLengthMemberField.h │ │ ├── SequenceElemFixedSerLengthFieldPrefix.h │ │ ├── SequenceElemLengthForcing.h │ │ ├── SequenceElemSerLengthFieldPrefix.h │ │ ├── SequenceFixedSize.h │ │ ├── SequenceLengthForcing.h │ │ ├── SequenceSerLengthFieldPrefix.h │ │ ├── SequenceSizeFieldPrefix.h │ │ ├── SequenceSizeForcing.h │ │ ├── SequenceTerminationFieldSuffix.h │ │ ├── SequenceTrailingFieldSuffix.h │ │ ├── SerOffset.h │ │ ├── VarLength.h │ │ ├── VariantResetOnDestruct.h │ │ └── VersionStorage.h │ ├── basic │ │ ├── ArrayList.h │ │ ├── Bitfield.h │ │ ├── Bundle.h │ │ ├── CommonFuncs.h │ │ ├── EnumValue.h │ │ ├── FloatValue.h │ │ ├── IntValue.h │ │ ├── Optional.h │ │ ├── String.h │ │ └── Variant.h │ ├── basics.h │ ├── details │ │ ├── AdaptBasicField.h │ │ ├── FieldOpHelpers.h │ │ ├── MembersVersionDependency.h │ │ ├── OptionsParser.h │ │ ├── VersionStorage.h │ │ └── adapters.h │ └── tag.h │ ├── field_cast.h │ ├── fields.h │ ├── frame │ ├── ChecksumLayer.h │ ├── ChecksumPrefixLayer.h │ ├── FrameLayerBase.h │ ├── MsgDataLayer.h │ ├── MsgIdLayer.h │ ├── MsgSizeLayer.h │ ├── SyncPrefixLayer.h │ ├── TransportValueLayer.h │ ├── checksum │ │ ├── BasicSum.h │ │ ├── BasicXor.h │ │ └── Crc.h │ └── details │ │ ├── ChecksumLayerBase.h │ │ ├── ChecksumLayerOptionsParser.h │ │ ├── ChecksumPrefixLayerBase.h │ │ ├── FrameLayerBaseOptionsParser.h │ │ ├── FrameLayerDetails.h │ │ ├── MsgDataLayerOptionsParser.h │ │ ├── MsgIdLayerBase.h │ │ ├── MsgIdLayerOptionsParser.h │ │ ├── MsgSizeLayerBase.h │ │ ├── MsgSizeLayerConstNullPtrCastHelper.h │ │ ├── MsgSizeLayerOptionsParser.h │ │ ├── SyncPrefixLayerBase.h │ │ ├── SyncPrefixLayerOptionsParser.h │ │ ├── TransportValueLayerAllBases.h │ │ ├── TransportValueLayerBase.h │ │ └── TransportValueLayerOptionsParser.h │ ├── frames.h │ ├── iterator.h │ ├── options.h │ ├── process.h │ ├── protocol │ ├── ChecksumLayer.h │ ├── ChecksumPrefixLayer.h │ ├── MsgDataLayer.h │ ├── MsgIdLayer.h │ ├── MsgSizeLayer.h │ ├── ProtocolLayerBase.h │ ├── SyncPrefixLayer.h │ ├── TransportValueLayer.h │ └── checksum │ │ ├── BasicSum.h │ │ ├── BasicXor.h │ │ └── Crc.h │ ├── protocols.h │ ├── traits.h │ ├── units.h │ ├── util │ ├── AlignedStorage.h │ ├── ArrayView.h │ ├── BitSizeToByteSize.h │ ├── MaxSizeOf.h │ ├── ScopeGuard.h │ ├── SizeToType.h │ ├── StaticQueue.h │ ├── StaticString.h │ ├── StaticVector.h │ ├── StringView.h │ ├── Tuple.h │ ├── access.h │ ├── alloc.h │ ├── assign.h │ ├── construct.h │ ├── details │ │ ├── AssignHelper.h │ │ ├── ConstructHelper.h │ │ ├── detect.h │ │ └── type_traits.h │ ├── detect.h │ └── type_traits.h │ └── version.h ├── script ├── dia ├── env_dev.sh ├── env_dev_clang.sh ├── env_dev_clang12.sh ├── env_dev_clang12_release.sh ├── env_dev_clang15.sh ├── env_dev_clang18_release.sh ├── env_dev_clang19_release.sh ├── env_dev_gcc.sh ├── env_dev_gcc11_release.sh ├── env_dev_gcc12.sh ├── env_dev_gcc12_release.sh ├── env_dev_gcc14.sh ├── env_dev_gcc_release.sh ├── env_dev_rel.sh ├── env_dev_size.sh └── env_dev_size_gcc.sh └── test ├── CMakeLists.txt ├── ChecksumLayer.th ├── ChecksumPrefixLayer.th ├── CommsTestCommon.h ├── CustomChecksumLayer.th ├── CustomChecksumPrefixLayer.th ├── CustomMsgIdLayer.th ├── CustomMsgSizeLayer.th ├── CustomSyncPrefixLayer.th ├── CustomTransportValueLayer.th ├── Dispatch.th ├── Fields.th ├── Fields2.th ├── Message.th ├── MsgDataLayer.th ├── MsgFactory.th ├── MsgIdLayer.th ├── MsgSizeLayer.th ├── SyncPrefixLayer.th ├── TransportValueLayer.th └── Util.th /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: arobenko 2 | custom: "https://www.paypal.me/arobenko" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build* 2 | .project 3 | .cproject 4 | CMakeLists.txt.user 5 | *autosave 6 | .vscode 7 | externals* 8 | -------------------------------------------------------------------------------- /cmake/CC_CommsPrefetch.cmake: -------------------------------------------------------------------------------- 1 | # This file contains contains a function that prefetches comms project. 2 | 3 | # ****************************************************** 4 | # cc_comms_prefetch( 5 | # SRC_DIR 6 | # [TAG ] 7 | # [REPO ] 8 | # ) 9 | # 10 | # - SRC_DIR - A directory where comms sources will end up. 11 | # - TAG - Override the default tag to checkout. 12 | # - REPO - Override the default repository of the comms. 13 | # 14 | 15 | set (CC_FETCH_DEFAULT_REPO "https://github.com/commschamp/comms.git") 16 | set (CC_FETCH_DEFAULT_TAG "master") 17 | 18 | function (cc_comms_prefetch) 19 | set (_prefix CC_FETCH) 20 | set (_options) 21 | set (_oneValueArgs SRC_DIR REPO TAG) 22 | set (_mutiValueArgs) 23 | cmake_parse_arguments(${_prefix} "${_options}" "${_oneValueArgs}" "${_mutiValueArgs}" ${ARGN}) 24 | 25 | if (NOT CC_FETCH_SRC_DIR) 26 | message (FATAL_ERROR "The SRC_DIR parameter is not provided") 27 | endif () 28 | 29 | if (NOT CC_FETCH_REPO) 30 | set (CC_FETCH_REPO ${CC_FETCH_DEFAULT_REPO}) 31 | endif () 32 | 33 | if (NOT CC_FETCH_TAG) 34 | set (CC_FETCH_TAG ${CC_FETCH_DEFAULT_TAG}) 35 | endif () 36 | 37 | if (NOT GIT_FOUND) 38 | find_package(Git REQUIRED) 39 | endif () 40 | 41 | if (EXISTS "${CC_FETCH_SRC_DIR}/.git") 42 | execute_process ( 43 | COMMAND ${GIT_EXECUTABLE} fetch 44 | WORKING_DIRECTORY ${CC_FETCH_SRC_DIR} 45 | ) 46 | 47 | execute_process ( 48 | COMMAND ${GIT_EXECUTABLE} checkout ${CC_FETCH_TAG} 49 | WORKING_DIRECTORY ${CC_FETCH_SRC_DIR} 50 | ) 51 | 52 | return () 53 | endif() 54 | 55 | execute_process ( 56 | COMMAND ${CMAKE_COMMAND} -E remove_directory "${CC_FETCH_SRC_DIR}" 57 | ) 58 | 59 | execute_process ( 60 | COMMAND ${CMAKE_COMMAND} -E make_directory "${CC_FETCH_SRC_DIR}" 61 | ) 62 | 63 | execute_process ( 64 | COMMAND 65 | ${GIT_EXECUTABLE} clone -b ${CC_FETCH_TAG} ${CC_FETCH_REPO} ${CC_FETCH_SRC_DIR} 66 | RESULT_VARIABLE git_result 67 | ) 68 | 69 | if (NOT "${git_result}" STREQUAL "0") 70 | message (WARNING "git clone/checkout failed") 71 | endif () 72 | 73 | endfunction() 74 | -------------------------------------------------------------------------------- /cmake/CC_DocCleanupScript.cmake: -------------------------------------------------------------------------------- 1 | # This script replaces all absolute paths in the generated HTML documentation 2 | # with relative one to make the documentation directory relocatable. 3 | # It can be useful when documentation contains images generated by DIA. 4 | # The reference to such images is usually an absolute path, that needs to be updated. 5 | # 6 | # Expected input variables 7 | # DOC_OUTPUT_DIR - Directory of the installed documenation 8 | 9 | file(GLOB_RECURSE all_doc_files "${DOC_OUTPUT_DIR}/*.html") 10 | 11 | foreach (f ${all_doc_files}) 12 | file (READ ${f} f_text) 13 | string (REPLACE "${DOC_OUTPUT_DIR}/html/" "" modified_f_text "${f_text}") 14 | file (WRITE "${f}" "${modified_f_text}") 15 | endforeach () 16 | -------------------------------------------------------------------------------- /cmake/CC_RunWithValgrindScript.cmake: -------------------------------------------------------------------------------- 1 | # This script allows running of prevously compiled binary (unit test) with 2 | # valgrind. 3 | # 4 | # Expected variables: 5 | # VALGRIND_EXECUTABLE - path the the valgrind. 6 | # TEST_EXECUTABLE - path to the test binary. 7 | 8 | if ("${VALGRIND_EXECUTABLE}" STREQUAL "") 9 | message (FATAL_ERROR "No valgrind is found!") 10 | endif () 11 | 12 | if (("${TEST_EXECUTABLE}" STREQUAL "") OR (NOT EXISTS ${TEST_EXECUTABLE})) 13 | message (FATAL_ERROR "Invalid test ${TEST_EXECUTABLE}!") 14 | endif () 15 | 16 | message ("Test: ${TEST_EXECUTABLE}") 17 | set (_cmd ${VALGRIND_EXECUTABLE} --leak-check=yes -q ${TEST_EXECUTABLE}) 18 | message ("Command: ${_cmd}") 19 | 20 | execute_process( 21 | COMMAND ${_cmd} 22 | RESULT_VARIABLE _result 23 | OUTPUT_VARIABLE _output 24 | ERROR_VARIABLE _output 25 | ) 26 | 27 | message("${_output}") 28 | 29 | if (NOT "${_result}" STREQUAL "0") 30 | message (FATAL_ERROR "Test failed with exit code ${_result}") 31 | endif () 32 | 33 | if ("${_output}" MATCHES "[.]*==[0-9]*== [.]*") 34 | message (FATAL_ERROR "Valgrind reported errors.") 35 | endif () 36 | 37 | 38 | -------------------------------------------------------------------------------- /cmake/LibCommsConfig.cmake: -------------------------------------------------------------------------------- 1 | # Find COMMS library from CommsChampion Ecosystem 2 | # 3 | # Output is provided using the following variables 4 | # CC_COMMS_FOUND - Found COMMS library, use CC_COMMS_INCLUDE_DIRS for includes. 5 | # CC_COMMS_INCLUDE_DIRS - Where to find all the headers. 6 | # CC_COMMS_CMAKE_DIR - Where to find all the COMMS library cmake scripts. 7 | # 8 | # Additional output targets 9 | # cc::comms - Link target for COMMS library 10 | 11 | if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/commsExport.cmake) 12 | include (${CMAKE_CURRENT_LIST_DIR}/commsExport.cmake) 13 | endif () 14 | 15 | # Load information for each installed configuration. 16 | file(GLOB config_files "${CMAKE_CURRENT_LIST_DIR}/LibCommsConfig-*.cmake") 17 | foreach(f ${config_files}) 18 | include(${f}) 19 | endforeach() 20 | 21 | if (NOT TARGET cc::comms) 22 | return () 23 | endif () 24 | 25 | get_target_property(CC_COMMS_INCLUDE_DIRS cc::comms INTERFACE_INCLUDE_DIRECTORIES) 26 | set (CC_COMMS_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR}) 27 | 28 | set (name "${CMAKE_FIND_PACKAGE_NAME}") 29 | if ("${name}" STREQUAL "") 30 | set (name "LibComms") 31 | endif () 32 | 33 | find_package(PackageHandleStandardArgs REQUIRED) 34 | FIND_PACKAGE_HANDLE_STANDARD_ARGS( 35 | ${name} 36 | REQUIRED_VARS CC_COMMS_INCLUDE_DIRS CC_COMMS_CMAKE_DIR) 37 | 38 | set (CC_COMMS_FOUND ${LibComms_FOUND}) 39 | 40 | if (CC_COMMS_FOUND) 41 | set (CC_COMMS_INCLUDE_DIR ${CC_COMMS_INCLUDE_DIRS}) 42 | endif () 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /doc/BUILD.md: -------------------------------------------------------------------------------- 1 | # How to Build 2 | 3 | This project uses [CMake](https://cmake.org) cross-platform build system to 4 | generate required build files native to the platform. 5 | 6 | ## Available CMake Options 7 | Please open major [CMakeLists.txt](../CMakeLists.txt) for the complete list 8 | of available options and other input parameters. 9 | 10 | ## Choosing C++ Standard 11 | 12 | Since CMake **v3.1** it became possible to set version of C++ standard by setting 13 | **CMAKE_CXX_STANDARD** variable. If no value of this variable is set in command 14 | line arguments, default value **11** will be assigned to it. In order to use 15 | c++14 standard in compilation, set the variable value to **14**. 16 | 17 | Please **NOTE**, that _clang_ compiler may have problems compiling valid c++11 18 | constructs used in this project. Usage of C++14 may fix the problem. 19 | 20 | ## Build and Install Examples 21 | 22 | The examples below are Linux/Unix system oriented, i.e. they use **make** utility 23 | to build the "install" target after configuration with **cmake**. 24 | 25 | On Windows 26 | systems with Visual Studio compiler, the CMake utility generates Visual Studio 27 | solution files by default. Build "install" project. It is also possible to 28 | generate Makefile-s on Windows by providing additional **-G "NMake Makefiles"** option 29 | to **cmake**. In this case use **nmake** utility instead of **make**. 30 | 31 | Please review the examples below and use appropriate option that suites your 32 | needs. 33 | 34 | ### Install Headers of the **COMMS** Library Linux Example 35 | 36 | ``` 37 | $> cd /path/to/comms 38 | $> mkdir build && cd build 39 | $> cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/some/install/dir 40 | $> make install 41 | ``` 42 | 43 | ### Build Unittests in Debug Mode Linux Example 44 | 45 | ``` 46 | $> cd /path/to/comms 47 | $> mkdir build && cd build 48 | $> cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/some/install/dir \ 49 | -DCC_COMMS_BUILD_UNIT_TESTS=ON 50 | $> make install 51 | ``` 52 | ### Windows + Visual Studio Build Example 53 | Generate Makefile-s with **cmake** and use Visual Studio compiler to build. 54 | 55 | ``` 56 | $> cd /path/to/comms 57 | $> mkdir build && cd build 58 | $> cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/some/install/dir \ 59 | -G "NMake Makefiles" 60 | $> nmake install 61 | ``` 62 | 63 | ### Using Clang Compiler 64 | Please use c++14 standard with clang compiler. 65 | 66 | ``` 67 | $> cd /path/to/comms/sources 68 | $> mkdir build && cd build 69 | $> CC=clang CXX=clang++ cmake -DCMAKE_BUILD_TYPE=Release \ 70 | -DCMAKE_INSTALL_PREFIX=/some/install/dir -DCMAKE_CXX_STANDARD=14 .. 71 | $> make install 72 | ``` 73 | 74 | ## Building Documentation 75 | The documentation is not created during normal build process. The documentation of 76 | the **COMMS Library** 77 | can be generated by building **doc_comms** target: 78 | 79 | ``` 80 | $> make doc_comms 81 | ``` 82 | 83 | The HTML documentation will reside in **${CMAKE_INSTALL_PREFIX}/share/doc/comms/html** directory. 84 | 85 | **NOTE**, that you must have 86 | [Doxygen](www.doxygen.org) 87 | and [Dia](https://wiki.gnome.org/Apps/Dia) 88 | being installed on your system in order to be able to properly generate the 89 | documentation. 90 | 91 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | The available documentation pages are: 3 | 4 | - [BUILD.md](BUILD.md) - Instructions how to build this project 5 | - [CMake.md](CMake.md) - Instructions how to use COMMS library in other cmake project. 6 | 7 | -------------------------------------------------------------------------------- /doxygen/dia/frame.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commschamp/comms/cd5c79581d119992b53a4c2ba710343380b27dce/doxygen/dia/frame.dia -------------------------------------------------------------------------------- /doxygen/dia/frame_layers.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commschamp/comms/cd5c79581d119992b53a4c2ba710343380b27dce/doxygen/dia/frame_layers.dia -------------------------------------------------------------------------------- /doxygen/dia/message_class_hierarchy.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commschamp/comms/cd5c79581d119992b53a4c2ba710343380b27dce/doxygen/dia/message_class_hierarchy.dia -------------------------------------------------------------------------------- /doxygen/main.dox: -------------------------------------------------------------------------------- 1 | /// @mainpage COMMS Library 2 | /// @tableofcontents 3 | /// @b COMMS is the headers only, platform independent library, 4 | /// which makes the implementation of a binary communication 5 | /// protocol to be an easy and relatively quick process. It provides all the necessary 6 | /// types and classes to make the definition of the custom messages, as well as 7 | /// wrapping transport data fields, to be simple declarative statements of type and 8 | /// class definitions. These statements will specify @b WHAT needs to be implemented. 9 | /// The @b COMMS library internals handle the **HOW** part. 10 | /// 11 | /// The internals of the @b COMMS library is mostly template classes which use 12 | /// multiple meta-programming techniques. As the result, only the functionality, 13 | /// required by the protocol being developed, gets compiled in, providing the best code size and 14 | /// speed performance possible. The down side is that compilation process may 15 | /// take a significant amount of time and consume a lot of memory. 16 | /// 17 | /// The @b COMMS library allows having single implementation of the binary 18 | /// protocol messages, which can be re-compiled and used for any possible application: 19 | /// bare-metal with constrained resources, Linux based embedded systems, even 20 | /// independent GUI analysis tools. 21 | /// 22 | /// The @b COMMS library was specifically developed to be used in **embedded** systems 23 | /// including @b bare-metal ones. It doesn't use exceptions and/or RTTI. It also 24 | /// minimises usage of dynamic memory allocation and provides an ability to exclude 25 | /// it altogether if required, which may be needed when developing @b bare-metal 26 | /// embedded systems. 27 | /// 28 | /// @ref page_use_prot is a tutorial on how to use already defined custom binary protocol. 29 | /// If you are about to develop one, it would be beneficial to read it as well 30 | /// in order to get an impresion on how the protocol definition code is going to be used. 31 | /// 32 | /// @ref page_define_prot is intended for developers that need to implement a library 33 | /// for custom binary protocol, which can be used in any application in the future, 34 | /// including bare-metal one with constrained environment. 35 | /// 36 | /// Refer to @ref version.h "comms/version.h" file for the version 37 | /// information of the @b COMMS library and this documentation. 38 | /// 39 | -------------------------------------------------------------------------------- /doxygen/page_assert.dox: -------------------------------------------------------------------------------- 1 | /// @page page_assert Custom Assertion Failure Behaviour 2 | /// First of all, there is a need to define a custom assertion failure report 3 | /// class which inherits from comms::Assert and overrides pure virtual member 4 | /// function fail(): 5 | /// @code 6 | /// #include "comms/comms.h" 7 | /// class MyAssert : public comms::Assert 8 | /// { 9 | /// public: 10 | /// MyAssert(...) {...} // The constructor may receive any parameters needed 11 | /// protected: 12 | /// virtual void fail( 13 | /// const char* expr, 14 | /// const char* file, 15 | /// unsigned int line, 16 | /// const char* function) override 17 | /// { 18 | /// ... // Do the failure report 19 | /// } 20 | /// private: 21 | /// ... // Any data members 22 | /// } 23 | /// @endcode 24 | /// The second stage is to enable/register the the custom assertion failure behaviour: 25 | /// @code 26 | /// int main(int argc, const char* argv[]) 27 | /// { 28 | /// comms::EnableAssert enabledAssert; 29 | /// // From this point custom assertion failure bahaviour takes place. 30 | /// ... 31 | /// } 32 | /// @endcode 33 | /// It is also possible to override custom assertion failure behavior several times: 34 | /// @code 35 | /// int main(int argc, const char* argv[]) 36 | /// { 37 | /// comms::EnableAssert assert1; 38 | /// // From this point custom assertion failure bahaviour takes place. 39 | /// ... 40 | /// { 41 | /// comms::EnableAssert assert2; 42 | /// // From this point different custom assertion failure bahaviour 43 | /// // defined in SomeOtherMyAssert class takes place. 44 | /// ... 45 | /// } // assert2 is out of scope, the custom assertion failure behavior 46 | /// // registered with assert1 is restored. 47 | /// ... 48 | /// } 49 | /// @endcode 50 | -------------------------------------------------------------------------------- /include/comms/EmptyHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::EmptyHandler class 10 | 11 | #pragma once 12 | 13 | namespace comms 14 | { 15 | 16 | /// @brief Empty message handler, does nothing. 17 | /// @details May be used in @ref comms::option::app::Handler option to force 18 | /// existence of "comms::Message::dispatch()" member function. 19 | class EmptyHandler 20 | { 21 | public: 22 | template 23 | void handle(TMessage&) {} 24 | }; 25 | 26 | } // namespace comms 27 | 28 | 29 | -------------------------------------------------------------------------------- /include/comms/ErrorStatus.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file comms/ErrorStatus.h 9 | /// @brief This file contain definition of error statuses used by comms module. 10 | 11 | #pragma once 12 | 13 | namespace comms 14 | { 15 | 16 | /// @brief Error statuses reported by the Communication module. 17 | enum class ErrorStatus { 18 | Success, ///< Used to indicate successful outcome of the operation. 19 | UpdateRequired, ///< Used to indicate that write operation wasn't complete, 20 | /// call to update(...) is required. 21 | NotEnoughData, ///< Used to indicate that stream buffer didn't contain 22 | /// enough data to complete read operation. 23 | ProtocolError, ///< Used to indicate that any of the used protocol layers 24 | /// encountered an error while processing the data. 25 | BufferOverflow, ///< Used to indicate that stream buffer was overflowed 26 | /// when attempting to write data. 27 | InvalidMsgId, ///< Used to indicate that received message has unknown id 28 | InvalidMsgData, /// 29 | details::ValueAssignWrapper cast_assign(T& value) 30 | { 31 | return details::ValueAssignWrapper(value); 32 | } 33 | 34 | /// @brief Cast between fields. 35 | /// @details Sometimes the protocol may treat some specific field differently 36 | /// based on indication bit in some other field. This function can be 37 | /// used to cast one field to another type. 38 | /// @code 39 | /// SomeFieldType someField = comms::field_cast(someOtherField); 40 | /// @endcode 41 | /// The function will perform some compile time analysis and will do a simple 42 | /// static_cast between the contained values if they are convertible. Otherwise 43 | /// the write + read operations will be performed, i.e. the source field will 44 | /// be written into a temporary buffer, and the target field will perform a 45 | /// read operation from that buffer. 46 | /// @tparam TFieldTo Type to cast to. 47 | /// @tparam TFieldFrom Type to cast from. 48 | /// @param[in] field Original field 49 | /// @return Field of the new type with internal value equivalent to one of the 50 | /// original field. 51 | /// @note Defined in "comms/cast.h" headerfile 52 | template 53 | TFieldTo field_cast(const TFieldFrom& field) 54 | { 55 | return details::FieldCastHelper<>::template cast(field); 56 | } 57 | 58 | 59 | } // namespace comms 60 | -------------------------------------------------------------------------------- /include/comms/comms.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Aggregates all the includes of the @b COMMS library interface 10 | 11 | #pragma once 12 | 13 | #include "comms/dispatch.h" 14 | #include "comms/fields.h" 15 | #include "comms/field_cast.h" 16 | #include "comms/frames.h" 17 | #include "comms/iterator.h" 18 | #include "comms/process.h" 19 | #include "comms/protocols.h" 20 | #include "comms/units.h" 21 | #include "comms/version.h" 22 | 23 | #include "comms/CompileControl.h" 24 | #include "comms/EmptyHandler.h" 25 | #include "comms/GenericHandler.h" 26 | #include "comms/GenericMessage.h" 27 | #include "comms/Message.h" 28 | #include "comms/MessageBase.h" 29 | #include "comms/MsgDispatcher.h" 30 | #include "comms/MsgFactory.h" 31 | 32 | #include "comms/util/assign.h" 33 | #include "comms/util/construct.h" 34 | #include "comms/util/detect.h" 35 | #include "comms/util/type_traits.h" 36 | -------------------------------------------------------------------------------- /include/comms/details/DispatchMsgHelperType.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/util/type_traits.h" 11 | 12 | namespace comms 13 | { 14 | 15 | namespace details 16 | { 17 | 18 | enum class DispatchMsgTypeEnum 19 | { 20 | Multiple, 21 | Single, 22 | None 23 | }; 24 | 25 | template 26 | using DispatchMsgHelperIntType = 27 | typename comms::util::Conditional< 28 | TCount == 0U 29 | >::template Type< 30 | std::integral_constant, 31 | typename comms::util::Conditional< 32 | TCount == 1U 33 | >::template Type< 34 | std::integral_constant, 35 | std::integral_constant 36 | > 37 | >; 38 | 39 | 40 | } // namespace details 41 | 42 | } // namespace comms 43 | -------------------------------------------------------------------------------- /include/comms/details/DispatchMsgIdRetrieveHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/CompileControl.h" 11 | #include "comms/details/message_check.h" 12 | #include "comms/details/tag.h" 13 | #include "comms/Message.h" 14 | #include "comms/MessageBase.h" 15 | #include "comms/util/Tuple.h" 16 | #include "comms/util/type_traits.h" 17 | 18 | #include 19 | #include 20 | 21 | namespace comms 22 | { 23 | 24 | namespace details 25 | { 26 | 27 | template 28 | class DispatchMsgIdRetrieveHelper 29 | { 30 | public: 31 | 32 | template 33 | static typename TMessage::MsgIdParamType doGetId() 34 | { 35 | static_assert(TMessage::hasMsgIdType(), "Message interface class must define its id type"); 36 | static_assert(!std::is_same, NoIdTag<> >::value, "Must be able to retrieve ID"); 37 | 38 | return doGetIdInternal(Tag()); 39 | } 40 | 41 | private: 42 | template 43 | using HasStaticIdTag = comms::details::tag::Tag1<>; 44 | 45 | template 46 | using HasDynamicIdTag = comms::details::tag::Tag2<>; 47 | 48 | template 49 | using NoIdTag = comms::details::tag::Tag3<>; 50 | 51 | template 52 | using DynamicCheckTag = 53 | typename comms::util::LazyShallowConditional< 54 | comms::isMessage() && TMessage::hasGetId() 55 | >::template Type< 56 | HasDynamicIdTag, 57 | NoIdTag 58 | >; 59 | 60 | template 61 | using Tag = 62 | typename comms::util::LazyShallowConditional< 63 | messageHasStaticNumId() 64 | >::template Type< 65 | HasStaticIdTag, 66 | DynamicCheckTag, 67 | TMessage 68 | >; 69 | 70 | template 71 | static typename TMessage::MsgIdParamType doGetIdInternal(HasStaticIdTag) 72 | { 73 | static_assert(comms::isMessageBase(), "Must be actual message"); 74 | static_assert(messageHasStaticNumId(), "Message must define static numeric ID"); 75 | 76 | return TMessage::doGetId(); 77 | } 78 | 79 | template 80 | static typename TMessage::MsgIdParamType doGetIdInternal(HasDynamicIdTag) 81 | { 82 | static_assert(comms::isMessage(), "Must be actual message"); 83 | static_assert(TMessage::hasGetId(), "Message interface must be able to return id polymorphically"); 84 | 85 | static const typename TMessage::MsgIdType Id = TMessage().getId(); 86 | return Id; 87 | } 88 | }; 89 | 90 | template 91 | auto dispatchMsgGetMsgId() -> decltype(DispatchMsgIdRetrieveHelper<>::template doGetId()) 92 | { 93 | return DispatchMsgIdRetrieveHelper<>::template doGetId(); 94 | } 95 | 96 | } // namespace details 97 | 98 | } // namespace comms -------------------------------------------------------------------------------- /include/comms/details/FieldBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/options.h" 11 | #include "comms/traits.h" 12 | 13 | namespace comms 14 | { 15 | 16 | namespace details 17 | { 18 | 19 | template 20 | class FieldBase; 21 | 22 | template <> 23 | class FieldBase<> 24 | { 25 | protected: 26 | // Use big endian by default 27 | using Endian = comms::traits::endian::Big; 28 | 29 | // Use unsigned type by default for versioning 30 | using VersionType = unsigned; 31 | }; 32 | 33 | template 34 | class FieldBase, TOptions...> : public FieldBase 35 | { 36 | protected: 37 | using Endian = TEndian; 38 | }; 39 | 40 | template 41 | class FieldBase, TOptions...> : public FieldBase 42 | { 43 | protected: 44 | using VersionType = T; 45 | }; 46 | 47 | template 48 | class FieldBase : public FieldBase 49 | { 50 | }; 51 | 52 | template 53 | class FieldBase, TOptions...> : public FieldBase 54 | { 55 | }; 56 | 57 | 58 | } // namespace details 59 | 60 | } // namespace comms 61 | 62 | 63 | -------------------------------------------------------------------------------- /include/comms/details/FieldCastHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/details/tag.h" 11 | #include "comms/ErrorStatus.h" 12 | #include "comms/util/type_traits.h" 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | namespace comms 19 | { 20 | 21 | namespace details 22 | { 23 | 24 | template 25 | class FieldCastHelper 26 | { 27 | public: 28 | template 29 | static TFieldTo cast(const TFieldFrom& field) 30 | { 31 | return castInternal(field, Tag()); 32 | } 33 | 34 | private: 35 | 36 | template 37 | using StaticCastTag = comms::details::tag::Tag1<>; 38 | 39 | template 40 | using WriteReadTag = comms::details::tag::Tag2<>; 41 | 42 | template 43 | using Convertible = 44 | std::is_convertible; 45 | 46 | template 47 | using IsIntegral = 48 | std::integral_constant< 49 | bool, 50 | std::is_enum::value || 51 | std::is_integral::value 52 | >; 53 | 54 | template 55 | using UseStaticCast = 56 | std::integral_constant< 57 | bool, 58 | Convertible::value || 59 | (IsIntegral::value && IsIntegral::value) 60 | >; 61 | 62 | template 63 | using Tag = 64 | typename comms::util::LazyShallowConditional< 65 | UseStaticCast::value 66 | >::template Type< 67 | StaticCastTag, 68 | WriteReadTag 69 | >; 70 | 71 | template 72 | static TFieldTo castInternal(const TFieldFrom& field, StaticCastTag) 73 | { 74 | TFieldTo result; 75 | result.value() = static_cast(field.value()); 76 | return result; 77 | } 78 | 79 | template 80 | static TFieldTo castInternal(const TFieldFrom& field, WriteReadTag) 81 | { 82 | static_assert(TFieldFrom::minLength() <= TFieldTo::maxLength(), "Casting between specified fields will fail ."); 83 | 84 | static const auto MaxBufSize = TFieldFrom::maxLength(); 85 | std::uint8_t buf[MaxBufSize] = {0}; 86 | auto* writeIter = &buf[0]; 87 | auto es = field.write(writeIter, MaxBufSize); 88 | COMMS_ASSERT(es == comms::ErrorStatus::Success); 89 | if (es != comms::ErrorStatus::Success) { 90 | return TFieldTo(); 91 | } 92 | 93 | auto len = static_cast(std::distance(&buf[0], writeIter)); 94 | COMMS_ASSERT(len <= MaxBufSize); 95 | 96 | TFieldTo result; 97 | const auto* readIter = &buf[0]; 98 | es = result.read(readIter, len); 99 | static_cast(es); 100 | COMMS_ASSERT(es == comms::ErrorStatus::Success); 101 | return result; 102 | } 103 | }; 104 | 105 | 106 | } // namespace details 107 | 108 | } // namespace comms 109 | 110 | 111 | -------------------------------------------------------------------------------- /include/comms/details/MessageIdTypeRetriever.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | namespace comms 11 | { 12 | 13 | namespace details 14 | { 15 | 16 | template 17 | struct MessageIdTypeRetriever 18 | { 19 | template 20 | using Type = typename TMsg::MsgIdType; 21 | }; 22 | 23 | } // namespace details 24 | 25 | } // namespace comms 26 | -------------------------------------------------------------------------------- /include/comms/details/MessageImplBuilder.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/CompileControl.h" 11 | #include "comms/Assert.h" 12 | #include "comms/details/MessageImplOptionsParser.h" 13 | #include "comms/ErrorStatus.h" 14 | #include "comms/util/access.h" 15 | #include "comms/util/Tuple.h" 16 | #include "comms/util/type_traits.h" 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | namespace comms 23 | { 24 | 25 | namespace details 26 | { 27 | 28 | template 29 | class MessageImplBuilder 30 | { 31 | using ParsedOptions = MessageImplOptionsParser; 32 | 33 | static_assert(ParsedOptions::HasFieldsImpl, "Option comms::option::def::FieldsImpl must be used"); 34 | 35 | using FieldsBase = 36 | typename ParsedOptions::template BuildFieldsImpl; 37 | 38 | using FailOnInvalidBase = 39 | typename ParsedOptions::template BuildFailOnInvalidImpl; 40 | 41 | using VersionBase = 42 | typename ParsedOptions::template BuildVersionImpl; 43 | 44 | using FieldsReadImplBase = 45 | typename ParsedOptions::template BuildReadImpl; 46 | 47 | using FieldsWriteImplBase = 48 | typename ParsedOptions::template BuildWriteImpl; 49 | 50 | using FieldsValidBase = 51 | typename ParsedOptions::template BuildValidImpl; 52 | 53 | using FieldsLengthBase = 54 | typename ParsedOptions::template BuildLengthImpl; 55 | 56 | using RefreshBase = 57 | typename ParsedOptions::template BuildRefreshImpl; 58 | 59 | using DispatchBase = 60 | typename ParsedOptions::template BuildDispatchImpl; 61 | 62 | using StaticNumIdBase = 63 | typename ParsedOptions::template BuildStaticMsgId; 64 | 65 | using PolymorphicStaticNumIdBase = 66 | typename ParsedOptions::template BuildMsgIdImpl; 67 | 68 | using NameBase = 69 | typename ParsedOptions::template BuildNameImpl; 70 | 71 | public: 72 | using Options = ParsedOptions; 73 | using Type = NameBase; 74 | }; 75 | 76 | template 77 | using MessageImplBuilderT = 78 | typename MessageImplBuilder::Type; 79 | 80 | } // namespace details 81 | 82 | } // namespace comms 83 | 84 | 85 | -------------------------------------------------------------------------------- /include/comms/details/MessageInterfaceBuilder.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/details/MessageInterfaceOptionsParser.h" 11 | 12 | namespace comms 13 | { 14 | 15 | namespace details 16 | { 17 | 18 | template 19 | class MessageInterfaceBuilder 20 | { 21 | using ParsedOptions = MessageInterfaceOptionsParser; 22 | 23 | static_assert((!ParsedOptions::HasVersionInExtraTransportFields) || ParsedOptions::HasExtraTransportFields, 24 | "comms::option::def::VersionInExtraTransportFields option should not be used " 25 | "without comms::option::def::ExtraTransportFields."); 26 | 27 | static constexpr bool MustHaveVirtualDestructor = 28 | (!ParsedOptions::HasNoVirtualDestructor) && 29 | ( 30 | ParsedOptions::HasReadIterator || 31 | ParsedOptions::HasWriteIterator || 32 | ParsedOptions::HasMsgIdInfo || 33 | ParsedOptions::HasHandler || 34 | ParsedOptions::HasValid || 35 | ParsedOptions::HasLength || 36 | ParsedOptions::HasRefresh || 37 | ParsedOptions::HasName 38 | ); 39 | 40 | using EndianBase = typename ParsedOptions::template BuildEndian<>; 41 | 42 | using IdTypeBase = 43 | typename ParsedOptions::template BuildMsgIdType; 44 | 45 | using TransportFieldsBase = 46 | typename ParsedOptions::template BuildExtraTransportFields; 47 | 48 | using VersionInTransportFieldsBase = 49 | typename ParsedOptions::template BuildVersionInExtraTransportFields; 50 | 51 | using IdInfoBase = 52 | typename ParsedOptions::template BuildMsgIdInfo; 53 | 54 | using ReadBase = 55 | typename ParsedOptions::template BuildReadBase; 56 | 57 | using WriteBase = 58 | typename ParsedOptions::template BuildWriteBase; 59 | 60 | using ValidBase = 61 | typename ParsedOptions::template BuildValid; 62 | 63 | using LengthBase = 64 | typename ParsedOptions::template BuildLength; 65 | 66 | using HandlerBase = 67 | typename ParsedOptions::template BuildHandler; 68 | 69 | using RefreshBase = 70 | typename ParsedOptions::template BuildRefresh; 71 | 72 | using NameBase = 73 | typename ParsedOptions::template BuildName; 74 | 75 | using VirtDestructorBase = 76 | typename comms::util::LazyShallowDeepConditional< 77 | MustHaveVirtualDestructor 78 | >::template Type< 79 | MessageInterfaceVirtDestructorBase, 80 | comms::util::TypeDeepWrap, 81 | NameBase 82 | >; 83 | public: 84 | using Options = ParsedOptions; 85 | using Type = VirtDestructorBase; 86 | }; 87 | 88 | template 89 | using MessageInterfaceBuilderT = 90 | typename MessageInterfaceBuilder::Type; 91 | 92 | } // namespace details 93 | 94 | } // namespace comms 95 | 96 | 97 | -------------------------------------------------------------------------------- /include/comms/details/MsgDispatcherOptionsParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/options.h" 11 | 12 | namespace comms 13 | { 14 | 15 | namespace details 16 | { 17 | 18 | template 19 | class MsgDispatcherOptionsParser; 20 | 21 | template <> 22 | class MsgDispatcherOptionsParser<> 23 | { 24 | public: 25 | static const bool HasForcedDispatch = false; 26 | using ForcedDispatch = void; 27 | }; 28 | 29 | template 30 | class MsgDispatcherOptionsParser, TOptions...> : 31 | public MsgDispatcherOptionsParser 32 | { 33 | public: 34 | static const bool HasForcedDispatch = true; 35 | using ForcedDispatch = T; 36 | }; 37 | 38 | 39 | template 40 | class MsgDispatcherOptionsParser< 41 | comms::option::app::EmptyOption, 42 | TOptions...> : public MsgDispatcherOptionsParser 43 | { 44 | }; 45 | 46 | template 47 | class MsgDispatcherOptionsParser< 48 | std::tuple, 49 | TOptions...> : public MsgDispatcherOptionsParser 50 | { 51 | }; 52 | 53 | } // namespace details 54 | 55 | } // namespace comms 56 | -------------------------------------------------------------------------------- /include/comms/details/MsgFactoryOptionsParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/options.h" 11 | 12 | #include 13 | 14 | namespace comms 15 | { 16 | 17 | namespace details 18 | { 19 | 20 | template 21 | class MsgFactoryOptionsParser; 22 | 23 | template <> 24 | class MsgFactoryOptionsParser<> 25 | { 26 | public: 27 | static constexpr bool HasInPlaceAllocation = false; 28 | static constexpr bool HasSupportGenericMessage = false; 29 | static constexpr bool HasForcedDispatch = false; 30 | 31 | using GenericMessage = void; 32 | 33 | template 34 | using AllMessages = TAll; 35 | }; 36 | 37 | template 38 | class MsgFactoryOptionsParser : 39 | public MsgFactoryOptionsParser 40 | { 41 | public: 42 | static constexpr bool HasInPlaceAllocation = true; 43 | }; 44 | 45 | template 46 | class MsgFactoryOptionsParser, TOptions...> : 47 | public MsgFactoryOptionsParser 48 | { 49 | public: 50 | static constexpr bool HasSupportGenericMessage = true; 51 | using GenericMessage = TMsg; 52 | 53 | template 54 | using AllMessages = 55 | typename std::decay< 56 | decltype( 57 | std::tuple_cat( 58 | std::declval(), 59 | std::declval >() 60 | ) 61 | ) 62 | >::type; 63 | }; 64 | 65 | template 66 | class MsgFactoryOptionsParser, TOptions...> : 67 | public MsgFactoryOptionsParser 68 | { 69 | public: 70 | static constexpr bool HasForcedDispatch = true; 71 | using ForcedDispatch = T; 72 | }; 73 | 74 | 75 | template 76 | class MsgFactoryOptionsParser< 77 | comms::option::app::EmptyOption, 78 | TOptions...> : public MsgFactoryOptionsParser 79 | { 80 | }; 81 | 82 | template 83 | class MsgFactoryOptionsParser< 84 | std::tuple, 85 | TOptions...> : public MsgFactoryOptionsParser 86 | { 87 | }; 88 | 89 | } // namespace details 90 | 91 | } // namespace comms 92 | -------------------------------------------------------------------------------- /include/comms/details/ReadIteratorHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/details/detect.h" 11 | #include "comms/details/tag.h" 12 | #include "comms/Message.h" 13 | #include "comms/util/type_traits.h" 14 | 15 | namespace comms 16 | { 17 | 18 | namespace details 19 | { 20 | 21 | template 22 | class ReadIteratorHelper 23 | { 24 | template 25 | using HasReadIterTag = comms::details::tag::Tag1<>; 26 | 27 | template 28 | using MsgPointerTag = comms::details::tag::Tag2<>; 29 | 30 | template 31 | using CastTag = comms::details::tag::Tag3<>; 32 | 33 | template 34 | using MsgObjTag = 35 | typename comms::util::LazyShallowConditional< 36 | TMsg::hasRead() 37 | >::template Type< 38 | HasReadIterTag, 39 | CastTag 40 | >; 41 | 42 | template 43 | using MsgPtrOrCastTag = 44 | typename comms::util::LazyShallowConditional< 45 | hasElementType() 46 | >::template Type< 47 | MsgPointerTag, 48 | CastTag 49 | >; 50 | 51 | template 52 | using Tag = 53 | typename comms::util::LazyShallowConditional< 54 | comms::isMessage() 55 | >::template Type< 56 | MsgObjTag, 57 | MsgPtrOrCastTag, 58 | TMsg 59 | >; 60 | 61 | template 62 | static auto getInternal(TIter&& iter, HasReadIterTag) -> typename TMsg::ReadIterator 63 | { 64 | static_assert(std::is_convertible::type, typename TMsg::ReadIterator>::value, 65 | "Provided iterator is not convertible to read iterator type used by message interface"); 66 | return typename TMsg::ReadIterator(std::forward(iter)); 67 | } 68 | 69 | template 70 | static auto getInternal(TIter&& iter, CastTag) -> decltype(std::forward(iter)) 71 | { 72 | return std::forward(iter); 73 | } 74 | 75 | template 76 | static auto getInternal(TIter&& iter, MsgPointerTag) -> 77 | decltype(getInternal(std::forward(iter), Tag())) 78 | { 79 | return getInternal(std::forward(iter), Tag()); 80 | } 81 | 82 | public: 83 | template 84 | static auto get(TIter&& iter) -> decltype(getInternal(std::forward(iter), Tag())) 85 | { 86 | return getInternal(std::forward(iter), Tag()); 87 | } 88 | }; 89 | 90 | } // namespace details 91 | 92 | } // namespace comms 93 | -------------------------------------------------------------------------------- /include/comms/details/ValueAssignWrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace comms 13 | { 14 | 15 | namespace details 16 | { 17 | 18 | template 19 | class ValueAssignWrapper 20 | { 21 | using ValueType = typename std::decay::type; 22 | 23 | public: 24 | explicit ValueAssignWrapper(T& value) : m_value(value) {} 25 | 26 | template 27 | ValueAssignWrapper& operator=(U&& val) 28 | { 29 | m_value = static_cast(val); 30 | return *this; 31 | } 32 | 33 | operator ValueType&() 34 | { 35 | return m_value; 36 | } 37 | 38 | operator const ValueType&() const 39 | { 40 | return m_value; 41 | } 42 | 43 | private: 44 | 45 | T& m_value; 46 | }; 47 | 48 | } // namespace details 49 | 50 | } // namespace comms 51 | -------------------------------------------------------------------------------- /include/comms/details/WriteIteratorHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #include "comms/Message.h" 9 | #include "comms/details/detect.h" 10 | #include "comms/details/tag.h" 11 | #include "comms/util/type_traits.h" 12 | 13 | namespace comms 14 | { 15 | 16 | namespace details 17 | { 18 | 19 | template 20 | class WriteIteratorHelper 21 | { 22 | template 23 | using HasWriteIterTag = comms::details::tag::Tag1<>; 24 | 25 | template 26 | using MsgPointerTag = comms::details::tag::Tag2<>; 27 | 28 | template 29 | using CastTag = comms::details::tag::Tag3<>; 30 | 31 | template 32 | using MsgObjTag = 33 | typename comms::util::LazyShallowConditional< 34 | TMsg::hasWrite() 35 | >::template Type< 36 | HasWriteIterTag, 37 | CastTag 38 | >; 39 | 40 | template 41 | using MsgPtrOrCastTag = 42 | typename comms::util::LazyShallowConditional< 43 | hasElementType() 44 | >::template Type< 45 | MsgPointerTag, 46 | CastTag 47 | >; 48 | 49 | template 50 | using Tag = 51 | typename comms::util::LazyShallowConditional< 52 | comms::isMessage() 53 | >::template Type< 54 | MsgObjTag, 55 | MsgPtrOrCastTag, 56 | TMsg 57 | >; 58 | 59 | template 60 | static auto getInternal(TIter&& iter, HasWriteIterTag) -> typename TMsg::WriteIterator 61 | { 62 | static_assert(std::is_convertible::type, typename TMsg::WriteIterator>::value, 63 | "Provided iterator is not convertible to read iterator type used by message interface"); 64 | return typename TMsg::WriteIterator(std::forward(iter)); 65 | } 66 | 67 | template 68 | static auto getInternal(TIter&& iter, CastTag) -> decltype(std::forward(iter)) 69 | { 70 | return std::forward(iter); 71 | } 72 | 73 | template 74 | static auto getInternal(TIter&& iter, MsgPointerTag) -> 75 | decltype(getInternal(std::forward(iter), Tag())) 76 | { 77 | return getInternal(std::forward(iter), Tag()); 78 | } 79 | 80 | public: 81 | template 82 | static auto get(TIter&& iter) -> decltype(getInternal(std::forward(iter), Tag())) 83 | { 84 | return getInternal(std::forward(iter), Tag()); 85 | } 86 | }; 87 | 88 | } // namespace details 89 | 90 | } // namespace comms 91 | -------------------------------------------------------------------------------- /include/comms/details/base_detection.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/CompileControl.h" 11 | 12 | #if (!COMMS_IS_CPP14) 13 | 14 | #if COMMS_IS_CLANG 15 | #define COMMS_MUST_DEFINE_BASE 16 | #endif 17 | 18 | #if !defined(COMMS_MUST_DEFINE_BASE) && COMMS_IS_GCC 19 | #if __GNUC__ < 5 20 | #define COMMS_MUST_DEFINE_BASE 21 | #endif // #if __GNUC__ < 5 22 | #endif // #if !defined(COMMS_MUST_DEFINE_BASE) && defined(__GNUC__) 23 | 24 | #endif // #if (!COMMS_IS_CPP14) 25 | 26 | -------------------------------------------------------------------------------- /include/comms/details/detect.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | namespace comms 14 | { 15 | 16 | namespace details 17 | { 18 | 19 | template 20 | struct EnableIfHasInterfaceOptions { using Type = R; }; 21 | 22 | template 23 | struct HasInterfaceOptions 24 | { 25 | static const bool Value = false; 26 | }; 27 | 28 | template 29 | struct HasInterfaceOptions::Type> 30 | { 31 | static const bool Value = true; 32 | }; 33 | 34 | template 35 | constexpr bool hasInterfaceOptions() 36 | { 37 | return HasInterfaceOptions::Value; 38 | } 39 | 40 | template 41 | struct EnableIfHasImplOptions { using Type = R; }; 42 | 43 | template 44 | struct HasImplOptions 45 | { 46 | static const bool Value = false; 47 | }; 48 | 49 | template 50 | struct HasImplOptions::Type> 51 | { 52 | static const bool Value = true; 53 | }; 54 | 55 | template 56 | constexpr bool hasImplOptions() 57 | { 58 | return HasImplOptions::Value; 59 | } 60 | 61 | template 62 | struct EnableIfHasElementType { using Type = R; }; 63 | 64 | template 65 | struct HasElementType 66 | { 67 | static const bool Value = false; 68 | }; 69 | 70 | template 71 | struct HasElementType::Type> 72 | { 73 | static const bool Value = true; 74 | }; 75 | 76 | template 77 | constexpr bool hasElementType() 78 | { 79 | return HasElementType::Value; 80 | } 81 | 82 | } // namespace details 83 | 84 | } // namespace comms 85 | -------------------------------------------------------------------------------- /include/comms/details/dispatch_impl.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/details/DispatchMsgPolymorphicHelper.h" 11 | #include "comms/details/DispatchMsgStaticBinSearchHelper.h" 12 | #include "comms/details/DispatchMsgLinearSwitchHelper.h" 13 | 14 | -------------------------------------------------------------------------------- /include/comms/details/macro_common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/CompileControl.h" 11 | 12 | #define COMMS_EXPAND(x_) x_ 13 | #define COMMS_CONCATENATE_(x_, y_) x_##y_ 14 | #define COMMS_CONCATENATE(x_, y_) COMMS_CONCATENATE_(x_, y_) 15 | 16 | /// MSVC doesn't allow more than 127 macro arguments 17 | #define COMMS_NUM_ARGS_(X,\ 18 | X123,X122,X121,X120,\ 19 | X119,X118,X117,X116,X115,X114,X113,X112,X111,X110,\ 20 | X109,X108,X107,X106,X105,X104,X103,X102,X101,X100,\ 21 | X99,X98,X97,X96,X95,X94,X93,X92,X91,X90,\ 22 | X89,X88,X87,X86,X85,X84,X83,X82,X81,X80,\ 23 | X79,X78,X77,X76,X75,X74,X73,X72,X71,X70,\ 24 | X69,X68,X67,X66,X65,X64,X63,X62,X61,X60,\ 25 | X59,X58,X57,X56,X55,X54,X53,X52,X51,X50,\ 26 | X49,X48,X47,X46,X45,X44,X43,X42,X41,X40,\ 27 | X39,X38,X37,X36,X35,X34,X33,X32,X31,X30,\ 28 | X29,X28,X27,X26,X25,X24,X23,X22,X21,X20,\ 29 | X19,X18,X17,X16,X15,X14,X13,X12,X11,X10,\ 30 | X9,X8,X7,X6,X5,X4,X3,X2,X1,N,...) N 31 | #define COMMS_NUM_ARGS(...) COMMS_EXPAND(COMMS_NUM_ARGS_(0, __VA_ARGS__ ,\ 32 | 123,122,121,120,\ 33 | 119,118,117,116,115,114,113,112,111,110,\ 34 | 109,108,106,106,105,104,103,102,101,100,\ 35 | 99,98,97,96,95,94,93,92,91,90,\ 36 | 89,88,87,86,85,84,83,82,81,80,\ 37 | 79,78,77,76,75,74,73,72,71,70,\ 38 | 69,68,67,66,65,64,63,62,61,60,\ 39 | 59,58,57,56,55,54,53,52,51,50,\ 40 | 49,48,47,46,45,44,43,42,41,40,\ 41 | 39,38,37,36,35,34,33,32,31,30,\ 42 | 29,28,27,26,25,24,23,22,21,20,\ 43 | 19,18,17,16,15,14,13,12,11,10,\ 44 | 9,8,7,6,5,4,3,2,1,0)) 45 | 46 | #if COMMS_IS_CPP14 47 | 48 | #define FUNC_AUTO_REF_RETURN(name_, ret_) decltype(auto) name_ () 49 | #define FUNC_AUTO_REF_RETURN_CONST(name_, ret_) decltype(auto) name_ () const 50 | #define FUNC_ARGS_AUTO_REF_RETURN(name_, args_, ret_) decltype(auto) name_(args_) 51 | #define FUNC_ARGS_AUTO_REF_RETURN_CONST(name_, args_, ret_) decltype(auto) name_(args_) const 52 | 53 | #else // #if COMMS_IS_CPP14 54 | #define FUNC_AUTO_REF_RETURN(name_, ret_) auto name_ () -> ret_ 55 | #define FUNC_AUTO_REF_RETURN_CONST(name_, ret_) auto name_ () const -> ret_ 56 | #define FUNC_ARGS_AUTO_REF_RETURN(name_, args_, ret_) auto name_(args_) -> ret_ 57 | #define FUNC_ARGS_AUTO_REF_RETURN_CONST(name_, args_, ret_) auto name_(args_) const -> ret_ 58 | 59 | #endif // #if COMMS_IS_CPP14 60 | -------------------------------------------------------------------------------- /include/comms/details/process.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/Message.h" 11 | #include "comms/details/detect.h" 12 | 13 | #include 14 | 15 | namespace comms 16 | { 17 | 18 | namespace details 19 | { 20 | 21 | template 22 | using ProcessMsgDecayType = typename std::decay::type; 23 | 24 | template 25 | struct ProcessMsgIdRetrieveHelper 26 | { 27 | template 28 | using Type = void; 29 | }; 30 | 31 | template <> 32 | struct ProcessMsgIdRetrieveHelper 33 | { 34 | template 35 | using Type = comms::MessageIdType; 36 | }; 37 | 38 | template <> 39 | struct ProcessMsgIdRetrieveHelper 40 | { 41 | private: 42 | template 43 | using ElementType = typename T::element_type; 44 | public: 45 | template 46 | using Type = 47 | typename ProcessMsgIdRetrieveHelper >(), hasElementType >()>:: 48 | template Type >; 49 | }; 50 | 51 | template 52 | using ProcessMsgIdType = 53 | typename ProcessMsgIdRetrieveHelper >(), hasElementType >()>:: 54 | template Type >; 55 | 56 | 57 | template 58 | struct ProcessMsgCastToMsgObjHelper; 59 | 60 | template <> 61 | struct ProcessMsgCastToMsgObjHelper 62 | { 63 | template 64 | static auto cast(T& msg) -> decltype(msg) 65 | { 66 | return msg; 67 | } 68 | }; 69 | 70 | template <> 71 | struct ProcessMsgCastToMsgObjHelper 72 | { 73 | template 74 | static auto cast(T& msg) -> decltype(*msg) 75 | { 76 | return *msg; 77 | } 78 | }; 79 | 80 | template 81 | using ProcessMsgCastParamIsMessage = 82 | std::integral_constant< 83 | bool, 84 | isMessage >() 85 | >; 86 | 87 | template 88 | using ProcessMsgCastParamIsMsgPtr = 89 | std::integral_constant< 90 | bool, 91 | hasElementType >() 92 | >; 93 | 94 | template 95 | auto processMsgCastToMsgObj(T& msg) -> 96 | decltype(ProcessMsgCastToMsgObjHelper::value, ProcessMsgCastParamIsMsgPtr::value>::cast(msg)) 97 | { 98 | return ProcessMsgCastToMsgObjHelper::value, ProcessMsgCastParamIsMsgPtr::value>::cast(msg); 99 | } 100 | 101 | } // namespace details 102 | 103 | } // namespace comms 104 | -------------------------------------------------------------------------------- /include/comms/details/reverse_macro_args.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/details/macro_common.h" 11 | 12 | //#define COMMS_DO_REVERSE_MACRO_ARGS_0() 13 | #define COMMS_DO_REVERSE_MACRO_ARGS_1(n_) COMMS_EXPAND(n_) 14 | #define COMMS_DO_REVERSE_MACRO_ARGS_2(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_1(__VA_ARGS__)) , COMMS_EXPAND(n_) 15 | #define COMMS_DO_REVERSE_MACRO_ARGS_3(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_2(__VA_ARGS__)) , COMMS_EXPAND(n_) 16 | #define COMMS_DO_REVERSE_MACRO_ARGS_4(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_3(__VA_ARGS__)) , COMMS_EXPAND(n_) 17 | #define COMMS_DO_REVERSE_MACRO_ARGS_5(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_4(__VA_ARGS__)) , COMMS_EXPAND(n_) 18 | #define COMMS_DO_REVERSE_MACRO_ARGS_6(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_5(__VA_ARGS__)) , COMMS_EXPAND(n_) 19 | #define COMMS_DO_REVERSE_MACRO_ARGS_7(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_6(__VA_ARGS__)) , COMMS_EXPAND(n_) 20 | #define COMMS_DO_REVERSE_MACRO_ARGS_8(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_7(__VA_ARGS__)) , COMMS_EXPAND(n_) 21 | #define COMMS_DO_REVERSE_MACRO_ARGS_9(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_8(__VA_ARGS__)) , COMMS_EXPAND(n_) 22 | #define COMMS_DO_REVERSE_MACRO_ARGS_10(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_9(__VA_ARGS__)) , COMMS_EXPAND(n_) 23 | #define COMMS_DO_REVERSE_MACRO_ARGS_11(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_10(__VA_ARGS__)) , COMMS_EXPAND(n_) 24 | #define COMMS_DO_REVERSE_MACRO_ARGS_12(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_11(__VA_ARGS__)) , COMMS_EXPAND(n_) 25 | #define COMMS_DO_REVERSE_MACRO_ARGS_13(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_12(__VA_ARGS__)) , COMMS_EXPAND(n_) 26 | #define COMMS_DO_REVERSE_MACRO_ARGS_14(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_13(__VA_ARGS__)) , COMMS_EXPAND(n_) 27 | #define COMMS_DO_REVERSE_MACRO_ARGS_15(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_14(__VA_ARGS__)) , COMMS_EXPAND(n_) 28 | #define COMMS_DO_REVERSE_MACRO_ARGS_16(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_15(__VA_ARGS__)) , COMMS_EXPAND(n_) 29 | #define COMMS_DO_REVERSE_MACRO_ARGS_17(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_16(__VA_ARGS__)) , COMMS_EXPAND(n_) 30 | #define COMMS_DO_REVERSE_MACRO_ARGS_18(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_17(__VA_ARGS__)) , COMMS_EXPAND(n_) 31 | #define COMMS_DO_REVERSE_MACRO_ARGS_19(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_18(__VA_ARGS__)) , COMMS_EXPAND(n_) 32 | #define COMMS_DO_REVERSE_MACRO_ARGS_20(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_19(__VA_ARGS__)) , COMMS_EXPAND(n_) 33 | #define COMMS_DO_REVERSE_MACRO_ARGS_21(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_20(__VA_ARGS__)) , COMMS_EXPAND(n_) 34 | #define COMMS_DO_REVERSE_MACRO_ARGS_22(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_21(__VA_ARGS__)) , COMMS_EXPAND(n_) 35 | #define COMMS_DO_REVERSE_MACRO_ARGS_23(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_22(__VA_ARGS__)) , COMMS_EXPAND(n_) 36 | #define COMMS_DO_REVERSE_MACRO_ARGS_24(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_23(__VA_ARGS__)) , COMMS_EXPAND(n_) 37 | #define COMMS_DO_REVERSE_MACRO_ARGS_25(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_24(__VA_ARGS__)) , COMMS_EXPAND(n_) 38 | #define COMMS_DO_REVERSE_MACRO_ARGS_26(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_25(__VA_ARGS__)) , COMMS_EXPAND(n_) 39 | #define COMMS_DO_REVERSE_MACRO_ARGS_27(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_26(__VA_ARGS__)) , COMMS_EXPAND(n_) 40 | #define COMMS_DO_REVERSE_MACRO_ARGS_28(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_27(__VA_ARGS__)) , COMMS_EXPAND(n_) 41 | #define COMMS_DO_REVERSE_MACRO_ARGS_29(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_28(__VA_ARGS__)) , COMMS_EXPAND(n_) 42 | #define COMMS_DO_REVERSE_MACRO_ARGS_30(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_29(__VA_ARGS__)) , COMMS_EXPAND(n_) 43 | #define COMMS_DO_REVERSE_MACRO_ARGS_31(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_30(__VA_ARGS__)) , COMMS_EXPAND(n_) 44 | #define COMMS_DO_REVERSE_MACRO_ARGS_32(n_, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_31(__VA_ARGS__)) , COMMS_EXPAND(n_) 45 | 46 | #define COMMS_REVERSE_MACRO_ARGS_INTERNAL_(N, ...) COMMS_EXPAND(COMMS_DO_REVERSE_MACRO_ARGS_ ## N(__VA_ARGS__)) 47 | #define COMMS_REVERSE_MACRO_ARGS_INTERNAL(N, ...) COMMS_EXPAND(COMMS_REVERSE_MACRO_ARGS_INTERNAL_(N, __VA_ARGS__)) 48 | #define COMMS_REVERSE_MACRO_ARGS(...) \ 49 | COMMS_EXPAND(COMMS_REVERSE_MACRO_ARGS_INTERNAL(COMMS_NUM_ARGS(__VA_ARGS__), __VA_ARGS__)) 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /include/comms/details/tag.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | namespace comms 11 | { 12 | 13 | namespace details 14 | { 15 | 16 | namespace tag 17 | { 18 | 19 | template 20 | struct Tag1 {}; 21 | 22 | template 23 | struct Tag2 {}; 24 | 25 | template 26 | struct Tag3 {}; 27 | 28 | template 29 | struct Tag4 {}; 30 | 31 | template 32 | struct Tag5 {}; 33 | 34 | template 35 | struct Tag6 {}; 36 | 37 | template 38 | struct Tag7 {}; 39 | 40 | template 41 | struct Tag8 {}; 42 | 43 | template 44 | struct Tag9 {}; 45 | 46 | template 47 | struct Tag10 {}; 48 | 49 | template 50 | struct Tag11 {}; 51 | 52 | template 53 | struct Tag12 {}; 54 | 55 | } // namespace tag 56 | 57 | } // namespace details 58 | 59 | } // namespace comms 60 | -------------------------------------------------------------------------------- /include/comms/field/OptionalMode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of the mode used for comms::field::Optional fields. 10 | 11 | #pragma once 12 | 13 | namespace comms 14 | { 15 | 16 | namespace field 17 | { 18 | 19 | /// @brief Mode to be used by comms::field::Optional 20 | /// @headerfile comms/field/OptionalMode.h 21 | enum class OptionalMode 22 | { 23 | Tentative, ///< The field existence is tentative, i.e. If there is enough bytes 24 | /// to read the field's value, than field exists, if not 25 | /// then it doesn't exist. 26 | Exists, ///< Field must exist 27 | Missing, ///< Field doesn't exist 28 | NumOfModes ///< Number of possible modes, must be last 29 | }; 30 | 31 | } // namespace field 32 | 33 | } // namespace comms 34 | 35 | 36 | -------------------------------------------------------------------------------- /include/comms/field/adapter/CustomReadWrap.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | namespace comms 11 | { 12 | 13 | namespace field 14 | { 15 | 16 | namespace adapter 17 | { 18 | 19 | template 20 | class CustomReadWrap : public TBase 21 | { 22 | public: 23 | static constexpr bool hasReadNoStatus() 24 | { 25 | return false; 26 | } 27 | 28 | template 29 | void readNoStatus(TIter& iter) = delete; 30 | }; 31 | 32 | } // namespace adapter 33 | 34 | } // namespace field 35 | 36 | } // namespace comms 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /include/comms/field/adapter/CustomRefreshWrap.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | namespace comms 11 | { 12 | 13 | namespace field 14 | { 15 | 16 | namespace adapter 17 | { 18 | 19 | template 20 | class CustomRefreshWrap : public TBase 21 | { 22 | public: 23 | static constexpr bool hasNonDefaultRefresh() 24 | { 25 | return true; 26 | } 27 | }; 28 | 29 | } // namespace adapter 30 | 31 | } // namespace field 32 | 33 | } // namespace comms 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /include/comms/field/adapter/CustomValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | namespace comms 11 | { 12 | 13 | namespace field 14 | { 15 | 16 | namespace adapter 17 | { 18 | 19 | template 20 | class CustomValidator : public TBase 21 | { 22 | using BaseImpl = TBase; 23 | using Validator = TValidator; 24 | 25 | public: 26 | 27 | using ValueType = typename BaseImpl::ValueType; 28 | 29 | CustomValidator() = default; 30 | 31 | explicit CustomValidator(const ValueType& val) 32 | : BaseImpl(val) 33 | { 34 | } 35 | 36 | explicit CustomValidator(ValueType&& val) 37 | : BaseImpl(std::move(val)) 38 | { 39 | } 40 | 41 | CustomValidator(const CustomValidator&) = default; 42 | CustomValidator(CustomValidator&&) = default; 43 | CustomValidator& operator=(const CustomValidator&) = default; 44 | CustomValidator& operator=(CustomValidator&&) = default; 45 | 46 | bool valid() const 47 | { 48 | return BaseImpl::valid() && (Validator()(*this)); 49 | } 50 | }; 51 | 52 | } // namespace adapter 53 | 54 | } // namespace field 55 | 56 | } // namespace comms 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /include/comms/field/adapter/CustomWriteWrap.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | namespace comms 11 | { 12 | 13 | namespace field 14 | { 15 | 16 | namespace adapter 17 | { 18 | 19 | template 20 | class CustomWriteWrap : public TBase 21 | { 22 | public: 23 | static constexpr bool hasWriteNoStatus() 24 | { 25 | return false; 26 | } 27 | 28 | template 29 | void writeNoStatus(TIter& iter) const = delete; 30 | }; 31 | 32 | } // namespace adapter 33 | 34 | } // namespace field 35 | 36 | } // namespace comms 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /include/comms/field/adapter/DefaultValueInitialiser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/ErrorStatus.h" 11 | 12 | namespace comms 13 | { 14 | 15 | namespace field 16 | { 17 | 18 | namespace adapter 19 | { 20 | 21 | template 22 | class DefaultValueInitialiser : public TBase 23 | { 24 | using BaseImpl = TBase; 25 | using Initialiser = TInitialiser; 26 | public: 27 | using ValueType = typename BaseImpl::ValueType; 28 | 29 | DefaultValueInitialiser() 30 | { 31 | Initialiser()(*this); 32 | } 33 | 34 | explicit DefaultValueInitialiser(const ValueType& val) 35 | : BaseImpl(val) 36 | { 37 | } 38 | 39 | explicit DefaultValueInitialiser(ValueType&& val) 40 | : BaseImpl(std::move(val)) 41 | { 42 | } 43 | 44 | DefaultValueInitialiser(const DefaultValueInitialiser&) = default; 45 | DefaultValueInitialiser(DefaultValueInitialiser&&) = default; 46 | DefaultValueInitialiser& operator=(const DefaultValueInitialiser&) = default; 47 | DefaultValueInitialiser& operator=(DefaultValueInitialiser&&) = default; 48 | }; 49 | 50 | } // namespace adapter 51 | 52 | } // namespace field 53 | 54 | } // namespace comms 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /include/comms/field/adapter/DisplayOffset.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | namespace comms 14 | { 15 | 16 | namespace field 17 | { 18 | 19 | namespace adapter 20 | { 21 | 22 | 23 | template 24 | class DisplayOffset : public TBase 25 | { 26 | using BaseImpl = TBase; 27 | public: 28 | using DisplayOffsetType = typename TBase::DisplayOffsetType; 29 | 30 | static constexpr DisplayOffsetType displayOffset() 31 | { 32 | return static_cast(TOffset); 33 | } 34 | }; 35 | 36 | } // namespace adapter 37 | 38 | } // namespace field 39 | 40 | } // namespace comms 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /include/comms/field/adapter/EmptySerialization.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/Assert.h" 11 | #include "comms/ErrorStatus.h" 12 | 13 | namespace comms 14 | { 15 | 16 | namespace field 17 | { 18 | 19 | namespace adapter 20 | { 21 | 22 | template 23 | class EmptySerialization : public TBase 24 | { 25 | using BaseImpl = TBase; 26 | public: 27 | 28 | using ValueType = typename BaseImpl::ValueType; 29 | 30 | EmptySerialization() = default; 31 | 32 | explicit EmptySerialization(const ValueType& val) 33 | : BaseImpl(val) 34 | { 35 | } 36 | 37 | explicit EmptySerialization(ValueType&& val) 38 | : BaseImpl(std::move(val)) 39 | { 40 | } 41 | 42 | EmptySerialization(const EmptySerialization&) = default; 43 | EmptySerialization(EmptySerialization&&) = default; 44 | EmptySerialization& operator=(const EmptySerialization&) = default; 45 | EmptySerialization& operator=(EmptySerialization&&) = default; 46 | 47 | static constexpr std::size_t length() 48 | { 49 | return 0U; 50 | } 51 | 52 | static constexpr std::size_t minLength() 53 | { 54 | return length(); 55 | } 56 | 57 | static constexpr std::size_t maxLength() 58 | { 59 | return length(); 60 | } 61 | 62 | template 63 | static comms::ErrorStatus read(TIter&, std::size_t) 64 | { 65 | return comms::ErrorStatus::Success; 66 | } 67 | 68 | template 69 | static void readNoStatus(TIter&) 70 | { 71 | } 72 | 73 | static constexpr bool canWrite() 74 | { 75 | return true; 76 | } 77 | 78 | template 79 | static comms::ErrorStatus write(TIter&, std::size_t) 80 | { 81 | return comms::ErrorStatus::Success; 82 | } 83 | 84 | template 85 | static void writeNoStatus(TIter&) 86 | { 87 | } 88 | }; 89 | 90 | } // namespace adapter 91 | 92 | } // namespace field 93 | 94 | } // namespace comms 95 | 96 | -------------------------------------------------------------------------------- /include/comms/field/adapter/ExistsBetweenVersions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/Assert.h" 11 | #include "comms/CompileControl.h" 12 | #include "comms/details/tag.h" 13 | #include "comms/field/OptionalMode.h" 14 | #include "comms/util/type_traits.h" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | COMMS_GNU_WARNING_PUSH 22 | COMMS_GNU_WARNING_DISABLE("-Wtype-limits") 23 | 24 | namespace comms 25 | { 26 | 27 | namespace field 28 | { 29 | 30 | namespace adapter 31 | { 32 | 33 | template 34 | class ExistsBetweenVersions : public TBase 35 | { 36 | using BaseImpl = TBase; 37 | static_assert(TFrom <= TUntil, "Invalid parameters"); 38 | public: 39 | 40 | using ValueType = typename BaseImpl::ValueType; 41 | using VersionType = typename BaseImpl::VersionType; 42 | 43 | ExistsBetweenVersions() = default; 44 | 45 | explicit ExistsBetweenVersions(const ValueType& val) 46 | : BaseImpl(val) 47 | { 48 | } 49 | 50 | explicit ExistsBetweenVersions(ValueType&& val) 51 | : BaseImpl(std::move(val)) 52 | { 53 | } 54 | 55 | ExistsBetweenVersions(const ExistsBetweenVersions&) = default; 56 | ExistsBetweenVersions(ExistsBetweenVersions&&) = default; 57 | ExistsBetweenVersions& operator=(const ExistsBetweenVersions&) = default; 58 | ExistsBetweenVersions& operator=(ExistsBetweenVersions&&) = default; 59 | 60 | static constexpr bool isVersionDependent() 61 | { 62 | return true; 63 | } 64 | 65 | bool setVersion(VersionType version) 66 | { 67 | bool updated = BaseImpl::setVersion(version); 68 | auto mode = comms::field::OptionalMode::Missing; 69 | if (aboveFrom(version) && belowUntil(version)) { 70 | mode = comms::field::OptionalMode::Exists; 71 | } 72 | 73 | if (mode == BaseImpl::getMode()) { 74 | return updated; 75 | } 76 | 77 | BaseImpl::setMode(mode); 78 | return true; 79 | } 80 | 81 | private: 82 | template 83 | using AlwaysTrueTag = comms::details::tag::Tag1<>; 84 | template 85 | using CompareTag = comms::details::tag::Tag2<>; 86 | 87 | static bool aboveFrom(VersionType version) 88 | { 89 | using Tag = 90 | typename comms::util::LazyShallowConditional< 91 | TFrom == 0 92 | >::template Type< 93 | AlwaysTrueTag, 94 | CompareTag 95 | >; 96 | return aboveFrom(version, Tag()); 97 | } 98 | 99 | template 100 | static constexpr bool aboveFrom(VersionType, AlwaysTrueTag) 101 | { 102 | return true; 103 | } 104 | 105 | template 106 | static bool aboveFrom(VersionType version, CompareTag) 107 | { 108 | static const VersionType MinVersion = 109 | static_cast( 110 | std::min( 111 | static_cast(std::numeric_limits::max()), 112 | TFrom)); 113 | 114 | return MinVersion <= version; 115 | } 116 | 117 | static bool belowUntil(VersionType version) 118 | { 119 | using Tag = 120 | typename comms::util::LazyShallowConditional< 121 | static_cast(std::numeric_limits::max()) <= TUntil 122 | >::template Type< 123 | AlwaysTrueTag, 124 | CompareTag 125 | >; 126 | return belowUntil(version, Tag()); 127 | } 128 | 129 | template 130 | static constexpr bool belowUntil(VersionType, AlwaysTrueTag) 131 | { 132 | return true; 133 | } 134 | 135 | template 136 | static bool belowUntil(VersionType version, CompareTag) 137 | { 138 | static const VersionType MaxVersion = 139 | static_cast( 140 | std::min( 141 | static_cast(std::numeric_limits::max()), 142 | TUntil)); 143 | 144 | return version <= MaxVersion; 145 | } 146 | }; 147 | 148 | } // namespace adapter 149 | 150 | } // namespace field 151 | 152 | } // namespace comms 153 | 154 | COMMS_GNU_WARNING_POP 155 | -------------------------------------------------------------------------------- /include/comms/field/adapter/FailOnInvalid.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/Assert.h" 11 | #include "comms/ErrorStatus.h" 12 | 13 | namespace comms 14 | { 15 | 16 | namespace field 17 | { 18 | 19 | namespace adapter 20 | { 21 | 22 | template 23 | class FailOnInvalid : public TBase 24 | { 25 | using BaseImpl = TBase; 26 | public: 27 | 28 | using ValueType = typename BaseImpl::ValueType; 29 | 30 | FailOnInvalid() = default; 31 | 32 | explicit FailOnInvalid(const ValueType& val) 33 | : BaseImpl(val) 34 | { 35 | } 36 | 37 | explicit FailOnInvalid(ValueType&& val) 38 | : BaseImpl(std::move(val)) 39 | { 40 | } 41 | 42 | FailOnInvalid(const FailOnInvalid&) = default; 43 | FailOnInvalid(FailOnInvalid&&) = default; 44 | FailOnInvalid& operator=(const FailOnInvalid&) = default; 45 | FailOnInvalid& operator=(FailOnInvalid&&) = default; 46 | 47 | template 48 | comms::ErrorStatus read(TIter& iter, std::size_t len) 49 | { 50 | BaseImpl tmp; 51 | auto es = tmp.read(iter, len); 52 | if (es != comms::ErrorStatus::Success) { 53 | return es; 54 | } 55 | 56 | if (!tmp.valid()) { 57 | return TStatus; 58 | } 59 | 60 | static_cast(*this) = std::move(tmp); 61 | return comms::ErrorStatus::Success; 62 | } 63 | 64 | static constexpr bool hasReadNoStatus() 65 | { 66 | return false; 67 | } 68 | 69 | template 70 | void readNoStatus(TIter& iter) = delete; 71 | }; 72 | 73 | } // namespace adapter 74 | 75 | } // namespace field 76 | 77 | } // namespace comms 78 | 79 | -------------------------------------------------------------------------------- /include/comms/field/adapter/FieldType.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/cast.h" 11 | #include "comms/util/ScopeGuard.h" 12 | 13 | #include 14 | #include 15 | 16 | namespace comms 17 | { 18 | 19 | namespace field 20 | { 21 | 22 | namespace adapter 23 | { 24 | 25 | 26 | template 27 | class FieldType : public TBase 28 | { 29 | using BaseImpl = TBase; 30 | public: 31 | using ValueType = typename BaseImpl::ValueType; 32 | 33 | bool valid() const 34 | { 35 | if (m_entered) { 36 | return BaseImpl::valid(); 37 | } 38 | 39 | m_entered = true; 40 | auto onExit = 41 | comms::util::makeScopeGuard( 42 | [this]() 43 | { 44 | m_entered = false; 45 | }); 46 | 47 | return static_cast(this)->valid(); 48 | } 49 | 50 | private: 51 | mutable bool m_entered = false; 52 | }; 53 | 54 | } // namespace adapter 55 | 56 | } // namespace field 57 | 58 | } // namespace comms 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /include/comms/field/adapter/FixedValue.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | 11 | namespace comms 12 | { 13 | 14 | namespace field 15 | { 16 | 17 | namespace adapter 18 | { 19 | 20 | template 21 | class FixedValue : public TBase 22 | { 23 | using BaseImpl = TBase; 24 | public: 25 | using ValueType = typename BaseImpl::ValueType; 26 | 27 | using BaseImpl::value; 28 | 29 | ValueType& value() = delete; 30 | 31 | template 32 | void setValue(U&& val) = delete; 33 | 34 | private: 35 | using BaseImpl::setValue; 36 | 37 | }; 38 | 39 | } // namespace adapter 40 | 41 | } // namespace field 42 | 43 | } // namespace comms 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /include/comms/field/adapter/IgnoreInvalid.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/Assert.h" 11 | #include "comms/ErrorStatus.h" 12 | 13 | namespace comms 14 | { 15 | 16 | namespace field 17 | { 18 | 19 | namespace adapter 20 | { 21 | 22 | template 23 | class IgnoreInvalid : public TBase 24 | { 25 | using BaseImpl = TBase; 26 | public: 27 | 28 | using ValueType = typename BaseImpl::ValueType; 29 | 30 | IgnoreInvalid() = default; 31 | 32 | explicit IgnoreInvalid(const ValueType& val) 33 | : BaseImpl(val) 34 | { 35 | } 36 | 37 | explicit IgnoreInvalid(ValueType&& val) 38 | : BaseImpl(std::move(val)) 39 | { 40 | } 41 | 42 | IgnoreInvalid(const IgnoreInvalid&) = default; 43 | IgnoreInvalid(IgnoreInvalid&&) = default; 44 | IgnoreInvalid& operator=(const IgnoreInvalid&) = default; 45 | IgnoreInvalid& operator=(IgnoreInvalid&&) = default; 46 | 47 | template 48 | comms::ErrorStatus read(TIter& iter, std::size_t len) 49 | { 50 | BaseImpl tmp; 51 | auto es = tmp.read(iter, len); 52 | if (es != comms::ErrorStatus::Success) { 53 | return es; 54 | } 55 | 56 | if (tmp.valid()) { 57 | static_cast(*this) = std::move(tmp); 58 | } 59 | 60 | return comms::ErrorStatus::Success; 61 | } 62 | 63 | template 64 | void readNoStatus(TIter& iter) 65 | { 66 | BaseImpl tmp; 67 | tmp.readNoStatus(iter); 68 | 69 | if (tmp.valid()) { 70 | static_cast(*this) = std::move(tmp); 71 | } 72 | } 73 | }; 74 | 75 | } // namespace adapter 76 | 77 | } // namespace field 78 | 79 | } // namespace comms 80 | 81 | -------------------------------------------------------------------------------- /include/comms/field/adapter/InvalidByDefault.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | namespace comms 11 | { 12 | 13 | namespace field 14 | { 15 | 16 | namespace adapter 17 | { 18 | 19 | template 20 | class InvalidByDefault : public TBase 21 | { 22 | using BaseImpl = TBase; 23 | public: 24 | 25 | using ValueType = typename BaseImpl::ValueType; 26 | 27 | InvalidByDefault() = default; 28 | 29 | explicit InvalidByDefault(const ValueType& val) 30 | : BaseImpl(val) 31 | { 32 | } 33 | 34 | explicit InvalidByDefault(ValueType&& val) 35 | : BaseImpl(std::move(val)) 36 | { 37 | } 38 | 39 | InvalidByDefault(const InvalidByDefault&) = default; 40 | InvalidByDefault(InvalidByDefault&&) = default; 41 | InvalidByDefault& operator=(const InvalidByDefault&) = default; 42 | InvalidByDefault& operator=(InvalidByDefault&&) = default; 43 | 44 | static constexpr bool valid() 45 | { 46 | return false; 47 | } 48 | }; 49 | 50 | } // namespace adapter 51 | 52 | } // namespace field 53 | 54 | } // namespace comms 55 | 56 | -------------------------------------------------------------------------------- /include/comms/field/adapter/MissingOnInvalid.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/cast.h" 11 | 12 | #include 13 | 14 | namespace comms 15 | { 16 | 17 | namespace field 18 | { 19 | 20 | namespace adapter 21 | { 22 | 23 | template 24 | class MissingOnInvalid : public TBase 25 | { 26 | using BaseImpl = TBase; 27 | public: 28 | 29 | template 30 | comms::ErrorStatus read(TIter& iter, std::size_t len) 31 | { 32 | auto iterTmp = iter; 33 | auto es = BaseImpl::read(iterTmp, len); 34 | if (es != comms::ErrorStatus::Success) { 35 | return es; 36 | } 37 | 38 | if (!BaseImpl::valid()) { 39 | BaseImpl::setMode(comms::field::OptionalMode::Missing); 40 | return es; 41 | } 42 | 43 | iter = iterTmp; 44 | return es; 45 | } 46 | 47 | static constexpr bool hasReadNoStatus() 48 | { 49 | return false; 50 | } 51 | 52 | template 53 | void readNoStatus(TIter& iter) = delete; 54 | 55 | static constexpr bool hasNonDefaultRefresh() 56 | { 57 | return true; 58 | } 59 | 60 | bool refresh() 61 | { 62 | bool updated = BaseImpl::refresh(); 63 | auto mode = BaseImpl::getMode(); 64 | if (!BaseImpl::valid()) { 65 | mode = comms::field::OptionalMode::Missing; 66 | } 67 | 68 | if (mode == BaseImpl::getMode()) { 69 | return updated; 70 | } 71 | 72 | BaseImpl::setMode(mode); 73 | return true; 74 | } 75 | }; 76 | 77 | } // namespace adapter 78 | 79 | } // namespace field 80 | 81 | } // namespace comms 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /include/comms/field/adapter/MissingOnReadFail.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/cast.h" 11 | 12 | #include 13 | 14 | namespace comms 15 | { 16 | 17 | namespace field 18 | { 19 | 20 | namespace adapter 21 | { 22 | 23 | 24 | template 25 | class MissingOnReadFail : public TBase 26 | { 27 | using BaseImpl = TBase; 28 | public: 29 | 30 | template 31 | comms::ErrorStatus read(TIter& iter, std::size_t len) 32 | { 33 | BaseImpl tmp; 34 | auto iterTmp = iter; 35 | auto es = tmp.read(iterTmp, len); 36 | if (es != comms::ErrorStatus::Success) { 37 | BaseImpl::setMode(comms::field::OptionalMode::Missing); 38 | return comms::ErrorStatus::Success; 39 | } 40 | 41 | static_cast(*this) = std::move(tmp); 42 | iter = iterTmp; 43 | return es; 44 | } 45 | 46 | static constexpr bool hasReadNoStatus() 47 | { 48 | return false; 49 | } 50 | 51 | template 52 | void readNoStatus(TIter& iter) = delete; 53 | }; 54 | 55 | } // namespace adapter 56 | 57 | } // namespace field 58 | 59 | } // namespace comms 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /include/comms/field/adapter/NumValueMultiRangeValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/util/Tuple.h" 11 | 12 | namespace comms 13 | { 14 | 15 | namespace field 16 | { 17 | 18 | namespace adapter 19 | { 20 | 21 | template 22 | class NumValueMultiRangeValidator : public TBase 23 | { 24 | using BaseImpl = TBase; 25 | 26 | static_assert(comms::util::isTuple(), "TRanges must be a tuple"); 27 | 28 | public: 29 | 30 | using ValueType = typename BaseImpl::ValueType; 31 | 32 | static_assert( 33 | std::is_integral::value || std::is_enum::value || std::is_floating_point::value, 34 | "Only numeric fields are supported for multi range validation."); 35 | 36 | NumValueMultiRangeValidator() = default; 37 | 38 | explicit NumValueMultiRangeValidator(const ValueType& val) 39 | : BaseImpl(val) 40 | { 41 | } 42 | 43 | explicit NumValueMultiRangeValidator(ValueType&& val) 44 | : BaseImpl(std::move(val)) 45 | { 46 | } 47 | 48 | NumValueMultiRangeValidator(const NumValueMultiRangeValidator&) = default; 49 | NumValueMultiRangeValidator(NumValueMultiRangeValidator&&) = default; 50 | NumValueMultiRangeValidator& operator=(const NumValueMultiRangeValidator&) = default; 51 | NumValueMultiRangeValidator& operator=(NumValueMultiRangeValidator&&) = default; 52 | 53 | bool valid() const 54 | { 55 | return BaseImpl::valid() && 56 | comms::util::tupleTypeAccumulate(false, Validator(BaseImpl::getValue())); 57 | } 58 | 59 | private: 60 | class Validator 61 | { 62 | public: 63 | Validator(ValueType val) : m_val(val) {} 64 | 65 | template 66 | bool operator()(bool val) const 67 | { 68 | static_cast(val); 69 | static_assert(comms::util::isTuple(), "TRange must be a tuple"); 70 | static_assert(std::tuple_size::value == 2, "Tuple with 2 elements is expected"); 71 | using MinVal = typename std::tuple_element<0, TRange>::type; 72 | using MaxVal = typename std::tuple_element<1, TRange>::type; 73 | static_assert(MinVal::value <= MaxVal::value, "Invalid range"); 74 | return 75 | val || 76 | ((static_cast(MinVal::value) <= m_val) && 77 | (m_val <= static_cast(MaxVal::value))); 78 | } 79 | 80 | private: 81 | ValueType m_val; 82 | }; 83 | }; 84 | 85 | } // namespace adapter 86 | 87 | } // namespace field 88 | 89 | } // namespace comms 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /include/comms/field/adapter/SequenceLengthForcing.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/Assert.h" 11 | #include "comms/ErrorStatus.h" 12 | 13 | #include 14 | #include 15 | 16 | namespace comms 17 | { 18 | 19 | namespace field 20 | { 21 | 22 | namespace adapter 23 | { 24 | 25 | template 26 | class SequenceLengthForcing : public TBase 27 | { 28 | using BaseImpl = TBase; 29 | public: 30 | using ValueType = typename BaseImpl::ValueType; 31 | using ElementType = typename BaseImpl::ElementType; 32 | 33 | SequenceLengthForcing() = default; 34 | 35 | explicit SequenceLengthForcing(const ValueType& val) 36 | : BaseImpl(val) 37 | { 38 | } 39 | 40 | explicit SequenceLengthForcing(ValueType&& val) 41 | : BaseImpl(std::move(val)) 42 | { 43 | } 44 | 45 | SequenceLengthForcing(const SequenceLengthForcing&) = default; 46 | SequenceLengthForcing(SequenceLengthForcing&&) = default; 47 | SequenceLengthForcing& operator=(const SequenceLengthForcing&) = default; 48 | SequenceLengthForcing& operator=(SequenceLengthForcing&&) = default; 49 | 50 | void forceReadLength(std::size_t val) 51 | { 52 | COMMS_ASSERT(val != Cleared); 53 | m_forced = val; 54 | } 55 | 56 | void clearReadLengthForcing() 57 | { 58 | m_forced = Cleared; 59 | } 60 | 61 | template 62 | comms::ErrorStatus read(TIter& iter, std::size_t len) 63 | { 64 | if (m_forced == Cleared) { 65 | return BaseImpl::read(iter, len); 66 | } 67 | 68 | if (len < m_forced) { 69 | return comms::ErrorStatus::NotEnoughData; 70 | } 71 | 72 | return BaseImpl::read(iter, m_forced); 73 | } 74 | 75 | template 76 | ErrorStatus readN(std::size_t count, TIter& iter, std::size_t& len) 77 | { 78 | if (m_forced == Cleared) { 79 | return BaseImpl::read(iter, len); 80 | } 81 | 82 | if (len < m_forced) { 83 | return comms::ErrorStatus::NotEnoughData; 84 | } 85 | 86 | return BaseImpl::readN(count, iter, m_forced); 87 | } 88 | 89 | static constexpr bool hasReadNoStatus() 90 | { 91 | return false; 92 | } 93 | 94 | template 95 | void readNoStatus(TIter& iter) = delete; 96 | 97 | template 98 | void readNoStatusN(std::size_t count, TIter& iter) = delete; 99 | 100 | 101 | private: 102 | static const std::size_t Cleared = std::numeric_limits::max(); 103 | std::size_t m_forced = Cleared; 104 | }; 105 | 106 | } // namespace adapter 107 | 108 | } // namespace field 109 | 110 | } // namespace comms 111 | 112 | 113 | -------------------------------------------------------------------------------- /include/comms/field/adapter/SequenceSerLengthFieldPrefix.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/Assert.h" 11 | #include "comms/ErrorStatus.h" 12 | 13 | namespace comms 14 | { 15 | 16 | namespace field 17 | { 18 | 19 | namespace adapter 20 | { 21 | 22 | template 23 | class SequenceSerLengthFieldPrefix : public TBase 24 | { 25 | using BaseImpl = TBase; 26 | using LenField = TLenField; 27 | 28 | static const std::size_t MaxAllowedLength = 29 | static_cast(LenField::maxValue()); 30 | 31 | 32 | static_assert(!LenField::isVersionDependent(), 33 | "Prefix fields must not be version dependent"); 34 | 35 | public: 36 | using ValueType = typename BaseImpl::ValueType; 37 | using ElementType = typename BaseImpl::ElementType; 38 | 39 | SequenceSerLengthFieldPrefix() = default; 40 | 41 | explicit SequenceSerLengthFieldPrefix(const ValueType& val) 42 | : BaseImpl(val) 43 | { 44 | } 45 | 46 | explicit SequenceSerLengthFieldPrefix(ValueType&& val) 47 | : BaseImpl(std::move(val)) 48 | { 49 | } 50 | 51 | SequenceSerLengthFieldPrefix(const SequenceSerLengthFieldPrefix&) = default; 52 | SequenceSerLengthFieldPrefix(SequenceSerLengthFieldPrefix&&) = default; 53 | SequenceSerLengthFieldPrefix& operator=(const SequenceSerLengthFieldPrefix&) = default; 54 | SequenceSerLengthFieldPrefix& operator=(SequenceSerLengthFieldPrefix&&) = default; 55 | 56 | std::size_t length() const 57 | { 58 | auto valLength = BaseImpl::length(); 59 | LenField lenField; 60 | lenField.setValue(std::min(valLength, std::size_t(MaxAllowedLength))); 61 | return lenField.length() + valLength; 62 | } 63 | 64 | static constexpr std::size_t minLength() 65 | { 66 | return LenField::minLength(); 67 | } 68 | 69 | static constexpr std::size_t maxLength() 70 | { 71 | return LenField::maxLength() + BaseImpl::maxLength(); 72 | } 73 | 74 | bool valid() const 75 | { 76 | if ((!BaseImpl::valid()) || (!canWrite())) { 77 | return false; 78 | } 79 | 80 | LenField lenField; 81 | auto lenValue = std::min(BaseImpl::length(), std::size_t(MaxAllowedLength)); 82 | lenField.setValue(lenValue); 83 | return lenField.valid(); 84 | } 85 | 86 | template 87 | comms::ErrorStatus read(TIter& iter, std::size_t len) 88 | { 89 | auto fromIter = iter; 90 | LenField lenField; 91 | auto es = lenField.read(iter, len); 92 | if (es != comms::ErrorStatus::Success) { 93 | return es; 94 | } 95 | 96 | auto diff = static_cast(std::distance(fromIter, iter)); 97 | COMMS_ASSERT(diff <= len); 98 | len -= diff; 99 | auto remLen = static_cast(lenField.getValue()); 100 | if (len < remLen) { 101 | return TStatus; 102 | } 103 | 104 | es = BaseImpl::read(iter, remLen); 105 | if (es == comms::ErrorStatus::NotEnoughData) { 106 | return TStatus; 107 | } 108 | 109 | return es; 110 | } 111 | 112 | static constexpr bool hasReadNoStatus() 113 | { 114 | return false; 115 | } 116 | 117 | template 118 | void readNoStatus(TIter& iter) = delete; 119 | 120 | bool canWrite() const 121 | { 122 | if (!BaseImpl::canWrite()) { 123 | return false; 124 | } 125 | 126 | auto len = BaseImpl::length(); 127 | if (MaxAllowedLength < len) { 128 | return false; 129 | } 130 | 131 | LenField lenField; 132 | lenField.setValue(len); 133 | return lenField.canWrite(); 134 | } 135 | 136 | template 137 | comms::ErrorStatus write(TIter& iter, std::size_t len) const 138 | { 139 | if (!canWrite()) { 140 | return comms::ErrorStatus::InvalidMsgData; 141 | } 142 | 143 | auto lenVal = BaseImpl::length(); 144 | LenField lenField; 145 | lenField.setValue(lenVal); 146 | auto es = lenField.write(iter, len); 147 | if (es != comms::ErrorStatus::Success) { 148 | return es; 149 | } 150 | 151 | COMMS_ASSERT(lenField.length() <= len); 152 | return BaseImpl::write(iter, lenVal); 153 | } 154 | 155 | static constexpr bool hasWriteNoStatus() 156 | { 157 | return false; 158 | } 159 | 160 | template 161 | void writeNoStatus(TIter& iter) const = delete; 162 | }; 163 | 164 | } // namespace adapter 165 | 166 | } // namespace field 167 | 168 | } // namespace comms 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /include/comms/field/adapter/SequenceSizeFieldPrefix.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/Assert.h" 11 | #include "comms/ErrorStatus.h" 12 | 13 | namespace comms 14 | { 15 | 16 | namespace field 17 | { 18 | 19 | namespace adapter 20 | { 21 | 22 | template 23 | class SequenceSizeFieldPrefix : public TBase 24 | { 25 | using BaseImpl = TBase; 26 | using SizeField = TSizeField; 27 | 28 | static const std::size_t MaxAllowedSize = 29 | static_cast(SizeField::maxValue()); 30 | 31 | static_assert(!SizeField::isVersionDependent(), 32 | "Prefix fields must not be version dependent"); 33 | 34 | public: 35 | using ValueType = typename BaseImpl::ValueType; 36 | using ElementType = typename BaseImpl::ElementType; 37 | 38 | SequenceSizeFieldPrefix() = default; 39 | 40 | explicit SequenceSizeFieldPrefix(const ValueType& val) 41 | : BaseImpl(val) 42 | { 43 | } 44 | 45 | explicit SequenceSizeFieldPrefix(ValueType&& val) 46 | : BaseImpl(std::move(val)) 47 | { 48 | } 49 | 50 | SequenceSizeFieldPrefix(const SequenceSizeFieldPrefix&) = default; 51 | SequenceSizeFieldPrefix(SequenceSizeFieldPrefix&&) = default; 52 | SequenceSizeFieldPrefix& operator=(const SequenceSizeFieldPrefix&) = default; 53 | SequenceSizeFieldPrefix& operator=(SequenceSizeFieldPrefix&&) = default; 54 | 55 | std::size_t length() const 56 | { 57 | SizeField sizeField; 58 | sizeField.setValue(BaseImpl::getValue().size()); 59 | return sizeField.length() + BaseImpl::length(); 60 | } 61 | 62 | static constexpr std::size_t minLength() 63 | { 64 | return SizeField::minLength(); 65 | } 66 | 67 | static constexpr std::size_t maxLength() 68 | { 69 | return SizeField::maxLength() + BaseImpl::maxLength(); 70 | } 71 | 72 | bool valid() const 73 | { 74 | if ((!BaseImpl::valid()) || (!canWrite())) { 75 | return false; 76 | } 77 | SizeField sizeField; 78 | sizeField.setValue(BaseImpl::getValue().size()); 79 | return sizeField.valid() && BaseImpl::valid(); 80 | } 81 | 82 | template 83 | comms::ErrorStatus read(TIter& iter, std::size_t len) 84 | { 85 | auto fromIter = iter; 86 | SizeField sizeField; 87 | auto es = sizeField.read(iter, len); 88 | if (es != comms::ErrorStatus::Success) { 89 | return es; 90 | } 91 | 92 | auto diff = static_cast(std::distance(fromIter, iter)); 93 | COMMS_ASSERT(diff <= len); 94 | len -= diff; 95 | 96 | auto count = static_cast(sizeField.getValue()); 97 | return BaseImpl::readN(count, iter, len); 98 | } 99 | 100 | template 101 | void readNoStatus(TIter& iter) 102 | { 103 | SizeField sizeField; 104 | sizeField.readNoStatus(iter); 105 | auto count = static_cast(sizeField.getValue()); 106 | BaseImpl::readNoStatusN(count, iter); 107 | } 108 | 109 | bool canWrite() const 110 | { 111 | if (!BaseImpl::canWrite()) { 112 | return false; 113 | } 114 | 115 | if (MaxAllowedSize < BaseImpl::getValue().size()) { 116 | return false; 117 | } 118 | 119 | SizeField sizeField; 120 | sizeField.setValue(BaseImpl::getValue().size()); 121 | return sizeField.canWrite(); 122 | } 123 | 124 | template 125 | comms::ErrorStatus write(TIter& iter, std::size_t len) const 126 | { 127 | if (!canWrite()) { 128 | return comms::ErrorStatus::InvalidMsgData; 129 | } 130 | 131 | SizeField sizeField; 132 | sizeField.setValue(BaseImpl::getValue().size()); 133 | auto es = sizeField.write(iter, len); 134 | if (es != comms::ErrorStatus::Success) { 135 | return es; 136 | } 137 | 138 | COMMS_ASSERT(sizeField.length() <= len); 139 | return BaseImpl::write(iter, len - sizeField.length()); 140 | } 141 | 142 | static constexpr bool hasWriteNoStatus() 143 | { 144 | return false; 145 | } 146 | 147 | template 148 | void writeNoStatus(TIter& iter) const = delete; 149 | }; 150 | 151 | } // namespace adapter 152 | 153 | } // namespace field 154 | 155 | } // namespace comms 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /include/comms/field/adapter/SequenceSizeForcing.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/Assert.h" 11 | #include "comms/ErrorStatus.h" 12 | 13 | #include 14 | 15 | namespace comms 16 | { 17 | 18 | namespace field 19 | { 20 | 21 | namespace adapter 22 | { 23 | 24 | template 25 | class SequenceSizeForcing : public TBase 26 | { 27 | using BaseImpl = TBase; 28 | public: 29 | using ValueType = typename BaseImpl::ValueType; 30 | using ElementType = typename BaseImpl::ElementType; 31 | 32 | SequenceSizeForcing() = default; 33 | 34 | explicit SequenceSizeForcing(const ValueType& val) 35 | : BaseImpl(val) 36 | { 37 | } 38 | 39 | explicit SequenceSizeForcing(ValueType&& val) 40 | : BaseImpl(std::move(val)) 41 | { 42 | } 43 | 44 | SequenceSizeForcing(const SequenceSizeForcing&) = default; 45 | SequenceSizeForcing(SequenceSizeForcing&&) = default; 46 | SequenceSizeForcing& operator=(const SequenceSizeForcing&) = default; 47 | SequenceSizeForcing& operator=(SequenceSizeForcing&&) = default; 48 | 49 | void forceReadElemCount(std::size_t val) 50 | { 51 | COMMS_ASSERT(val != Cleared); 52 | m_forced = val; 53 | } 54 | 55 | void clearReadElemCount() 56 | { 57 | m_forced = Cleared; 58 | } 59 | 60 | template 61 | comms::ErrorStatus read(TIter& iter, std::size_t len) 62 | { 63 | if (m_forced == Cleared) { 64 | return BaseImpl::read(iter, len); 65 | } 66 | 67 | return BaseImpl::readN(m_forced, iter, len); 68 | } 69 | 70 | template 71 | ErrorStatus readN(std::size_t count, TIter& iter, std::size_t& len) = delete; 72 | 73 | 74 | template 75 | void readNoStatus(TIter& iter) 76 | { 77 | if (m_forced == Cleared) { 78 | BaseImpl::readNoStatus(iter); 79 | return; 80 | } 81 | 82 | BaseImpl::readNoStatusN(m_forced, iter); 83 | } 84 | 85 | template 86 | void readNoStatusN(std::size_t count, TIter& iter) = delete; 87 | 88 | 89 | private: 90 | static const std::size_t Cleared = std::numeric_limits::max(); 91 | std::size_t m_forced = Cleared; 92 | }; 93 | 94 | } // namespace adapter 95 | 96 | } // namespace field 97 | 98 | } // namespace comms 99 | 100 | 101 | -------------------------------------------------------------------------------- /include/comms/field/adapter/SequenceTrailingFieldSuffix.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/Assert.h" 11 | #include "comms/ErrorStatus.h" 12 | 13 | namespace comms 14 | { 15 | 16 | namespace field 17 | { 18 | 19 | namespace adapter 20 | { 21 | 22 | template 23 | class SequenceTrailingFieldSuffix : public TBase 24 | { 25 | using BaseImpl = TBase; 26 | using TrailField = TTrailField; 27 | 28 | static_assert(!TrailField::isVersionDependent(), 29 | "Suffix fields must not be version dependent"); 30 | 31 | public: 32 | using ValueType = typename BaseImpl::ValueType; 33 | using ElementType = typename BaseImpl::ElementType; 34 | 35 | SequenceTrailingFieldSuffix() = default; 36 | 37 | explicit SequenceTrailingFieldSuffix(const ValueType& val) 38 | : BaseImpl(val) 39 | { 40 | } 41 | 42 | explicit SequenceTrailingFieldSuffix(ValueType&& val) 43 | : BaseImpl(std::move(val)) 44 | { 45 | } 46 | 47 | SequenceTrailingFieldSuffix(const SequenceTrailingFieldSuffix&) = default; 48 | SequenceTrailingFieldSuffix(SequenceTrailingFieldSuffix&&) = default; 49 | SequenceTrailingFieldSuffix& operator=(const SequenceTrailingFieldSuffix&) = default; 50 | SequenceTrailingFieldSuffix& operator=(SequenceTrailingFieldSuffix&&) = default; 51 | 52 | constexpr std::size_t length() const 53 | { 54 | return m_trailField.length() + BaseImpl::length(); 55 | } 56 | 57 | static constexpr std::size_t minLength() 58 | { 59 | return TrailField::minLength() + BaseImpl::minLength(); 60 | } 61 | 62 | static constexpr std::size_t maxLength() 63 | { 64 | return TrailField::maxLength() + BaseImpl::maxLength(); 65 | } 66 | 67 | bool valid() const 68 | { 69 | return m_trailField.valid() && BaseImpl::valid(); 70 | } 71 | 72 | template 73 | comms::ErrorStatus read(TIter& iter, std::size_t len) 74 | { 75 | auto es = BaseImpl::read(iter, len - TrailField::minLength()); 76 | if (es != comms::ErrorStatus::Success) { 77 | return es; 78 | } 79 | 80 | return m_trailField.read(iter, len - BaseImpl::length()); 81 | } 82 | 83 | static constexpr bool hasReadNoStatus() 84 | { 85 | return false; 86 | } 87 | 88 | template 89 | void readNoStatus(TIter& iter) = delete; 90 | 91 | template 92 | comms::ErrorStatus write(TIter& iter, std::size_t len) const 93 | { 94 | auto trailLen = m_trailField.length(); 95 | auto es = BaseImpl::write(iter, len - trailLen); 96 | if (es != comms::ErrorStatus::Success) { 97 | return es; 98 | } 99 | 100 | return m_trailField.write(iter, trailLen); 101 | } 102 | 103 | template 104 | void writeNoStatus(TIter& iter) const 105 | { 106 | BaseImpl::writeNoStatus(iter); 107 | m_trailField.writeNoStatus(iter); 108 | } 109 | 110 | private: 111 | TrailField m_trailField; 112 | }; 113 | 114 | } // namespace adapter 115 | 116 | } // namespace field 117 | 118 | } // namespace comms 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /include/comms/field/adapter/SerOffset.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/ErrorStatus.h" 11 | #include "comms/util/access.h" 12 | 13 | namespace comms 14 | { 15 | 16 | namespace field 17 | { 18 | 19 | namespace adapter 20 | { 21 | 22 | template 23 | class SerOffset : public TBase 24 | { 25 | using BaseImpl = TBase; 26 | static const auto Offset = TOffset; 27 | public: 28 | 29 | using ValueType = typename BaseImpl::ValueType; 30 | using SerialisedType = typename BaseImpl::SerialisedType; 31 | using Endian = typename BaseImpl::Endian; 32 | 33 | SerOffset() = default; 34 | 35 | explicit SerOffset(const ValueType& val) 36 | : BaseImpl(val) 37 | { 38 | } 39 | 40 | explicit SerOffset(ValueType&& val) 41 | : BaseImpl(std::move(val)) 42 | { 43 | } 44 | 45 | SerOffset(const SerOffset&) = default; 46 | SerOffset(SerOffset&&) = default; 47 | SerOffset& operator=(const SerOffset&) = default; 48 | SerOffset& operator=(SerOffset&&) = default; 49 | 50 | 51 | template 52 | ErrorStatus read(TIter& iter, std::size_t size) 53 | { 54 | if (size < BaseImpl::length()) { 55 | return ErrorStatus::NotEnoughData; 56 | } 57 | 58 | readNoStatus(iter); 59 | return ErrorStatus::Success; 60 | } 61 | 62 | template 63 | void readNoStatus(TIter& iter) 64 | { 65 | auto serialisedValue = 66 | comms::util::readData(iter, Endian()); 67 | BaseImpl::setValue(fromSerialised(serialisedValue)); 68 | } 69 | 70 | template 71 | ErrorStatus write(TIter& iter, std::size_t size) const 72 | { 73 | if (size < BaseImpl::length()) { 74 | return ErrorStatus::BufferOverflow; 75 | } 76 | 77 | writeNoStatus(iter); 78 | return ErrorStatus::Success; 79 | } 80 | 81 | template 82 | void writeNoStatus(TIter& iter) const 83 | { 84 | comms::util::writeData(toSerialised(BaseImpl::getValue()), iter, Endian()); 85 | } 86 | 87 | static constexpr SerialisedType toSerialised(ValueType val) 88 | { 89 | return adjustToSerialised(BaseImpl::toSerialised(val)); 90 | } 91 | 92 | static constexpr ValueType fromSerialised(SerialisedType val) 93 | { 94 | return BaseImpl::fromSerialised(adjustFromSerialised(val)); 95 | } 96 | 97 | private: 98 | static SerialisedType adjustToSerialised(SerialisedType val) 99 | { 100 | return static_cast(Offset + val); 101 | } 102 | 103 | static SerialisedType adjustFromSerialised(SerialisedType val) 104 | { 105 | return static_cast((-Offset) + val); 106 | } 107 | }; 108 | 109 | } // namespace adapter 110 | 111 | } // namespace field 112 | 113 | } // namespace comms 114 | 115 | -------------------------------------------------------------------------------- /include/comms/field/adapter/VariantResetOnDestruct.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace comms 14 | { 15 | 16 | namespace field 17 | { 18 | 19 | namespace adapter 20 | { 21 | 22 | template 23 | class VariantResetOnDestruct : public TBase 24 | { 25 | using BaseImpl = TBase; 26 | static_assert(std::is_same::value, "Applicable only to variant fields"); 27 | public: 28 | 29 | ~VariantResetOnDestruct() 30 | { 31 | BaseImpl::reset(); 32 | } 33 | 34 | VariantResetOnDestruct() = default; 35 | VariantResetOnDestruct(const VariantResetOnDestruct&) = default; 36 | VariantResetOnDestruct(VariantResetOnDestruct&&) = default; 37 | VariantResetOnDestruct& operator=(const VariantResetOnDestruct&) = default; 38 | VariantResetOnDestruct& operator=(VariantResetOnDestruct&&) = default; 39 | 40 | template 41 | ErrorStatus read(TIter& iter, std::size_t len) 42 | { 43 | BaseImpl::reset(); 44 | return BaseImpl::read(iter, len); 45 | } 46 | 47 | }; 48 | 49 | } // namespace adapter 50 | 51 | } // namespace field 52 | 53 | } // namespace comms 54 | 55 | -------------------------------------------------------------------------------- /include/comms/field/adapter/VersionStorage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | 9 | #pragma once 10 | 11 | namespace comms 12 | { 13 | 14 | namespace field 15 | { 16 | 17 | namespace adapter 18 | { 19 | 20 | template 21 | class VersionStorage : public TBase 22 | { 23 | using BaseImpl = TBase; 24 | public: 25 | 26 | using ValueType = typename BaseImpl::ValueType; 27 | using VersionType = typename BaseImpl::VersionType; 28 | 29 | VersionStorage() = default; 30 | 31 | explicit VersionStorage(const ValueType& val) 32 | : BaseImpl(val) 33 | { 34 | } 35 | 36 | explicit VersionStorage(ValueType&& val) 37 | : BaseImpl(std::move(val)) 38 | { 39 | } 40 | 41 | VersionStorage(const VersionStorage&) = default; 42 | VersionStorage(VersionStorage&&) = default; 43 | VersionStorage& operator=(const VersionStorage&) = default; 44 | VersionStorage& operator=(VersionStorage&&) = default; 45 | 46 | static constexpr bool isVersionDependent() 47 | { 48 | return true; 49 | } 50 | 51 | VersionType getVersion() const 52 | { 53 | return m_version; 54 | } 55 | 56 | bool setVersion(VersionType val) 57 | { 58 | bool updated = BaseImpl::setVersion(val); 59 | if (m_version != val) { 60 | m_version = val; 61 | return true; 62 | } 63 | return updated; 64 | } 65 | 66 | private: 67 | VersionType m_version = static_cast(0); 68 | }; 69 | 70 | } // namespace adapter 71 | 72 | } // namespace field 73 | 74 | } // namespace comms 75 | 76 | -------------------------------------------------------------------------------- /include/comms/field/basic/EnumValue.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/ErrorStatus.h" 11 | #include "comms/field/basic/IntValue.h" 12 | #include "comms/field/tag.h" 13 | 14 | #include 15 | 16 | namespace comms 17 | { 18 | 19 | namespace field 20 | { 21 | 22 | namespace basic 23 | { 24 | 25 | template 26 | class EnumValue : public TFieldBase 27 | { 28 | static_assert(std::is_enum::value, "T must be enum"); 29 | 30 | using UnderlyingType = typename std::underlying_type::type; 31 | 32 | using BaseImpl = TFieldBase; 33 | 34 | using IntValueField = 35 | comms::field::basic::IntValue< 36 | BaseImpl, 37 | UnderlyingType 38 | >; 39 | 40 | using IntValueType = typename IntValueField::ValueType; 41 | public: 42 | 43 | using ValueType = T; 44 | 45 | using SerialisedType = typename IntValueField::ValueType; 46 | 47 | using ScalingRatio = typename IntValueField::ScalingRatio; 48 | 49 | using CommsTag = comms::field::tag::Enum; 50 | 51 | EnumValue() = default; 52 | 53 | explicit EnumValue(ValueType val) 54 | : m_value(val) 55 | { 56 | } 57 | 58 | EnumValue(const EnumValue&) = default; 59 | EnumValue(EnumValue&&) = default; 60 | ~EnumValue() noexcept = default; 61 | 62 | EnumValue& operator=(const EnumValue&) = default; 63 | EnumValue& operator=(EnumValue&&) = default; 64 | 65 | const ValueType& value() const 66 | { 67 | return m_value; 68 | } 69 | 70 | ValueType& value() 71 | { 72 | return m_value; 73 | } 74 | 75 | const ValueType& getValue() const 76 | { 77 | return value(); 78 | } 79 | 80 | template 81 | void setValue(U&& val) 82 | { 83 | value() = static_cast(std::forward(val)); 84 | } 85 | 86 | static constexpr std::size_t length() 87 | { 88 | return IntValueField::length(); 89 | } 90 | 91 | static constexpr std::size_t minLength() 92 | { 93 | return length(); 94 | } 95 | 96 | static constexpr std::size_t maxLength() 97 | { 98 | return length(); 99 | } 100 | 101 | static constexpr SerialisedType toSerialised(ValueType val) 102 | { 103 | return IntValueField::toSerialised(static_cast(val)); 104 | } 105 | 106 | static constexpr ValueType fromSerialised(SerialisedType val) 107 | { 108 | return static_cast(IntValueField::fromSerialised(val)); 109 | } 110 | 111 | template 112 | ErrorStatus read(TIter& iter, std::size_t size) 113 | { 114 | IntValueField intField; 115 | auto es = intField.read(iter, size); 116 | if (es == ErrorStatus::Success) { 117 | m_value = static_cast(intField.value()); 118 | } 119 | return es; 120 | } 121 | 122 | template 123 | void readNoStatus(TIter& iter) 124 | { 125 | IntValueField intField; 126 | intField.readNoStatus(iter); 127 | m_value = static_cast(intField.value()); 128 | } 129 | 130 | template 131 | ErrorStatus write(TIter& iter, std::size_t size) const 132 | { 133 | return IntValueField(static_cast(m_value)).write(iter, size); 134 | } 135 | 136 | template 137 | void writeNoStatus(TIter& iter) const 138 | { 139 | IntValueField(static_cast(m_value)).writeNoStatus(iter); 140 | } 141 | 142 | private: 143 | ValueType m_value = static_cast(0); 144 | }; 145 | 146 | } // namespace basic 147 | 148 | } // namespace field 149 | 150 | } // namespace comms 151 | 152 | 153 | -------------------------------------------------------------------------------- /include/comms/field/basic/FloatValue.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/ErrorStatus.h" 11 | #include "comms/field/tag.h" 12 | #include "comms/util/SizeToType.h" 13 | 14 | #include 15 | #include 16 | 17 | namespace comms 18 | { 19 | 20 | namespace field 21 | { 22 | 23 | namespace basic 24 | { 25 | 26 | template 27 | class FloatValue : public TFieldBase 28 | { 29 | static_assert(std::is_floating_point::value, "T must be floating point value"); 30 | 31 | using BaseImpl = TFieldBase; 32 | public: 33 | 34 | using ValueType = T; 35 | using SerialisedType = typename comms::util::SizeToType::Type; 36 | using ScalingRatio = std::ratio<1, 1>; 37 | using CommsTag = comms::field::tag::Float; 38 | 39 | FloatValue() = default; 40 | 41 | explicit FloatValue(ValueType val) 42 | : m_value(val) 43 | { 44 | } 45 | 46 | FloatValue(const FloatValue&) = default; 47 | FloatValue(FloatValue&&) = default; 48 | ~FloatValue() noexcept = default; 49 | 50 | FloatValue& operator=(const FloatValue&) = default; 51 | FloatValue& operator=(FloatValue&&) = default; 52 | 53 | const ValueType& value() const 54 | { 55 | return m_value; 56 | } 57 | 58 | ValueType& value() 59 | { 60 | return m_value; 61 | } 62 | 63 | const ValueType& getValue() const 64 | { 65 | return value(); 66 | } 67 | 68 | template 69 | void setValue(U&& val) 70 | { 71 | value() = static_cast(std::forward(val)); 72 | } 73 | 74 | static constexpr std::size_t length() 75 | { 76 | return sizeof(SerialisedType); 77 | } 78 | 79 | static constexpr std::size_t minLength() 80 | { 81 | return length(); 82 | } 83 | 84 | static constexpr std::size_t maxLength() 85 | { 86 | return length(); 87 | } 88 | 89 | static SerialisedType toSerialised(ValueType val) 90 | { 91 | CastUnion<> castUnion; 92 | castUnion.m_value = val; 93 | return castUnion.m_serValue; 94 | } 95 | 96 | static ValueType fromSerialised(SerialisedType val) 97 | { 98 | CastUnion<> castUnion; 99 | castUnion.m_serValue = val; 100 | return castUnion.m_value; 101 | } 102 | 103 | template 104 | ErrorStatus read(TIter& iter, std::size_t size) 105 | { 106 | if (size < length()) { 107 | return ErrorStatus::NotEnoughData; 108 | } 109 | 110 | readNoStatus(iter); 111 | return ErrorStatus::Success; 112 | } 113 | 114 | template 115 | void readNoStatus(TIter& iter) 116 | { 117 | auto serialisedValue = 118 | BaseImpl::template readData(iter); 119 | m_value = fromSerialised(serialisedValue); 120 | } 121 | 122 | template 123 | ErrorStatus write(TIter& iter, std::size_t size) const 124 | { 125 | if (size < length()) { 126 | return ErrorStatus::BufferOverflow; 127 | } 128 | 129 | writeNoStatus(iter); 130 | return ErrorStatus::Success; 131 | } 132 | 133 | template 134 | void writeNoStatus(TIter& iter) const 135 | { 136 | BaseImpl::writeData(toSerialised(m_value), iter); 137 | } 138 | 139 | private: 140 | template 141 | union CastUnion 142 | { 143 | ValueType m_value; 144 | SerialisedType m_serValue; 145 | }; 146 | 147 | ValueType m_value = static_cast(0.0); 148 | }; 149 | 150 | } // namespace basic 151 | 152 | } // namespace field 153 | 154 | } // namespace comms 155 | 156 | 157 | -------------------------------------------------------------------------------- /include/comms/field/basic/IntValue.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/ErrorStatus.h" 11 | #include "comms/field/tag.h" 12 | 13 | #include 14 | 15 | namespace comms 16 | { 17 | 18 | namespace field 19 | { 20 | 21 | namespace basic 22 | { 23 | 24 | template 25 | class IntValue : public TFieldBase 26 | { 27 | static_assert(std::is_integral::value, "T must be integral value"); 28 | 29 | using BaseImpl = TFieldBase; 30 | public: 31 | 32 | using ValueType = T; 33 | using SerialisedType = ValueType; 34 | using ScalingRatio = std::ratio<1, 1>; 35 | using CommsTag = comms::field::tag::Int; 36 | using DisplayOffsetType = typename std::make_signed::type; 37 | 38 | IntValue() = default; 39 | 40 | explicit IntValue(ValueType val) 41 | : m_value(val) 42 | { 43 | } 44 | 45 | IntValue(const IntValue&) = default; 46 | IntValue(IntValue&&) = default; 47 | ~IntValue() noexcept = default; 48 | 49 | IntValue& operator=(const IntValue&) = default; 50 | IntValue& operator=(IntValue&&) = default; 51 | 52 | const ValueType& value() const 53 | { 54 | return m_value; 55 | } 56 | 57 | ValueType& value() 58 | { 59 | return m_value; 60 | } 61 | 62 | const ValueType& getValue() const 63 | { 64 | return value(); 65 | } 66 | 67 | template 68 | void setValue(U&& val) 69 | { 70 | value() = static_cast(std::forward(val)); 71 | } 72 | 73 | static constexpr std::size_t length() 74 | { 75 | return sizeof(SerialisedType); 76 | } 77 | 78 | static constexpr std::size_t minLength() 79 | { 80 | return length(); 81 | } 82 | 83 | static constexpr std::size_t maxLength() 84 | { 85 | return length(); 86 | } 87 | 88 | static constexpr SerialisedType toSerialised(ValueType val) 89 | { 90 | return static_cast(val); 91 | } 92 | 93 | static constexpr ValueType fromSerialised(SerialisedType val) 94 | { 95 | return static_cast(val); 96 | } 97 | 98 | template 99 | ErrorStatus read(TIter& iter, std::size_t size) 100 | { 101 | if (size < length()) { 102 | return ErrorStatus::NotEnoughData; 103 | } 104 | 105 | readNoStatus(iter); 106 | return ErrorStatus::Success; 107 | } 108 | 109 | template 110 | void readNoStatus(TIter& iter) 111 | { 112 | auto serialisedValue = 113 | BaseImpl::template readData(iter); 114 | m_value = fromSerialised(serialisedValue); 115 | } 116 | 117 | template 118 | ErrorStatus write(TIter& iter, std::size_t size) const 119 | { 120 | if (size < length()) { 121 | return ErrorStatus::BufferOverflow; 122 | } 123 | 124 | writeNoStatus(iter); 125 | return ErrorStatus::Success; 126 | } 127 | 128 | template 129 | void writeNoStatus(TIter& iter) const 130 | { 131 | BaseImpl::writeData(toSerialised(m_value), iter); 132 | } 133 | 134 | static constexpr DisplayOffsetType displayOffset() 135 | { 136 | return static_cast(0); 137 | } 138 | 139 | private: 140 | ValueType m_value = static_cast(0); 141 | }; 142 | 143 | } // namespace basic 144 | 145 | } // namespace field 146 | 147 | } // namespace comms 148 | 149 | 150 | -------------------------------------------------------------------------------- /include/comms/field/basics.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "basic/ArrayList.h" 11 | #include "basic/Bitfield.h" 12 | #include "basic/Bundle.h" 13 | #include "basic/EnumValue.h" 14 | #include "basic/FloatValue.h" 15 | #include "basic/IntValue.h" 16 | #include "basic/Variant.h" 17 | -------------------------------------------------------------------------------- /include/comms/field/details/MembersVersionDependency.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | namespace comms 11 | { 12 | 13 | namespace field 14 | { 15 | 16 | namespace details 17 | { 18 | 19 | enum MembersVersionDependency 20 | { 21 | MembersVersionDependency_NotSpecified, 22 | MembersVersionDependency_Independent, 23 | MembersVersionDependency_Dependent 24 | }; 25 | 26 | } // namespace details 27 | 28 | } // namespace field 29 | 30 | } // namespace comms -------------------------------------------------------------------------------- /include/comms/field/details/VersionStorage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | namespace comms 11 | { 12 | 13 | namespace field 14 | { 15 | 16 | namespace details 17 | { 18 | 19 | template 20 | struct VersionStorage 21 | { 22 | TVersionType getVersion() const 23 | { 24 | return m_version; 25 | } 26 | 27 | protected: 28 | TVersionType m_version = TVersionType(); 29 | }; 30 | 31 | } // namespace details 32 | 33 | } // namespace field 34 | 35 | } // namespace comms 36 | -------------------------------------------------------------------------------- /include/comms/field/details/adapters.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/field/adapter/AvailableLength.h" 11 | #include "comms/field/adapter/CustomValidator.h" 12 | #include "comms/field/adapter/CustomReadWrap.h" 13 | #include "comms/field/adapter/CustomRefreshWrap.h" 14 | #include "comms/field/adapter/CustomWriteWrap.h" 15 | #include "comms/field/adapter/DefaultValueInitialiser.h" 16 | #include "comms/field/adapter/DisplayOffset.h" 17 | #include "comms/field/adapter/EmptySerialization.h" 18 | #include "comms/field/adapter/ExistsBetweenVersions.h" 19 | #include "comms/field/adapter/FailOnInvalid.h" 20 | #include "comms/field/adapter/FieldType.h" 21 | #include "comms/field/adapter/FixedBitLength.h" 22 | #include "comms/field/adapter/FixedLength.h" 23 | #include "comms/field/adapter/FixedValue.h" 24 | #include "comms/field/adapter/IgnoreInvalid.h" 25 | #include "comms/field/adapter/InvalidByDefault.h" 26 | #include "comms/field/adapter/MissingOnInvalid.h" 27 | #include "comms/field/adapter/MissingOnReadFail.h" 28 | #include "comms/field/adapter/NumValueMultiRangeValidator.h" 29 | #include "comms/field/adapter/RemLengthMemberField.h" 30 | #include "comms/field/adapter/SequenceElemFixedSerLengthFieldPrefix.h" 31 | #include "comms/field/adapter/SequenceElemLengthForcing.h" 32 | #include "comms/field/adapter/SequenceElemSerLengthFieldPrefix.h" 33 | #include "comms/field/adapter/SequenceFixedSize.h" 34 | #include "comms/field/adapter/SequenceLengthForcing.h" 35 | #include "comms/field/adapter/SequenceSerLengthFieldPrefix.h" 36 | #include "comms/field/adapter/SequenceSizeFieldPrefix.h" 37 | #include "comms/field/adapter/SequenceSizeForcing.h" 38 | #include "comms/field/adapter/SequenceTrailingFieldSuffix.h" 39 | #include "comms/field/adapter/SequenceTerminationFieldSuffix.h" 40 | #include "comms/field/adapter/SerOffset.h" 41 | #include "comms/field/adapter/VariantResetOnDestruct.h" 42 | #include "comms/field/adapter/VarLength.h" 43 | #include "comms/field/adapter/VersionStorage.h" 44 | -------------------------------------------------------------------------------- /include/comms/field/tag.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of various tag classes 10 | 11 | #pragma once 12 | 13 | #include "comms/details/tag.h" 14 | 15 | namespace comms 16 | { 17 | 18 | namespace field 19 | { 20 | 21 | namespace tag 22 | { 23 | 24 | using RawArrayList = comms::details::tag::Tag1<>; 25 | using ArrayList = comms::details::tag::Tag2<>; 26 | using Bitfield = comms::details::tag::Tag3<>; 27 | using Bitmask = comms::details::tag::Tag4<>; 28 | using Bundle = comms::details::tag::Tag5<>; 29 | using Enum = comms::details::tag::Tag6<>; 30 | using Float = comms::details::tag::Tag7<>; 31 | using Int = comms::details::tag::Tag8<>; 32 | using Optional = comms::details::tag::Tag9<>; 33 | using String = comms::details::tag::Tag10<>; 34 | using Variant = comms::details::tag::Tag11<>; 35 | 36 | } // namespace tag 37 | 38 | } // namespace field 39 | 40 | } // namespace comms 41 | 42 | 43 | -------------------------------------------------------------------------------- /include/comms/field_cast.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contained definition of field_cast() function. Now deprecated, use "comms/cast.h" instead. 10 | 11 | #pragma once 12 | 13 | #include "comms/cast.h" 14 | 15 | 16 | -------------------------------------------------------------------------------- /include/comms/fields.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief This file provides all the definitions from comms::field namespace. 10 | 11 | #pragma once 12 | 13 | #include "comms/field/ArrayList.h" 14 | #include "comms/field/Bitfield.h" 15 | #include "comms/field/BitmaskValue.h" 16 | #include "comms/field/Bundle.h" 17 | #include "comms/field/EnumValue.h" 18 | #include "comms/field/FloatValue.h" 19 | #include "comms/field/IntValue.h" 20 | #include "comms/field/Optional.h" 21 | #include "comms/field/String.h" 22 | #include "comms/field/Variant.h" 23 | 24 | #include "comms/cast.h" 25 | -------------------------------------------------------------------------------- /include/comms/frame/checksum/BasicSum.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::frame::checksum::BasicSum 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | namespace comms 16 | { 17 | 18 | namespace frame 19 | { 20 | 21 | namespace checksum 22 | { 23 | 24 | /// @brief Summary of all bytes checksum calculator. 25 | /// @details The checksum calculator class that sums all the bytes and 26 | /// returns the result as a checksum value. 27 | /// @tparam TResult Type of the checksum result value. 28 | /// @tparam TInitValue Initial value 29 | /// @headerfile comms/frame/checksum/BasicSum.h 30 | template 31 | class BasicSum 32 | { 33 | public: 34 | /// @brief Operator that is invoked to calculate the checksum value 35 | /// @param[in, out] iter Input iterator, 36 | /// @param[in] len Number of bytes to summarise. 37 | /// @return The checksum value. 38 | /// @post The iterator is advanced by number of bytes read (len). 39 | template 40 | TResult operator()(TIter& iter, std::size_t len) const 41 | { 42 | using ByteType = typename std::make_unsigned< 43 | typename std::decay::type 44 | >::type; 45 | 46 | TResult checksum = TInitValue; 47 | for (auto idx = 0U; idx < len; ++idx) { 48 | checksum = static_cast(checksum + static_cast(*iter)); 49 | ++iter; 50 | } 51 | return checksum; 52 | } 53 | }; 54 | 55 | } // namespace checksum 56 | 57 | } // namespace frame 58 | 59 | } // namespace comms 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /include/comms/frame/checksum/BasicXor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2021 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::frame::checksum::BasicXor 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | namespace comms 16 | { 17 | 18 | namespace frame 19 | { 20 | 21 | namespace checksum 22 | { 23 | 24 | /// @brief Exclusive OR (XOR) of all bytes checksum calculator. 25 | /// @details The checksum calculator class that applies XOR operation on all the bytes and 26 | /// returns the result as a checksum value. 27 | /// @tparam TResult Type of the checksum result value. 28 | /// @tparam TInitValue Initial value 29 | /// @headerfile comms/frame/checksum/BasicXor.h 30 | template 31 | class BasicXor 32 | { 33 | public: 34 | /// @brief Operator that is invoked to calculate the checksum value 35 | /// @param[in, out] iter Input iterator, 36 | /// @param[in] len Number of bytes to summarise. 37 | /// @return The checksum value. 38 | /// @post The iterator is advanced by number of bytes read (len). 39 | template 40 | TResult operator()(TIter& iter, std::size_t len) const 41 | { 42 | using ByteType = typename std::make_unsigned< 43 | typename std::decay::type 44 | >::type; 45 | 46 | TResult checksum = TInitValue; 47 | for (auto idx = 0U; idx < len; ++idx) { 48 | checksum = static_cast(checksum ^ static_cast(*iter)); 49 | ++iter; 50 | } 51 | return checksum; 52 | } 53 | }; 54 | 55 | } // namespace checksum 56 | 57 | } // namespace frame 58 | 59 | } // namespace comms 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /include/comms/frame/details/ChecksumLayerBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/frame/details/ChecksumLayerOptionsParser.h" 11 | #include "comms/frame/FrameLayerBase.h" 12 | 13 | #include 14 | 15 | namespace comms 16 | { 17 | 18 | namespace frame 19 | { 20 | 21 | // Forward declaration 22 | template 23 | class ChecksumLayer; 24 | 25 | namespace details 26 | { 27 | 28 | template 29 | class ChecksumLayerBaseHelper 30 | { 31 | using ParsedOptionsInternal = comms::frame::details::ChecksumLayerOptionsParser; 32 | using ActualLayer = 33 | typename ParsedOptionsInternal::template DefineExtendingClass< 34 | ChecksumLayer 35 | >; 36 | 37 | using TopBase = 38 | comms::frame::FrameLayerBase< 39 | TField, 40 | TNextLayer, 41 | ActualLayer, 42 | comms::option::def::FrameLayerDisallowReadUntilDataSplit 43 | >; 44 | 45 | public: 46 | using Base = TopBase; 47 | }; 48 | 49 | template 50 | using ChecksumLayerBase = typename ChecksumLayerBaseHelper::Base; 51 | 52 | } // namespace details 53 | 54 | } // namespace frame 55 | 56 | } // namespace comms 57 | -------------------------------------------------------------------------------- /include/comms/frame/details/ChecksumLayerOptionsParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/options.h" 11 | 12 | namespace comms 13 | { 14 | 15 | namespace frame 16 | { 17 | 18 | namespace details 19 | { 20 | 21 | 22 | template 23 | class ChecksumLayerOptionsParser; 24 | 25 | template <> 26 | class ChecksumLayerOptionsParser<> 27 | { 28 | public: 29 | static constexpr bool HasVerifyBeforeRead = false; 30 | static constexpr bool HasExtendingClass = false; 31 | 32 | using ExtendingClass = void; 33 | 34 | template 35 | using DefineExtendingClass = TLayer; 36 | 37 | template 38 | using SuppressForVerifyBeforeRead = TOpt; 39 | 40 | }; 41 | 42 | template 43 | class ChecksumLayerOptionsParser : 44 | public ChecksumLayerOptionsParser 45 | { 46 | public: 47 | static constexpr bool HasVerifyBeforeRead = true; 48 | 49 | template 50 | using SuppressForVerifyBeforeRead = comms::option::app::EmptyOption; 51 | }; 52 | 53 | template 54 | class ChecksumLayerOptionsParser, TOptions...> : 55 | public ChecksumLayerOptionsParser 56 | { 57 | public: 58 | static constexpr bool HasExtendingClass = true; 59 | using ExtendingClass = T; 60 | 61 | template 62 | using DefineExtendingClass = ExtendingClass; 63 | }; 64 | 65 | template 66 | class ChecksumLayerOptionsParser< 67 | comms::option::app::EmptyOption, 68 | TOptions...> : public ChecksumLayerOptionsParser 69 | { 70 | }; 71 | 72 | template 73 | class ChecksumLayerOptionsParser< 74 | std::tuple, 75 | TOptions...> : public ChecksumLayerOptionsParser 76 | { 77 | }; 78 | 79 | } // namespace details 80 | 81 | } // namespace frame 82 | 83 | } // namespace comms 84 | -------------------------------------------------------------------------------- /include/comms/frame/details/ChecksumPrefixLayerBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/frame/details/ChecksumLayerOptionsParser.h" 11 | #include "comms/frame/FrameLayerBase.h" 12 | 13 | #include 14 | 15 | namespace comms 16 | { 17 | 18 | namespace frame 19 | { 20 | 21 | // Forward declaration 22 | template 23 | class ChecksumPrefixLayer; 24 | 25 | namespace details 26 | { 27 | 28 | template 29 | class ChecksumPrefixLayerBaseHelper 30 | { 31 | using ParsedOptionsInternal = comms::frame::details::ChecksumLayerOptionsParser; 32 | using ActualLayer = 33 | typename ParsedOptionsInternal::template DefineExtendingClass< 34 | ChecksumPrefixLayer 35 | >; 36 | 37 | using TopBase = 38 | comms::frame::FrameLayerBase< 39 | TField, 40 | TNextLayer, 41 | ActualLayer, 42 | typename ParsedOptionsInternal::template SuppressForVerifyBeforeRead 43 | >; 44 | 45 | public: 46 | using Base = TopBase; 47 | }; 48 | 49 | template 50 | using ChecksumPrefixLayerBase = typename ChecksumPrefixLayerBaseHelper::Base; 51 | 52 | } // namespace details 53 | 54 | } // namespace frame 55 | 56 | } // namespace comms 57 | -------------------------------------------------------------------------------- /include/comms/frame/details/FrameLayerBaseOptionsParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/options.h" 11 | 12 | namespace comms 13 | { 14 | 15 | namespace frame 16 | { 17 | 18 | namespace details 19 | { 20 | 21 | 22 | template 23 | class FrameLayerBaseOptionsParser; 24 | 25 | template <> 26 | class FrameLayerBaseOptionsParser<> 27 | { 28 | public: 29 | static constexpr bool HasForceReadUntilDataSplit = false; 30 | static constexpr bool HasDisallowReadUntilDataSplit = false; 31 | }; 32 | 33 | template 34 | class FrameLayerBaseOptionsParser< 35 | comms::option::def::FrameLayerForceReadUntilDataSplit, TOptions...> : 36 | public FrameLayerBaseOptionsParser 37 | { 38 | public: 39 | static constexpr bool HasForceReadUntilDataSplit = true; 40 | }; 41 | 42 | template 43 | class FrameLayerBaseOptionsParser< 44 | comms::option::def::FrameLayerDisallowReadUntilDataSplit, TOptions...> : 45 | public FrameLayerBaseOptionsParser 46 | { 47 | public: 48 | static constexpr bool HasDisallowReadUntilDataSplit = true; 49 | }; 50 | 51 | template 52 | class FrameLayerBaseOptionsParser< 53 | comms::option::app::EmptyOption, 54 | TOptions...> : public FrameLayerBaseOptionsParser 55 | { 56 | }; 57 | 58 | template 59 | class FrameLayerBaseOptionsParser< 60 | std::tuple, 61 | TOptions...> : public FrameLayerBaseOptionsParser 62 | { 63 | }; 64 | 65 | } // namespace details 66 | 67 | } // namespace frame 68 | 69 | } // namespace comms 70 | -------------------------------------------------------------------------------- /include/comms/frame/details/MsgDataLayerOptionsParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/Field.h" 11 | #include "comms/field/ArrayList.h" 12 | #include "comms/options.h" 13 | 14 | namespace comms 15 | { 16 | 17 | namespace frame 18 | { 19 | 20 | namespace details 21 | { 22 | 23 | class MsgDataLayerField : public 24 | comms::field::ArrayList< 25 | comms::Field, 26 | std::uint8_t, 27 | comms::option::HasName 28 | > 29 | { 30 | public: 31 | static const char* name() 32 | { 33 | return "Data"; 34 | } 35 | }; 36 | 37 | template 38 | class MsgDataLayerOptionsParser; 39 | 40 | template <> 41 | class MsgDataLayerOptionsParser<> 42 | { 43 | public: 44 | static constexpr bool HasFieldType = false; 45 | using FieldType = MsgDataLayerField; 46 | }; 47 | 48 | template 49 | class MsgDataLayerOptionsParser, TOptions...> : 50 | public MsgDataLayerOptionsParser 51 | { 52 | public: 53 | static constexpr bool HasFieldType = true; 54 | using FieldType = TField; 55 | }; 56 | 57 | template 58 | class MsgDataLayerOptionsParser< 59 | comms::option::app::EmptyOption, 60 | TOptions...> : public MsgDataLayerOptionsParser 61 | { 62 | }; 63 | 64 | template 65 | class MsgDataLayerOptionsParser< 66 | std::tuple, 67 | TOptions...> : public MsgDataLayerOptionsParser 68 | { 69 | }; 70 | 71 | } // namespace details 72 | 73 | } // namespace frame 74 | 75 | } // namespace comms 76 | -------------------------------------------------------------------------------- /include/comms/frame/details/MsgIdLayerBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/frame/details/MsgIdLayerOptionsParser.h" 11 | #include "comms/frame/FrameLayerBase.h" 12 | 13 | #include 14 | 15 | namespace comms 16 | { 17 | 18 | namespace frame 19 | { 20 | 21 | // Forward declaration 22 | template 23 | class MsgIdLayer; 24 | 25 | namespace details 26 | { 27 | 28 | template 29 | class MsgIdLayerBaseHelper 30 | { 31 | using ParsedOptionsInternal = comms::frame::details::MsgIdLayerOptionsParser; 32 | using ActualLayer = typename ParsedOptionsInternal::template DefineExtendingClass>; 33 | using TopBase = 34 | comms::frame::FrameLayerBase< 35 | TField, 36 | TNextLayer, 37 | ActualLayer 38 | >; 39 | 40 | public: 41 | using Base = TopBase; 42 | }; 43 | 44 | template 45 | using MsgIdLayerBase = typename MsgIdLayerBaseHelper::Base; 46 | 47 | } // namespace details 48 | 49 | } // namespace frame 50 | 51 | } // namespace comms 52 | -------------------------------------------------------------------------------- /include/comms/frame/details/MsgIdLayerOptionsParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/MsgFactory.h" 11 | #include "comms/options.h" 12 | #include "comms/util/type_traits.h" 13 | 14 | #include 15 | 16 | namespace comms 17 | { 18 | 19 | namespace frame 20 | { 21 | 22 | namespace details 23 | { 24 | 25 | 26 | template 27 | class MsgIdLayerOptionsParser; 28 | 29 | template <> 30 | class MsgIdLayerOptionsParser<> 31 | { 32 | public: 33 | static const bool HasExtendingClass = false; 34 | static const bool HasMsgFactory = false; 35 | 36 | using ExtendingClass = void; 37 | using FactoryOptions = std::tuple<>; 38 | 39 | template 40 | using MsgFactory = comms::MsgFactory; 41 | 42 | template 43 | using DefineExtendingClass = TLayer; 44 | }; 45 | 46 | template 47 | class MsgIdLayerOptionsParser, TOptions...> : 48 | public MsgIdLayerOptionsParser 49 | { 50 | public: 51 | static const bool HasExtendingClass = true; 52 | using ExtendingClass = T; 53 | 54 | template 55 | using DefineExtendingClass = ExtendingClass; 56 | }; 57 | 58 | template 59 | class MsgIdLayerOptionsParser, TOptions...> : 60 | public MsgIdLayerOptionsParser 61 | { 62 | public: 63 | static const bool HasMsgFactory = true; 64 | 65 | template 66 | using MsgFactory = TFactory; 67 | }; 68 | 69 | template class TFactory, typename... TOptions> 70 | class MsgIdLayerOptionsParser, TOptions...> : 71 | public MsgIdLayerOptionsParser 72 | { 73 | using BaseImpl = MsgIdLayerOptionsParser; 74 | public: 75 | 76 | static const bool HasMsgFactory = true; 77 | 78 | template 79 | using MsgFactory = TFactory; 80 | }; 81 | 82 | 83 | template 84 | class MsgIdLayerOptionsParser< 85 | comms::option::app::EmptyOption, 86 | TOptions...> : public MsgIdLayerOptionsParser 87 | { 88 | }; 89 | 90 | template 91 | class MsgIdLayerOptionsParser< 92 | std::tuple, 93 | TOptions...> : public MsgIdLayerOptionsParser 94 | { 95 | }; 96 | 97 | template 98 | class MsgIdLayerOptionsParser : public MsgIdLayerOptionsParser 99 | { 100 | using BaseImpl = MsgIdLayerOptionsParser; 101 | public: 102 | using FactoryOptions = 103 | typename std::decay< 104 | decltype( 105 | std::tuple_cat( 106 | std::declval >(), 107 | std::declval() 108 | ) 109 | ) 110 | >::type; 111 | 112 | // Ignoring all the options if MsgFactory is overriden 113 | template 114 | using MsgFactory = 115 | typename comms::util::Conditional< 116 | BaseImpl::HasMsgFactory 117 | >::template Type< 118 | typename BaseImpl::template MsgFactory, 119 | comms::MsgFactory 120 | >; 121 | }; 122 | 123 | } // namespace details 124 | 125 | } // namespace frame 126 | 127 | } // namespace comms 128 | -------------------------------------------------------------------------------- /include/comms/frame/details/MsgSizeLayerBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/frame/details/MsgSizeLayerOptionsParser.h" 11 | #include "comms/frame/FrameLayerBase.h" 12 | #include "comms/options.h" 13 | 14 | #include 15 | 16 | namespace comms 17 | { 18 | 19 | namespace frame 20 | { 21 | 22 | // Forward declaration 23 | template 24 | class MsgSizeLayer; 25 | 26 | namespace details 27 | { 28 | 29 | template 30 | class MsgSizeLayerBaseHelper 31 | { 32 | using ParsedOptionsInternal = comms::frame::details::MsgSizeLayerOptionsParser; 33 | using ActualLayer = typename ParsedOptionsInternal::template DefineExtendingClass>; 34 | using TopBase = 35 | comms::frame::FrameLayerBase< 36 | TField, 37 | TNextLayer, 38 | ActualLayer, 39 | comms::option::FrameLayerDisallowReadUntilDataSplit 40 | >; 41 | 42 | public: 43 | using Base = TopBase; 44 | }; 45 | 46 | template 47 | using MsgSizeLayerBase = typename MsgSizeLayerBaseHelper::Base; 48 | 49 | } // namespace details 50 | 51 | } // namespace frame 52 | 53 | } // namespace comms 54 | -------------------------------------------------------------------------------- /include/comms/frame/details/MsgSizeLayerConstNullPtrCastHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | namespace comms 11 | { 12 | 13 | namespace frame 14 | { 15 | 16 | namespace details 17 | { 18 | 19 | template 20 | struct MsgSizeLayerConstNullPtrCastHelper 21 | { 22 | template 23 | using Type = const typename TPtr::element_type*; 24 | }; 25 | 26 | template <> 27 | struct MsgSizeLayerConstNullPtrCastHelper 28 | { 29 | template 30 | using Type = const void*; 31 | }; 32 | 33 | } // namespace details 34 | 35 | } // namespace frame 36 | 37 | } // namespace comms 38 | -------------------------------------------------------------------------------- /include/comms/frame/details/MsgSizeLayerOptionsParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/options.h" 11 | 12 | #include 13 | 14 | namespace comms 15 | { 16 | 17 | namespace frame 18 | { 19 | 20 | namespace details 21 | { 22 | 23 | 24 | template 25 | class MsgSizeLayerOptionsParser; 26 | 27 | template <> 28 | class MsgSizeLayerOptionsParser<> 29 | { 30 | public: 31 | static constexpr bool HasExtendingClass = false; 32 | 33 | using ExtendingClass = void; 34 | 35 | template 36 | using DefineExtendingClass = TLayer; 37 | }; 38 | 39 | template 40 | class MsgSizeLayerOptionsParser, TOptions...> : 41 | public MsgSizeLayerOptionsParser 42 | { 43 | public: 44 | static constexpr bool HasExtendingClass = true; 45 | using ExtendingClass = T; 46 | 47 | template 48 | using DefineExtendingClass = ExtendingClass; 49 | }; 50 | 51 | template 52 | class MsgSizeLayerOptionsParser< 53 | comms::option::app::EmptyOption, 54 | TOptions...> : public MsgSizeLayerOptionsParser 55 | { 56 | }; 57 | 58 | template 59 | class MsgSizeLayerOptionsParser< 60 | std::tuple, 61 | TOptions...> : public MsgSizeLayerOptionsParser 62 | { 63 | }; 64 | 65 | } // namespace details 66 | 67 | } // namespace frame 68 | 69 | } // namespace comms 70 | -------------------------------------------------------------------------------- /include/comms/frame/details/SyncPrefixLayerBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/frame/details/SyncPrefixLayerOptionsParser.h" 11 | #include "comms/frame/FrameLayerBase.h" 12 | 13 | #include 14 | 15 | namespace comms 16 | { 17 | 18 | namespace frame 19 | { 20 | 21 | // Forward declaration 22 | template 23 | class SyncPrefixLayer; 24 | 25 | namespace details 26 | { 27 | 28 | template 29 | class SyncPrefixLayerBaseHelper 30 | { 31 | using ParsedOptionsInternal = comms::frame::details::SyncPrefixLayerOptionsParser; 32 | using ActualLayer = typename ParsedOptionsInternal::template DefineExtendingClass>; 33 | using TopBase = 34 | comms::frame::FrameLayerBase< 35 | TField, 36 | TNextLayer, 37 | ActualLayer 38 | >; 39 | 40 | public: 41 | using Base = TopBase; 42 | }; 43 | 44 | template 45 | using SyncPrefixLayerBase = typename SyncPrefixLayerBaseHelper::Base; 46 | 47 | } // namespace details 48 | 49 | } // namespace frame 50 | 51 | } // namespace comms 52 | -------------------------------------------------------------------------------- /include/comms/frame/details/SyncPrefixLayerOptionsParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2021 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/options.h" 11 | 12 | namespace comms 13 | { 14 | 15 | namespace frame 16 | { 17 | 18 | namespace details 19 | { 20 | 21 | 22 | template 23 | class SyncPrefixLayerOptionsParser; 24 | 25 | template <> 26 | class SyncPrefixLayerOptionsParser<> 27 | { 28 | public: 29 | static constexpr bool HasExtendingClass = false; 30 | 31 | using ExtendingClass = void; 32 | 33 | template 34 | using DefineExtendingClass = TLayer; 35 | }; 36 | 37 | template 38 | class SyncPrefixLayerOptionsParser, TOptions...> : 39 | public SyncPrefixLayerOptionsParser 40 | { 41 | public: 42 | static constexpr bool HasExtendingClass = true; 43 | using ExtendingClass = T; 44 | 45 | template 46 | using DefineExtendingClass = ExtendingClass; 47 | }; 48 | 49 | template 50 | class SyncPrefixLayerOptionsParser< 51 | comms::option::app::EmptyOption, 52 | TOptions...> : public SyncPrefixLayerOptionsParser 53 | { 54 | }; 55 | 56 | template 57 | class SyncPrefixLayerOptionsParser< 58 | std::tuple, 59 | TOptions...> : public SyncPrefixLayerOptionsParser 60 | { 61 | }; 62 | 63 | } // namespace details 64 | 65 | } // namespace frame 66 | 67 | } // namespace comms 68 | -------------------------------------------------------------------------------- /include/comms/frame/details/TransportValueLayerAllBases.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | namespace comms 11 | { 12 | 13 | namespace frame 14 | { 15 | 16 | namespace details 17 | { 18 | 19 | template 20 | class TransportValueLayerPseudoBase : public TBase 21 | { 22 | using BaseImpl = TBase; 23 | using FieldImpl = typename BaseImpl::Field; 24 | public: 25 | FieldImpl& pseudoField() 26 | { 27 | return m_pseudoField; 28 | } 29 | 30 | const FieldImpl& pseudoField() const 31 | { 32 | return m_pseudoField; 33 | } 34 | 35 | private: 36 | FieldImpl m_pseudoField; 37 | }; 38 | 39 | } // namespace details 40 | 41 | } // namespace frame 42 | 43 | } // namespace comms 44 | -------------------------------------------------------------------------------- /include/comms/frame/details/TransportValueLayerBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/frame/details/TransportValueLayerOptionsParser.h" 11 | #include "comms/frame/FrameLayerBase.h" 12 | 13 | #include 14 | 15 | namespace comms 16 | { 17 | 18 | namespace frame 19 | { 20 | 21 | // Forward declaration 22 | template 23 | class TransportValueLayer; 24 | 25 | namespace details 26 | { 27 | 28 | template 29 | class TransportValueLayerBaseHelper 30 | { 31 | using ParsedOptionsInternal = comms::frame::details::TransportValueLayerOptionsParser; 32 | using ActualLayer = typename ParsedOptionsInternal::template DefineExtendingClass>; 33 | using TopBase = 34 | comms::frame::FrameLayerBase< 35 | TField, 36 | TNextLayer, 37 | ActualLayer, 38 | typename ParsedOptionsInternal::template ForceReadUntilDataSplitIfNeeded 39 | >; 40 | 41 | using AdaptedPseudoBase = typename ParsedOptionsInternal::template BuildPseudoBase; 42 | 43 | public: 44 | using Base = AdaptedPseudoBase; 45 | }; 46 | 47 | template 48 | using TransportValueLayerBase = typename TransportValueLayerBaseHelper::Base; 49 | 50 | } // namespace details 51 | 52 | } // namespace frame 53 | 54 | } // namespace comms 55 | -------------------------------------------------------------------------------- /include/comms/frame/details/TransportValueLayerOptionsParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/options.h" 11 | #include "comms/frame/details/TransportValueLayerAllBases.h" 12 | 13 | namespace comms 14 | { 15 | 16 | namespace frame 17 | { 18 | 19 | namespace details 20 | { 21 | 22 | template 23 | class TransportValueLayerOptionsParser; 24 | 25 | template <> 26 | class TransportValueLayerOptionsParser<> 27 | { 28 | public: 29 | static const bool HasPseudoValue = false; 30 | static constexpr bool HasExtendingClass = false; 31 | 32 | using ExtendingClass = void; 33 | 34 | template 35 | using BuildPseudoBase = TBase; 36 | 37 | template 38 | using DefineExtendingClass = TLayer; 39 | 40 | template 41 | using ForceReadUntilDataSplitIfNeeded = 42 | typename comms::util::Conditional< 43 | std::is_void::Type>::value 44 | >::template Type < 45 | comms::option::app::EmptyOption, 46 | comms::option::def::FrameLayerForceReadUntilDataSplit 47 | // If the MsgPtr is not defined, then the MsgIdLayer is 48 | // probably an outer layer, as the result the message 49 | // object is properly allocated when transport value 50 | // read operation is reached. 51 | >; 52 | }; 53 | 54 | template 55 | class TransportValueLayerOptionsParser : 56 | public TransportValueLayerOptionsParser 57 | { 58 | public: 59 | static const bool HasPseudoValue = true; 60 | 61 | template 62 | using BuildPseudoBase = TransportValueLayerPseudoBase; 63 | }; 64 | 65 | template 66 | class TransportValueLayerOptionsParser, TOptions...> : 67 | public TransportValueLayerOptionsParser 68 | { 69 | public: 70 | static constexpr bool HasExtendingClass = true; 71 | using ExtendingClass = T; 72 | 73 | template 74 | using DefineExtendingClass = ExtendingClass; 75 | }; 76 | 77 | template 78 | class TransportValueLayerOptionsParser< 79 | comms::option::def::FrameLayerSuppressReadUntilDataSplitForcing, 80 | TOptions...> : 81 | public TransportValueLayerOptionsParser 82 | { 83 | public: 84 | template 85 | using ForceReadUntilDataSplitIfNeeded = comms::option::app::EmptyOption; 86 | }; 87 | 88 | template 89 | class TransportValueLayerOptionsParser< 90 | comms::option::app::EmptyOption, 91 | TOptions...> : public TransportValueLayerOptionsParser 92 | { 93 | }; 94 | 95 | template 96 | class TransportValueLayerOptionsParser< 97 | std::tuple, 98 | TOptions...> : public TransportValueLayerOptionsParser 99 | { 100 | }; 101 | 102 | } // namespace details 103 | 104 | } // namespace frame 105 | 106 | } // namespace comms 107 | -------------------------------------------------------------------------------- /include/comms/frames.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief This file provides all the definitions from comms::frame namespace. 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/MsgDataLayer.h" 14 | #include "comms/frame/MsgIdLayer.h" 15 | #include "comms/frame/MsgSizeLayer.h" 16 | #include "comms/frame/SyncPrefixLayer.h" 17 | #include "comms/frame/ChecksumLayer.h" 18 | #include "comms/frame/ChecksumPrefixLayer.h" 19 | #include "comms/frame/TransportValueLayer.h" 20 | 21 | #include "comms/frame/checksum/BasicSum.h" 22 | #include "comms/frame/checksum/BasicXor.h" 23 | #include "comms/frame/checksum/Crc.h" 24 | -------------------------------------------------------------------------------- /include/comms/iterator.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | /// @file 11 | /// @brief Provides auxiliary functions for retrieving best type of iterator for read/write operations 12 | 13 | #include "comms/details/ReadIteratorHelper.h" 14 | #include "comms/details/WriteIteratorHelper.h" 15 | 16 | namespace comms 17 | { 18 | 19 | /// @brief Create and initialise iterator for message read 20 | /// @tparam TMessage Type of message interface class or smart pointer to it. 21 | /// @param[in] iter Iterator value. 22 | /// @return The same @b iter value, but casted to appropriate type 23 | template 24 | auto readIteratorFor(TIter&& iter) -> decltype(details::ReadIteratorHelper<>::template get(std::forward(iter))) 25 | { 26 | return details::ReadIteratorHelper<>::template get(std::forward(iter)); 27 | } 28 | 29 | /// @brief Create and initialise iterator for message read 30 | /// @tparam TMessage Type of message interface class or smart pointer to it. 31 | /// @param[in] msg Unused message object helps detecting proper message type. 32 | /// @param[in] iter Iterator value. 33 | /// @return The same @b iter value, but casted to appropriate type 34 | template 35 | auto readIteratorFor(TMessage&& msg, TIter&& iter) -> 36 | decltype(details::ReadIteratorHelper<>::template get::type>(std::forward(iter))) 37 | { 38 | static_cast(msg); 39 | return details::ReadIteratorHelper<>::template get::type>(std::forward(iter)); 40 | } 41 | 42 | /// @brief Create and initialise iterator for message write 43 | /// @tparam TMessage Type of message interface class or smart pointer to it. 44 | /// @param[in] iter Iterator value. 45 | /// @return The same @b iter value, but casted to appropriate type 46 | template 47 | auto writeIteratorFor(TIter&& iter) -> decltype(details::WriteIteratorHelper<>::template get(std::forward(iter))) 48 | { 49 | return details::WriteIteratorHelper<>::template get(std::forward(iter)); 50 | } 51 | 52 | /// @brief Create and initialise iterator for message write 53 | /// @tparam TMessage Type of message interface class or smart pointer to it. 54 | /// @param[in] msg Unused message object helps detecting proper message type. 55 | /// @param[in] iter Iterator value. 56 | /// @return The same @b iter value, but casted to appropriate type 57 | template 58 | auto writeIteratorFor(TMessage&& msg, TIter&& iter) -> 59 | decltype(details::WriteIteratorHelper<>::template get::type>(std::forward(iter))) 60 | { 61 | static_cast(msg); 62 | return details::WriteIteratorHelper<>::template get::type>(std::forward(iter)); 63 | } 64 | 65 | } // namespace comms 66 | -------------------------------------------------------------------------------- /include/comms/protocol/ChecksumLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::protocol::ChecksumLayer 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/ChecksumLayer.h" 14 | #include "comms/protocol/ProtocolLayerBase.h" 15 | 16 | namespace comms 17 | { 18 | 19 | namespace protocol 20 | { 21 | 22 | /// @brief Alias to the @ref comms::frame::ChecksumLayer 23 | /// @deprecated Use @ref comms::frame::ChecksumLayer class instead 24 | template 25 | using ChecksumLayer = comms::frame::ChecksumLayer; 26 | 27 | } // namespace protocol 28 | 29 | } // namespace comms 30 | 31 | -------------------------------------------------------------------------------- /include/comms/protocol/ChecksumPrefixLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::protocol::ChecksumPrefixLayer 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/ChecksumPrefixLayer.h" 14 | #include "comms/protocol/ProtocolLayerBase.h" 15 | 16 | namespace comms 17 | { 18 | 19 | namespace protocol 20 | { 21 | 22 | /// @brief Alias to the @ref comms::frame::ChecksumPrefixLayer 23 | /// @deprecated Use @ref comms::frame::ChecksumPrefixLayer class instead 24 | template 25 | using ChecksumPrefixLayer = comms::frame::ChecksumPrefixLayer; 26 | 27 | } // namespace protocol 28 | 29 | } // namespace comms 30 | -------------------------------------------------------------------------------- /include/comms/protocol/MsgDataLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::protocol::MsgDataLayer 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/MsgDataLayer.h" 14 | #include "comms/protocol/ProtocolLayerBase.h" 15 | 16 | namespace comms 17 | { 18 | 19 | namespace protocol 20 | { 21 | 22 | /// @brief Alias to the @ref comms::frame::MsgDataLayer 23 | /// @deprecated Use @ref comms::frame::MsgDataLayer class instead 24 | template 25 | using MsgDataLayer = comms::frame::MsgDataLayer; 26 | 27 | } // namespace protocol 28 | 29 | } // namespace comms 30 | -------------------------------------------------------------------------------- /include/comms/protocol/MsgIdLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::protocol::MsgIdLayer 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/MsgIdLayer.h" 14 | #include "comms/protocol/ProtocolLayerBase.h" 15 | 16 | namespace comms 17 | { 18 | 19 | namespace protocol 20 | { 21 | 22 | /// @brief Alias to the @ref comms::frame::MsgIdLayer 23 | /// @deprecated Use @ref comms::frame::MsgIdLayer class instead 24 | template 25 | using MsgIdLayer = comms::frame::MsgIdLayer; 26 | 27 | } // namespace protocol 28 | 29 | } // namespace comms 30 | -------------------------------------------------------------------------------- /include/comms/protocol/MsgSizeLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::protocol::MsgSizeLayer 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/MsgSizeLayer.h" 14 | #include "comms/protocol/ProtocolLayerBase.h" 15 | 16 | namespace comms 17 | { 18 | 19 | namespace protocol 20 | { 21 | 22 | /// @brief Alias to the @ref comms::frame::MsgSizeLayer 23 | /// @deprecated Use @ref comms::frame::MsgSizeLayer class instead 24 | template 25 | using MsgSizeLayer = comms::frame::MsgSizeLayer; 26 | 27 | } // namespace protocol 28 | 29 | } // namespace comms 30 | -------------------------------------------------------------------------------- /include/comms/protocol/ProtocolLayerBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::protocol::ProtocolLayerBase 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/FrameLayerBase.h" 14 | 15 | namespace comms 16 | { 17 | 18 | namespace protocol 19 | { 20 | 21 | /// @brief Alias to the @ref comms::frame::FrameLayerBase 22 | /// @deprecated Use @ref comms::frame::FrameLayerBase class instead 23 | template 24 | using ProtocolLayerBase = comms::frame::FrameLayerBase; 25 | 26 | /// @brief Same as @ref comms::frame::toFrameLayerBase() 27 | /// @deprecated Use @ref comms::frame::toFrameLayerBase() instead 28 | template 29 | auto toProtocolLayerBase(ProtocolLayerBase& layer) -> decltype(comms::frame::toFrameLayerBase(layer)) 30 | { 31 | return comms::frame::toFrameLayerBase(layer); 32 | } 33 | 34 | /// @brief Same as @ref comms::frame::toFrameLayerBase() 35 | /// @deprecated Use @ref comms::frame::toFrameLayerBase() instead 36 | template 37 | constexpr auto toFrameLayerBase(const ProtocolLayerBase& layer) -> decltype(comms::frame::toFrameLayerBase(layer)) 38 | { 39 | return comms::frame::toFrameLayerBase(layer); 40 | } 41 | 42 | /// @brief Same as @ref comms::frame::missingSize() 43 | /// @deprecated Use @ref comms::frame::missingSize() instead 44 | inline auto missingSize(std::size_t& val) -> decltype(comms::frame::missingSize(val)) 45 | { 46 | return comms::frame::missingSize(val); 47 | } 48 | 49 | /// @brief Same as @ref comms::frame::msgId() 50 | /// @deprecated Use @ref comms::frame::msgId() instead 51 | template 52 | auto msgId(TId& val) -> decltype(comms::frame::msgId(val)) 53 | { 54 | return comms::frame::msgId(val); 55 | } 56 | 57 | /// @brief Same as @ref comms::frame::msgIndex() 58 | /// @deprecated Use @ref comms::frame::msgIndex() instead 59 | inline auto msgIndex(std::size_t& val) -> decltype(comms::frame::msgIndex(val)) 60 | { 61 | return comms::frame::msgIndex(val); 62 | } 63 | 64 | /// @brief Same as @ref comms::frame::msgPayload() 65 | /// @deprecated Use @ref comms::frame::msgPayload() instead 66 | template 67 | auto msgPayload(TIter& iter, std::size_t& len) -> decltype(comms::frame::msgPayload(iter, len)) 68 | { 69 | return comms::frame::msgPayload(iter, len); 70 | } 71 | 72 | } // namespace protocol 73 | 74 | } // namespace comms 75 | 76 | /// @brief Same as #COMMS_FRAME_LAYERS_ACCESS() 77 | /// @deprecated Use #COMMS_FRAME_LAYERS_ACCESS() instead 78 | #define COMMS_PROTOCOL_LAYERS_ACCESS(...) COMMS_FRAME_LAYERS_ACCESS(__VA_ARGS__) 79 | 80 | /// @brief Same as #COMMS_FRAME_LAYERS_NAMES() 81 | /// @deprecated Use #COMMS_FRAME_LAYERS_NAMES() instead 82 | #define COMMS_PROTOCOL_LAYERS_NAMES(...) COMMS_FRAME_LAYERS_NAMES(__VA_ARGS__) 83 | 84 | /// @brief Same as #COMMS_FRAME_LAYERS_ACCESS_INNER() 85 | /// @deprecated Use #COMMS_FRAME_LAYERS_ACCESS_INNER() instead 86 | #define COMMS_PROTOCOL_LAYERS_ACCESS_INNER(...) COMMS_FRAME_LAYERS_ACCESS_INNER(__VA_ARGS__) 87 | 88 | /// @brief Same as #COMMS_FRAME_LAYERS_NAMES_INNER() 89 | /// @deprecated Use #COMMS_FRAME_LAYERS_NAMES_INNER() instead 90 | #define COMMS_PROTOCOL_LAYERS_NAMES_INNER(...) COMMS_FRAME_LAYERS_NAMES_INNER(__VA_ARGS__) 91 | 92 | /// @brief Same as #COMMS_FRAME_LAYERS_ACCESS_OUTER() 93 | /// @deprecated Use #COMMS_FRAME_LAYERS_ACCESS_OUTER() instead 94 | #define COMMS_PROTOCOL_LAYERS_ACCESS_OUTER(...) COMMS_FRAME_LAYERS_ACCESS_OUTER(__VA_ARGS__) 95 | 96 | /// @brief Same as #COMMS_FRAME_LAYERS_NAMES_OUTER() 97 | /// @deprecated Use #COMMS_FRAME_LAYERS_NAMES_OUTER() instead 98 | #define COMMS_PROTOCOL_LAYERS_NAMES_OUTER(...) COMMS_FRAME_LAYERS_NAMES_OUTER(__VA_ARGS__) 99 | -------------------------------------------------------------------------------- /include/comms/protocol/SyncPrefixLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::protocol::SyncPrefixLayer 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/SyncPrefixLayer.h" 14 | #include "comms/protocol/ProtocolLayerBase.h" 15 | 16 | namespace comms 17 | { 18 | 19 | namespace protocol 20 | { 21 | 22 | /// @brief Alias to the @ref comms::frame::SyncPrefixLayer 23 | /// @deprecated Use @ref comms::frame::SyncPrefixLayer class instead 24 | template 25 | using SyncPrefixLayer = comms::frame::SyncPrefixLayer; 26 | 27 | } // namespace protocol 28 | 29 | } // namespace comms 30 | -------------------------------------------------------------------------------- /include/comms/protocol/TransportValueLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::protocol::TransportValueLayer 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/TransportValueLayer.h" 14 | #include "comms/protocol/ProtocolLayerBase.h" 15 | 16 | namespace comms 17 | { 18 | 19 | namespace protocol 20 | { 21 | 22 | /// @brief Alias to the @ref comms::frame::TransportValueLayer 23 | /// @deprecated Use @ref comms::frame::TransportValueLayer class instead 24 | template 25 | using TransportValueLayer = comms::frame::TransportValueLayer; 26 | 27 | } // namespace protocol 28 | 29 | } // namespace comms 30 | -------------------------------------------------------------------------------- /include/comms/protocol/checksum/BasicSum.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::protocol::checksum::BasicSum 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/checksum/BasicSum.h" 14 | 15 | namespace comms 16 | { 17 | 18 | namespace protocol 19 | { 20 | 21 | namespace checksum 22 | { 23 | 24 | /// @brief Alias to the @ref comms::frame::checksum::BasicSum 25 | /// @deprecated Use @ref comms::frame::checksum::BasicSum class instead 26 | template 27 | using BasicSum = comms::frame::checksum::BasicSum; 28 | 29 | } // namespace checksum 30 | 31 | } // namespace protocol 32 | 33 | } // namespace comms 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /include/comms/protocol/checksum/BasicXor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::protocol::checksum::BasicXor 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/checksum/BasicXor.h" 14 | 15 | namespace comms 16 | { 17 | 18 | namespace protocol 19 | { 20 | 21 | namespace checksum 22 | { 23 | 24 | /// @brief Alias to the @ref comms::frame::checksum::BasicXor 25 | /// @deprecated Use @ref comms::frame::checksum::BasicXor class instead 26 | template 27 | using BasicXor = comms::frame::checksum::BasicXor; 28 | 29 | } // namespace checksum 30 | 31 | } // namespace protocol 32 | 33 | } // namespace comms 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /include/comms/protocol/checksum/Crc.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains definition of @ref comms::protocol::checksum::Crc 10 | 11 | #pragma once 12 | 13 | #include "comms/frame/checksum/Crc.h" 14 | 15 | namespace comms 16 | { 17 | 18 | namespace protocol 19 | { 20 | 21 | namespace checksum 22 | { 23 | 24 | /// @brief Alias to the @ref comms::frame::checksum::Crc 25 | /// @deprecated Use @ref comms::frame::checksum::Crc class instead 26 | template < 27 | typename TResult, 28 | TResult TPoly, 29 | TResult TInit = 0, 30 | TResult TFin = 0, 31 | bool TReflect = false, 32 | bool TReflectRem = false 33 | > 34 | using Crc = comms::frame::checksum::Crc; 35 | 36 | /// @brief Alias to the @ref comms::frame::checksum::Crc_CCITT 37 | /// @deprecated Use @ref comms::frame::checksum::Crc_CCITT class instead 38 | using Crc_CCITT = comms::frame::checksum::Crc_CCITT; 39 | 40 | /// @brief Alias to the @ref comms::frame::checksum::Crc_16 41 | /// @deprecated Use @ref comms::frame::checksum::Crc_16 class instead 42 | using Crc_16 = comms::frame::checksum::Crc_16; 43 | 44 | /// @brief Alias to the @ref comms::frame::checksum::Crc_32 45 | /// @deprecated Use @ref comms::frame::checksum::Crc_32 class instead 46 | using Crc_32 = comms::frame::checksum::Crc_32; 47 | 48 | } // namespace checksum 49 | 50 | } // namespace protocol 51 | 52 | } // namespace comms 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /include/comms/protocols.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2014 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief This file provides all the definitions from comms::protocol namespace. 10 | 11 | #pragma once 12 | 13 | #include "comms/protocol/MsgDataLayer.h" 14 | #include "comms/protocol/MsgIdLayer.h" 15 | #include "comms/protocol/MsgSizeLayer.h" 16 | #include "comms/protocol/SyncPrefixLayer.h" 17 | #include "comms/protocol/ChecksumLayer.h" 18 | #include "comms/protocol/ChecksumPrefixLayer.h" 19 | #include "comms/protocol/TransportValueLayer.h" 20 | 21 | #include "comms/protocol/checksum/BasicSum.h" 22 | #include "comms/protocol/checksum/BasicXor.h" 23 | #include "comms/protocol/checksum/Crc.h" 24 | -------------------------------------------------------------------------------- /include/comms/util/AlignedStorage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2024 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file comms/util/AlignedStorage.h 9 | /// @brief Replacement of std::aligned_storage due to deprecation since C++23. 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace comms 18 | { 19 | 20 | namespace util 21 | { 22 | 23 | #if COMMS_IS_CPP23 24 | 25 | template 26 | using AlignedStorage = std::uint8_t[TSize]; 27 | 28 | #else // #if COMMS_IS_CPP23 29 | 30 | template 31 | using AlignedStorage = typename std::aligned_storage::type; 32 | 33 | #endif // #if COMMS_IS_CPP23 34 | 35 | } // namespace util 36 | 37 | } // namespace comms 38 | -------------------------------------------------------------------------------- /include/comms/util/BitSizeToByteSize.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace comms 13 | { 14 | 15 | namespace util 16 | { 17 | 18 | /// @cond SKIP_DOC 19 | template 20 | struct BitSizeToByteSize 21 | { 22 | static_assert(0 < TSize, "The number of bits must be greater than 0"); 23 | static_assert(TSize < 64, "The number of bits is too high."); 24 | static const std::size_t Value = BitSizeToByteSize::Value; 25 | }; 26 | 27 | template <> 28 | struct BitSizeToByteSize<8> 29 | { 30 | static const std::size_t Value = sizeof(std::uint8_t); 31 | }; 32 | 33 | template <> 34 | struct BitSizeToByteSize<16> 35 | { 36 | static const std::size_t Value = sizeof(std::uint16_t); 37 | }; 38 | 39 | template <> 40 | struct BitSizeToByteSize<32> 41 | { 42 | static const std::size_t Value = sizeof(std::uint32_t); 43 | }; 44 | 45 | template <> 46 | struct BitSizeToByteSize<64> 47 | { 48 | static const std::size_t Value = sizeof(std::uint64_t); 49 | }; 50 | 51 | /// @endcond 52 | 53 | } // namespace util 54 | 55 | } // namespace comms 56 | 57 | 58 | -------------------------------------------------------------------------------- /include/comms/util/MaxSizeOf.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2023 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/details/tag.h" 11 | #include "comms/util/detect.h" 12 | #include "comms/util/type_traits.h" 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | namespace comms 19 | { 20 | 21 | namespace util 22 | { 23 | 24 | namespace details 25 | { 26 | 27 | class MaxSizeOfHelper 28 | { 29 | public: 30 | template 31 | static std::size_t maxSizeOf(const T& val) 32 | { 33 | using DecayedType = typename std::decay::type; 34 | using Tag = 35 | typename comms::util::LazyShallowConditional< 36 | comms::util::detect::hasMaxSizeFunc() 37 | >::template Type< 38 | HasMaxSizeTag, 39 | NoMaxSizeTag 40 | >; 41 | 42 | return maxSizeOfInternal(val, Tag()); 43 | } 44 | 45 | private: 46 | template 47 | using HasMaxSizeTag = comms::details::tag::Tag1<>; 48 | 49 | template 50 | using NoMaxSizeTag = comms::details::tag::Tag2<>; 51 | 52 | template 53 | static std::size_t maxSizeOfInternal(const T& val, HasMaxSizeTag<>) 54 | { 55 | return val.max_size(); 56 | } 57 | 58 | template 59 | static std::size_t maxSizeOfInternal(const T& val, NoMaxSizeTag<>) 60 | { 61 | static_cast(val); 62 | return std::numeric_limits::max(); 63 | } 64 | }; 65 | 66 | } // namespace details 67 | 68 | /// @cond SKIP_DOC 69 | template 70 | std::size_t maxSizeOf(const T& val) 71 | { 72 | return details::MaxSizeOfHelper::maxSizeOf(val); 73 | } 74 | 75 | /// @endcond 76 | 77 | } // namespace util 78 | 79 | } // namespace comms 80 | 81 | 82 | -------------------------------------------------------------------------------- /include/comms/util/SizeToType.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | namespace comms 14 | { 15 | 16 | namespace util 17 | { 18 | 19 | namespace details 20 | { 21 | 22 | template 23 | struct SizeToTypeHelper { 24 | using Type = std::array; 25 | }; 26 | 27 | template <> 28 | struct SizeToTypeHelper<1> 29 | { 30 | using Type = std::uint8_t; 31 | }; 32 | 33 | template <> 34 | struct SizeToTypeHelper<2> 35 | { 36 | using Type = std::uint16_t; 37 | }; 38 | 39 | template <> 40 | struct SizeToTypeHelper<4> 41 | { 42 | using Type = std::uint32_t; 43 | }; 44 | 45 | template <> 46 | struct SizeToTypeHelper<8> 47 | { 48 | using Type = std::uint64_t; 49 | }; 50 | 51 | template <> 52 | struct SizeToTypeHelper<3> 53 | { 54 | using Type = SizeToTypeHelper<4>::Type; 55 | }; 56 | 57 | template <> 58 | struct SizeToTypeHelper<5> 59 | { 60 | using Type = SizeToTypeHelper<8>::Type; 61 | }; 62 | 63 | template <> 64 | struct SizeToTypeHelper<6> 65 | { 66 | using Type = SizeToTypeHelper<8>::Type; 67 | }; 68 | 69 | template <> 70 | struct SizeToTypeHelper<7> 71 | { 72 | using Type = SizeToTypeHelper<8>::Type; 73 | }; 74 | 75 | 76 | } // namespace details 77 | 78 | /// @cond SKIP_DOC 79 | 80 | template 81 | class SizeToType 82 | { 83 | using ByteType = typename SizeToType<1, TSigned>::Type; 84 | 85 | public: 86 | using Type = std::array; 87 | }; 88 | 89 | template 90 | struct SizeToType 91 | { 92 | using Type = typename details::SizeToTypeHelper::Type; 93 | }; 94 | 95 | template 96 | struct SizeToType 97 | { 98 | using Type = typename 99 | std::make_signed< 100 | typename SizeToType::Type 101 | >::type; 102 | }; 103 | 104 | template 105 | using SizeToTypeT = typename SizeToType::Type; 106 | 107 | /// @endcond 108 | 109 | } // namespace util 110 | 111 | } // namespace comms 112 | -------------------------------------------------------------------------------- /include/comms/util/assign.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Provides helper assign() function to allow easy assignment of values to collections or views. 10 | 11 | #pragma once 12 | 13 | #include "comms/util/details/AssignHelper.h" 14 | 15 | namespace comms 16 | { 17 | 18 | namespace util 19 | { 20 | 21 | /// @brief Assigns a new value to provided object 22 | /// @details The function detects at compile-time presence of 23 | /// assign() member function and uses it. In case the assign() 24 | /// member function does not exist (for types like @b std::string_view or @b std::span) 25 | /// the function checks for presence of a constructor that can receive a pointer to 26 | /// the first element + number of elements (size) and uses it instead to create temporary 27 | /// object and then uses move / copy constructor to assign the value. 28 | /// @code 29 | /// static const std::string Str("hello"); 30 | /// 31 | /// std::string s1; 32 | /// comms::util::assign(s1, Str.begin(), Str.end()) // <-- equivalent to s1.assign(Str.begin(), Str.end()); 33 | /// 34 | /// std::string_view s2; 35 | /// comms::util::assign(s2, Str.begin(), Str.end()) // <-- equivalent to s2 = std::string_view(&(*Str.begin()), std::distance(Str.begin(), Str.end())); 36 | /// @endcode 37 | /// 38 | template 39 | void assign(T& obj, TIter from, TIter to) 40 | { 41 | details::AssignHelper<>::assign(obj, from, to); 42 | } 43 | 44 | } // namespace util 45 | 46 | } // namespace comms 47 | 48 | -------------------------------------------------------------------------------- /include/comms/util/construct.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2024 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Provides helper construct() function to allow easy construction of various collection types. 10 | 11 | #pragma once 12 | 13 | #include "comms/util/details/ConstructHelper.h" 14 | 15 | namespace comms 16 | { 17 | 18 | namespace util 19 | { 20 | 21 | /// @brief Construct collection objects given two range iterators 22 | /// @details The function selects proper constructor of the selected type 23 | /// @param[in] from Iterator to the first element of the range 24 | /// @param[in] to Iterator to one behind the last element of the range. 25 | template 26 | T construct(TIter from, TIter to) 27 | { 28 | return details::ConstructHelper::construct(from, to); 29 | } 30 | 31 | } // namespace util 32 | 33 | } // namespace comms 34 | 35 | -------------------------------------------------------------------------------- /include/comms/util/details/ConstructHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2024 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | #pragma once 9 | 10 | #include "comms/CompileControl.h" 11 | 12 | #include 13 | 14 | #if COMMS_HAS_CPP20_SPAN 15 | #include 16 | #endif // #if COMMS_HAS_CPP20_SPAN 17 | 18 | namespace comms 19 | { 20 | 21 | namespace util 22 | { 23 | 24 | namespace details 25 | { 26 | 27 | template 28 | class ConstructHelper 29 | { 30 | public: 31 | using RetType = T; 32 | 33 | template 34 | static RetType construct(TIter from, TIter to) 35 | { 36 | return RetType(from, to); 37 | } 38 | }; 39 | 40 | #if COMMS_HAS_CPP20_SPAN 41 | template 42 | class ConstructHelper> 43 | { 44 | public: 45 | using RetType = std::span; 46 | 47 | template 48 | static RetType construct(TIter from, TIter to) 49 | { 50 | return RetType(&(*from), static_cast(std::distance(from, to))); 51 | } 52 | }; 53 | #endif // #if COMMS_HAS_CPP20_SPAN 54 | 55 | } // namespace details 56 | 57 | } // namespace util 58 | 59 | } // namespace comms 60 | -------------------------------------------------------------------------------- /include/comms/util/detect.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Various compile-time detection functions of whether specific member functions and/or types exist 10 | 11 | #pragma once 12 | 13 | #include "comms/util/details/detect.h" 14 | 15 | namespace comms 16 | { 17 | 18 | namespace util 19 | { 20 | 21 | namespace detect 22 | { 23 | 24 | /// @brief Detect whether provided type has @b clear() member function 25 | /// @details 26 | /// @code 27 | /// static_assert(comms::util::detect::hasClearFunc(), "std::string is expected to have clear() member function."); 28 | /// @endcode 29 | template 30 | constexpr bool hasClearFunc() 31 | { 32 | return details::HasClearFunc::Value; 33 | // return details::PresenceDetector::Value; 34 | } 35 | 36 | /// @brief Detect whether provided type has @b reserve() member function 37 | /// @details 38 | /// @code 39 | /// static_assert(comms::util::detect::hasReserveFunc(), "std::string is expected to have reserve() member function."); 40 | /// @endcode 41 | template 42 | constexpr bool hasReserveFunc() 43 | { 44 | return details::HasReserveFunc::Value; 45 | } 46 | 47 | /// @brief Detect whether provided type has @b resize() member function 48 | /// @details 49 | /// @code 50 | /// static_assert(comms::util::detect::hasResizeFunc(), "std::string is expected to have resize() member function."); 51 | /// @endcode 52 | template 53 | constexpr bool hasResizeFunc() 54 | { 55 | return details::HasResizeFunc::Value; 56 | } 57 | 58 | /// @brief Detect whether provided type has @b remove_suffix() member function 59 | /// @details 60 | /// @code 61 | /// static_assert(comms::util::detect::hasRemoveSuffixFunc, 62 | /// "comms::util::StringView is expected to have remove_suffix() member function."); 63 | /// static_assert(comms::util::detect::hasRemoveSuffixFunc, 64 | /// "std::string_view is expected to have remove_suffix() member function."); 65 | /// @endcode 66 | template 67 | constexpr bool hasRemoveSuffixFunc() 68 | { 69 | return details::HasRemoveSuffixFunc::Value; 70 | } 71 | 72 | /// @brief Detect whether provided type has @b assign() member function which can 73 | /// receive two pointers in its arguments 74 | /// @details 75 | /// @code 76 | /// static_assert(comms::util::detect::HasAssignFunc(), "std::string is expected to have assign() member function."); 77 | /// @endcode 78 | template 79 | constexpr bool hasAssignFunc() 80 | { 81 | return details::HasAssignFunc::Value; 82 | } 83 | 84 | /// @brief Detect whether provided type has a constructor that receives a pointer + size parameters. 85 | /// @details 86 | /// @code 87 | /// static_assert(comms::util::detect::hasPtrSizeConstructor(), 88 | /// "std::string_view is expected to have ptr + size constructor."); 89 | /// @endcode 90 | template 91 | constexpr bool hasPtrSizeConstructor() 92 | { 93 | return details::HasPtrSizeConstructor::Value; 94 | } 95 | 96 | /// @brief Detect whether provided type is std::span 97 | template 98 | constexpr bool isStdSpan() 99 | { 100 | return details::IsStdSpan::Value; 101 | } 102 | 103 | /// @brief Detect whether provided type has @b max_size() member function 104 | /// @details 105 | /// @code 106 | /// static_assert(comms::util::detect::hasMaxSizeFunc(), "std::string is expected to have max_size() member function."); 107 | /// @endcode 108 | template 109 | constexpr bool hasMaxSizeFunc() 110 | { 111 | return details::HasMaxSizeFunc::Value; 112 | } 113 | 114 | } // namespace detect 115 | 116 | } // namespace util 117 | 118 | } // namespace comms -------------------------------------------------------------------------------- /include/comms/version.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2018 - 2025 (C). Alex Robenko. All rights reserved. 3 | // 4 | // This Source Code Form is subject to the terms of the Mozilla Public 5 | // License, v. 2.0. If a copy of the MPL was not distributed with this 6 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | /// @file 9 | /// @brief Contains version information of the library 10 | 11 | #pragma once 12 | 13 | /// @brief Major verion of the library 14 | #define COMMS_MAJOR_VERSION 5U 15 | 16 | /// @brief Minor verion of the library 17 | #define COMMS_MINOR_VERSION 4U 18 | 19 | /// @brief Patch level of the library 20 | #define COMMS_PATCH_VERSION 3U 21 | 22 | /// @brief Macro to create numeric version as single unsigned number 23 | #define COMMS_MAKE_VERSION(major_, minor_, patch_) \ 24 | ((static_cast(major_) << 24) | \ 25 | (static_cast(minor_) << 8) | \ 26 | (static_cast(patch_))) 27 | 28 | /// @brief Version of the COMMS library as single numeric value 29 | #define COMMS_VERSION COMMS_MAKE_VERSION(COMMS_MAJOR_VERSION, COMMS_MINOR_VERSION, COMMS_PATCH_VERSION) 30 | 31 | namespace comms 32 | { 33 | 34 | /// @brief Major verion of the library 35 | inline 36 | constexpr unsigned versionMajor() 37 | { 38 | return COMMS_MAJOR_VERSION; 39 | } 40 | 41 | /// @brief Minor verion of the library 42 | inline 43 | constexpr unsigned versionMinor() 44 | { 45 | return COMMS_MINOR_VERSION; 46 | } 47 | 48 | /// @brief Patch level of the library 49 | inline 50 | constexpr unsigned versionPatch() 51 | { 52 | return COMMS_PATCH_VERSION; 53 | } 54 | 55 | /// @brief Create version of the library as single unsigned numeric value. 56 | inline 57 | constexpr unsigned versionCreate(unsigned major, unsigned minor, unsigned patch) 58 | { 59 | return COMMS_MAKE_VERSION(major, minor, patch); 60 | } 61 | 62 | /// @brief Version of the COMMS library as single numeric value 63 | inline 64 | constexpr unsigned version() 65 | { 66 | return COMMS_VERSION; 67 | } 68 | 69 | } // namespace comms 70 | -------------------------------------------------------------------------------- /script/dia: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Replacement of "dia" on Linux, because doxygen hardcodes "-t png-libart" parameters while "dia" doesn't have this filter any more 4 | 5 | MISSING_FILTER="png-libart" 6 | REPLACEMENT_FILTER="cairo-png" 7 | DIA_PATH="/usr/bin/dia" 8 | 9 | ########################################### 10 | 11 | has_requested_filter=$(${DIA_PATH} --list-filters 2>/dev/null | grep ${MISSING_FILTER}) 12 | if [ -n "${has_requested_filter}" ]; then 13 | exec ${DIA_PATH} "$@" 14 | exit 0 15 | fi 16 | 17 | new_params=() 18 | 19 | while [[ $# -gt 0 ]]; do 20 | case "$1" in 21 | -t) 22 | # If the current argument is "-t", shift and check the next argument 23 | shift 24 | if [ "$1" == "${MISSING_FILTER}" ]; then 25 | new_params+=("-t" "${REPLACEMENT_FILTER}") 26 | else 27 | new_params+=("-t" "$1") 28 | fi 29 | ;; 30 | *) 31 | # For all other arguments, just add them to the array 32 | new_params+=("$1") 33 | ;; 34 | esac 35 | shift 36 | done 37 | 38 | exec ${DIA_PATH} "${new_params[@]}" -------------------------------------------------------------------------------- /script/env_dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "${CC}" -o -z "${CXX}" ]; then 4 | echo "ERROR: Compilers are not provided" 5 | exit 1 6 | fi 7 | 8 | if [ -z "${BUILD_TYPE}" ]; then 9 | export BUILD_TYPE=Debug 10 | fi 11 | 12 | if [ -z "${SANITIZERS}" ]; then 13 | export SANITIZERS="ON" 14 | fi 15 | 16 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 17 | ROOT_DIR=$( dirname ${SCRIPT_DIR} ) 18 | BUILD_DIR="${ROOT_DIR}/build.${CC}.${BUILD_TYPE}" 19 | mkdir -p ${BUILD_DIR} 20 | cd ${BUILD_DIR} 21 | 22 | cmake .. -DCMAKE_INSTALL_PREFIX=install -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ 23 | -DCC_COMMS_USE_CCACHE=ON \ 24 | -DCC_COMMS_BUILD_UNIT_TESTS=ON -DCC_COMMS_UNIT_TESTS_USE_SANITIZERS=${SANITIZERS} "$@" 25 | -------------------------------------------------------------------------------- /script/env_dev_clang.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=clang 4 | export CXX=clang++ 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_clang12.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=clang-12 4 | export CXX=clang++-12 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_clang12_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=clang-12 4 | export CXX=clang++-12 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev_rel.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_clang15.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=clang-15 4 | export CXX=clang++-15 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_clang18_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=clang-18 4 | export CXX=clang++-18 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev_rel.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_clang19_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=clang-19 4 | export CXX=clang++-19 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev_rel.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_gcc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=gcc 4 | export CXX=g++ 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_gcc11_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=gcc-11 4 | export CXX=g++-11 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev_rel.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_gcc12.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=gcc-12 4 | export CXX=g++-12 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_gcc12_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=gcc-12 4 | export CXX=g++-12 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev_rel.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_gcc14.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=gcc-14 4 | export CXX=g++-14 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_gcc_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=gcc 4 | export CXX=g++ 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev_rel.sh "$@" 8 | -------------------------------------------------------------------------------- /script/env_dev_rel.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "${CC}" -o -z "${CXX}" ]; then 4 | echo "ERROR: Compilers are not provided" 5 | exit 1 6 | fi 7 | 8 | export BUILD_TYPE=Release 9 | 10 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 11 | source ${SCRIPT_DIR}/env_dev.sh "$@" 12 | -------------------------------------------------------------------------------- /script/env_dev_size.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "${CC}" -o -z "${CXX}" ]; then 4 | echo "ERROR: Compilers are not provided" 5 | exit 1 6 | fi 7 | 8 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 9 | source ${SCRIPT_DIR}/env_dev.sh -DCMAKE_BUILD_TYPE=MinSizeRel "$@" 10 | -------------------------------------------------------------------------------- /script/env_dev_size_gcc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=gcc 4 | export CXX=g++ 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | source ${SCRIPT_DIR}/env_dev_size.sh "$@" 8 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # In order to run the unittests the following conditions must be true: 2 | # - find_package (CxxTest) was exectued, CXXTEST_FOUND is defined and has true value. 3 | 4 | if (NOT BUILD_TESTING) 5 | return () 6 | endif () 7 | 8 | set (COMPONENT_NAME "comms") 9 | 10 | ################################################################# 11 | 12 | function (test_func test_suite_name) 13 | set (tests "${CMAKE_CURRENT_SOURCE_DIR}/${test_suite_name}.th") 14 | 15 | set (name "${COMPONENT_NAME}.${test_suite_name}Test") 16 | 17 | set (valgrand_args) 18 | if (VALGRIND_EXECUTABLE) 19 | set (valgrand_args VALGRIND_EXECUTABLE ${VALGRIND_EXECUTABLE}) 20 | endif () 21 | 22 | cc_cxxtest_add_test (NAME ${name} SRC ${tests} ${valgrand_args}) 23 | endfunction () 24 | 25 | ################################################################# 26 | 27 | if ((NOT CC_COMMS_UNIT_TESTS_USE_SANITIZERS) AND CC_COMMS_UNIT_TESTS_USE_VALGRIND) 28 | if ("${CC_VALGRAND_EXE_NAME}" STREQUAL "") 29 | set (CC_VALGRAND_EXE_NAME "valgrind") 30 | endif () 31 | find_program(VALGRIND_EXECUTABLE NAMES "${CC_VALGRAND_EXE_NAME}") 32 | endif () 33 | 34 | if (TARGET cxxtest::cxxtest) 35 | test_func ("Fields") 36 | test_func ("Fields2") 37 | test_func ("Message") 38 | test_func ("MsgDataLayer") 39 | test_func ("MsgIdLayer") 40 | test_func ("MsgSizeLayer") 41 | test_func ("SyncPrefixLayer") 42 | test_func ("ChecksumLayer") 43 | test_func ("ChecksumPrefixLayer") 44 | test_func ("TransportValueLayer") 45 | test_func ("Util") 46 | test_func ("CustomMsgIdLayer") 47 | test_func ("CustomMsgSizeLayer") 48 | test_func ("CustomTransportValueLayer") 49 | test_func ("CustomChecksumLayer") 50 | test_func ("CustomChecksumPrefixLayer") 51 | test_func ("CustomSyncPrefixLayer") 52 | test_func ("Dispatch") 53 | test_func ("MsgFactory") 54 | else () 55 | message (Warning "Testing is enabled, but cxxtest hasn't been found!") 56 | endif () 57 | --------------------------------------------------------------------------------