diff --git a/src/NimBLEAttValue.h b/src/NimBLEAttValue.h index 0416781..aa8882a 100644 --- a/src/NimBLEAttValue.h +++ b/src/NimBLEAttValue.h @@ -84,16 +84,15 @@ class NimBLEAttValue { * @param[in] len The size in bytes of the value to set. * @param[in] max_len The max size in bytes that the value can be. */ - NimBLEAttValue(const uint8_t *value, uint16_t len, - uint16_t max_len = BLE_ATT_ATTR_MAX_LEN); + NimBLEAttValue(const uint8_t* value, uint16_t len, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN); /** * @brief Construct with an initial value from a const char string. * @param value A pointer to the initial value to set. * @param[in] max_len The max size in bytes that the value can be. */ - NimBLEAttValue(const char *value, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN) - :NimBLEAttValue((uint8_t*)value, (uint16_t)strlen(value), max_len){} + 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. @@ -221,14 +220,61 @@ class NimBLEAttValue { /*********************** Template Functions ************************/ +# if __cplusplus < 201703L + /** + * @brief Template to set value to the value of val. + * @param [in] v The value to set. + * @details Only used for types without a `c_str()` and `length()` or `data()` and `size()` method. + * size must be evaluatable by `sizeof()`. + */ + template +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value && !Has_c_str_length::value && !Has_data_size::value, bool>::type +# endif + setValue(const T& v) { + return setValue(reinterpret_cast(&v), sizeof(T)); + } + /** * @brief Template to set value to the value of val. * @param [in] s The value to set. - * @note This function is only availabe if the type T is not a pointer. + * @details Only used if the has a `c_str()` method. */ template - typename std::enable_if::value, bool>::type +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value && !Has_data_size::value, bool>::type +# endif setValue(const T& s) { + return setValue(reinterpret_cast(s.c_str()), s.length()); + } + + /** + * @brief Template to set value to the value of val. + * @param [in] v The value to set. + * @details Only used if the has a `data()` and `size()` method. + */ + template +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value, bool>::type +# endif + setValue(const T& v) { + return setValue(reinterpret_cast(v.data()), v.size()); + } + +# else + /** + * @brief Template to set value to the value of val. + * @param [in] s The value to set. + * @note This function is only available if the type T is not a pointer. + */ + template + typename std::enable_if::value, bool>::type setValue(const T& s) { if constexpr (Has_data_size::value) { return setValue(reinterpret_cast(s.data()), s.size()); } else if constexpr (Has_c_str_length::value) { @@ -237,6 +283,7 @@ class NimBLEAttValue { return setValue(reinterpret_cast(&s), sizeof(s)); } } +# endif /** * @brief Template to return the value as a . diff --git a/src/NimBLECharacteristic.h b/src/NimBLECharacteristic.h index 221d437..612a305 100644 --- a/src/NimBLECharacteristic.h +++ b/src/NimBLECharacteristic.h @@ -72,6 +72,101 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute { /*********************** Template Functions ************************/ +# if __cplusplus < 201703L + /** + * @brief Template to send a notification with a value from a struct or array. + * @param [in] v The value to send. + * @param [in] connHandle Optional, a connection handle to send the notification to. + * @details size must be evaluatable by `sizeof()`. + */ + template +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value && !Has_c_str_length::value && !Has_data_size::value, bool>::type +# endif + notify(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const { + return notify(reinterpret_cast(&v), sizeof(T), connHandle); + } + + /** + * @brief Template to send a notification with a value from a class that has a c_str() and length() method. + * @param [in] s The value to send. + * @param [in] connHandle Optional, a connection handle to send the notification to. + */ + template +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value && !Has_data_size::value, bool>::type +# endif + notify(const T& s, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const { + return notify(reinterpret_cast(s.c_str()), s.length(), connHandle); + } + + /** + * @brief Template to send a notification with a value from a class that has a data() and size() method. + * @param [in] v The value to send. + * @param [in] connHandle Optional, a connection handle to send the notification to. + */ + template +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value, bool>::type +# endif + notify(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const { + return notify(reinterpret_cast(v.data()), v.size(), connHandle); + } + + /** + * @brief Template to send an indication with a value from a struct or array. + * @param [in] v The value to send. + * @param [in] connHandle Optional, a connection handle to send the notification to. + * @details size must be evaluatable by `sizeof()`. + */ + template +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value && !Has_c_str_length::value && !Has_data_size::value, bool>::type +# endif + indicate(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const { + return indicate(reinterpret_cast(&v), sizeof(T), connHandle); + } + + /** + * @brief Template to send a indication with a value from a class that has a c_str() and length() method. + * @param [in] s The value to send. + * @param [in] connHandle Optional, a connection handle to send the notification to. + */ + template +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value && !Has_data_size::value, bool>::type +# endif + indicate(const T& s, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const { + return indicate(reinterpret_cast(s.c_str()), s.length(), connHandle); + } + + /** + * @brief Template to send a indication with a value from a class that has a data() and size() method. + * @param [in] v The value to send. + * @param [in] connHandle Optional, a connection handle to send the notification to. + */ + template +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value, bool>::type +# endif + indicate(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const { + return indicate(reinterpret_cast(v.data()), v.size(), connHandle); + } + +# else + /** * @brief Template to send a notification for classes which may have * data()/size() or c_str()/length() methods. Falls back to sending @@ -115,6 +210,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute { return indicate(reinterpret_cast(&value), sizeof(value), connHandle); } } +# endif private: friend class NimBLEServer; diff --git a/src/NimBLERemoteValueAttribute.h b/src/NimBLERemoteValueAttribute.h index 90e4c00..7849b2a 100644 --- a/src/NimBLERemoteValueAttribute.h +++ b/src/NimBLERemoteValueAttribute.h @@ -74,6 +74,57 @@ class NimBLERemoteValueAttribute : public NimBLEAttribute { return writeValue(reinterpret_cast(str), length ? length : strlen(str), response); } +# if __cplusplus < 201703L + /** + * @brief Template to set the remote characteristic value to val. + * @param [in] v The value to write. + * @param [in] response True == request write response. + * @details Only used for types without a `c_str()` and `length()` or `data()` and `size()` method. + * size must be evaluatable by `sizeof()` if no length is provided. + */ + template +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value && !Has_c_str_length::value && !Has_data_size::value, bool>::type +# endif + writeValue(const T& v, bool response = false) const { + return writeValue(reinterpret_cast(&v), sizeof(T), response); + } + + /** + * @brief Template to set the remote characteristic value to val. + * @param [in] s The value to write. + * @param [in] response True == request write response. + * @details Only used if the has a `c_str()` and `length()` method. + */ + template +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value && !Has_data_size::value, bool>::type +# endif + writeValue(const T& s, bool response = false) const { + return writeValue(reinterpret_cast(s.c_str()), s.length(), response); + } + + /** + * @brief Template to set the remote characteristic value to val. + * @param [in] v The value to write. + * @param [in] response True == request write response. + * @details Only used if the has a `data()` and `size()` method. + */ + template +# ifdef _DOXYGEN_ + bool +# else + typename std::enable_if::value, bool>::type +# endif + writeValue(const T& v, bool response = false) const { + return writeValue(reinterpret_cast(v.data()), v.size(), response); + } + +# else /** * @brief Template to set the remote characteristic value to val. * @param [in] s The value to write. @@ -81,8 +132,7 @@ class NimBLERemoteValueAttribute : public NimBLEAttribute { * @note This function is only available if the type T is not a pointer. */ template - typename std::enable_if::value, bool>::type - writeValue(const T& v, bool response = false) const { + typename std::enable_if::value, bool>::type writeValue(const T& v, bool response = false) const { if constexpr (Has_data_size::value) { return writeValue(reinterpret_cast(v.data()), v.size(), response); } else if constexpr (Has_c_str_length::value) { @@ -91,6 +141,7 @@ class NimBLERemoteValueAttribute : public NimBLEAttribute { return writeValue(reinterpret_cast(&v), sizeof(v), response); } } +# endif /** * @brief Template to convert the remote characteristic data to .