NimBLE-Arduino 2.1.2
Loading...
Searching...
No Matches
NimBLEAttValue.h
1/*
2 * Copyright 2020-2024 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#include "nimconfig.h"
21#if defined(CONFIG_BT_ENABLED)
22
23# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
24# include <Arduino.h>
25# endif
26
27# include "NimBLELog.h"
28# include <string>
29# include <vector>
30# include <ctime>
31# include <cstring>
32# include <cstdint>
33
34# ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
35# define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
36# endif
37
38# ifndef BLE_ATT_ATTR_MAX_LEN
39# define BLE_ATT_ATTR_MAX_LEN 512
40# endif
41
42# if !defined(CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH)
43# define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
44# elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH > BLE_ATT_ATTR_MAX_LEN
45# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be larger than 512 (BLE_ATT_ATTR_MAX_LEN)
46# elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH < 1
47# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512
48# endif
49
50/* Used to determine if the type passed to a template has a data() and size() method. */
51template <typename T, typename = void, typename = void>
52struct Has_data_size : std::false_type {};
53
54template <typename T>
55struct Has_data_size<T, decltype(void(std::declval<T&>().data())), decltype(void(std::declval<T&>().size()))>
56 : std::true_type {};
57
58/* Used to determine if the type passed to a template has a c_str() and length() method. */
59template <typename T, typename = void, typename = void>
60struct Has_c_str_length : std::false_type {};
61
62template <typename T>
63struct Has_c_str_length<T, decltype(void(std::declval<T&>().c_str())), decltype(void(std::declval<T&>().length()))>
64 : std::true_type {};
65
73 uint8_t* m_attr_value{};
74 uint16_t m_attr_max_len{};
75 uint16_t m_attr_len{};
76 uint16_t m_capacity{};
77# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
78 time_t m_timestamp{};
79# endif
80 void deepCopy(const NimBLEAttValue& source);
81
82 public:
88 NimBLEAttValue(uint16_t init_len = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
89
96 NimBLEAttValue(const uint8_t* value, uint16_t len, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
97
103 NimBLEAttValue(const char* value, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
104 : NimBLEAttValue((uint8_t*)value, (uint16_t)strlen(value), max_len) {}
105
111 NimBLEAttValue(std::initializer_list<uint8_t> list, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
112 : NimBLEAttValue(list.begin(), list.size(), max_len) {}
113
119 NimBLEAttValue(const std::string str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
120 : NimBLEAttValue(reinterpret_cast<const uint8_t*>(&str[0]), str.length(), max_len) {}
121
127 NimBLEAttValue(const std::vector<uint8_t> vec, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
128 : NimBLEAttValue(&vec[0], vec.size(), max_len) {}
129
130# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
136 NimBLEAttValue(const String str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
137 : NimBLEAttValue(reinterpret_cast<const uint8_t*>(str.c_str()), str.length(), max_len) {}
138# endif
139
141 NimBLEAttValue(const NimBLEAttValue& source) { deepCopy(source); }
142
144 NimBLEAttValue(NimBLEAttValue&& source) { *this = std::move(source); }
145
148
150 uint16_t max_size() const { return m_attr_max_len; }
151
153 uint16_t capacity() const { return m_capacity; }
154
156 uint16_t length() const { return m_attr_len; }
157
159 uint16_t size() const { return m_attr_len; }
160
162 const uint8_t* data() const { return m_attr_value; }
163
165 const char* c_str() const { return reinterpret_cast<const char*>(m_attr_value); }
166
168 const uint8_t* begin() const { return m_attr_value; }
169
171 const uint8_t* end() const { return m_attr_value + m_attr_len; }
172
173# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
175 time_t getTimeStamp() const { return m_timestamp; }
176
178 void setTimeStamp() { m_timestamp = time(nullptr); }
179
184 void setTimeStamp(time_t t) { m_timestamp = t; }
185# else
186 time_t getTimeStamp() const { return 0; }
187 void setTimeStamp() {}
188 void setTimeStamp(time_t t) {}
189# endif
190
197 bool setValue(const uint8_t* value, uint16_t len);
198
204 bool setValue(const char* s, uint16_t len = 0) {
205 if (len == 0) {
206 len = strlen(s);
207 }
208 return setValue(reinterpret_cast<const uint8_t*>(s), len);
209 }
210
211 const NimBLEAttValue& getValue(time_t* timestamp = nullptr) const {
212 if (timestamp != nullptr) {
213# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
214 *timestamp = m_timestamp;
215# else
216 *timestamp = 0;
217# endif
218 }
219 return *this;
220 }
221
228 NimBLEAttValue& append(const uint8_t* value, uint16_t len);
229
230 /*********************** Template Functions ************************/
231
232# if __cplusplus < 201703L
239 template <typename T>
240# ifdef _DOXYGEN_
241 bool
242# else
243 typename std::enable_if<!std::is_pointer<T>::value && !Has_c_str_length<T>::value && !Has_data_size<T>::value, bool>::type
244# endif
245 setValue(const T& v) {
246 return setValue(reinterpret_cast<const uint8_t*>(&v), sizeof(T));
247 }
248
254 template <typename T>
255# ifdef _DOXYGEN_
256 bool
257# else
258 typename std::enable_if<Has_c_str_length<T>::value && !Has_data_size<T>::value, bool>::type
259# endif
260 setValue(const T& s) {
261 return setValue(reinterpret_cast<const uint8_t*>(s.c_str()), s.length());
262 }
263
269 template <typename T>
270# ifdef _DOXYGEN_
271 bool
272# else
273 typename std::enable_if<Has_data_size<T>::value, bool>::type
274# endif
275 setValue(const T& v) {
276 return setValue(reinterpret_cast<const uint8_t*>(v.data()), v.size());
277 }
278
279# else
285 template <typename T>
286 typename std::enable_if<!std::is_pointer<T>::value, bool>::type setValue(const T& s) {
287 if constexpr (Has_data_size<T>::value) {
288 return setValue(reinterpret_cast<const uint8_t*>(s.data()), s.size());
289 } else if constexpr (Has_c_str_length<T>::value) {
290 return setValue(reinterpret_cast<const uint8_t*>(s.c_str()), s.length());
291 } else {
292 return setValue(reinterpret_cast<const uint8_t*>(&s), sizeof(s));
293 }
294 }
295# endif
296
307 template <typename T>
308 T getValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const {
309 if (!skipSizeCheck && size() < sizeof(T)) {
310 return T();
311 }
312 if (timestamp != nullptr) {
313# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
314 *timestamp = m_timestamp;
315# else
316 *timestamp = 0;
317# endif
318 }
319
320 return *(reinterpret_cast<const T*>(m_attr_value));
321 }
322
323 /*********************** Operators ************************/
324
326 uint8_t operator[](int pos) const {
327 NIMBLE_CPP_DEBUG_ASSERT(pos < m_attr_len);
328 return m_attr_value[pos];
329 }
330
332 operator std::vector<uint8_t>() const { return std::vector<uint8_t>(m_attr_value, m_attr_value + m_attr_len); }
333
335 operator std::string() const { return std::string(reinterpret_cast<char*>(m_attr_value), m_attr_len); }
336
338 operator const uint8_t*() const { return m_attr_value; }
339
341 NimBLEAttValue& operator+=(const NimBLEAttValue& source) { return append(source.data(), source.size()); }
342
344 NimBLEAttValue& operator=(const std::string& source) {
345 setValue(reinterpret_cast<const uint8_t*>(&source[0]), source.size());
346 return *this;
347 }
348
351
354
356 bool operator==(const NimBLEAttValue& source) const {
357 return (m_attr_len == source.size()) ? memcmp(m_attr_value, source.data(), m_attr_len) == 0 : false;
358 }
359
361 bool operator!=(const NimBLEAttValue& source) const { return !(*this == source); }
362
363# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
365 operator String() const { return String(reinterpret_cast<char*>(m_attr_value)); }
366# endif
367};
368
369#endif /*(CONFIG_BT_ENABLED) */
370#endif /* NIMBLE_CPP_ATTVALUE_H_ */
A specialized container class to hold BLE attribute values.
Definition NimBLEAttValue.h:72
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:127
~NimBLEAttValue()
Destructor.
Definition NimBLEAttValue.cpp:51
uint16_t length() const
Returns the current length of the value in bytes.
Definition NimBLEAttValue.h:156
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:103
uint16_t capacity() const
Returns the currently allocated capacity in bytes.
Definition NimBLEAttValue.h:153
const char * c_str() const
Returns a pointer to the internal buffer of the value as a const char*.
Definition NimBLEAttValue.h:165
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:119
bool setValue(const uint8_t *value, uint16_t len)
Set the value from a buffer.
Definition NimBLEAttValue.cpp:96
NimBLEAttValue(std::initializer_list< uint8_t > list, uint16_t max_len=BLE_ATT_ATTR_MAX_LEN)
Construct with an initializer list.
Definition NimBLEAttValue.h:111
NimBLEAttValue & operator+=(const NimBLEAttValue &source)
Operator; Append another NimBLEAttValue.
Definition NimBLEAttValue.h:341
NimBLEAttValue(const NimBLEAttValue &source)
Copy constructor.
Definition NimBLEAttValue.h:141
NimBLEAttValue(NimBLEAttValue &&source)
Move constructor.
Definition NimBLEAttValue.h:144
const uint8_t * data() const
Returns a pointer to the internal buffer of the value.
Definition NimBLEAttValue.h:162
uint8_t operator[](int pos) const
Subscript operator.
Definition NimBLEAttValue.h:326
const uint8_t * end() const
Iterator end.
Definition NimBLEAttValue.h:171
bool setValue(const T &v)
Template to set value to the value of <type>val.
Definition NimBLEAttValue.h:245
NimBLEAttValue & append(const uint8_t *value, uint16_t len)
Append data to the value.
Definition NimBLEAttValue.cpp:103
uint16_t size() const
Returns the current size of the value in bytes.
Definition NimBLEAttValue.h:159
bool setValue(const char *s, uint16_t len=0)
Set value to the value of const char*.
Definition NimBLEAttValue.h:204
T getValue(time_t *timestamp=nullptr, bool skipSizeCheck=false) const
Template to return the value as a <type>.
Definition NimBLEAttValue.h:308
uint16_t max_size() const
Returns the max size in bytes.
Definition NimBLEAttValue.h:150
bool setValue(const T &s)
Template to set value to the value of <type>val.
Definition NimBLEAttValue.h:260
bool operator==(const NimBLEAttValue &source) const
Equality operator.
Definition NimBLEAttValue.h:356
NimBLEAttValue & operator=(const std::string &source)
Operator; Set the value from a std::string source.
Definition NimBLEAttValue.h:344
const uint8_t * begin() const
Iterator begin.
Definition NimBLEAttValue.h:168
bool operator!=(const NimBLEAttValue &source) const
Inequality operator.
Definition NimBLEAttValue.h:361