Skip to content

Commit 5031c55

Browse files
srggh2zero
authored andcommitted
fix: correct byte size calculation for ATT values set from containers
1 parent 0403ab3 commit 5031c55

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
@@ -63,6 +63,14 @@ template <typename T>
6363
struct Has_c_str_length<T, decltype(void(std::declval<T&>().c_str())), decltype(void(std::declval<T&>().length()))>
6464
: std::true_type {};
6565

66+
/* Used to determine if the type passed to a template has a value_type member (std::vector, std::array, std::string, etc.). */
67+
template <typename T, typename = void>
68+
struct Has_value_type : std::false_type {};
69+
70+
template <typename T>
71+
struct Has_value_type<T, decltype(void(sizeof(typename T::value_type)))>
72+
: std::true_type {};
73+
6674
/**
6775
* @brief A specialized container class to hold BLE attribute values.
6876
* @details This class is designed to be more memory efficient than using\n
@@ -264,13 +272,32 @@ class NimBLEAttValue {
264272
/**
265273
* @brief Template to set value to the value of <type\>val.
266274
* @param [in] v The <type\>value to set.
267-
* @details Only used if the <type\> has a `data()` and `size()` method.
275+
* @details Only used if the <type\> has a `data()` and `size()` method with `value_type`.
276+
* Correctly calculates byte size for containers with multi-byte element types.
277+
*/
278+
template <typename T>
279+
# ifdef _DOXYGEN_
280+
bool
281+
# else
282+
typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value, bool>::type
283+
# endif
284+
setValue(const T& v) {
285+
return setValue(
286+
reinterpret_cast<const uint8_t*>(v.data()),
287+
v.size() * sizeof(typename T::value_type)
288+
);
289+
}
290+
291+
/**
292+
* @brief Template to set value to the value of <type\>val.
293+
* @param [in] v The <type\>value to set.
294+
* @details Only used if the <type\> has a `data()` and `size()` method without `value_type`.
268295
*/
269296
template <typename T>
270297
# ifdef _DOXYGEN_
271298
bool
272299
# else
273-
typename std::enable_if<Has_data_size<T>::value, bool>::type
300+
typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value, bool>::type
274301
# endif
275302
setValue(const T& v) {
276303
return setValue(reinterpret_cast<const uint8_t*>(v.data()), v.size());
@@ -285,7 +312,11 @@ class NimBLEAttValue {
285312
template <typename T>
286313
typename std::enable_if<!std::is_pointer<T>::value, bool>::type setValue(const T& s) {
287314
if constexpr (Has_data_size<T>::value) {
288-
return setValue(reinterpret_cast<const uint8_t*>(s.data()), s.size());
315+
if constexpr (Has_value_type<T>::value) {
316+
return setValue(reinterpret_cast<const uint8_t*>(s.data()), s.size() * sizeof(typename T::value_type));
317+
} else {
318+
return setValue(reinterpret_cast<const uint8_t*>(s.data()), s.size());
319+
}
289320
} else if constexpr (Has_c_str_length<T>::value) {
290321
return setValue(reinterpret_cast<const uint8_t*>(s.c_str()), s.length());
291322
} else {

0 commit comments

Comments
 (0)