esp-nimble-cpp 2.3.3
Loading...
Searching...
No Matches
NimBLEAttValue.h
1/*
2 * Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
3 * esp-nimble-cpp, NimBLE-Arduino contributors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#ifndef NIMBLE_CPP_ATTVALUE_H
19#define NIMBLE_CPP_ATTVALUE_H
20
21#include "syscfg/syscfg.h"
22#if CONFIG_BT_NIMBLE_ENABLED
23
24# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
25# include <Arduino.h>
26# endif
27
28# include <string>
29# include <vector>
30# include <ctime>
31# include <cstring>
32# include <cstdint>
33
34# ifndef MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
35# ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
36# define MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
37# else
38# define MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
39# endif
40# endif
41
42# ifndef BLE_ATT_ATTR_MAX_LEN
43# define BLE_ATT_ATTR_MAX_LEN 512
44# endif
45
46# ifndef MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH
47# ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH
48# define MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
49# else
50# define MYNEWT_VAL_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH
51# endif
52# endif
53
54# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH) > BLE_ATT_ATTR_MAX_LEN
55# error NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be larger than 512 (BLE_ATT_ATTR_MAX_LEN)
56# elif MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH) < 1
57# error NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512
58# endif
59
60/* Used to determine if the type passed to a template has a data() and size() method. */
61template <typename T, typename = void, typename = void>
62struct Has_data_size : std::false_type {};
63
64template <typename T>
65struct Has_data_size<T, decltype(void(std::declval<T&>().data())), decltype(void(std::declval<T&>().size()))>
66 : std::true_type {};
67
68/* Used to determine if the type passed to a template has a c_str() and length() method. */
69template <typename T, typename = void, typename = void>
70struct Has_c_str_length : std::false_type {};
71
72template <typename T>
73struct Has_c_str_length<T, decltype(void(std::declval<T&>().c_str())), decltype(void(std::declval<T&>().length()))>
74 : std::true_type {};
75
76/* Used to determine if the type passed to a template has a value_type member (std::vector, std::array, std::string, etc.). */
77template <typename T, typename = void>
78struct Has_value_type : std::false_type {};
79
80template <typename T>
81struct Has_value_type<T, decltype(void(sizeof(typename T::value_type)))>
82 : std::true_type {};
83
91 uint8_t* m_attr_value{};
92 uint16_t m_attr_max_len{};
93 uint16_t m_attr_len{};
94 uint16_t m_capacity{};
95# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
96 time_t m_timestamp{};
97# endif
98 void deepCopy(const NimBLEAttValue& source);
99
100 public:
106 NimBLEAttValue(uint16_t init_len = MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH), uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
107
114 NimBLEAttValue(const uint8_t* value, uint16_t len, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
115
121 NimBLEAttValue(const char* value, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
122 : NimBLEAttValue((uint8_t*)value, (uint16_t)strlen(value), max_len) {}
123
129 NimBLEAttValue(std::initializer_list<uint8_t> list, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
130 : NimBLEAttValue(list.begin(), list.size(), max_len) {}
131
137 NimBLEAttValue(const std::string str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
138 : NimBLEAttValue(reinterpret_cast<const uint8_t*>(&str[0]), str.length(), max_len) {}
139
145 NimBLEAttValue(const std::vector<uint8_t> vec, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
146 : NimBLEAttValue(&vec[0], vec.size(), max_len) {}
147
148# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
154 NimBLEAttValue(const String str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
155 : NimBLEAttValue(reinterpret_cast<const uint8_t*>(str.c_str()), str.length(), max_len) {}
156# endif
157
159 NimBLEAttValue(const NimBLEAttValue& source) { deepCopy(source); }
160
162 NimBLEAttValue(NimBLEAttValue&& source) { *this = std::move(source); }
163
166
168 uint16_t max_size() const { return m_attr_max_len; }
169
171 uint16_t capacity() const { return m_capacity; }
172
174 uint16_t length() const { return m_attr_len; }
175
177 uint16_t size() const { return m_attr_len; }
178
180 const uint8_t* data() const { return m_attr_value; }
181
183 const char* c_str() const { return reinterpret_cast<const char*>(m_attr_value); }
184
186 const uint8_t* begin() const { return m_attr_value; }
187
189 const uint8_t* end() const { return m_attr_value + m_attr_len; }
190
191# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
193 time_t getTimeStamp() const { return m_timestamp; }
194
196 void setTimeStamp() { m_timestamp = time(nullptr); }
197
202 void setTimeStamp(time_t t) { m_timestamp = t; }
203# else
204 time_t getTimeStamp() const { return 0; }
205 void setTimeStamp() {}
206 void setTimeStamp(time_t t) {}
207# endif
208
215 bool setValue(const uint8_t* value, uint16_t len);
216
222 bool setValue(const char* s, uint16_t len = 0) {
223 if (len == 0) {
224 len = strlen(s);
225 }
226 return setValue(reinterpret_cast<const uint8_t*>(s), len);
227 }
228
229 const NimBLEAttValue& getValue(time_t* timestamp = nullptr) const {
230 if (timestamp != nullptr) {
231# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
232 *timestamp = m_timestamp;
233# else
234 *timestamp = 0;
235# endif
236 }
237 return *this;
238 }
239
246 NimBLEAttValue& append(const uint8_t* value, uint16_t len);
247
248 /*********************** Template Functions ************************/
249
250# if __cplusplus < 201703L
257 template <typename T>
258# ifdef _DOXYGEN_
259 bool
260# else
261 typename std::enable_if<!std::is_pointer<T>::value && !Has_c_str_length<T>::value && !Has_data_size<T>::value, bool>::type
262# endif
263 setValue(const T& v) {
264 return setValue(reinterpret_cast<const uint8_t*>(&v), sizeof(T));
265 }
266
272 template <typename T>
273# ifdef _DOXYGEN_
274 bool
275# else
276 typename std::enable_if<Has_c_str_length<T>::value && !Has_data_size<T>::value, bool>::type
277# endif
278 setValue(const T& s) {
279 return setValue(reinterpret_cast<const uint8_t*>(s.c_str()), s.length());
280 }
281
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
306 template <typename T>
307# ifdef _DOXYGEN_
308 bool
309# else
310 typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value, bool>::type
311# endif
312 setValue(const T& v) {
313 return setValue(reinterpret_cast<const uint8_t*>(v.data()), v.size());
314 }
315
316# else
322 template <typename T>
323 typename std::enable_if<!std::is_pointer<T>::value, bool>::type setValue(const T& s) {
324 if constexpr (Has_data_size<T>::value) {
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 }
330 } else if constexpr (Has_c_str_length<T>::value) {
331 return setValue(reinterpret_cast<const uint8_t*>(s.c_str()), s.length());
332 } else {
333 return setValue(reinterpret_cast<const uint8_t*>(&s), sizeof(s));
334 }
335 }
336# endif
337
348 template <typename T>
349 T getValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const {
350 if (timestamp != nullptr) {
351# if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED)
352 *timestamp = m_timestamp;
353# else
354 *timestamp = 0;
355# endif
356 }
357
358 if (!skipSizeCheck && size() < sizeof(T)) {
359 return T();
360 }
361 return *(reinterpret_cast<const T*>(m_attr_value));
362 }
363
364 /*********************** Operators ************************/
365
367 uint8_t operator[](int pos) const;
368
370 operator std::vector<uint8_t>() const { return std::vector<uint8_t>(m_attr_value, m_attr_value + m_attr_len); }
371
373 operator std::string() const { return std::string(reinterpret_cast<char*>(m_attr_value), m_attr_len); }
374
376 operator const uint8_t*() const { return m_attr_value; }
377
379 NimBLEAttValue& operator+=(const NimBLEAttValue& source) { return append(source.data(), source.size()); }
380
382 NimBLEAttValue& operator=(const std::string& source) {
383 setValue(reinterpret_cast<const uint8_t*>(&source[0]), source.size());
384 return *this;
385 }
386
389
392
394 bool operator==(const NimBLEAttValue& source) const {
395 return (m_attr_len == source.size()) ? memcmp(m_attr_value, source.data(), m_attr_len) == 0 : false;
396 }
397
399 bool operator!=(const NimBLEAttValue& source) const { return !(*this == source); }
400
401# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
403 operator String() const { return String(reinterpret_cast<char*>(m_attr_value)); }
404# endif
405};
406
407#endif // CONFIG_BT_NIMBLE_ENABLED
408#endif // NIMBLE_CPP_ATTVALUE_H_
A specialized container class to hold BLE attribute values.
Definition NimBLEAttValue.h:90
NimBLEAttValue(const std::vector< uint8_t > vec, uint16_t max_len=BLE_ATT_ATTR_MAX_LEN)
Construct with an initial value from a std::vector<uint8_t>.
Definition NimBLEAttValue.h:145
~NimBLEAttValue()
Destructor.
Definition NimBLEAttValue.cpp:58
uint16_t length() const
Returns the current length of the value in bytes.
Definition NimBLEAttValue.h:174
NimBLEAttValue(const char *value, uint16_t max_len=BLE_ATT_ATTR_MAX_LEN)
Construct with an initial value from a const char string.
Definition NimBLEAttValue.h:121
uint16_t capacity() const
Returns the currently allocated capacity in bytes.
Definition NimBLEAttValue.h:171
const char * c_str() const
Returns a pointer to the internal buffer of the value as a const char*.
Definition NimBLEAttValue.h:183
NimBLEAttValue(const std::string str, uint16_t max_len=BLE_ATT_ATTR_MAX_LEN)
Construct with an initial value from a std::string.
Definition NimBLEAttValue.h:137
bool setValue(const uint8_t *value, uint16_t len)
Set the value from a buffer.
Definition NimBLEAttValue.cpp:107
NimBLEAttValue(std::initializer_list< uint8_t > list, uint16_t max_len=BLE_ATT_ATTR_MAX_LEN)
Construct with an initializer list.
Definition NimBLEAttValue.h:129
NimBLEAttValue & operator+=(const NimBLEAttValue &source)
Operator; Append another NimBLEAttValue.
Definition NimBLEAttValue.h:379
NimBLEAttValue(const NimBLEAttValue &source)
Copy constructor.
Definition NimBLEAttValue.h:159
NimBLEAttValue(NimBLEAttValue &&source)
Move constructor.
Definition NimBLEAttValue.h:162
const uint8_t * data() const
Returns a pointer to the internal buffer of the value.
Definition NimBLEAttValue.h:180
uint8_t operator[](int pos) const
Subscript operator.
Definition NimBLEAttValue.cpp:154
const uint8_t * end() const
Iterator end.
Definition NimBLEAttValue.h:189
bool setValue(const T &v)
Template to set value to the value of <type>val.
Definition NimBLEAttValue.h:263
NimBLEAttValue & append(const uint8_t *value, uint16_t len)
Append data to the value.
Definition NimBLEAttValue.cpp:115
uint16_t size() const
Returns the current size of the value in bytes.
Definition NimBLEAttValue.h:177
bool setValue(const char *s, uint16_t len=0)
Set value to the value of const char*.
Definition NimBLEAttValue.h:222
T getValue(time_t *timestamp=nullptr, bool skipSizeCheck=false) const
Template to return the value as a <type>.
Definition NimBLEAttValue.h:349
uint16_t max_size() const
Returns the max size in bytes.
Definition NimBLEAttValue.h:168
bool setValue(const T &s)
Template to set value to the value of <type>val.
Definition NimBLEAttValue.h:278
bool operator==(const NimBLEAttValue &source) const
Equality operator.
Definition NimBLEAttValue.h:394
NimBLEAttValue & operator=(const std::string &source)
Operator; Set the value from a std::string source.
Definition NimBLEAttValue.h:382
const uint8_t * begin() const
Iterator begin.
Definition NimBLEAttValue.h:186
bool operator!=(const NimBLEAttValue &source) const
Inequality operator.
Definition NimBLEAttValue.h:399