Skip to content

Commit 9d7c91e

Browse files
srggh2zero
authored andcommitted
correct container byte size calculation to writeValue, notify, and indicate
1 parent 41fd276 commit 9d7c91e

File tree

2 files changed

+82
-9
lines changed

2 files changed

+82
-9
lines changed

src/NimBLECharacteristic.h

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,35 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
112112
}
113113

114114
/**
115-
* @brief Template to send a notification with a value from a class that has a data() and size() method.
115+
* @brief Template to send a notification with a value from a class that has a data() and size() method with value_type.
116116
* @param [in] v The value to send.
117117
* @param [in] connHandle Optional, a connection handle to send the notification to.
118+
* @details Correctly calculates byte size for containers with multi-byte element types.
118119
*/
119120
template <typename T>
120121
# ifdef _DOXYGEN_
121122
bool
122123
# else
123-
typename std::enable_if<Has_data_size<T>::value, bool>::type
124+
typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value, bool>::type
125+
# endif
126+
notify(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
127+
return notify(
128+
reinterpret_cast<const uint8_t*>(v.data()),
129+
v.size() * sizeof(typename T::value_type),
130+
connHandle
131+
);
132+
}
133+
134+
/**
135+
* @brief Template to send a notification with a value from a class that has a data() and size() method without value_type.
136+
* @param [in] v The value to send.
137+
* @param [in] connHandle Optional, a connection handle to send the notification to.
138+
*/
139+
template <typename T>
140+
# ifdef _DOXYGEN_
141+
bool
142+
# else
143+
typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value, bool>::type
124144
# endif
125145
notify(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
126146
return notify(reinterpret_cast<const uint8_t*>(v.data()), v.size(), connHandle);
@@ -160,15 +180,35 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
160180
}
161181

162182
/**
163-
* @brief Template to send a indication with a value from a class that has a data() and size() method.
183+
* @brief Template to send a indication with a value from a class that has a data() and size() method with value_type.
184+
* @param [in] v The value to send.
185+
* @param [in] connHandle Optional, a connection handle to send the notification to.
186+
* @details Correctly calculates byte size for containers with multi-byte element types.
187+
*/
188+
template <typename T>
189+
# ifdef _DOXYGEN_
190+
bool
191+
# else
192+
typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value, bool>::type
193+
# endif
194+
indicate(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
195+
return indicate(
196+
reinterpret_cast<const uint8_t*>(v.data()),
197+
v.size() * sizeof(typename T::value_type),
198+
connHandle
199+
);
200+
}
201+
202+
/**
203+
* @brief Template to send a indication with a value from a class that has a data() and size() method without value_type.
164204
* @param [in] v The value to send.
165205
* @param [in] connHandle Optional, a connection handle to send the notification to.
166206
*/
167207
template <typename T>
168208
# ifdef _DOXYGEN_
169209
bool
170210
# else
171-
typename std::enable_if<Has_data_size<T>::value, bool>::type
211+
typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value, bool>::type
172212
# endif
173213
indicate(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
174214
return indicate(reinterpret_cast<const uint8_t*>(v.data()), v.size(), connHandle);
@@ -190,7 +230,11 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
190230
typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value, bool>::type notify(
191231
const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
192232
if constexpr (Has_data_size<T>::value) {
193-
return notify(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
233+
if constexpr (Has_value_type<T>::value) {
234+
return notify(reinterpret_cast<const uint8_t*>(value.data()), value.size() * sizeof(typename T::value_type), connHandle);
235+
} else {
236+
return notify(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
237+
}
194238
} else if constexpr (Has_c_str_length<T>::value) {
195239
return notify(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), connHandle);
196240
} else {
@@ -212,7 +256,11 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
212256
typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value, bool>::type indicate(
213257
const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
214258
if constexpr (Has_data_size<T>::value) {
215-
return indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
259+
if constexpr (Has_value_type<T>::value) {
260+
return indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size() * sizeof(typename T::value_type), connHandle);
261+
} else {
262+
return indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
263+
}
216264
} else if constexpr (Has_c_str_length<T>::value) {
217265
return indicate(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), connHandle);
218266
} else {

src/NimBLERemoteValueAttribute.h

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,34 @@ class NimBLERemoteValueAttribute : public NimBLEValueAttribute, public NimBLEAtt
109109
* @brief Template to set the remote characteristic value to <type\>val.
110110
* @param [in] v The value to write.
111111
* @param [in] response True == request write response.
112-
* @details Only used if the <type\> has a `data()` and `size()` method.
112+
* @details Only used if the <type\> has a `data()` and `size()` method with `value_type`.
113+
* Correctly calculates byte size for containers with multi-byte element types.
113114
*/
114115
template <typename T>
115116
# ifdef _DOXYGEN_
116117
bool
117118
# else
118-
typename std::enable_if<Has_data_size<T>::value, bool>::type
119+
typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value, bool>::type
120+
# endif
121+
writeValue(const T& v, bool response = false) const {
122+
return writeValue(
123+
reinterpret_cast<const uint8_t*>(v.data()),
124+
v.size() * sizeof(typename T::value_type),
125+
response
126+
);
127+
}
128+
129+
/**
130+
* @brief Template to set the remote characteristic value to <type\>val.
131+
* @param [in] v The value to write.
132+
* @param [in] response True == request write response.
133+
* @details Only used if the <type\> has a `data()` and `size()` method without `value_type`.
134+
*/
135+
template <typename T>
136+
# ifdef _DOXYGEN_
137+
bool
138+
# else
139+
typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value, bool>::type
119140
# endif
120141
writeValue(const T& v, bool response = false) const {
121142
return writeValue(reinterpret_cast<const uint8_t*>(v.data()), v.size(), response);
@@ -131,7 +152,11 @@ class NimBLERemoteValueAttribute : public NimBLEValueAttribute, public NimBLEAtt
131152
template <typename T>
132153
typename std::enable_if<!std::is_pointer<T>::value, bool>::type writeValue(const T& v, bool response = false) const {
133154
if constexpr (Has_data_size<T>::value) {
134-
return writeValue(reinterpret_cast<const uint8_t*>(v.data()), v.size(), response);
155+
if constexpr (Has_value_type<T>::value) {
156+
return writeValue(reinterpret_cast<const uint8_t*>(v.data()), v.size() * sizeof(typename T::value_type), response);
157+
} else {
158+
return writeValue(reinterpret_cast<const uint8_t*>(v.data()), v.size(), response);
159+
}
135160
} else if constexpr (Has_c_str_length<T>::value) {
136161
return writeValue(reinterpret_cast<const uint8_t*>(v.c_str()), v.length(), response);
137162
} else {

0 commit comments

Comments
 (0)