@@ -63,6 +63,14 @@ template <typename T>
6363struct 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