Skip to content

Commit 3c1aa03

Browse files
committed
fix: correct byte size calculation for ATT values set from containers
1 parent 5dad893 commit 3c1aa03

File tree

1 file changed

+34
-3
lines changed

1 file changed

+34
-3
lines changed

src/NimBLEAttValue.h

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ template <typename T>
7373
struct Has_c_str_length<T, decltype(void(std::declval<T&>().c_str())), decltype(void(std::declval<T&>().length()))>
7474
: std::true_type {};
7575

76+
/* Used to determine if the type passed to a template has a value_type member (std::vector, std::array, std::string, etc.). */
77+
template <typename T, typename = void>
78+
struct Has_value_type : std::false_type {};
79+
80+
template <typename T>
81+
struct Has_value_type<T, decltype(void(sizeof(typename T::value_type)))>
82+
: std::true_type {};
83+
7684
/**
7785
* @brief A specialized container class to hold BLE attribute values.
7886
* @details This class is designed to be more memory efficient than using\n
@@ -274,13 +282,32 @@ class NimBLEAttValue {
274282
/**
275283
* @brief Template to set value to the value of <type\>val.
276284
* @param [in] v The <type\>value to set.
277-
* @details Only used if the <type\> has a `data()` and `size()` method.
285+
* @details Only used if the <type\> has a `data()` and `size()` method with `value_type`.
286+
* Correctly calculates byte size for containers with multi-byte element types.
287+
*/
288+
template <typename T>
289+
# ifdef _DOXYGEN_
290+
bool
291+
# else
292+
typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value, bool>::type
293+
# endif
294+
setValue(const T& v) {
295+
return setValue(
296+
reinterpret_cast<const uint8_t*>(v.data()),
297+
v.size() * sizeof(typename T::value_type)
298+
);
299+
}
300+
301+
/**
302+
* @brief Template to set value to the value of <type\>val.
303+
* @param [in] v The <type\>value to set.
304+
* @details Only used if the <type\> has a `data()` and `size()` method without `value_type`.
278305
*/
279306
template <typename T>
280307
# ifdef _DOXYGEN_
281308
bool
282309
# else
283-
typename std::enable_if<Has_data_size<T>::value, bool>::type
310+
typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value, bool>::type
284311
# endif
285312
setValue(const T& v) {
286313
return setValue(reinterpret_cast<const uint8_t*>(v.data()), v.size());
@@ -295,7 +322,11 @@ class NimBLEAttValue {
295322
template <typename T>
296323
typename std::enable_if<!std::is_pointer<T>::value, bool>::type setValue(const T& s) {
297324
if constexpr (Has_data_size<T>::value) {
298-
return setValue(reinterpret_cast<const uint8_t*>(s.data()), s.size());
325+
if constexpr (Has_value_type<T>::value) {
326+
return setValue(reinterpret_cast<const uint8_t*>(s.data()), s.size() * sizeof(typename T::value_type));
327+
} else {
328+
return setValue(reinterpret_cast<const uint8_t*>(s.data()), s.size());
329+
}
299330
} else if constexpr (Has_c_str_length<T>::value) {
300331
return setValue(reinterpret_cast<const uint8_t*>(s.c_str()), s.length());
301332
} else {

0 commit comments

Comments
 (0)