diff --git a/container/FixedArrayList.h b/container/FixedArrayList.h index 12e292b4a..5d93db90c 100644 --- a/container/FixedArrayList.h +++ b/container/FixedArrayList.h @@ -12,14 +12,26 @@ class FixedArrayList: public ArrayList { private: T data[MAX_SIZE]; public: + /** + * (Robin) Maybe we should also implement move assignment and move ctor. + * Or at least delete them. + */ FixedArrayList() : ArrayList(data, MAX_SIZE) { } - //We could create a constructor to initialize the fixed array list with data and the known size field - //so it can be used for serialization too (with SerialFixedArrrayListAdapter) - //is this feasible? - FixedArrayList(T * data_, count_t count, bool swapArrayListEndianess = false): + // (Robin): We could create a constructor to initialize the fixed array list with data and the known size field + // so it can be used for serialization too (with SerialFixedArrrayListAdapter) + // is this feasible? + /** + * Initialize a fixed array list with data and number of data fields. + * Endianness of entries can be swapped optionally. + * @param data_ + * @param count + * @param swapArrayListEndianess + */ + FixedArrayList(T * data_, count_t count, + bool swapArrayListEndianess = false): ArrayList(data, MAX_SIZE) { memcpy(this->data, data_, count * sizeof(T)); this->size = count; diff --git a/container/FixedMap.h b/container/FixedMap.h index 7f3d28f7d..c0eb90b2a 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -201,7 +201,7 @@ public: return printSize; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size, buffer, size, bigEndian); diff --git a/container/IsDerivedFrom.h b/container/IsDerivedFrom.h index 520033dbd..8142a3781 100644 --- a/container/IsDerivedFrom.h +++ b/container/IsDerivedFrom.h @@ -1,6 +1,13 @@ #ifndef ISDERIVEDFROM_H_ #define ISDERIVEDFROM_H_ +/** + * These template type checks are based on SFINAE + * (https://en.cppreference.com/w/cpp/language/sfinae) + * + * @tparam D Derived Type + * @tparam B Base Type + */ template class IsDerivedFrom { class No { @@ -9,7 +16,9 @@ class IsDerivedFrom { No no[3]; }; + // This will be chosen if B is the base type static Yes Test(B*); // declared, but not defined + // This will be chosen for anything else static No Test(... ); // declared, but not defined public: diff --git a/datapool/DataPoolParameterWrapper.cpp b/datapool/DataPoolParameterWrapper.cpp index 7139a0d89..11399fb6e 100644 --- a/datapool/DataPoolParameterWrapper.cpp +++ b/datapool/DataPoolParameterWrapper.cpp @@ -80,7 +80,7 @@ size_t DataPoolParameterWrapper::getSerializedSize() const { } ReturnValue_t DataPoolParameterWrapper::deSerialize(const uint8_t** buffer, - ssize_t* size, bool bigEndian) { + size_t* size, bool bigEndian) { return HasReturnvaluesIF::RETURN_FAILED; } diff --git a/datapool/DataPoolParameterWrapper.h b/datapool/DataPoolParameterWrapper.h index 45d3de537..99593310e 100644 --- a/datapool/DataPoolParameterWrapper.h +++ b/datapool/DataPoolParameterWrapper.h @@ -16,7 +16,7 @@ public: virtual size_t getSerializedSize() const; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian); ReturnValue_t copyFrom(const ParameterWrapper *from, diff --git a/datapool/DataSet.cpp b/datapool/DataSet.cpp index eabb4b8c1..28cc45009 100644 --- a/datapool/DataSet.cpp +++ b/datapool/DataSet.cpp @@ -136,7 +136,7 @@ void DataSet::setValid(uint8_t valid) { } } -ReturnValue_t DataSet::deSerialize(const uint8_t** buffer, ssize_t* size, +ReturnValue_t DataSet::deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { ReturnValue_t result = RETURN_FAILED; for (uint16_t count = 0; count < fill_count; count++) { diff --git a/datapool/DataSet.h b/datapool/DataSet.h index 888d45e65..1e34e07c9 100644 --- a/datapool/DataSet.h +++ b/datapool/DataSet.h @@ -126,7 +126,7 @@ public: virtual size_t getSerializedSize() const; - ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian); private: diff --git a/datapool/PIDReader.h b/datapool/PIDReader.h index 26a9e2a80..7572cd2c8 100644 --- a/datapool/PIDReader.h +++ b/datapool/PIDReader.h @@ -136,7 +136,7 @@ public: return SerializeAdapter::getSerializedSize(&value); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { return SerializeAdapter::deSerialize(&value, buffer, size, bigEndian); } diff --git a/datapool/PoolRawAccess.cpp b/datapool/PoolRawAccess.cpp index b5f94c8c5..a2f79343e 100644 --- a/datapool/PoolRawAccess.cpp +++ b/datapool/PoolRawAccess.cpp @@ -197,11 +197,11 @@ size_t PoolRawAccess::getSerializedSize() const { return typeSize; } -ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, ssize_t* size, +ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { - *size -= typeSize; - if (*size >= 0) { - + // TODO: Needs to be tested!!! + if (*size >= typeSize) { + *size -= typeSize; if (bigEndian) { #ifndef BYTE_ORDER_SYSTEM #error BYTE_ORDER_SYSTEM not defined @@ -212,12 +212,14 @@ ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, ssize_t* size, #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN memcpy(value, *buffer, typeSize); #endif - } else { + } + else { memcpy(value, *buffer, typeSize); } *buffer += typeSize; return HasReturnvaluesIF::RETURN_OK; - } else { + } + else { return SerializeIF::STREAM_TOO_SHORT; } } diff --git a/datapool/PoolRawAccess.h b/datapool/PoolRawAccess.h index 955c640ba..b491d949a 100644 --- a/datapool/PoolRawAccess.h +++ b/datapool/PoolRawAccess.h @@ -127,7 +127,7 @@ public: size_t getSerializedSize() const; - ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian); protected: diff --git a/datapool/PoolRawAccessHelper.cpp b/datapool/PoolRawAccessHelper.cpp index cac6e5064..643c76099 100644 --- a/datapool/PoolRawAccessHelper.cpp +++ b/datapool/PoolRawAccessHelper.cpp @@ -25,7 +25,7 @@ ReturnValue_t PoolRawAccessHelper::serialize(uint8_t **buffer, size_t *size, const size_t max_size, bool bigEndian) { SerializationArgs serializationArgs = {buffer, size, max_size, bigEndian}; ReturnValue_t result; - ssize_t remainingParametersSize = numberOfParameters * 4; + size_t remainingParametersSize = numberOfParameters * 4; for(uint8_t count=0; count < numberOfParameters; count++) { result = serializeCurrentPoolEntryIntoBuffer(serializationArgs, &remainingParametersSize, false); @@ -44,7 +44,7 @@ ReturnValue_t PoolRawAccessHelper::serializeWithValidityMask(uint8_t ** buffer, size_t * size, const size_t max_size, bool bigEndian) { ReturnValue_t result; SerializationArgs argStruct = {buffer, size, max_size, bigEndian}; - ssize_t remainingParametersSize = numberOfParameters * 4; + size_t remainingParametersSize = numberOfParameters * 4; uint8_t validityMaskSize = ceil((float)numberOfParameters/8.0); uint8_t validityMask[validityMaskSize]; memset(validityMask,0, validityMaskSize); @@ -67,49 +67,60 @@ ReturnValue_t PoolRawAccessHelper::serializeWithValidityMask(uint8_t ** buffer, return result; } -ReturnValue_t PoolRawAccessHelper::serializeCurrentPoolEntryIntoBuffer(SerializationArgs argStruct, - ssize_t * remainingParameters, bool withValidMask, uint8_t * validityMask) { +ReturnValue_t PoolRawAccessHelper::serializeCurrentPoolEntryIntoBuffer( + SerializationArgs argStruct, size_t * remainingParameters, + bool withValidMask, uint8_t * validityMask) { uint32_t currentPoolId; // Deserialize current pool ID from pool ID buffer ReturnValue_t result = AutoSerializeAdapter::deSerialize(¤tPoolId, &poolIdBuffer,remainingParameters,true); if(result != RETURN_OK) { - debug << std::hex << "Pool Raw Access Helper: Error deSeralizing pool IDs" << std::dec << std::endl; + debug << std::hex << "Pool Raw Access Helper: Error deSeralizing " + "pool IDs" << std::dec << std::endl; return result; } - result = handlePoolEntrySerialization(currentPoolId, argStruct, withValidMask, validityMask); + result = handlePoolEntrySerialization(currentPoolId, argStruct, + withValidMask, validityMask); return result; } -ReturnValue_t PoolRawAccessHelper::handlePoolEntrySerialization(uint32_t currentPoolId,SerializationArgs argStruct, - bool withValidMask, uint8_t * validityMask) { +ReturnValue_t PoolRawAccessHelper::handlePoolEntrySerialization( + uint32_t currentPoolId,SerializationArgs argStruct, bool withValidMask, + uint8_t * validityMask) { ReturnValue_t result = RETURN_FAILED; uint8_t arrayPosition = 0; uint8_t counter = 0; bool poolEntrySerialized = false; - //debug << "Pool Raw Access Helper: Handling Pool ID: " << std::hex << currentPoolId << std::endl; + //debug << "Pool Raw Access Helper: Handling Pool ID: " + // << std::hex << currentPoolId << std::endl; while(not poolEntrySerialized) { if(counter > DataSet::DATA_SET_MAX_SIZE) { - error << "Pool Raw Access Helper: Config error, max. number of possible data set variables exceeded" << std::endl; + error << "Pool Raw Access Helper: Config error, " + "max. number of possible data set variables exceeded" + << std::endl; return result; } counter ++; DataSet currentDataSet = DataSet(); //debug << "Current array position: " << (int)arrayPosition << std::endl; - PoolRawAccess currentPoolRawAccess(currentPoolId,arrayPosition,¤tDataSet,PoolVariableIF::VAR_READ); + PoolRawAccess currentPoolRawAccess(currentPoolId,arrayPosition, + ¤tDataSet,PoolVariableIF::VAR_READ); result = currentDataSet.read(); if (result != RETURN_OK) { - debug << std::hex << "Pool Raw Access Helper: Error reading raw dataset with returncode 0x" + debug << std::hex << "Pool Raw Access Helper: Error reading raw " + "dataset with returncode 0x" << result << std::dec << std::endl; return result; } - result = checkRemainingSize(¤tPoolRawAccess, &poolEntrySerialized, &arrayPosition); + result = checkRemainingSize(¤tPoolRawAccess, &poolEntrySerialized, + &arrayPosition); if(result != RETURN_OK) { - error << "Pool Raw Access Helper: Configuration Error at pool ID " << std::hex << currentPoolId + error << "Pool Raw Access Helper: Configuration Error at pool ID " + << std::hex << currentPoolId << ". Size till end smaller than 0" << std::dec << std::endl; return result; } @@ -125,8 +136,9 @@ ReturnValue_t PoolRawAccessHelper::handlePoolEntrySerialization(uint32_t current result = currentDataSet.serialize(argStruct.buffer, argStruct.size, argStruct.max_size, argStruct.bigEndian); if (result != RETURN_OK) { - debug << "Pool Raw Access Helper: Error serializing pool data with ID 0x" << std::hex << - currentPoolId << " into send buffer with return code " << result << std::dec << std::endl; + debug << "Pool Raw Access Helper: Error serializing pool data with " + "ID 0x" << std::hex << currentPoolId << " into send buffer " + "with return code " << result << std::dec << std::endl; return result; } @@ -134,9 +146,10 @@ ReturnValue_t PoolRawAccessHelper::handlePoolEntrySerialization(uint32_t current return result; } -ReturnValue_t PoolRawAccessHelper::checkRemainingSize(PoolRawAccess * currentPoolRawAccess, - bool * isSerialized, uint8_t * arrayPosition) { - int8_t remainingSize = currentPoolRawAccess->getSizeTillEnd() - currentPoolRawAccess->getSizeOfType(); +ReturnValue_t PoolRawAccessHelper::checkRemainingSize(PoolRawAccess* + currentPoolRawAccess, bool * isSerialized, uint8_t * arrayPosition) { + int8_t remainingSize = currentPoolRawAccess->getSizeTillEnd() - + currentPoolRawAccess->getSizeOfType(); if(remainingSize == 0) { *isSerialized = true; } @@ -158,7 +171,8 @@ void PoolRawAccessHelper::handleMaskModification(uint8_t * validityMask) { } } -uint8_t PoolRawAccessHelper::bitSetter(uint8_t byte, uint8_t position, bool value) { +uint8_t PoolRawAccessHelper::bitSetter(uint8_t byte, uint8_t position, + bool value) { if(position < 1 or position > 8) { debug << "Pool Raw Access: Bit setting invalid position" << std::endl; return byte; diff --git a/datapool/PoolRawAccessHelper.h b/datapool/PoolRawAccessHelper.h index 89974ea4f..61d79731a 100644 --- a/datapool/PoolRawAccessHelper.h +++ b/datapool/PoolRawAccessHelper.h @@ -69,7 +69,7 @@ private: struct SerializationArgs { uint8_t ** buffer; size_t * size; - const uint32_t max_size; + const size_t max_size; bool bigEndian; }; /** @@ -80,13 +80,15 @@ private: * @param hkDataSize * @param max_size * @param bigEndian - * @param withValidMask Can be set optionally to set a provided validity mask - * @param validityMask Can be supplied and will be set if @c withValidMask is set to true + * @param withValidMask Can be set optionally to set a + * provided validity mask + * @param validityMask Can be supplied and will be set if + * @c withValidMask is set to true * @return */ - ReturnValue_t serializeCurrentPoolEntryIntoBuffer(SerializationArgs argStruct, - ssize_t * remainingParameters, bool withValidMask = false, - uint8_t * validityMask = nullptr); + ReturnValue_t serializeCurrentPoolEntryIntoBuffer( + SerializationArgs argStruct, size_t * remainingParameters, + bool withValidMask = false, uint8_t * validityMask = nullptr); ReturnValue_t handlePoolEntrySerialization(uint32_t currentPoolId, SerializationArgs argStruct, bool withValidMask = false, diff --git a/datapool/PoolVariable.h b/datapool/PoolVariable.h index d32cdf22a..e85e3b159 100644 --- a/datapool/PoolVariable.h +++ b/datapool/PoolVariable.h @@ -203,7 +203,7 @@ public: return SerializeAdapter::getSerializedSize(&value); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { return SerializeAdapter::deSerialize(&value, buffer, size, bigEndian); } diff --git a/datapool/PoolVector.h b/datapool/PoolVector.h index 3e82a721a..3e5482111 100644 --- a/datapool/PoolVector.h +++ b/datapool/PoolVector.h @@ -215,7 +215,7 @@ public: return vector_size * SerializeAdapter::getSerializedSize(value); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { uint16_t i; ReturnValue_t result; diff --git a/devicehandlers/CookieIF.h b/devicehandlers/CookieIF.h index ca171ff40..6b2bb5598 100644 --- a/devicehandlers/CookieIF.h +++ b/devicehandlers/CookieIF.h @@ -13,8 +13,9 @@ typedef uint32_t address_t; * single interface (like RMAP or I2C) * @details * To use this class, implement a communication specific child cookie which - * inherits Cookie. Cookie instances are created in config/ Factory.cpp by calling - * CookieIF* childCookie = new ChildCookie(...). + * inherits Cookie. Cookie instances are created in config/Factory.cpp by + * calling @code{.cpp} CookieIF* childCookie = new ChildCookie(...) + * @endcode . * * This cookie is then passed to the child device handlers, which stores the * pointer and passes it to the communication interface functions. diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index 39cfadd75..bb0951164 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -60,9 +60,9 @@ public: * this can be performed in this function, which is called on device handler * initialization. * @param cookie - * @return -@c RETURN_OK if initialization was successfull - * - Everything else triggers failure event with - * returnvalue as parameter 1 + * @return + * - @c RETURN_OK if initialization was successfull + * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t initializeInterface(CookieIF * cookie) = 0; @@ -73,9 +73,9 @@ public: * @param cookie * @param data * @param len - * @return -@c RETURN_OK for successfull send - * - Everything else triggers failure event with - * returnvalue as parameter 1 + * @return + * - @c RETURN_OK for successfull send + * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t * sendData, size_t sendLen) = 0; @@ -84,9 +84,9 @@ public: * Called by DHB in the GET_WRITE doGetWrite(). * Get send confirmation that the data in sendMessage() was sent successfully. * @param cookie - * @return -@c RETURN_OK if data was sent successfull + * @return - @c RETURN_OK if data was sent successfull * - Everything else triggers falure event with - * returnvalue as parameter 1 + * returnvalue as parameter 1 */ virtual ReturnValue_t getSendSuccess(CookieIF *cookie) = 0; @@ -99,9 +99,9 @@ public: * * @param cookie * @param requestLen Size of data to read - * @return -@c RETURN_OK to confirm the request for data has been sent. + * @return - @c RETURN_OK to confirm the request for data has been sent. * - Everything else triggers failure event with - * returnvalue as parameter 1 + * returnvalue as parameter 1 */ virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) = 0; @@ -113,8 +113,8 @@ public: * @param buffer [out] Set reply here (by using *buffer = ...) * @param size [out] size pointer to set (by using *size = ...). * Set to 0 if no reply was received - * @return -@c RETURN_OK for successfull receive - * -@c NO_REPLY_RECEIVED if not reply was received. Setting size to + * @return - @c RETURN_OK for successfull receive + * - @c NO_REPLY_RECEIVED if not reply was received. Setting size to * 0 has the same effect * - Everything else triggers failure event with * returnvalue as parameter 1 diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 5fb5a9e5f..374ebaf6e 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -114,7 +114,7 @@ ReturnValue_t DeviceHandlerBase::initialize() { AcceptsDeviceResponsesIF *rawReceiver = objectManager->get< AcceptsDeviceResponsesIF>(rawDataReceiverId); - if (rawReceiver == NULL) { + if (rawReceiver == nullptr) { return RETURN_FAILED; } diff --git a/devicehandlers/DeviceTmReportingWrapper.cpp b/devicehandlers/DeviceTmReportingWrapper.cpp index 4987c7fb5..adddf4f3f 100644 --- a/devicehandlers/DeviceTmReportingWrapper.cpp +++ b/devicehandlers/DeviceTmReportingWrapper.cpp @@ -31,7 +31,7 @@ size_t DeviceTmReportingWrapper::getSerializedSize() const { } ReturnValue_t DeviceTmReportingWrapper::deSerialize(const uint8_t** buffer, - ssize_t* size, bool bigEndian) { + size_t* size, bool bigEndian) { ReturnValue_t result = SerializeAdapter::deSerialize(&objectId, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { diff --git a/devicehandlers/DeviceTmReportingWrapper.h b/devicehandlers/DeviceTmReportingWrapper.h index fce748147..e2fa43164 100644 --- a/devicehandlers/DeviceTmReportingWrapper.h +++ b/devicehandlers/DeviceTmReportingWrapper.h @@ -16,7 +16,7 @@ public: virtual size_t getSerializedSize() const; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian); private: object_id_t objectId; diff --git a/events/eventmatching/EventRangeMatcherBase.h b/events/eventmatching/EventRangeMatcherBase.h index 8dea3e101..328a6b690 100644 --- a/events/eventmatching/EventRangeMatcherBase.h +++ b/events/eventmatching/EventRangeMatcherBase.h @@ -18,7 +18,7 @@ public: size_t getSerializedSize() const { return rangeMatcher.getSerializedSize(); } - ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { return rangeMatcher.deSerialize(buffer, size, bigEndian); } diff --git a/framework.mk b/framework.mk index a5a653641..6f64b7205 100644 --- a/framework.mk +++ b/framework.mk @@ -54,3 +54,4 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/test/*.cpp) \ No newline at end of file diff --git a/globalfunctions/Type.cpp b/globalfunctions/Type.cpp index ea2ad896f..11269dc23 100644 --- a/globalfunctions/Type.cpp +++ b/globalfunctions/Type.cpp @@ -85,7 +85,7 @@ size_t Type::getSerializedSize() const { return 2 * SerializeAdapter::getSerializedSize(&dontcare); } -ReturnValue_t Type::deSerialize(const uint8_t** buffer, ssize_t* size, +ReturnValue_t Type::deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { uint8_t ptc; uint8_t pfc; diff --git a/globalfunctions/Type.h b/globalfunctions/Type.h index 244091f71..f4146f4ea 100644 --- a/globalfunctions/Type.h +++ b/globalfunctions/Type.h @@ -44,7 +44,7 @@ public: virtual size_t getSerializedSize() const; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian); private: diff --git a/globalfunctions/matching/MatchTree.h b/globalfunctions/matching/MatchTree.h index 498fe8603..5a897f407 100644 --- a/globalfunctions/matching/MatchTree.h +++ b/globalfunctions/matching/MatchTree.h @@ -115,7 +115,7 @@ public: return size; } - ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { return HasReturnvaluesIF::RETURN_OK; } diff --git a/globalfunctions/matching/RangeMatcher.h b/globalfunctions/matching/RangeMatcher.h index c09802554..3342cc276 100644 --- a/globalfunctions/matching/RangeMatcher.h +++ b/globalfunctions/matching/RangeMatcher.h @@ -29,32 +29,38 @@ public: ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t max_size, bool bigEndian) const { - ReturnValue_t result = SerializeAdapter::serialize(&lowerBound, buffer, size, max_size, bigEndian); + ReturnValue_t result = SerializeAdapter::serialize(&lowerBound, + buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&upperBound, buffer, size, max_size, bigEndian); + result = SerializeAdapter::serialize(&upperBound, buffer, size, + max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return SerializeAdapter::serialize(&inverted, buffer, size, max_size, bigEndian); + return SerializeAdapter::serialize(&inverted, buffer, size, + max_size, bigEndian); } size_t getSerializedSize() const { return sizeof(lowerBound) + sizeof(upperBound) + sizeof(bool); } - ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { - ReturnValue_t result = SerializeAdapter::deSerialize(&lowerBound, buffer, size, bigEndian); + ReturnValue_t result = SerializeAdapter::deSerialize(&lowerBound, + buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::deSerialize(&upperBound, buffer, size, bigEndian); + result = SerializeAdapter::deSerialize(&upperBound, buffer, + size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return SerializeAdapter::deSerialize(&inverted, buffer, size, bigEndian); + return SerializeAdapter::deSerialize(&inverted, buffer, + size, bigEndian); } protected: bool doMatch(T input) { diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index 05c97ae2e..e2cddacc0 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -138,10 +138,8 @@ ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t sema BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, higherPriorityTaskWoken); if (returncode == pdPASS) { if(*higherPriorityTaskWoken == pdPASS) { - // Request context switch - // TODO: I don't know if this will ever happen but if it does, - // I want to to know in case this causes issues. If it doesn't - // we should remove this. + // Request context switch because unblocking the semaphore + // caused a high priority task unblock. TaskManagement::requestContextSwitch(CallContext::isr); } return HasReturnvaluesIF::RETURN_OK; diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 541266929..373e26bfc 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -35,24 +35,20 @@ public: static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2); static constexpr ReturnValue_t SEMAPHORE_NULLPOINTER = MAKE_RETURN_CODE(3); - /** - * Create a binary semaphore - */ BinarySemaphore(); /** - * Copy ctor - * @param + * @brief Copy ctor */ BinarySemaphore(const BinarySemaphore&); /** - * Copy assignment + * @brief Copy assignment */ BinarySemaphore& operator=(const BinarySemaphore&); /** - * Move constructor + * @brief Move constructor */ BinarySemaphore (BinarySemaphore &&); @@ -81,16 +77,16 @@ public: /** * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. * @param timeoutTicks - * @return -@c RETURN_OK on success - * -@c RETURN_FAILED on failure + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure */ ReturnValue_t takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks = BinarySemaphore::NO_BLOCK_TICKS); /** * Give back the binary semaphore - * @return -@c RETURN_OK on success - * -@c RETURN_FAILED on failure + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure */ ReturnValue_t giveBinarySemaphore(); @@ -108,8 +104,8 @@ public: /** * Wrapper function to give back semaphore from handle * @param semaphore - * @return -@c RETURN_OK on success - * -@c RETURN_FAILED on failure + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure */ static ReturnValue_t giveBinarySemaphore(SemaphoreHandle_t semaphore); @@ -118,8 +114,8 @@ public: * @param semaphore * @param higherPriorityTaskWoken This will be set to pdPASS if a task with a higher priority * was unblocked - * @return -@c RETURN_OK on success - * -@c RETURN_FAILED on failure + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure */ static ReturnValue_t giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken); diff --git a/osal/linux/FixedTimeslotTask.cpp b/osal/linux/FixedTimeslotTask.cpp index 21040e6ef..7f117301a 100644 --- a/osal/linux/FixedTimeslotTask.cpp +++ b/osal/linux/FixedTimeslotTask.cpp @@ -9,7 +9,9 @@ uint32_t FixedTimeslotTask::deadlineMissedCount = 0; const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN; -FixedTimeslotTask::FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, uint32_t periodMs_):PosixThread(name_,priority_,stackSize_),pst(periodMs_),started(false) { +FixedTimeslotTask::FixedTimeslotTask(const char* name_, int priority_, + size_t stackSize_, uint32_t periodMs_): + PosixThread(name_,priority_,stackSize_),pst(periodMs_),started(false) { } FixedTimeslotTask::~FixedTimeslotTask() { diff --git a/osal/linux/PeriodicPosixTask.h b/osal/linux/PeriodicPosixTask.h index e3fa57229..43647eda1 100644 --- a/osal/linux/PeriodicPosixTask.h +++ b/osal/linux/PeriodicPosixTask.h @@ -9,7 +9,8 @@ class PeriodicPosixTask: public PosixThread, public PeriodicTaskIF { public: - PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, uint32_t period_, void(*deadlineMissedFunc_)()); + PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, + uint32_t period_, void(*deadlineMissedFunc_)()); virtual ~PeriodicPosixTask(); /** * @brief The method to start the task. diff --git a/parameters/ParameterWrapper.cpp b/parameters/ParameterWrapper.cpp index 1420c0761..475764c58 100644 --- a/parameters/ParameterWrapper.cpp +++ b/parameters/ParameterWrapper.cpp @@ -112,7 +112,7 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow, //treat from as a continuous Stream as we copy all of it const uint8_t *fromAsStream = (const uint8_t *) from; - ssize_t streamSize = fromRows * fromColumns * sizeof(T); + size_t streamSize = fromRows * fromColumns * sizeof(T); ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; @@ -137,12 +137,12 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow, } ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer, - ssize_t* size, bool bigEndian) { + size_t* size, bool bigEndian) { return deSerialize(buffer, size, bigEndian, 0); } ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer, - ssize_t* size, bool bigEndian, uint16_t startWritingAtIndex) { + size_t* size, bool bigEndian, uint16_t startWritingAtIndex) { ParameterWrapper streamDescription; ReturnValue_t result = streamDescription.set(*buffer, *size, buffer, size); @@ -153,8 +153,10 @@ ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer, return copyFrom(&streamDescription, startWritingAtIndex); } -ReturnValue_t ParameterWrapper::set(const uint8_t* stream, ssize_t streamSize, - const uint8_t **remainingStream, ssize_t *remainingSize) { +ReturnValue_t ParameterWrapper::set(const uint8_t* stream, size_t streamSize, + const uint8_t **remainingStream, size_t *remainingSize) { + // TODO: Replaced ssize_t for remainingSize and streamSize + // is the logic here correct? ReturnValue_t result = SerializeAdapter::deSerialize(&type, &stream, &streamSize, true); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -172,22 +174,22 @@ ReturnValue_t ParameterWrapper::set(const uint8_t* stream, ssize_t streamSize, return result; } - int32_t dataSize = type.getSize() * rows * columns; + size_t dataSize = type.getSize() * rows * columns; if (streamSize < dataSize) { return SerializeIF::STREAM_TOO_SHORT; } - data = NULL; + data = nullptr; readonlyData = stream; pointsToStream = true; stream += dataSize; - if (remainingStream != NULL) { + if (remainingStream != nullptr) { *remainingStream = stream; } streamSize -= dataSize; - if (remainingSize != NULL) { + if (remainingSize != nullptr) { *remainingSize = streamSize; } diff --git a/parameters/ParameterWrapper.h b/parameters/ParameterWrapper.h index 6f8f6fc97..ef54fe6d7 100644 --- a/parameters/ParameterWrapper.h +++ b/parameters/ParameterWrapper.h @@ -30,10 +30,10 @@ public: virtual size_t getSerializedSize() const; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian); - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian, uint16_t startWritingAtIndex = 0); template @@ -111,8 +111,8 @@ public: void setMatrix(const T& member) { this->set(member[0], sizeof(member)/sizeof(member[0]), sizeof(member[0])/sizeof(member[0][0])); } - ReturnValue_t set(const uint8_t *stream, ssize_t streamSize, - const uint8_t **remainingStream = NULL, ssize_t *remainingSize = + ReturnValue_t set(const uint8_t *stream, size_t streamSize, + const uint8_t **remainingStream = NULL, size_t *remainingSize = NULL); ReturnValue_t copyFrom(const ParameterWrapper *from, diff --git a/power/Fuse.cpp b/power/Fuse.cpp index 6a4e6caf6..04079bb06 100644 --- a/power/Fuse.cpp +++ b/power/Fuse.cpp @@ -108,7 +108,7 @@ uint32_t Fuse::getSerializedSize() const { return size; } -ReturnValue_t Fuse::deSerialize(const uint8_t** buffer, ssize_t* size, +ReturnValue_t Fuse::deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { ReturnValue_t result = RETURN_FAILED; for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); diff --git a/power/Fuse.h b/power/Fuse.h index b3c9547ac..aee03778a 100644 --- a/power/Fuse.h +++ b/power/Fuse.h @@ -52,7 +52,7 @@ public: ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t max_size, bool bigEndian) const; uint32_t getSerializedSize() const; - ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian); void setAllMonitorsToUnchecked(); ReturnValue_t performOperation(uint8_t opCode); diff --git a/power/PowerComponent.cpp b/power/PowerComponent.cpp index 77e60d0e1..0375adf0a 100644 --- a/power/PowerComponent.cpp +++ b/power/PowerComponent.cpp @@ -56,7 +56,7 @@ float PowerComponent::getMax() { return max; } -ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, ssize_t* size, +ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { ReturnValue_t result = SerializeAdapter::deSerialize(&min, buffer, size, bigEndian); diff --git a/power/PowerComponent.h b/power/PowerComponent.h index 1410e69d3..6ddc067f9 100644 --- a/power/PowerComponent.h +++ b/power/PowerComponent.h @@ -24,7 +24,7 @@ public: size_t getSerializedSize() const; - ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian); ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, diff --git a/serialize/EndianSwapper.h b/serialize/EndianSwapper.h index 25fb681e9..5ba6fd324 100644 --- a/serialize/EndianSwapper.h +++ b/serialize/EndianSwapper.h @@ -11,10 +11,14 @@ */ class EndianSwapper { private: - EndianSwapper() { - } - ; + EndianSwapper() {}; public: + /** + * Swap the endianness of a variable with arbitrary type + * @tparam T Type of variable + * @param in variable + * @return Variable with swapped endianness + */ template static T swap(T in) { #ifndef BYTE_ORDER_SYSTEM @@ -33,7 +37,14 @@ public: #error Unknown Byte Order #endif } - static void swap(uint8_t* out, const uint8_t* in, uint32_t size) { + + /** + * Swap the endianness of a buffer. + * @param out + * @param in + * @param size + */ + static void swap(uint8_t* out, const uint8_t* in, size_t size) { #ifndef BYTE_ORDER_SYSTEM #error BYTE_ORDER_SYSTEM not defined #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN @@ -49,21 +60,23 @@ public: /** * Swap endianness of buffer entries - * Template argument specifies buffer type + * Template argument specifies buffer type. The number of entries + * (not the buffer size!) must be supplied * @param out * @param in - * @param size + * @param size Number of buffer entries (not size of buffer in bytes!) */ template - static void swap(T * out, const T * in, uint32_t size) { + static void swap(T * out, const T * in, uint32_t entries) { #ifndef BYTE_ORDER_SYSTEM #error BYTE_ORDER_SYSTEM not defined #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN const uint8_t * in_buffer = reinterpret_cast(in); uint8_t * out_buffer = reinterpret_cast(out); - for (uint8_t count = 0; count < size; count++) { + for (uint8_t count = 0; count < entries; count++) { for(uint8_t i = 0; i < sizeof(T);i++) { - out_buffer[sizeof(T)* (count + 1) - i - 1] = in_buffer[count * sizeof(T) + i]; + out_buffer[sizeof(T)* (count + 1) - i - 1] = + in_buffer[count * sizeof(T) + i]; } } return; diff --git a/serialize/SerialArrayListAdapter.h b/serialize/SerialArrayListAdapter.h index 21a669c2d..4f3b82e68 100644 --- a/serialize/SerialArrayListAdapter.h +++ b/serialize/SerialArrayListAdapter.h @@ -13,7 +13,7 @@ /** * Also serializes length field ! - * \ingroup serialize + * @ingroup serialize */ template class SerialArrayListAdapter : public SerializeIF { @@ -22,7 +22,7 @@ public: } virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - const size_t max_size, bool bigEndian) const { + const size_t max_size, bool bigEndian) const override { return serialize(adaptee, buffer, size, max_size, bigEndian); } @@ -41,7 +41,7 @@ public: return result; } - virtual size_t getSerializedSize() const { + virtual size_t getSerializedSize() const override { return getSerializedSize(adaptee); } @@ -56,16 +56,19 @@ public: return printSize; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, - bool bigEndian) { + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + bool bigEndian) override { return deSerialize(adaptee, buffer, size, bigEndian); } static ReturnValue_t deSerialize(ArrayList* list, - const uint8_t** buffer, ssize_t* size, bool bigEndian) { + const uint8_t** buffer, size_t* size, bool bigEndian) { count_t tempSize = 0; ReturnValue_t result = SerializeAdapter::deSerialize(&tempSize, buffer, size, bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } if (tempSize > list->maxSize()) { return SerializeIF::TOO_MANY_ELEMENTS; } diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index f97d0d588..5fb5e3873 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -12,8 +12,8 @@ SerialBufferAdapter::SerialBufferAdapter(const void* buffer, } template -SerialBufferAdapter::SerialBufferAdapter(void* buffer, count_t bufferLength, - bool serializeLength) : +SerialBufferAdapter::SerialBufferAdapter(void* buffer, + count_t bufferLength, bool serializeLength) : serializeLength(serializeLength), bufferLength(bufferLength) { uint8_t * member_buffer = static_cast(buffer); m_buffer = member_buffer; @@ -26,8 +26,8 @@ SerialBufferAdapter::~SerialBufferAdapter() { } template -ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* size, - const size_t max_size, bool bigEndian) const { +ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, + size_t* size, const size_t max_size, bool bigEndian) const { uint32_t serializedLength = bufferLength; if (serializeLength) { serializedLength += AutoSerializeAdapter::getSerializedSize( @@ -61,36 +61,38 @@ size_t SerialBufferAdapter::getSerializedSize() const { return bufferLength; } } + template ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, - ssize_t* size, bool bigEndian) { + size_t* size, bool bigEndian) { //TODO Ignores Endian flag! - if (buffer != NULL) { - if(serializeLength){ - // Suggestion (would require removing rest of the block inside this if clause !): - //ReturnValue_t result = AutoSerializeAdapter::deSerialize(&bufferLength,buffer,size,bigEndian); - //if (result != HasReturnvaluesIF::RETURN_OK) { - // return result; - //} + // (Robin) the one of the buffer? wouldn't that be an issue for serialize + // as well? SerialFixedArrayListAdapter implements swapping of buffer + // fields (if buffer type is not uint8_t) + if (buffer != nullptr) { + if(serializeLength) { count_t serializedSize = AutoSerializeAdapter::getSerializedSize( &bufferLength); - if((*size - bufferLength - serializedSize) >= 0){ + if(bufferLength + serializedSize >= *size) { *buffer += serializedSize; *size -= serializedSize; - }else{ + } + else { return STREAM_TOO_SHORT; } } //No Else If, go on with buffer - if (*size - bufferLength >= 0) { + if (bufferLength >= *size) { *size -= bufferLength; memcpy(m_buffer, *buffer, bufferLength); (*buffer) += bufferLength; return HasReturnvaluesIF::RETURN_OK; - } else { + } + else { return STREAM_TOO_SHORT; } - } else { + } + else { return HasReturnvaluesIF::RETURN_FAILED; } } @@ -98,7 +100,8 @@ ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, template uint8_t * SerialBufferAdapter::getBuffer() { if(m_buffer == nullptr) { - error << "Wrong access function for stored type ! Use getConstBuffer()" << std::endl; + error << "Wrong access function for stored type !" + " Use getConstBuffer()" << std::endl; return nullptr; } return m_buffer; @@ -107,14 +110,16 @@ uint8_t * SerialBufferAdapter::getBuffer() { template const uint8_t * SerialBufferAdapter::getConstBuffer() { if(constBuffer == nullptr) { - error << "Wrong access function for stored type ! Use getBuffer()" << std::endl; + error << "Wrong access function for stored type !" + " Use getBuffer()" << std::endl; return nullptr; } return constBuffer; } template -void SerialBufferAdapter::setBuffer(void * buffer, count_t buffer_length) { +void SerialBufferAdapter::setBuffer(void * buffer, + count_t buffer_length) { m_buffer = static_cast(buffer); bufferLength = buffer_length; } diff --git a/serialize/SerialBufferAdapter.h b/serialize/SerialBufferAdapter.h index cf3ae07ed..d414573cb 100644 --- a/serialize/SerialBufferAdapter.h +++ b/serialize/SerialBufferAdapter.h @@ -8,11 +8,13 @@ * This adapter provides an interface for SerializeIF to serialize or deserialize * buffers with no length header but a known size. * - * Additionally, the buffer length can be serialized too and will be put in front of the serialized buffer. + * Additionally, the buffer length can be serialized too and will be put in + * front of the serialized buffer. * * Can be used with SerialLinkedListAdapter by declaring a SerializeElement with - * SerialElement> serialBufferElement. - * Right now, the SerialBufferAdapter must always be initialized with the buffer and size ! + * SerialElement>. + * Right now, the SerialBufferAdapter must always + * be initialized with the buffer and size ! * * \ingroup serialize */ @@ -27,26 +29,40 @@ public: * @param bufferLength * @param serializeLength */ - SerialBufferAdapter(const void* buffer, count_t bufferLength, bool serializeLength = false); + SerialBufferAdapter(const void* buffer, count_t bufferLength, + bool serializeLength = false); /** - * Constructor for non-constant uint8_t buffer. Length field can be serialized optionally. + * Constructor for non-constant uint8_t buffer. + * Length field can be serialized optionally. * Type of length can be supplied as template type. * @param buffer * @param bufferLength - * @param serializeLength + * @param serializeLength Length field will be serialized with size count_t */ SerialBufferAdapter(void* buffer, count_t bufferLength, bool serializeLength = false); virtual ~SerialBufferAdapter(); virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - const size_t max_size, bool bigEndian) const; + const size_t max_size, bool bigEndian) const override; virtual size_t getSerializedSize() const; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, - bool bigEndian); + /** + * @brief This function deserializes a buffer into the member buffer. + * @details + * If a length field is present, it is ignored, as the size should have + * been set in the constructor. If the size is not known beforehand, + * consider using SerialFixedArrayListAdapter instead. + * @param buffer [out] Resulting buffer + * @param size remaining size to deserialize, should be larger than buffer + * + size field size + * @param bigEndian + * @return + */ + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + bool bigEndian) override; uint8_t * getBuffer(); const uint8_t * getConstBuffer(); @@ -58,6 +74,4 @@ private: count_t bufferLength = 0; }; - - #endif /* SERIALBUFFERADAPTER_H_ */ diff --git a/serialize/SerialFixedArrayListAdapter.h b/serialize/SerialFixedArrayListAdapter.h index 8bcbf09e7..6e13ff6f4 100644 --- a/serialize/SerialFixedArrayListAdapter.h +++ b/serialize/SerialFixedArrayListAdapter.h @@ -5,49 +5,62 @@ #include /** - * @brief This adapter provides an interface for SerializeIF to serialize and deserialize - * buffers with a header containing the buffer length. + * @brief This adapter provides an interface for SerializeIF to serialize and + * deserialize buffers with a header containing the buffer length. * @details - * * Can be used by SerialLinkedListAdapter by declaring * as a linked element with SerializeElement>. - * The sequence of objects is defined in the constructor by using the setStart and setNext functions. + * The sequence of objects is defined in the constructor by + * using the setStart and setNext functions. * * 1. Buffers with a size header inside that class can be declared with - * SerialFixedArrayListAdapter. - * 2. MAX_BUFFER_LENGTH specifies the maximum allowed number of elements in FixedArrayList - * 3. LENGTH_FIELD_TYPE specifies the data type of the buffer header containing the buffer size - * (defaults to 1 byte length field) that follows + * @code + * SerialFixedArrayListAdapter mySerialFixedArrayList(...). + * @endcode + * 2. MAX_BUFFER_LENGTH specifies the maximum allowed number of elements + * in FixedArrayList. + * 3. LENGTH_FIELD_TYPE specifies the data type of the buffer header + * containing the buffer size (defaults to 1 byte length field) + * that follows. * * @ingroup serialize */ template -class SerialFixedArrayListAdapter : public FixedArrayList, public SerializeIF { +class SerialFixedArrayListAdapter : + public FixedArrayList, + public SerializeIF { public: /** - * Constructor Arguments are forwarded to FixedArrayList constructor + * Constructor Arguments are forwarded to FixedArrayList constructor. + * Refer to the fixed array list constructors for different options. * @param args */ template - SerialFixedArrayListAdapter(Args... args) : FixedArrayList(std::forward(args)...) { - } + SerialFixedArrayListAdapter(Args... args) : + FixedArrayList(std::forward(args)...) + {} - ReturnValue_t serialize(uint8_t** buffer, size_t* size, - const size_t max_size, bool bigEndian) const { - return SerialArrayListAdapter::serialize(this, buffer, size, max_size, bigEndian); + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + const size_t max_size, bool bigEndian) const override { + return SerialArrayListAdapter::serialize(this, + buffer, size, max_size, bigEndian); } size_t getSerializedSize() const { - return SerialArrayListAdapter::getSerializedSize(this); + return SerialArrayListAdapter:: + getSerializedSize(this); } - ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, - bool bigEndian) { + + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + bool bigEndian) override { return SerialArrayListAdapter::deSerialize(this, buffer, size, bigEndian); } void swapArrayListEndianness() { - SerialArrayListAdapter::swapArrayListEndianness(this); + SerialArrayListAdapter:: + swapArrayListEndianness(this); } }; diff --git a/serialize/SerialLinkedListAdapter.h b/serialize/SerialLinkedListAdapter.h index b5c06a166..8cb9afc8b 100644 --- a/serialize/SerialLinkedListAdapter.h +++ b/serialize/SerialLinkedListAdapter.h @@ -18,23 +18,25 @@ * or vice-versa, using linked lists. * @details * An alternative to the AutoSerializeAdapter functions - * - All object members with a datatype are declared as SerializeElement - * members inside the class implementing this adapter. - * - The element type can also be a SerialBufferAdapter to de-/serialize buffers, - * with a known size, where the size can also be serialized - * - The element type can also be a SerialFixedArrayListAdapter to de-/serialize buffers - * with a size header, which is scanned automatically + * - All object members with a datatype are declared as + * SerializeElement members inside the class + * implementing this adapter. + * - The element type can also be a SerialBufferAdapter to + * de-/serialize buffers with a known size + * - The element type can also be a SerialFixedArrayListAdapter to + * de-/serialize buffers with a size header, which is scanned automatically. * * The sequence of objects is defined in the constructor by using * the setStart and setNext functions. * - * - The serialization process is done by instantiating the class and - * calling serializ after all SerializeElement entries have been set by - * using the constructor or setter functions. An additional size variable can be supplied - * which is calculated/incremented automatically - * - The deserialization process is done by instantiating the class and supplying - * a buffer with the data which is converted into an object. The size of - * data to serialize can be supplied and is decremented in the function + * 1. The serialization process is done by instantiating the class and + * calling serialize after all SerializeElement entries have been set by + * using the constructor or setter functions. An additional size variable + * can be supplied which is calculated/incremented automatically. + * 2. The deserialization process is done by instantiating the class and + * supplying a buffer with the data which is converted into an object. + * The size of data to serialize can be supplied and is + * decremented in the function. Range checking is done internally. * * @ingroup serialize */ @@ -55,10 +57,12 @@ public: bool printCount = false) : SinglyLinkedList(start), printCount(printCount) { } + SerialLinkedListAdapter(LinkedElement* first, bool printCount = false) : SinglyLinkedList(first), printCount(printCount) { } + SerialLinkedListAdapter(bool printCount = false) : SinglyLinkedList(), printCount(printCount) { } @@ -66,15 +70,16 @@ public: /** * Serialize object implementing this adapter into the supplied buffer * and calculate the serialized size - * @param buffer [out] Object is serialized into this buffer. Note that the buffer pointer - * *buffer is incremented automatically inside the respective serialize functions + * @param buffer [out] Object is serialized into this buffer. + * Note that the buffer pointer *buffer is incremented automatically + * inside the respective serialize functions * @param size [out] Calculated serialized size. Don't forget to set to 0. * @param max_size * @param bigEndian Specify endianness * @return */ virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - const size_t max_size, bool bigEndian) const { + const size_t max_size, bool bigEndian) const override{ if (printCount) { count_t mySize = SinglyLinkedList::getSize(); ReturnValue_t result = SerializeAdapter::serialize(&mySize, @@ -98,7 +103,9 @@ public: } return result; } - virtual size_t getSerializedSize() const { + + + virtual size_t getSerializedSize() const override { if (printCount) { return SerialLinkedListAdapter::getSerializedSize() + sizeof(count_t); @@ -106,6 +113,7 @@ public: return getSerializedSize(SinglyLinkedList::start); } } + static uint32_t getSerializedSize(const LinkedElement *element) { uint32_t size = 0; while (element != NULL) { @@ -115,20 +123,22 @@ public: return size; } + /** - * Deserialize supplied buffer with supplied size into object implementing this adapter + * Deserialize supplied buffer with supplied size into object + * implementing this adapter. * @param buffer * @param size Decremented in respective deSerialize functions automatically * @param bigEndian Specify endianness * @return */ - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, - bool bigEndian) { + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + bool bigEndian) override { return deSerialize(SinglyLinkedList::start, buffer, size, bigEndian); } static ReturnValue_t deSerialize(LinkedElement* element, - const uint8_t** buffer, ssize_t* size, bool bigEndian) { + const uint8_t** buffer, size_t* size, bool bigEndian) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; while ((result == HasReturnvaluesIF::RETURN_OK) && (element != NULL)) { result = element->value->deSerialize(buffer, size, bigEndian); @@ -138,7 +148,6 @@ public: } bool printCount; - }; #endif /* SERIALLINKEDLISTADAPTER_H_ */ diff --git a/serialize/SerializeAdapter.h b/serialize/SerializeAdapter.h index 81a3730f8..87e4457ae 100644 --- a/serialize/SerializeAdapter.h +++ b/serialize/SerializeAdapter.h @@ -1,135 +1,86 @@ #ifndef SERIALIZEADAPTER_H_ #define SERIALIZEADAPTER_H_ -#include #include -#include #include -#include +#include +#include /** - * @brief This adapter provides an interface to use the SerializeIF functions - * with arbitrary template objects to facilitate and simplify the serialization of classes - * with different multiple different data types into buffers and vice-versa. + * @brief These adapters provides an interface to use the SerializeIF functions + * with arbitrary template objects to facilitate and simplify the + * serialization of classes with different multiple different data types + * into buffers and vice-versa. * @details - * Examples: - * A report class is converted into a TM buffer. The report class implements a serialize functions and calls - * the AutoSerializeAdapter::serialize function repeatedly on all object data fields. - * The getSerializedSize function is implemented by calling the - * AutoSerializeAdapter::getSerializedSize function repeatedly on all data fields. * - * The AutoSerializeAdapter functions can also be used as an alternative to memcpy - * to retrieve data out of a buffer directly into a class variable with data type T while being able to specify endianness. - * The boolean bigEndian specifies whether an endian swap is performed on the data before + * A report class is converted into a TM buffer. The report class implements a + * serialize functions and calls the AutoSerializeAdapter::serialize function + * repeatedly on all object data fields. The getSerializedSize function is + * implemented by calling the AutoSerializeAdapter::getSerializedSize function + * repeatedly on all data fields. + * + * The AutoSerializeAdapter functions can also be used as an alternative to + * memcpy to retrieve data out of a buffer directly into a class variable + * with data type T while being able to specify endianness. The boolean + * bigEndian specifies whether an endian swap is performed on the data before * serialization or deserialization. * - * If the target architecture is little endian (ARM), any data types created might - * have the wrong endiness if they are to be used for the FSFW. * There are three ways to retrieve data out of a buffer to be used in the FSFW - * to use regular aligned (big endian) data. - * This can also be applied to uint32_t and uint64_t: + * to use regular aligned (big endian) data. Examples: * * 1. Use the AutoSerializeAdapter::deSerialize function - * The pointer *buffer will be incremented automatically by the typeSize of the object, - * so this function can be called on &buffer repeatedly without adjusting pointer position. - * Set bigEndian parameter to true to perform endian swapping. - * + * The pointer *buffer will be incremented automatically by the typeSize + * of the object, so this function can be called on &buffer repeatedly + * without adjusting pointer position. Set bigEndian parameter to true + * to perform endian swapping, if necessary + * @code * uint16_t data; * int32_t dataLen = sizeof(data); - * ReturnValue_t result = AutoSerializeAdapter::deSerialize(&data,&buffer,&dataLen,true); - * - * 2. Perform a bitshift operation. Perform endian swapping if necessary: + * ReturnValue_t result = + * AutoSerializeAdapter::deSerialize(&data,&buffer,&dataLen,true); + * @endcode * + * 2. Perform a bitshift operation. Watch for for endianness: + * @code * uint16_t data; * data = buffer[targetByte1] << 8 | buffer[targetByte2]; - * data = EndianSwapper::swap(data); - * - * 3. Memcpy can be used when data is little-endian. Perform endian-swapping if necessary. + * data = EndianSwapper::swap(data); //optional, or swap order above + * @endcode * + * 3. memcpy or std::copy can also be used, but watch out if system + * endianness is different from required data endianness. + * Perform endian-swapping if necessary. + * @code * uint16_t data; * memcpy(&data,buffer + positionOfTargetByte1,sizeof(data)); - * data = EndianSwapper::swap(data); + * data = EndianSwapper::swap(data); //optional + * @endcode * - * When serializing for downlink, the packets are generally serialized assuming big endian data format - * like seen in TmPacketStored.cpp for example. + * When serializing for downlink, the packets are generally serialized assuming + * big endian data format like seen in TmPacketStored.cpp for example. * * @ingroup serialize */ -template -class SerializeAdapter_ { + +// No type specification necessary here. +class AutoSerializeAdapter { public: + template static ReturnValue_t serialize(const T* object, uint8_t** buffer, size_t* size, const size_t max_size, bool bigEndian) { - size_t ignoredSize = 0; - if (size == NULL) { - size = &ignoredSize; - } - if (sizeof(T) + *size <= max_size) { - T tmp; - if (bigEndian) { - tmp = EndianSwapper::swap(*object); - } else { - tmp = *object; - } - memcpy(*buffer, &tmp, sizeof(T)); - *size += sizeof(T); - (*buffer) += sizeof(T); - return HasReturnvaluesIF::RETURN_OK; - } else { - return SerializeIF::BUFFER_TOO_SHORT; - } + SerializeAdapter_::Is> adapter; + return adapter.serialize(object, buffer, size, max_size, bigEndian); } - - /** - * Deserialize buffer into object - * @param object [out] Object to be deserialized with buffer data - * @param buffer buffer containing the data. Non-Const pointer to non-const pointer to const buffer. - * @param size int32_t type to allow value to be values smaller than 0, needed for range/size checking - * @param bigEndian Specify endianness - * @return - */ - ReturnValue_t deSerialize(T* object, const uint8_t** buffer, ssize_t* size, - bool bigEndian) { - T tmp; - *size -= sizeof(T); - if (*size >= 0) { - memcpy(&tmp, *buffer, sizeof(T)); - if (bigEndian) { - *object = EndianSwapper::swap(tmp); - } else { - *object = tmp; - } - *buffer += sizeof(T); - return HasReturnvaluesIF::RETURN_OK; - } else { - return SerializeIF::STREAM_TOO_SHORT; - } + template + static size_t getSerializedSize(const T* object) { + SerializeAdapter_::Is> adapter; + return adapter.getSerializedSize(object); } - - uint32_t getSerializedSize(const T * object) { - return sizeof(T); - } - -}; - -template -class SerializeAdapter_ { -public: - ReturnValue_t serialize(const T* object, uint8_t** buffer, size_t* size, - const size_t max_size, bool bigEndian) const { - size_t ignoredSize = 0; - if (size == NULL) { - size = &ignoredSize; - } - return object->serialize(buffer, size, max_size, bigEndian); - } - uint32_t getSerializedSize(const T* object) const { - return object->getSerializedSize(); - } - - ReturnValue_t deSerialize(T* object, const uint8_t** buffer, ssize_t* size, - bool bigEndian) { - return object->deSerialize(buffer, size, bigEndian); + template + static ReturnValue_t deSerialize(T* object, const uint8_t** buffer, + size_t* size, bool bigEndian) { + SerializeAdapter_::Is> adapter; + return adapter.deSerialize(object, buffer, size, bigEndian); } }; @@ -147,29 +98,7 @@ public: } static ReturnValue_t deSerialize(T* object, const uint8_t** buffer, - ssize_t* size, bool bigEndian) { - SerializeAdapter_::Is> adapter; - return adapter.deSerialize(object, buffer, size, bigEndian); - } -}; - -// No type specification necessary here. -class AutoSerializeAdapter { -public: - template - static ReturnValue_t serialize(const T* object, uint8_t** buffer, - size_t* size, const size_t max_size, bool bigEndian) { - SerializeAdapter_::Is> adapter; - return adapter.serialize(object, buffer, size, max_size, bigEndian); - } - template - static uint32_t getSerializedSize(const T* object) { - SerializeAdapter_::Is> adapter; - return adapter.getSerializedSize(object); - } - template - static ReturnValue_t deSerialize(T* object, const uint8_t** buffer, - ssize_t* size, bool bigEndian) { + size_t* size, bool bigEndian) { SerializeAdapter_::Is> adapter; return adapter.deSerialize(object, buffer, size, bigEndian); } diff --git a/serialize/SerializeAdapterInternal.h b/serialize/SerializeAdapterInternal.h new file mode 100644 index 000000000..c57af0c95 --- /dev/null +++ b/serialize/SerializeAdapterInternal.h @@ -0,0 +1,118 @@ +/** + * @file SerializeAdapterInternal.h + * + * @date 13.04.2020 + * @author R. Mueller + */ + +#ifndef FRAMEWORK_SERIALIZE_SERIALIZEADAPTERINTERNAL_H_ +#define FRAMEWORK_SERIALIZE_SERIALIZEADAPTERINTERNAL_H_ +#include +#include +#include + +/** + * This template specialization will be chosen for fundamental types or + * anything else not implementing SerializeIF, based on partial + * template specialization. + * @tparam T + * @tparam + */ +template +class SerializeAdapter_ { +public: + /** + * + * @param object + * @param buffer + * @param size + * @param max_size + * @param bigEndian + * @return + */ + static ReturnValue_t serialize(const T* object, uint8_t** buffer, + size_t* size, const size_t max_size, bool bigEndian) { + // function eventuelly serializes structs here. + // does this work on every architecture? + // static_assert(std::is_fundamental::value); + size_t ignoredSize = 0; + if (size == nullptr) { + size = &ignoredSize; + } + if (sizeof(T) + *size <= max_size) { + T tmp; + if (bigEndian) { + tmp = EndianSwapper::swap(*object); + } else { + tmp = *object; + } + memcpy(*buffer, &tmp, sizeof(T)); + *size += sizeof(T); + (*buffer) += sizeof(T); + return HasReturnvaluesIF::RETURN_OK; + } else { + return SerializeIF::BUFFER_TOO_SHORT; + } + } + + /** + * Deserialize buffer into object + * @param object [out] Object to be deserialized with buffer data + * @param buffer contains the data. Non-Const pointer to non-const + * pointer to const data. + * @param size Size to deSerialize. wil be decremented by sizeof(T) + * @param bigEndian Specify endianness + * @return + */ + ReturnValue_t deSerialize(T* object, const uint8_t** buffer, size_t* size, + bool bigEndian) { + T tmp; + if (*size >= sizeof(T)) { + *size -= sizeof(T); + memcpy(&tmp, *buffer, sizeof(T)); + if (bigEndian) { + *object = EndianSwapper::swap(tmp); + } else { + *object = tmp; + } + *buffer += sizeof(T); + return HasReturnvaluesIF::RETURN_OK; + } else { + return SerializeIF::STREAM_TOO_SHORT; + } + } + + size_t getSerializedSize(const T * object) { + return sizeof(T); + } +}; + +/** + * This template specialization will be chosen for class derived from + * SerializeIF, based on partial template specialization. + * @tparam T + * @tparam + */ +template +class SerializeAdapter_ { +public: + ReturnValue_t serialize(const T* object, uint8_t** buffer, size_t* size, + const size_t max_size, bool bigEndian) const { + size_t ignoredSize = 0; + if (size == NULL) { + size = &ignoredSize; + } + return object->serialize(buffer, size, max_size, bigEndian); + } + + size_t getSerializedSize(const T* object) const { + return object->getSerializedSize(); + } + + ReturnValue_t deSerialize(T* object, const uint8_t** buffer, size_t* size, + bool bigEndian) { + return object->deSerialize(buffer, size, bigEndian); + } +}; + +#endif /* FRAMEWORK_SERIALIZE_SERIALIZEADAPTERINTERNAL_H_ */ diff --git a/serialize/SerializeElement.h b/serialize/SerializeElement.h index e2da5c141..4717ae17f 100644 --- a/serialize/SerializeElement.h +++ b/serialize/SerializeElement.h @@ -24,25 +24,26 @@ public: * @param args */ template - SerializeElement(Args... args) : LinkedElement(this), entry(std::forward(args)...) { + SerializeElement(Args... args): + LinkedElement(this), + entry(std::forward(args)...) {} - } - SerializeElement() : LinkedElement(this) { - } + SerializeElement() : LinkedElement(this) {} T entry; - ReturnValue_t serialize(uint8_t** buffer, size_t* size, - const size_t max_size, bool bigEndian) const { - return SerializeAdapter::serialize(&entry, buffer, size, max_size, bigEndian); + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + const size_t max_size, bool bigEndian) const override { + return SerializeAdapter::serialize(&entry, buffer, size, + max_size, bigEndian); } size_t getSerializedSize() const { return SerializeAdapter::getSerializedSize(&entry); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, - bool bigEndian) { + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + bool bigEndian) override { return SerializeAdapter::deSerialize(&entry, buffer, size, bigEndian); } diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index da401b2f9..5f8102c86 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -3,11 +3,6 @@ #include #include -#include - -#ifndef ssize_t -typedef std::make_signed::type ssize_t; -#endif /** * @defgroup serialize Serialization @@ -18,17 +13,21 @@ typedef std::make_signed::type ssize_t; * @brief An interface for alle classes which require * translation of objects data into data streams and vice-versa. * @details - * If the target architecture is little endian (e.g. ARM), any data types created might - * have the wrong endiness if they are to be used for the FSFW. - * There are three ways to retrieve data out of a buffer to be used in the FSFW to use - * regular aligned (big endian) data. This can also be applied to uint32_t and uint64_t: + * If the target architecture is little endian (e.g. ARM), any data types + * created might have the wrong endianess if they are to be used for the FSFW. + * Depending on the system architecture, endian correctness must be assured, + * This is important for incoming and outgoing data. The internal handling + * of data should be performed in the native system endianness. + * There are three ways to copy data (with different options to ensure + * endian correctness): * - * 1. Use the @c AutoSerializeAdapter::deSerialize function with @c bigEndian = true - * 2. Perform a bitshift operation - * 3. @c memcpy can be used when data is in little-endian format. Otherwise, @c EndianSwapper has to be used in conjuction. + * 1. Use the @c AutoSerializeAdapter::deSerialize function (with + * the endian flag) + * 2. Perform a bitshift operation (with correct order) + * 3. @c memcpy (with @c EndianSwapper if necessary) * - * When serializing for downlink, the packets are generally serialized assuming big endian data format - * like seen in TmPacketStored.cpp for example. + * When serializing for downlink, the packets are generally serialized + * assuming big endian data format like seen in TmPacketStored.cpp for example. * * @ingroup serialize */ @@ -47,7 +46,7 @@ public: virtual size_t getSerializedSize() const = 0; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) = 0; }; diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 6798b776d..a2365d000 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -1,13 +1,10 @@ #include #include #include -#include // to be implemented by bsp extern "C" void printChar(const char*); - - int ServiceInterfaceBuffer::overflow(int c) { // Handle output putChars(pbase(), pptr()); @@ -26,15 +23,16 @@ int ServiceInterfaceBuffer::sync(void) { if (this->isActive) { Clock::TimeOfDay_t loggerTime; Clock::getDateAndTime(&loggerTime); - char preamble[96] = { 0 }; - sprintf(preamble, "%s: | %" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%03" PRIu32 " | ", - this->log_message.c_str(), - loggerTime.hour, - loggerTime.minute, - loggerTime.second, - loggerTime.usecond /1000); + std::string preamble; + if(addCrToPreamble) { + preamble += "\r"; + } + preamble += log_message + ": | " + zero_padded(loggerTime.hour, 2) + + ":" + zero_padded(loggerTime.minute, 2) + ":" + + zero_padded(loggerTime.second, 2) + "." + + zero_padded(loggerTime.usecond/1000, 3) + " | "; // Write log_message and time - this->putChars(preamble, preamble + sizeof(preamble)); + this->putChars(preamble.c_str(), preamble.c_str() + preamble.size()); // Handle output this->putChars(pbase(), pptr()); } @@ -43,9 +41,13 @@ int ServiceInterfaceBuffer::sync(void) { return 0; } + + #ifndef UT699 -ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) { +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, + uint16_t port, bool addCrToPreamble) { + this->addCrToPreamble = addCrToPreamble; this->log_message = set_message; this->isActive = true; setp( buf, buf + BUF_SIZE ); @@ -59,17 +61,22 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { } memcpy(array, begin, length); - for( ; begin != end; begin++){ + for(; begin != end; begin++){ printChar(begin); } } #endif +/** + * TODO: This is architecture specific. Maybe there is a better solution + * to move this into the Bsp folder.. + */ #ifdef UT699 #include -ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) { +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, + uint16_t port) { this->log_message = set_message; this->isActive = true; setp( buf, buf + BUF_SIZE ); diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index b42c8a197..a2bc4f4b1 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -2,32 +2,36 @@ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ #include -#include #include #include +#include #ifndef UT699 -class ServiceInterfaceBuffer: public std::basic_streambuf > { +class ServiceInterfaceBuffer: + public std::basic_streambuf> { friend class ServiceInterfaceStream; public: - ServiceInterfaceBuffer(std::string set_message, uint16_t port); + ServiceInterfaceBuffer(std::string set_message, uint16_t port, + bool addCrToPreamble); protected: bool isActive; // This is called when buffer becomes full. If // buffer is not used, then this is called every // time when characters are put to stream. - virtual int overflow(int c = Traits::eof()); + int overflow(int c = Traits::eof()) override; // This function is called when stream is flushed, // for example when std::endl is put to stream. - virtual int sync(void); + int sync(void) override; private: // For additional message information std::string log_message; // For EOF detection typedef std::char_traits Traits; + // This is useful for some terminal programs which do not have + // implicit carriage return with newline characters. + bool addCrToPreamble; // Work in buffer mode. It is also possible to work without buffer. static size_t const BUF_SIZE = 128; @@ -35,6 +39,18 @@ private: // In this function, the characters are parsed. void putChars(char const* begin, char const* end); + + template + std::string zero_padded(const T& num, uint8_t width) { + std::ostringstream string_to_pad; + string_to_pad << std::setw(width) << std::setfill('0') << num; + std::string result = string_to_pad.str(); + if (result.length() > width) + { + result.erase(0, result.length() - width); + } + return result; + } }; #endif diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index c2979f369..40f52f1fe 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -5,7 +5,7 @@ void ServiceInterfaceStream::setActive( bool myActive) { } ServiceInterfaceStream::ServiceInterfaceStream(std::string set_message, - uint16_t port) : - std::basic_ostream >(&buf), buf( - set_message, port) { + bool addCrToPreamble, uint16_t port) : + std::basic_ostream>(&buf), + buf(set_message, port, addCrToPreamble) { } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index 44cf1168f..5e223f0eb 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -7,21 +7,22 @@ #include #include -//Unfortunately, there must be a forward declaration of log_fe +// Unfortunately, there must be a forward declaration of log_fe // (MUST be defined in main), to let the system know where to write to. extern std::ostream debug; extern std::ostream info; extern std::ostream warning; extern std::ostream error; -class ServiceInterfaceStream : public std::basic_ostream< char, std::char_traits< char > > { +class ServiceInterfaceStream : + public std::basic_ostream> { protected: ServiceInterfaceBuffer buf; public: - ServiceInterfaceStream( std::string set_message, uint16_t port = 1234 ); + ServiceInterfaceStream( std::string set_message, + bool addCrToPreamble = false, uint16_t port = 1234); void setActive( bool ); }; - #endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ */ diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index e8d8b413a..bb88931be 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -144,7 +144,8 @@ public: * @li RETURN_FAILED if data could not be added. * storageId is unchanged then. */ - virtual ReturnValue_t getFreeElement(store_address_t* storageId, const uint32_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; + virtual ReturnValue_t getFreeElement(store_address_t* storageId, + const uint32_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; /** * Clears the whole store. * Use with care! diff --git a/subsystem/Subsystem.cpp b/subsystem/Subsystem.cpp index e4a682bae..52f2c4741 100644 --- a/subsystem/Subsystem.cpp +++ b/subsystem/Subsystem.cpp @@ -168,7 +168,7 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage* message) { &sizeRead); if (result == RETURN_OK) { Mode_t fallbackId; - ssize_t size = sizeRead; + size_t size = sizeRead; result = SerializeAdapter::deSerialize(&fallbackId, &pointer, &size, true); if (result == RETURN_OK) { @@ -193,7 +193,7 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage* message) { ModeSequenceMessage::getStoreAddress(message), &pointer, &sizeRead); if (result == RETURN_OK) { - ssize_t size = sizeRead; + size_t size = sizeRead; result = SerialArrayListAdapter::deSerialize(&table, &pointer, &size, true); if (result == RETURN_OK) { diff --git a/subsystem/modes/ModeDefinitions.h b/subsystem/modes/ModeDefinitions.h index 4c0c4a261..5e5631b2c 100644 --- a/subsystem/modes/ModeDefinitions.h +++ b/subsystem/modes/ModeDefinitions.h @@ -53,7 +53,7 @@ public: return sizeof(value1) + sizeof(value2) + sizeof(value3) + sizeof(value4); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) { ReturnValue_t result; diff --git a/test/CatchExample.cpp b/test/CatchExample.cpp new file mode 100644 index 000000000..90fd1ed55 --- /dev/null +++ b/test/CatchExample.cpp @@ -0,0 +1,51 @@ +// Catch Example. +// Does not work yet. Problems with linker without main and config folder. +// propably because global object manager and some config files are not supplied +// but mandatory for full compilation of the framework. +// Let Catch provide main(): + +#if defined(UNIT_TEST) +#define CATCH_CONFIG_MAIN + +#include +#include +#include + +int Factorial( int number ) { + return number <= 1 ? number : Factorial( number - 1 ) * number; // fail +// return number <= 1 ? 1 : Factorial( number - 1 ) * number; // pass +} + + + +TEST_CASE( "Factorial of 0 is 1 (fail)", "[single-file]" ) { + REQUIRE( Factorial(0) == 1 ); +} + +TEST_CASE( "Factorials of 1 and higher are computed (pass)", "[single-file]" ) { + REQUIRE( Factorial(1) == 1 ); + REQUIRE( Factorial(2) == 2 ); + REQUIRE( Factorial(3) == 6 ); + REQUIRE( Factorial(10) == 3628800 ); +} + +TEST_CASE( "Custom test", "[single-file]" ) { + UnitTestClass unitTestClass; + REQUIRE( unitTestClass.test_autoserialization() == HasReturnvaluesIF::RETURN_OK ); +} + +// Compile & run: +// - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 010-TestCase 010-TestCase.cpp && ./010-TestCase --success +// - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 010-TestCase.cpp && 010-TestCase --success + +// Expected compact output (all assertions): +// +// prompt> 010-TestCase --reporter compact --success +// 010-TestCase.cpp:14: failed: Factorial(0) == 1 for: 0 == 1 +// 010-TestCase.cpp:18: passed: Factorial(1) == 1 for: 1 == 1 +// 010-TestCase.cpp:19: passed: Factorial(2) == 2 for: 2 == 2 +// 010-TestCase.cpp:20: passed: Factorial(3) == 6 for: 6 == 6 +// 010-TestCase.cpp:21: passed: Factorial(10) == 3628800 for: 3628800 (0x375f00) == 3628800 (0x375f00) +// Failed 1 test case, failed 1 assertion. + +#endif diff --git a/test/UnitTestClass.cpp b/test/UnitTestClass.cpp new file mode 100644 index 000000000..a0f65a088 --- /dev/null +++ b/test/UnitTestClass.cpp @@ -0,0 +1,302 @@ +/** + * @file UnitTestClass.cpp + * + * @date 11.04.2020 + * @author R. Mueller + */ +#include +#include +#include +#include + +#include + +#if defined(UNIT_TEST) +#include "catch.hpp" +#define CATCH_CONFIG_MAIN + +TEST_CASE( "Serialization Size tests", "[single-file]") { + //REQUIRE(UnitTestClass::test_serialization == RETURN_OK ); +} +#endif + +UnitTestClass::UnitTestClass() {} + +UnitTestClass::~UnitTestClass() {} + +ReturnValue_t UnitTestClass::perform_tests() { + ReturnValue_t result = test_serialization(); + if(result != RETURN_OK) { + return result; + } + + return RETURN_OK; +} + +ReturnValue_t UnitTestClass::test_serialization() { + // Here, we test all serialization tools. First test basic cases. + ReturnValue_t result = test_endianness_tools(); + if(result != RETURN_OK) { + return result; + } + result = test_autoserialization(); + if(result != RETURN_OK) { + return result; + } + result = test_serial_buffer_adapter(); + if(result != RETURN_OK) { + return result; + } + return RETURN_OK; +} + +ReturnValue_t UnitTestClass::test_endianness_tools() { + test_array[0] = 0; + test_array[1] = 0; + uint16_t two_byte_value = 1; + size_t size = 0; + uint8_t* p_array = test_array.data(); + AutoSerializeAdapter::serialize(&two_byte_value, &p_array, &size, 2, false); + // Little endian: Value one on first byte + if(test_array[0] != 1 and test_array[1] != 0) { + return put_error(TestIds::ENDIANNESS_TOOLS); + + } + + p_array = test_array.data(); + size = 0; + AutoSerializeAdapter::serialize(&two_byte_value, &p_array, &size, 2, true); + // Big endian: Value one on second byte + if(test_array[0] != 0 and test_array[1] != 1) { + return put_error(TestIds::ENDIANNESS_TOOLS); + } + + // Endianness paameter will be changed later. +// p_array = test_array.data(); +// ssize_t ssize = size; +// // Resulting parameter should be big endian +// AutoSerializeAdapter::deSerialize(&two_byte_value, +// const_cast(&p_array), &ssize, true); +// if(two_byte_value != 1) { +// return put_error(TestIds::ENDIANNESS_TOOLS); +// } +// +// ssize = size; +// p_array = test_array.data(); +// // Resulting parameter should be little endian +// AutoSerializeAdapter::deSerialize(&two_byte_value, +// const_cast(&p_array), &ssize, false); +// if(two_byte_value != 256) { +// return put_error(TestIds::ENDIANNESS_TOOLS); +// } + return RETURN_OK; +} + +ReturnValue_t UnitTestClass::test_autoserialization() { + current_id = TestIds::AUTO_SERIALIZATION_SIZE; + // Unit Test getSerializedSize + if(AutoSerializeAdapter:: + getSerializedSize(&test_value_bool) != sizeof(test_value_bool) or + AutoSerializeAdapter:: + getSerializedSize(&tv_uint8) != sizeof(tv_uint8) or + AutoSerializeAdapter:: + getSerializedSize(&tv_uint16) != sizeof(tv_uint16) or + AutoSerializeAdapter:: + getSerializedSize(&tv_uint32) != sizeof(tv_uint32) or + AutoSerializeAdapter:: + getSerializedSize(&tv_uint64) != sizeof(tv_uint64) or + AutoSerializeAdapter:: + getSerializedSize(&tv_int8) != sizeof(tv_int8) or + AutoSerializeAdapter:: + getSerializedSize(&tv_double) != sizeof(tv_double) or + AutoSerializeAdapter:: + getSerializedSize(&tv_int16) != sizeof(tv_int16) or + AutoSerializeAdapter:: + getSerializedSize(&tv_int32) != sizeof(tv_int32) or + AutoSerializeAdapter:: + getSerializedSize(&tv_float) != sizeof(tv_float)) + { + return put_error(current_id); + } + + // Unit Test AutoSerializeAdapter deserialize + current_id = TestIds::AUTO_SERIALIZATION_SERIALIZE; + + size_t serialized_size = 0; + uint8_t * p_array = test_array.data(); + + AutoSerializeAdapter::serialize(&test_value_bool, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint8, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint16, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint32, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_int8, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_int16, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_int32, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint64, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_float, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_double, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_sfloat, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_sdouble, &p_array, + &serialized_size, test_array.size(), false); + // expected size is 1 + 1 + 2 + 4 + 1 + 2 + 4 + 8 + 4 + 8 + 4 + 8 + if(serialized_size != 47) { + return put_error(current_id); + } + + // Unit Test AutoSerializeAdapter serialize + current_id = TestIds::AUTO_SERIALIZATION_DESERIALIZE; + p_array = test_array.data(); + size_t remaining_size = serialized_size; + AutoSerializeAdapter::deSerialize(&test_value_bool, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_uint8, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_uint16, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_uint32, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_int8, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_int16, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_int32, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_uint64, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_float, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_double, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_sfloat, + const_cast(&p_array), &remaining_size, false); + AutoSerializeAdapter::deSerialize(&tv_sdouble, + const_cast(&p_array), &remaining_size, false); + + if(test_value_bool != true or tv_uint8 != 5 or tv_uint16 != 283 or + tv_uint32 != 929221 or tv_uint64 != 2929329429 or tv_int8 != -16 or + tv_int16 != -829 or tv_int32 != -2312) + { + return put_error(current_id); + } + + // These epsilon values were just guessed.. It appears to work though. + if(abs(tv_float - 8.214921) > 0.0001 or + abs(tv_double - 9.2132142141e8) > 0.01 or + abs(tv_sfloat - (-922.2321321)) > 0.0001 or + abs(tv_sdouble - (-2.2421e19)) > 0.01) { + return put_error(current_id); + } + + // Check overflow + return RETURN_OK; +} + +// TODO: Also test for constant buffers. +ReturnValue_t UnitTestClass::test_serial_buffer_adapter() { + current_id = TestIds::SERIALIZATION_BUFFER_ADAPTER; + + // I will skip endian swapper testing, its going to be changed anyway.. + // uint8_t tv_uint8_swapped = EndianSwapper::swap(tv_uint8); + + size_t serialized_size = 0; + test_value_bool = true; + uint8_t * p_array = test_array.data(); + std::array test_serial_buffer {5, 4, 3, 2, 1}; + SerialBufferAdapter tv_serial_buffer_adapter = + SerialBufferAdapter(test_serial_buffer.data(), + test_serial_buffer.size(), false); + tv_uint16 = 16; + + AutoSerializeAdapter::serialize(&test_value_bool, &p_array,&serialized_size, + test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_serial_buffer_adapter, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint16, &p_array, &serialized_size, + test_array.size(), false); + + if(serialized_size != 8 or test_array[0] != true or test_array[1] != 5 + or test_array[2] != 4 or test_array[3] != 3 or test_array[4] != 2 + or test_array[5] != 1) + { + return put_error(current_id); + } + memcpy(&tv_uint16, test_array.data() + 6, sizeof(tv_uint16)); + if(tv_uint16 != 16) { + return put_error(current_id); + } + + // Serialize with size field + SerialBufferAdapter tv_serial_buffer_adapter2 = + SerialBufferAdapter(test_serial_buffer.data(), + test_serial_buffer.size(), true); + serialized_size = 0; + p_array = test_array.data(); + AutoSerializeAdapter::serialize(&test_value_bool, &p_array,&serialized_size, + test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_serial_buffer_adapter2, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint16, &p_array, &serialized_size, + test_array.size(), false); + + if(serialized_size != 9 or test_array[0] != true or test_array[1] != 5 + or test_array[2] != 5 or test_array[3] != 4 or test_array[4] != 3 + or test_array[5] != 2 or test_array[6] != 1) + { + return put_error(current_id); + } + memcpy(&tv_uint16, test_array.data() + 7, sizeof(tv_uint16)); + if(tv_uint16 != 16) { + return put_error(current_id); + } + + // Serialize with size field + SerialBufferAdapter tv_serial_buffer_adapter3 = + SerialBufferAdapter( + const_cast(test_serial_buffer.data()), + test_serial_buffer.size(), false); + serialized_size = 0; + p_array = test_array.data(); + AutoSerializeAdapter::serialize(&test_value_bool, &p_array,&serialized_size, + test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_serial_buffer_adapter3, &p_array, + &serialized_size, test_array.size(), false); + AutoSerializeAdapter::serialize(&tv_uint16, &p_array, &serialized_size, + test_array.size(), false); + + if(serialized_size != 8 or test_array[0] != true or test_array[1] != 5 + or test_array[2] != 4 or test_array[3] != 3 or test_array[4] != 2 + or test_array[5] != 1) + { + return put_error(current_id); + } + memcpy(&tv_uint16, test_array.data() + 6, sizeof(tv_uint16)); + if(tv_uint16 != 16) { + return put_error(current_id); + } + return RETURN_OK; +} + +ReturnValue_t UnitTestClass::put_error(TestIds currentId) { + auto errorIter = testResultMap.find(currentId); + if(errorIter != testResultMap.end()) { + testResultMap.emplace(currentId, 1); + } + else { + errorIter->second ++; + } + error << "Unit Tester failed at test ID " + << static_cast(currentId) << "\r\n" << std::flush; + return RETURN_FAILED; +} + diff --git a/test/UnitTestClass.h b/test/UnitTestClass.h new file mode 100644 index 000000000..ffc7a2a2b --- /dev/null +++ b/test/UnitTestClass.h @@ -0,0 +1,84 @@ +/** + * @file UnitTestClass.h + * + * @date 11.04.2020 + * @author R. Mueller + */ + +#ifndef FRAMEWORK_TEST_UNITTESTCLASS_H_ +#define FRAMEWORK_TEST_UNITTESTCLASS_H_ + +#include + +#include +#include + +/** + * We could start doing basic forms of Unit Testing (without a framework, first) + * for framework components. This could include: + * + * 1. TMTC Services + * 2. Serialization tools + * 3. Framework internal algorithms + * + * TODO: Maybe use specialized framework. + */ + +class UnitTestClass: public HasReturnvaluesIF { +public: + UnitTestClass(); + virtual~ UnitTestClass(); + + enum class TestIds { + ENDIANNESS_TOOLS, + AUTO_SERIALIZATION_SIZE, + AUTO_SERIALIZATION_SERIALIZE, + AUTO_SERIALIZATION_DESERIALIZE , + SERIALIZATION_BUFFER_ADAPTER, + SERIALIZATION_FIXED_ARRAY_LIST_ADAPTER, + SERIALIZATION_COMBINATION, + TMTC_SERVICES , + MISC + }; + + /** + * Some function which calls all other tests + * @return + */ + ReturnValue_t perform_tests(); + + ReturnValue_t test_serialization(); + ReturnValue_t test_autoserialization(); + ReturnValue_t test_serial_buffer_adapter(); + ReturnValue_t test_endianness_tools(); +private: + uint32_t errorCounter = 0; + TestIds current_id = TestIds::MISC; + std::array test_array; + + using error_count_t = uint8_t; + using TestResultMap = std::map; + using TestBuffer = std::vector; + TestResultMap testResultMap; + + // POD test values + bool test_value_bool = true; + uint8_t tv_uint8 {5}; + uint16_t tv_uint16 {283}; + uint32_t tv_uint32 {929221}; + uint64_t tv_uint64 {2929329429}; + + int8_t tv_int8 {-16}; + int16_t tv_int16 {-829}; + int32_t tv_int32 {-2312}; + + float tv_float {8.2149214}; + float tv_sfloat = {-922.2321321}; + double tv_double {9.2132142141e8}; + double tv_sdouble {-2.2421e19}; + + ReturnValue_t put_error(TestIds currentId); +}; + + +#endif /* FRAMEWORK_TEST_UNITTESTCLASS_H_ */ diff --git a/test/catch2/catch.hpp b/test/catch2/catch.hpp new file mode 100644 index 000000000..51618b38e --- /dev/null +++ b/test/catch2/catch.hpp @@ -0,0 +1,17618 @@ +/* + * Catch v2.11.3 + * Generated: 2020-03-19 13:44:21.042491 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp + + +#define CATCH_VERSION_MAJOR 2 +#define CATCH_VERSION_MINOR 11 +#define CATCH_VERSION_PATCH 3 + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// start catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ + // Because REQUIREs trigger GCC's -Wparentheses, and because still + // supported version of g++ have only buggy support for _Pragmas, + // Wparentheses have to be suppressed globally. +# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details + +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wpadded" +#endif +// end catch_suppress_warnings.h +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +# define CATCH_CONFIG_ALL_PARTS +#endif + +// In the impl file, we want to have access to all parts of the headers +// Can also be used to sanely support PCHs +#if defined(CATCH_CONFIG_ALL_PARTS) +# define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif +# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +# endif +#endif + +#if !defined(CATCH_CONFIG_IMPL_ONLY) +// start catch_platform.h + +#ifdef __APPLE__ +# include +# if TARGET_OS_OSX == 1 +# define CATCH_PLATFORM_MAC +# elif TARGET_OS_IPHONE == 1 +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// start catch_user_interfaces.h + +namespace Catch { + unsigned int rngSeed(); +} + +// end catch_user_interfaces.h +// start catch_tag_alias_autoregistrar.h + +// start catch_common.h + +// start catch_compiler_capabilities.h + +// Detect a number of compiler features - by compiler +// The following features are defined: +// +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? +// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +#ifdef __cplusplus + +# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +# define CATCH_CPP14_OR_GREATER +# endif + +# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define CATCH_CPP17_OR_GREATER +# endif + +#endif + +#if defined(CATCH_CPP17_OR_GREATER) +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +// We have to avoid both ICC and Clang, because they try to mask themselves +// as gcc, and we want only GCC in this block +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +#endif + +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Assume that non-Windows platforms support posix signals by default +#if !defined(CATCH_PLATFORM_WINDOWS) + #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#endif + +//////////////////////////////////////////////////////////////////////////////// +// We know some environments not to support full POSIX signals +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) + #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#endif + +#ifdef __OS400__ +# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +# define CATCH_CONFIG_COLOUR_NONE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// PS4 +#if defined(__ORBIS__) +# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cygwin +#ifdef __CYGWIN__ + +// Required for some versions of Cygwin to declare gettimeofday +// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +# define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 +# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) + +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING + +# endif +#endif // __CYGWIN__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#if defined(_MSC_VER) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) + +# if _MSC_VER >= 1900 // Visual Studio 2015 or newer +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +# endif + +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif + +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +# if !defined(__clang__) // Handle Clang masquerading for msvc +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL +# endif // __clang__ + +#endif // _MSC_VER + +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// Check if we are compiled with -fno-exceptions or equivalent +#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) +# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#endif + +//////////////////////////////////////////////////////////////////////////////// +// DJGPP +#ifdef __DJGPP__ +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ + +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// Otherwise all supported compilers support COUNTER macro, +// but user still might want to turn it off +#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) + #define CATCH_INTERNAL_CONFIG_COUNTER +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE +#endif + +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Various stdlib support checks that require __has_include +#if defined(__has_include) + // Check if string_view is available and usable + #if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) + +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +# define CATCH_CONFIG_WINDOWS_SEH +#endif +// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) +# define CATCH_CONFIG_POSIX_SIGNALS +#endif +// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +# define CATCH_CONFIG_WCHAR +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +# define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) +# define CATCH_CONFIG_CPP17_OPTIONAL +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) +# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +# define CATCH_CONFIG_CPP17_STRING_VIEW +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) +# define CATCH_CONFIG_CPP17_VARIANT +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) +# define CATCH_CONFIG_NEW_CAPTURE +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) +# define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_TRY if ((true)) +#define CATCH_CATCH_ALL if ((false)) +#define CATCH_CATCH_ANON(type) if ((false)) +#else +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) +#endif + +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif + +// end catch_compiler_capabilities.h +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#include +#include +#include + +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy {}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); + +namespace Catch { + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; + + protected: + NonCopyable(); + virtual ~NonCopyable(); + }; + + struct SourceLineInfo { + + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} + + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo( SourceLineInfo&& ) noexcept = default; + SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; + + bool empty() const noexcept { return file[0] == '\0'; } + bool operator == ( SourceLineInfo const& other ) const noexcept; + bool operator < ( SourceLineInfo const& other ) const noexcept; + + char const* file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // Bring in operator<< from global namespace into Catch namespace + // This is necessary because the overload of operator<< above makes + // lookup stop at namespace Catch + using ::operator<<; + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() const; + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + +// end catch_common.h +namespace Catch { + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.h + +// start catch_interfaces_testcase.h + +#include + +namespace Catch { + + class TestSpec; + + struct ITestInvoker { + virtual void invoke () const = 0; + virtual ~ITestInvoker(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include +#include + +namespace Catch { + + /// A non-owning string class (similar to the forthcoming std::string_view) + /// Note that, because a StringRef may be a substring of another string, + /// it may not be null terminated. + class StringRef { + public: + using size_type = std::size_t; + using const_iterator = const char*; + + private: + static constexpr char const* const s_empty = ""; + + char const* m_start = s_empty; + size_type m_size = 0; + + public: // construction + constexpr StringRef() noexcept = default; + + StringRef( char const* rawChars ) noexcept; + + constexpr StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + {} + + StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + explicit operator std::string() const { + return std::string(m_start, m_size); + } + + public: // operators + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } + + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } + + public: // named queries + constexpr auto empty() const noexcept -> bool { + return m_size == 0; + } + constexpr auto size() const noexcept -> size_type { + return m_size; + } + + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception + auto c_str() const -> char const*; + + public: // substrings and searches + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; + + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; + + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } + + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; + + auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + return StringRef( rawChars, size ); + } +} // namespace Catch + +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { + return Catch::StringRef( rawChars, size ); +} + +// end catch_stringref.h +// start catch_preprocessor.hpp + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, +// and passes userdata as the first parameter to each invocation, +// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) + +#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define INTERNAL_CATCH_TYPE_GEN\ + template struct TypeList {};\ + template\ + constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + template class...> struct TemplateTypeList{};\ + template class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ + template\ + struct append;\ + template\ + struct rewrap;\ + template class, typename...>\ + struct create;\ + template class, typename>\ + struct convert;\ + \ + template \ + struct append { using type = T; };\ + template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ + struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ + template< template class L1, typename...E1, typename...Rest>\ + struct append, TypeList, Rest...> { using type = L1; };\ + \ + template< template class Container, template class List, typename...elems>\ + struct rewrap, List> { using type = TypeList>; };\ + template< template class Container, template class List, class...Elems, typename...Elements>\ + struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ + \ + template