From d1d1b49a262eba7693e35a170d5e416820ef9eee Mon Sep 17 00:00:00 2001 From: h2zero Date: Wed, 17 Jul 2024 15:35:13 -0600 Subject: [PATCH] Refactor NimBLEAttValue. * Add length parameter to `setValue()` templates, with defaults for backward compatibility. * Changed `setValue(const char*)` to add an optional length parameter so that a NULL character can be included, defaults to strlen. * Moved non-inline functions to `NimBLEAttValue.cpp` file. * Corrected includes to permit compilation as a stand-alone utility. * Removed repeated code in `setValue()` by using `append()` after clearing the value. * General code cleanup. --- CMakeLists.txt | 1 + src/NimBLEAttValue.cpp | 130 ++++++++++++++ src/NimBLEAttValue.h | 398 ++++++++++++++--------------------------- 3 files changed, 268 insertions(+), 261 deletions(-) create mode 100644 src/NimBLEAttValue.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bed65b..769d80a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ idf_component_register( "src/NimBLEAddress.cpp" "src/NimBLEAdvertisedDevice.cpp" "src/NimBLEAdvertising.cpp" + "src/NimBLEAttValue.cpp" "src/NimBLEBeacon.cpp" "src/NimBLECharacteristic.cpp" "src/NimBLEClient.cpp" diff --git a/src/NimBLEAttValue.cpp b/src/NimBLEAttValue.cpp new file mode 100644 index 0000000..0a7a771 --- /dev/null +++ b/src/NimBLEAttValue.cpp @@ -0,0 +1,130 @@ +/* + * NimBLEAttValue.cpp + * + * Created: on July 17, 2024 + * Author H2zero + * + */ + +#include "nimconfig.h" +#if defined(CONFIG_BT_ENABLED) + +# if defined(CONFIG_NIMBLE_CPP_IDF) +# include "nimble/nimble_npl.h" +# else +# include "nimble/nimble/include/nimble/nimble_npl.h" +# endif + +# include "NimBLEAttValue.h" + +// Default constructor implementation. +NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len) + : m_attr_value{static_cast(calloc(init_len + 1, 1))}, + m_attr_max_len{std::min(BLE_ATT_ATTR_MAX_LEN, max_len)}, + m_attr_len{}, + m_capacity{init_len} +# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED + , + m_timestamp{} +# endif +{ + NIMBLE_CPP_DEBUG_ASSERT(m_attr_value); +} + +// Value constructor implementation. +NimBLEAttValue::NimBLEAttValue(const uint8_t *value, uint16_t len, uint16_t max_len) +: NimBLEAttValue(len, max_len) { + memcpy(m_attr_value, value, len); + m_attr_value[len] = '\0'; + m_attr_len = len; +} + +// Destructor implementation. +NimBLEAttValue::~NimBLEAttValue() { + if (m_attr_value != nullptr) { + free(m_attr_value); + } +} + +// Move assignment operator implementation. +NimBLEAttValue& NimBLEAttValue::operator=(NimBLEAttValue&& source) { + if (this != &source) { + free(m_attr_value); + m_attr_value = source.m_attr_value; + m_attr_max_len = source.m_attr_max_len; + m_attr_len = source.m_attr_len; + m_capacity = source.m_capacity; + setTimeStamp(source.getTimeStamp()); + source.m_attr_value = nullptr; + } + + return *this; +} + +// Copy assignment implementation. +NimBLEAttValue& NimBLEAttValue::operator=(const NimBLEAttValue& source) { + if (this != &source) { + deepCopy(source); + } + return *this; +} + +// Copy all the data from the source object to this object, including allocated space. +void NimBLEAttValue::deepCopy(const NimBLEAttValue& source) { + uint8_t* res = static_cast(realloc(m_attr_value, source.m_capacity + 1)); + NIMBLE_CPP_DEBUG_ASSERT(res); + + ble_npl_hw_enter_critical(); + m_attr_value = res; + m_attr_max_len = source.m_attr_max_len; + m_attr_len = source.m_attr_len; + m_capacity = source.m_capacity; + setTimeStamp(source.getTimeStamp()); + memcpy(m_attr_value, source.m_attr_value, m_attr_len + 1); + ble_npl_hw_exit_critical(0); +} + +// Set the value of the attribute. +bool NimBLEAttValue::setValue(const uint8_t* value, uint16_t len) { + m_attr_len = 0; // Just set the value length to 0 and append instead of repeating code. + append(value, len); + return memcmp(m_attr_value, value, len) == 0 && m_attr_len == len; +} + +// Append the new data, allocate as necessary. +NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) { + if (len == 0) { + return *this; + } + + if ((m_attr_len + len) > m_attr_max_len) { + NIMBLE_LOGE("NimBLEAttValue", "val > max, len=%u, max=%u", len, m_attr_max_len); + return *this; + } + + uint8_t* res = m_attr_value; + uint16_t new_len = m_attr_len + len; + if (new_len > m_capacity) { + res = static_cast(realloc(m_attr_value, (new_len + 1))); + m_capacity = new_len; + } + NIMBLE_CPP_DEBUG_ASSERT(res); + +# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED + time_t t = time(nullptr); +# else + time_t t = 0; +# endif + + ble_npl_hw_enter_critical(); + memcpy(res + m_attr_len, value, len); + m_attr_value = res; + m_attr_len = new_len; + m_attr_value[m_attr_len] = '\0'; + setTimeStamp(t); + ble_npl_hw_exit_critical(0); + + return *this; +} + +#endif // CONFIG_BT_ENABLED diff --git a/src/NimBLEAttValue.h b/src/NimBLEAttValue.h index cc8599a..b95e38d 100644 --- a/src/NimBLEAttValue.h +++ b/src/NimBLEAttValue.h @@ -6,50 +6,45 @@ * */ -#ifndef MAIN_NIMBLEATTVALUE_H_ -#define MAIN_NIMBLEATTVALUE_H_ +#ifndef NIMBLE_CPP_ATTVALUE_H +#define NIMBLE_CPP_ATTVALUE_H #include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) -#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE -#include -#endif +# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE +# include +# endif -#include "NimBLELog.h" +# include "NimBLELog.h" +# include +# include +# include +# include +# include -/**** FIX COMPILATION ****/ -#undef min -#undef max -/**************************/ +# ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED +# define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0 +# endif -#include -#include -#include +# ifndef BLE_ATT_ATTR_MAX_LEN +# define BLE_ATT_ATTR_MAX_LEN 512 +# endif -#ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED -# define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0 -#endif - -#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED -# include -#endif - -#if !defined(CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH) -# define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20 -#elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH > BLE_ATT_ATTR_MAX_LEN -# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be larger than 512 (BLE_ATT_ATTR_MAX_LEN) -#elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH < 1 -# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512 -#endif +# if !defined(CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH) +# define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20 +# elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH > BLE_ATT_ATTR_MAX_LEN +# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be larger than 512 (BLE_ATT_ATTR_MAX_LEN) +# elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH < 1 +# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512 +# endif /* Used to determine if the type passed to a template has a c_str() and length() method. */ template struct Has_c_str_len : std::false_type {}; template -struct Has_c_str_len().c_str())), - decltype(void(std::declval().length()))> : std::true_type {}; - +struct Has_c_str_len().c_str())), decltype(void(std::declval().length()))> + : std::true_type {}; /** * @brief A specialized container class to hold BLE attribute values. @@ -57,25 +52,23 @@ struct Has_c_str_len().c_str())), * standard container types for value storage, while being convertible to\n * many different container classes. */ -class NimBLEAttValue -{ - uint8_t* m_attr_value = nullptr; - uint16_t m_attr_max_len = 0; - uint16_t m_attr_len = 0; - uint16_t m_capacity = 0; -#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED - time_t m_timestamp = 0; -#endif - void deepCopy(const NimBLEAttValue & source); +class NimBLEAttValue { + uint8_t* m_attr_value{}; + uint16_t m_attr_max_len{}; + uint16_t m_attr_len{}; + uint16_t m_capacity{}; +# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED + time_t m_timestamp{}; +# endif + void deepCopy(const NimBLEAttValue& source); -public: + public: /** * @brief Default constructor. * @param[in] init_len The initial size in bytes. * @param[in] max_len The max size in bytes that the value can be. */ - NimBLEAttValue(uint16_t init_len = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH, - uint16_t max_len = BLE_ATT_ATTR_MAX_LEN); + NimBLEAttValue(uint16_t init_len = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN); /** * @brief Construct with an initial value from a buffer. @@ -86,15 +79,6 @@ public: NimBLEAttValue(const uint8_t *value, uint16_t len, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN); - /** - * @brief Construct with an initializer list. - * @param list An initializer list containing the initial value to set. - * @param[in] max_len The max size in bytes that the value can be. - */ - NimBLEAttValue(std::initializer_list list, - uint16_t max_len = BLE_ATT_ATTR_MAX_LEN) - :NimBLEAttValue(list.begin(), (uint16_t)list.size(), max_len){} - /** * @brief Construct with an initial value from a const char string. * @param value A pointer to the initial value to set. @@ -103,13 +87,21 @@ public: NimBLEAttValue(const char *value, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN) :NimBLEAttValue((uint8_t*)value, (uint16_t)strlen(value), max_len){} + /** + * @brief Construct with an initializer list. + * @param list An initializer list containing the initial value to set. + * @param[in] max_len The max size in bytes that the value can be. + */ + NimBLEAttValue(std::initializer_list list, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN) + : NimBLEAttValue(list.begin(), list.size(), max_len) {} + /** * @brief Construct with an initial value from a std::string. * @param str A std::string containing to the initial value to set. * @param[in] max_len The max size in bytes that the value can be. */ NimBLEAttValue(const std::string str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN) - :NimBLEAttValue((uint8_t*)str.data(), (uint16_t)str.length(), max_len){} + : NimBLEAttValue(reinterpret_cast(&str[0]), str.length(), max_len) {} /** * @brief Construct with an initial value from a std::vector. @@ -117,90 +109,104 @@ public: * @param[in] max_len The max size in bytes that the value can be. */ NimBLEAttValue(const std::vector vec, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN) - :NimBLEAttValue(&vec[0], (uint16_t)vec.size(), max_len){} + : NimBLEAttValue(&vec[0], vec.size(), max_len) {} -#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE +# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE /** * @brief Construct with an initial value from an Arduino String. * @param str An Arduino String containing to the initial value to set. * @param[in] max_len The max size in bytes that the value can be. */ NimBLEAttValue(const String str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN) - :NimBLEAttValue((uint8_t*)str.c_str(), str.length(), max_len){} -#endif + : NimBLEAttValue(reinterpret_cast(str.c_str()), str.length(), max_len) {} +# endif /** @brief Copy constructor */ - NimBLEAttValue(const NimBLEAttValue & source) { deepCopy(source); } + NimBLEAttValue(const NimBLEAttValue& source) { deepCopy(source); } /** @brief Move constructor */ - NimBLEAttValue(NimBLEAttValue && source) { *this = std::move(source); } + NimBLEAttValue(NimBLEAttValue&& source) { *this = std::move(source); } /** @brief Destructor */ ~NimBLEAttValue(); /** @brief Returns the max size in bytes */ - uint16_t max_size() const { return m_attr_max_len; } + uint16_t max_size() const { return m_attr_max_len; } /** @brief Returns the currently allocated capacity in bytes */ - uint16_t capacity() const { return m_capacity; } + uint16_t capacity() const { return m_capacity; } /** @brief Returns the current length of the value in bytes */ - uint16_t length() const { return m_attr_len; } + uint16_t length() const { return m_attr_len; } /** @brief Returns the current size of the value in bytes */ - uint16_t size() const { return m_attr_len; } + uint16_t size() const { return m_attr_len; } /** @brief Returns a pointer to the internal buffer of the value */ - const uint8_t* data() const { return m_attr_value; } + const uint8_t* data() const { return m_attr_value; } /** @brief Returns a pointer to the internal buffer of the value as a const char* */ - const char* c_str() const { return (const char*)m_attr_value; } + const char* c_str() const { return reinterpret_cast(m_attr_value); } /** @brief Iterator begin */ - const uint8_t* begin() const { return m_attr_value; } + const uint8_t* begin() const { return m_attr_value; } /** @brief Iterator end */ - const uint8_t* end() const { return m_attr_value + m_attr_len; } + const uint8_t* end() const { return m_attr_value + m_attr_len; } -#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED +# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED /** @brief Returns a timestamp of when the value was last updated */ - time_t getTimeStamp() const { return m_timestamp; } + time_t getTimeStamp() const { return m_timestamp; } /** @brief Set the timestamp to the current time */ - void setTimeStamp() { m_timestamp = time(nullptr); } + void setTimeStamp() { m_timestamp = time(nullptr); } /** * @brief Set the timestamp to the specified time * @param[in] t The timestamp value to set */ - void setTimeStamp(time_t t) { m_timestamp = t; } -#else - time_t getTimeStamp() const { return 0; } - void setTimeStamp() { } - void setTimeStamp(time_t t) { } -#endif + void setTimeStamp(time_t t) { m_timestamp = t; } +# else + time_t getTimeStamp() const { return 0; } + void setTimeStamp() {} + void setTimeStamp(time_t t) {} +# endif /** * @brief Set the value from a buffer - * @param[in] value A ponter to a buffer containing the value. + * @param[in] value A pointer to a buffer containing the value. * @param[in] len The length of the value in bytes. * @returns True if successful. */ - bool setValue(const uint8_t *value, uint16_t len); + bool setValue(const uint8_t* value, uint16_t len); /** * @brief Set value to the value of const char*. - * @param [in] s A ponter to a const char value to set. + * @param [in] s A pointer to a const char value to set. + * @param [in] len The length of the value in bytes, defaults to strlen(s). */ - bool setValue(const char* s) { - return setValue((uint8_t*)s, (uint16_t)strlen(s)); } + bool setValue(const char* s, uint16_t len = 0) { + if (len == 0) { + len = strlen(s); + } + return setValue(reinterpret_cast(s), len); + } /** * @brief Get a pointer to the value buffer with timestamp. - * @param[in] timestamp A ponter to a time_t variable to store the timestamp. + * @param[in] timestamp A pointer to a time_t variable to store the timestamp. * @returns A pointer to the internal value buffer. */ - const uint8_t* getValue(time_t *timestamp); + const uint8_t* getValue(time_t* timestamp = nullptr) const { + if (timestamp != nullptr) { +# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED + *timestamp = m_timestamp; +# else + *timestamp = 0; +# endif + } + return m_attr_value; + } /** * @brief Append data to the value. @@ -208,39 +214,46 @@ public: * @param[in] len The length of the value to append in bytes. * @returns A reference to the appended NimBLEAttValue. */ - NimBLEAttValue& append(const uint8_t *value, uint16_t len); - + NimBLEAttValue& append(const uint8_t* value, uint16_t len); /*********************** Template Functions ************************/ /** * @brief Template to set value to the value of val. * @param [in] s The value to set. + * @param [in] len The length of the value in bytes, defaults to sizeof(T). * @details Only used for types without a `c_str()` method. */ - template -#ifdef _DOXYGEN_ + template +# ifdef _DOXYGEN_ bool -#else +# else typename std::enable_if::value, bool>::type -#endif - setValue(const T &s) { - return setValue((uint8_t*)&s, sizeof(T)); +# endif + setValue(const T& s, uint16_t len = 0) { + if (len == 0) { + len = sizeof(T); + } + return setValue(reinterpret_cast(&s), len); } /** * @brief Template to set value to the value of val. * @param [in] s The value to set. + * @param [in] len The length of the value in bytes, defaults to string.length(). * @details Only used if the has a `c_str()` method. */ - template -#ifdef _DOXYGEN_ + template +# ifdef _DOXYGEN_ bool -#else +# else typename std::enable_if::value, bool>::type -#endif - setValue(const T & s) { - return setValue((uint8_t*)s.c_str(), (uint16_t)s.length()); +# endif + setValue(const T& s, uint16_t len = 0) { + if (len == 0) { + len = s.length(); + } + return setValue(reinterpret_cast(s.c_str()), len); } /** @@ -253,196 +266,59 @@ public: * less than sizeof(). * @details Use: getValue(×tamp, skipSizeCheck); */ - template - T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) { - if(!skipSizeCheck && size() < sizeof(T)) { - return T(); - } - return *((T *)getValue(timestamp)); + template + T getValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const { + if (!skipSizeCheck && size() < sizeof(T)) { + return T(); + } + return *(reinterpret_cast(getValue(timestamp))); } - /*********************** Operators ************************/ /** @brief Subscript operator */ - uint8_t operator [](int pos) const { + uint8_t operator[](int pos) const { NIMBLE_CPP_DEBUG_ASSERT(pos < m_attr_len); - return m_attr_value[pos]; } + return m_attr_value[pos]; + } /** @brief Operator; Get the value as a std::vector. */ - operator std::vector() const { - return std::vector(m_attr_value, m_attr_value + m_attr_len); } + operator std::vector() const { return std::vector(m_attr_value, m_attr_value + m_attr_len); } /** @brief Operator; Get the value as a std::string. */ - operator std::string() const { - return std::string((char*)m_attr_value, m_attr_len); } + operator std::string() const { return std::string(reinterpret_cast(m_attr_value), m_attr_len); } /** @brief Operator; Get the value as a const uint8_t*. */ operator const uint8_t*() const { return m_attr_value; } /** @brief Operator; Append another NimBLEAttValue. */ - NimBLEAttValue& operator +=(const NimBLEAttValue & source) { - return append(source.data(), source.size()); } + NimBLEAttValue& operator+=(const NimBLEAttValue& source) { return append(source.data(), source.size()); } /** @brief Operator; Set the value from a std::string source. */ - NimBLEAttValue& operator =(const std::string & source) { - setValue((uint8_t*)source.data(), (uint16_t)source.size()); return *this; } + NimBLEAttValue& operator=(const std::string& source) { + setValue(reinterpret_cast(&source[0]), source.size()); + return *this; + } /** @brief Move assignment operator */ - NimBLEAttValue& operator =(NimBLEAttValue && source); + NimBLEAttValue& operator=(NimBLEAttValue&& source); /** @brief Copy assignment operator */ - NimBLEAttValue& operator =(const NimBLEAttValue & source); + NimBLEAttValue& operator=(const NimBLEAttValue& source); /** @brief Equality operator */ - bool operator ==(const NimBLEAttValue & source) { - return (m_attr_len == source.size()) ? - memcmp(m_attr_value, source.data(), m_attr_len) == 0 : false; } + bool operator==(const NimBLEAttValue& source) const { + return (m_attr_len == source.size()) ? memcmp(m_attr_value, source.data(), m_attr_len) == 0 : false; + } /** @brief Inequality operator */ - bool operator !=(const NimBLEAttValue & source){ return !(*this == source); } + bool operator!=(const NimBLEAttValue& source) const { return !(*this == source); } -#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE +# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE /** @brief Operator; Get the value as an Arduino String value. */ - operator String() const { return String((char*)m_attr_value); } -#endif - + operator String() const { return String(reinterpret_cast(m_attr_value)); } +# endif }; - -inline NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len) { - m_attr_value = (uint8_t*)calloc(init_len + 1, 1); - NIMBLE_CPP_DEBUG_ASSERT(m_attr_value); - m_attr_max_len = std::min(BLE_ATT_ATTR_MAX_LEN, (int)max_len); - m_attr_len = 0; - m_capacity = init_len; - setTimeStamp(0); -} - -inline NimBLEAttValue::NimBLEAttValue(const uint8_t *value, uint16_t len, uint16_t max_len) -: NimBLEAttValue(len, max_len) { - memcpy(m_attr_value, value, len); - m_attr_value[len] = '\0'; - m_attr_len = len; -} - -inline NimBLEAttValue::~NimBLEAttValue() { - if(m_attr_value != nullptr) { - free(m_attr_value); - } -} - -inline NimBLEAttValue& NimBLEAttValue::operator =(NimBLEAttValue && source) { - if (this != &source){ - free(m_attr_value); - - m_attr_value = source.m_attr_value; - m_attr_max_len = source.m_attr_max_len; - m_attr_len = source.m_attr_len; - m_capacity = source.m_capacity; - setTimeStamp(source.getTimeStamp()); - source.m_attr_value = nullptr; - } - return *this; -} - -inline NimBLEAttValue& NimBLEAttValue::operator =(const NimBLEAttValue & source) { - if (this != &source) { - deepCopy(source); - } - return *this; -} - -inline void NimBLEAttValue::deepCopy(const NimBLEAttValue & source) { - uint8_t* res = (uint8_t*)realloc( m_attr_value, source.m_capacity + 1); - NIMBLE_CPP_DEBUG_ASSERT(res); - - ble_npl_hw_enter_critical(); - m_attr_value = res; - m_attr_max_len = source.m_attr_max_len; - m_attr_len = source.m_attr_len; - m_capacity = source.m_capacity; - setTimeStamp(source.getTimeStamp()); - memcpy(m_attr_value, source.m_attr_value, m_attr_len + 1); - ble_npl_hw_exit_critical(0); -} - -inline const uint8_t* NimBLEAttValue::getValue(time_t *timestamp) { - if(timestamp != nullptr) { -#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED - *timestamp = m_timestamp; -#else - *timestamp = 0; -#endif - } - return m_attr_value; -} - -inline bool NimBLEAttValue::setValue(const uint8_t *value, uint16_t len) { - if (len > m_attr_max_len) { - NIMBLE_LOGE("NimBLEAttValue", "value exceeds max, len=%u, max=%u", - len, m_attr_max_len); - return false; - } - - uint8_t *res = m_attr_value; - if (len > m_capacity) { - res = (uint8_t*)realloc(m_attr_value, (len + 1)); - m_capacity = len; - } - NIMBLE_CPP_DEBUG_ASSERT(res); - -#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED - time_t t = time(nullptr); -#else - time_t t = 0; -#endif - - ble_npl_hw_enter_critical(); - m_attr_value = res; - memcpy(m_attr_value, value, len); - m_attr_value[len] = '\0'; - m_attr_len = len; - setTimeStamp(t); - ble_npl_hw_exit_critical(0); - return true; -} - -inline NimBLEAttValue& NimBLEAttValue::append(const uint8_t *value, uint16_t len) { - if (len < 1) { - return *this; - } - - if ((m_attr_len + len) > m_attr_max_len) { - NIMBLE_LOGE("NimBLEAttValue", "val > max, len=%u, max=%u", - len, m_attr_max_len); - return *this; - } - - uint8_t* res = m_attr_value; - uint16_t new_len = m_attr_len + len; - if (new_len > m_capacity) { - res = (uint8_t*)realloc(m_attr_value, (new_len + 1)); - m_capacity = new_len; - } - NIMBLE_CPP_DEBUG_ASSERT(res); - -#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED - time_t t = time(nullptr); -#else - time_t t = 0; -#endif - - ble_npl_hw_enter_critical(); - m_attr_value = res; - memcpy(m_attr_value + m_attr_len, value, len); - m_attr_len = new_len; - m_attr_value[m_attr_len] = '\0'; - setTimeStamp(t); - ble_npl_hw_exit_critical(0); - - return *this; -} - #endif /*(CONFIG_BT_ENABLED) */ -#endif /* MAIN_NIMBLEATTVALUE_H_ */ +#endif /* NIMBLE_CPP_ATTVALUE_H_ */