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