Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2023 Project CHIP Authors
4 : * Copyright (c) 2013-2017 Nest Labs, Inc.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : /**
20 : * @file
21 : * This file contains definitions for working with data encoded in CHIP TLV format.
22 : *
23 : * CHIP TLV (Tag-Length-Value) is a generalized encoding method for simple structured data. It
24 : * shares many properties with the commonly used JSON serialization format while being considerably
25 : * more compact over the wire.
26 : */
27 :
28 : #pragma once
29 :
30 : #include <cstdio>
31 : #include <stdint.h>
32 : #include <type_traits>
33 : #include <utility>
34 :
35 : #include <lib/core/CHIPError.h>
36 : #include <lib/core/TLVReader.h>
37 : #include <lib/core/TLVTags.h>
38 : #include <lib/core/TLVTypes.h>
39 : #include <lib/support/BitFlags.h>
40 : #include <lib/support/BitMask.h>
41 : #include <lib/support/CodeUtils.h>
42 : #include <lib/support/DLLUtil.h>
43 : #include <lib/support/EnforceFormat.h>
44 : #include <lib/support/ScopedBuffer.h>
45 : #include <lib/support/Span.h>
46 : #include <lib/support/TypeTraits.h>
47 : #include <system/SystemConfig.h>
48 :
49 : /**
50 : * @namespace chip::TLV
51 : *
52 : * Definitions for working with data encoded in CHIP TLV format.
53 : *
54 : * CHIP TLV is a generalized encoding method for simple structured data. It shares many properties
55 : * with the commonly used JSON serialization format while being considerably more compact over the wire.
56 : */
57 :
58 : namespace chip {
59 : namespace TLV {
60 :
61 : /**
62 : * Provides a memory efficient encoder for writing data in CHIP TLV format.
63 : *
64 : * TLVWriter implements a forward-only, stream-style encoder for CHIP TLV data. Applications
65 : * write data to an encoding by calling one of the writer's Put() methods, passing associated
66 : * tag and value information as necessary. Similarly applications can encode TLV container types
67 : * (structures, arrays or paths) by calling the writer's OpenContainer() or EnterContainer()
68 : * methods.
69 : *
70 : * A TLVWriter object can write data directly to a fixed output buffer, or to memory provided by
71 : * a TLVBackingStore.
72 : */
73 : class DLL_EXPORT TLVWriter
74 : {
75 : friend class TLVUpdater;
76 :
77 : public:
78 : TLVWriter();
79 :
80 : // TODO(#30825): We do not cleanly handle copies for all backing stores, but we don't disallow copy...
81 : #if 0
82 : // Disable copy (and move) semantics.
83 : TLVWriter(const TLVWriter&) = delete;
84 : TLVWriter& operator=(const TLVWriter&) = delete;
85 : #endif
86 :
87 : // Initialization cookie that is set when properly initialized. Randomly-picked 16 bit value.
88 : static constexpr uint16_t kExpectedInitializationCookie = 0x52b1;
89 :
90 : /**
91 : * Initializes a TLVWriter object to write into a single output buffer.
92 : *
93 : * @note Applications must call Finalize() on the writer before using the contents of the output
94 : * buffer.
95 : *
96 : * @param[in] buf A pointer to the buffer into which TLV should be written.
97 : * @param[in] maxLen The maximum number of bytes that should be written to the output buffer.
98 : *
99 : */
100 : void Init(uint8_t * buf, size_t maxLen);
101 :
102 : /**
103 : * Initializes a TLVWriter object to write into a single output buffer
104 : * represented by a MutableSpan. See documentation for the two-arg Init()
105 : * form for details.
106 : *
107 : */
108 880 : void Init(const MutableByteSpan & data) { Init(data.data(), data.size()); }
109 :
110 : /**
111 : * Initializes a TLVWriter object to write into a single output buffer
112 : * represented by a fixed-size byte array. See documentation for the
113 : * two-arg Init() form for details.
114 : *
115 : */
116 : template <size_t N>
117 3086 : void Init(uint8_t (&data)[N])
118 : {
119 3086 : Init(data, N);
120 3086 : }
121 :
122 : /**
123 : * Initializes a TLVWriter object to write into memory provided by a TLVBackingStore.
124 : *
125 : * @note Applications must call Finalize() on the writer before using the contents of the buffer.
126 : *
127 : * @param[in] backingStore A TLVBackingStore providing memory, which must outlive the TVLWriter.
128 : * @param[in] maxLen The maximum number of bytes that should be written to the output buffer.
129 : *
130 : * @retval #CHIP_NO_ERROR If the method succeeded.
131 : * @retval other Other error codes returned by TLVBackingStore::OnInit().
132 : */
133 : CHIP_ERROR Init(TLVBackingStore & backingStore, uint32_t maxLen = UINT32_MAX);
134 :
135 : /**
136 : * Finish the writing of a TLV encoding.
137 : *
138 : * The Finalize() method completes the process of writing a TLV encoding to the underlying output
139 : * buffer. The method must be called by the application before it uses the contents of the buffer.
140 : * Finalize() can only be called when there are no container writers open for the current writer.
141 : * (See @p OpenContainer()).
142 : *
143 : * @retval #CHIP_NO_ERROR If the encoding was finalized successfully.
144 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
145 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
146 : * If a container writer has been opened on the current writer and not
147 : * yet closed.
148 : * @retval other Other CHIP or platform-specific errors returned by the configured
149 : * FinalizeBuffer() function.
150 : */
151 : CHIP_ERROR Finalize();
152 :
153 : /**
154 : * Reserve some buffer for encoding future fields.
155 : *
156 : * @retval #CHIP_NO_ERROR Successfully reserved required buffer size.
157 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
158 : * @retval #CHIP_ERROR_NO_MEMORY The reserved buffer size cannot fits into the remaining buffer size.
159 : * @retval #CHIP_ERROR_INCORRECT_STATE
160 : * Uses TLVBackingStore and is in a state where it might allocate
161 : * additional non-contigious memory, thus making it difficult/impossible
162 : * to properly reserve space.
163 : */
164 : CHIP_ERROR ReserveBuffer(uint32_t aBufferSize);
165 :
166 : /**
167 : * Release previously reserved buffer.
168 : *
169 : * @retval #CHIP_NO_ERROR Successfully released reserved buffer size.
170 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
171 : * @retval #CHIP_ERROR_NO_MEMORY The released buffer is larger than previously reserved buffer size.
172 : */
173 10418 : CHIP_ERROR UnreserveBuffer(uint32_t aBufferSize)
174 : {
175 10418 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
176 10418 : VerifyOrReturnError(mReservedSize >= aBufferSize, CHIP_ERROR_NO_MEMORY);
177 10418 : mReservedSize -= aBufferSize;
178 10418 : mRemainingLen += aBufferSize;
179 10418 : return CHIP_NO_ERROR;
180 : }
181 :
182 : /**
183 : * Encodes a TLV signed integer value.
184 : *
185 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
186 : * value should be encoded without a tag. Tag values should be
187 : * constructed with one of the tag definition functions ProfileTag(),
188 : * ContextTag() or CommonTag().
189 : * @param[in] v The value to be encoded.
190 : *
191 : * @retval #CHIP_NO_ERROR If the method succeeded.
192 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
193 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
194 : * If a container writer has been opened on the current writer and not
195 : * yet closed.
196 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
197 : * If the specified tag value is invalid or inappropriate in the context
198 : * in which the value is being written.
199 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
200 : * If writing the value would exceed the limit on the maximum number of
201 : * bytes specified when the writer was initialized.
202 : * @retval #CHIP_ERROR_NO_MEMORY
203 : * If an attempt to allocate an output buffer failed due to lack of
204 : * memory.
205 : * @retval other Other CHIP or platform-specific errors returned by the configured
206 : * TLVBackingStore.
207 : *
208 : */
209 : CHIP_ERROR Put(Tag tag, int8_t v);
210 :
211 : /**
212 : * Encodes a TLV signed integer value.
213 : *
214 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
215 : * value should be encoded without a tag. Tag values should be
216 : * constructed with one of the tag definition functions ProfileTag(),
217 : * ContextTag() or CommonTag().
218 : * @param[in] v The value to be encoded.
219 : * @param[in] preserveSize True if the value should be encoded in the same number of bytes as
220 : * at the input type. False if value should be encoded in the minimum
221 : * number of bytes necessary to represent the value. Note: Applications
222 : * are strongly encouraged to set this parameter to false.
223 : *
224 : * @retval #CHIP_NO_ERROR If the method succeeded.
225 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
226 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
227 : * If a container writer has been opened on the current writer and not
228 : * yet closed.
229 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
230 : * If the specified tag value is invalid or inappropriate in the context
231 : * in which the value is being written.
232 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
233 : * If writing the value would exceed the limit on the maximum number of
234 : * bytes specified when the writer was initialized.
235 : * @retval #CHIP_ERROR_NO_MEMORY
236 : * If an attempt to allocate an output buffer failed due to lack of
237 : * memory.
238 : * @retval other Other CHIP or platform-specific errors returned by the configured
239 : * TLVBackingStore.
240 : *
241 : */
242 : CHIP_ERROR Put(Tag tag, int8_t v, bool preserveSize);
243 :
244 : /**
245 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, int8_t v)
246 : */
247 : CHIP_ERROR Put(Tag tag, int16_t v);
248 :
249 : /**
250 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, int8_t v, bool preserveSize)
251 : */
252 : CHIP_ERROR Put(Tag tag, int16_t v, bool preserveSize);
253 :
254 : /**
255 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, int8_t v)
256 : */
257 : CHIP_ERROR Put(Tag tag, int32_t v);
258 :
259 : /**
260 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, int8_t v, bool preserveSize)
261 : */
262 : CHIP_ERROR Put(Tag tag, int32_t v, bool preserveSize);
263 :
264 : /**
265 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, int8_t v)
266 : */
267 : CHIP_ERROR Put(Tag tag, int64_t v);
268 :
269 : /**
270 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, int8_t v, bool preserveSize)
271 : */
272 : CHIP_ERROR Put(Tag tag, int64_t v, bool preserveSize);
273 :
274 : /**
275 : * Encodes a TLV unsigned integer value.
276 : *
277 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
278 : * value should be encoded without a tag. Tag values should be
279 : * constructed with one of the tag definition functions ProfileTag(),
280 : * ContextTag() or CommonTag().
281 : * @param[in] v The value to be encoded.
282 : *
283 : * @retval #CHIP_NO_ERROR If the method succeeded.
284 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
285 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
286 : * If a container writer has been opened on the current writer and not
287 : * yet closed.
288 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
289 : * If the specified tag value is invalid or inappropriate in the context
290 : * in which the value is being written.
291 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
292 : * If writing the value would exceed the limit on the maximum number of
293 : * bytes specified when the writer was initialized.
294 : * @retval #CHIP_ERROR_NO_MEMORY
295 : * If an attempt to allocate an output buffer failed due to lack of
296 : * memory.
297 : * @retval other Other CHIP or platform-specific errors returned by the configured
298 : * TLVBackingStore.
299 : *
300 : */
301 : CHIP_ERROR Put(Tag tag, uint8_t v);
302 :
303 : /**
304 : * Encodes a TLV unsigned integer value.
305 : *
306 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
307 : * value should be encoded without a tag. Tag values should be
308 : * constructed with one of the tag definition functions ProfileTag(),
309 : * ContextTag() or CommonTag().
310 : * @param[in] v The value to be encoded.
311 : * @param[in] preserveSize True if the value should be encoded in the same number of bytes as
312 : * at the input type. False if value should be encoded in the minimum
313 : * number of bytes necessary to represent the value. Note: Applications
314 : * are strongly encouraged to set this parameter to false.
315 : *
316 : * @retval #CHIP_NO_ERROR If the method succeeded.
317 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
318 : * If a container writer has been opened on the current writer and not
319 : * yet closed.
320 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
321 : * If the specified tag value is invalid or inappropriate in the context
322 : * in which the value is being written.
323 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
324 : * If writing the value would exceed the limit on the maximum number of
325 : * bytes specified when the writer was initialized.
326 : * @retval #CHIP_ERROR_NO_MEMORY
327 : * If an attempt to allocate an output buffer failed due to lack of
328 : * memory.
329 : * @retval other Other CHIP or platform-specific errors returned by the configured
330 : * TLVBackingStore.
331 : *
332 : */
333 : CHIP_ERROR Put(Tag tag, uint8_t v, bool preserveSize);
334 :
335 : /**
336 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, uint8_t v)
337 : */
338 : CHIP_ERROR Put(Tag tag, uint16_t v);
339 :
340 : /**
341 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, uint8_t v, bool preserveSize)
342 : */
343 : CHIP_ERROR Put(Tag tag, uint16_t v, bool preserveSize);
344 :
345 : /**
346 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, uint8_t v)
347 : */
348 : CHIP_ERROR Put(Tag tag, uint32_t v);
349 :
350 : /**
351 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, uint8_t v, bool preserveSize)
352 : */
353 : CHIP_ERROR Put(Tag tag, uint32_t v, bool preserveSize);
354 :
355 : /**
356 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, uint8_t v)
357 : */
358 : CHIP_ERROR Put(Tag tag, uint64_t v);
359 :
360 : /**
361 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, uint8_t v, bool preserveSize)
362 : */
363 : CHIP_ERROR Put(Tag tag, uint64_t v, bool preserveSize);
364 :
365 : /**
366 : * Encodes a TLV floating point value.
367 : *
368 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
369 : * value should be encoded without a tag. Tag values should be
370 : * constructed with one of the tag definition functions ProfileTag(),
371 : * ContextTag() or CommonTag().
372 : * @param[in] v The value to be encoded.
373 : *
374 : * @retval #CHIP_NO_ERROR If the method succeeded.
375 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
376 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
377 : * If a container writer has been opened on the current writer and not
378 : * yet closed.
379 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
380 : * If the specified tag value is invalid or inappropriate in the context
381 : * in which the value is being written.
382 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
383 : * If writing the value would exceed the limit on the maximum number of
384 : * bytes specified when the writer was initialized.
385 : * @retval #CHIP_ERROR_NO_MEMORY
386 : * If an attempt to allocate an output buffer failed due to lack of
387 : * memory.
388 : * @retval other Other CHIP or platform-specific errors returned by the configured
389 : * TLVBackingStore.
390 : *
391 : */
392 : CHIP_ERROR Put(Tag tag, double v);
393 :
394 : /**
395 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, double v)
396 : */
397 : CHIP_ERROR Put(Tag tag, float v);
398 :
399 : /**
400 : * Encodes a TLV byte string value using ByteSpan class.
401 : *
402 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
403 : * value should be encoded without a tag. Tag values should be
404 : * constructed with one of the tag definition functions ProfileTag(),
405 : * ContextTag() or CommonTag().
406 : * @param[in] data A ByteSpan object containing the bytes string to be encoded.
407 : *
408 : * @retval #CHIP_NO_ERROR If the method succeeded.
409 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
410 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
411 : * If a container writer has been opened on the current writer and not
412 : * yet closed.
413 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
414 : * If the specified tag value is invalid or inappropriate in the context
415 : * in which the value is being written.
416 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
417 : * If writing the value would exceed the limit on the maximum number of
418 : * bytes specified when the writer was initialized.
419 : * @retval #CHIP_ERROR_NO_MEMORY
420 : * If an attempt to allocate an output buffer failed due to lack of
421 : * memory.
422 : * @retval other Other CHIP or platform-specific errors returned by the configured
423 : * TLVBackingStore.
424 : *
425 : */
426 : CHIP_ERROR Put(Tag tag, ByteSpan data);
427 :
428 : /**
429 : * static_cast to enumerations' underlying type when data is an enumeration.
430 : */
431 : template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
432 4278 : CHIP_ERROR Put(Tag tag, T data)
433 : {
434 4278 : return Put(tag, to_underlying(data));
435 : }
436 :
437 : /**
438 : *
439 : * Encodes an unsigned integer with bits corresponding to the flags set when data is a BitFlags
440 : */
441 : template <typename T>
442 : CHIP_ERROR Put(Tag tag, BitFlags<T> data)
443 : {
444 : return Put(tag, data.Raw());
445 : }
446 :
447 : /**
448 : *
449 : * Encodes an unsigned integer with bits corresponding to the flags set when data is a BitMask
450 : */
451 : template <typename T>
452 : CHIP_ERROR Put(Tag tag, BitMask<T> data)
453 : {
454 : return Put(tag, data.Raw());
455 : }
456 :
457 : /**
458 : * Encodes a TLV boolean value.
459 : *
460 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
461 : * value should be encoded without a tag. Tag values should be
462 : * constructed with one of the tag definition functions ProfileTag(),
463 : * ContextTag() or CommonTag().
464 : * @param[in] v The value to be encoded.
465 : *
466 : * @retval #CHIP_NO_ERROR If the method succeeded.
467 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
468 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
469 : * If a container writer has been opened on the current writer and not
470 : * yet closed.
471 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
472 : * If the specified tag value is invalid or inappropriate in the context
473 : * in which the value is being written.
474 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
475 : * If writing the value would exceed the limit on the maximum number of
476 : * bytes specified when the writer was initialized.
477 : * @retval #CHIP_ERROR_NO_MEMORY
478 : * If an attempt to allocate an output buffer failed due to lack of
479 : * memory.
480 : * @retval other Other CHIP or platform-specific errors returned by the configured
481 : * TLVBackingStore.
482 : *
483 : */
484 : CHIP_ERROR PutBoolean(Tag tag, bool v);
485 :
486 : /**
487 : * @overload CHIP_ERROR TLVWriter::Put(Tag tag, bool v)
488 : */
489 311 : CHIP_ERROR Put(Tag tag, bool v)
490 : {
491 : /*
492 : * In TLV, boolean values are encoded as standalone tags without actual values, so we have a separate
493 : * PutBoolean method.
494 : */
495 311 : return PutBoolean(tag, v);
496 : }
497 :
498 : /**
499 : * Encodes a TLV byte string value.
500 : *
501 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
502 : * value should be encoded without a tag. Tag values should be
503 : * constructed with one of the tag definition functions ProfileTag(),
504 : * ContextTag() or CommonTag().
505 : * @param[in] buf A pointer to a buffer containing the bytes string to be encoded.
506 : * @param[in] len The number of bytes to be encoded.
507 : *
508 : * @retval #CHIP_NO_ERROR If the method succeeded.
509 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
510 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
511 : * If a container writer has been opened on the current writer and not
512 : * yet closed.
513 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
514 : * If the specified tag value is invalid or inappropriate in the context
515 : * in which the value is being written.
516 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
517 : * If writing the value would exceed the limit on the maximum number of
518 : * bytes specified when the writer was initialized.
519 : * @retval #CHIP_ERROR_NO_MEMORY
520 : * If an attempt to allocate an output buffer failed due to lack of
521 : * memory.
522 : * @retval other Other CHIP or platform-specific errors returned by the configured
523 : * TLVBackingStore.
524 : *
525 : */
526 : CHIP_ERROR PutBytes(Tag tag, const uint8_t * buf, uint32_t len);
527 :
528 : /**
529 : * Encodes a TLV UTF8 string value.
530 : *
531 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
532 : * value should be encoded without a tag. Tag values should be
533 : * constructed with one of the tag definition functions ProfileTag(),
534 : * ContextTag() or CommonTag().
535 : * @param[in] buf A pointer to the null-terminated UTF-8 string to be encoded.
536 : *
537 : * @retval #CHIP_NO_ERROR If the method succeeded.
538 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
539 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
540 : * If a container writer has been opened on the current writer and not
541 : * yet closed.
542 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
543 : * If the specified tag value is invalid or inappropriate in the context
544 : * in which the value is being written.
545 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
546 : * If writing the value would exceed the limit on the maximum number of
547 : * bytes specified when the writer was initialized.
548 : * @retval #CHIP_ERROR_NO_MEMORY
549 : * If an attempt to allocate an output buffer failed due to lack of
550 : * memory.
551 : * @retval other Other CHIP or platform-specific errors returned by the configured
552 : * TLVBackingStore.
553 : *
554 : */
555 : CHIP_ERROR PutString(Tag tag, const char * buf);
556 :
557 : /**
558 : * Encodes a TLV UTF8 string value.
559 : *
560 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
561 : * value should be encoded without a tag. Tag values should be
562 : * constructed with one of the tag definition functions ProfileTag(),
563 : * ContextTag() or CommonTag().
564 : * @param[in] buf A pointer to the UTF-8 string to be encoded.
565 : * @param[in] len The length (in bytes) of the string to be encoded.
566 : *
567 : * @retval #CHIP_NO_ERROR If the method succeeded.
568 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
569 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
570 : * If a container writer has been opened on the current writer and not
571 : * yet closed.
572 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
573 : * If the specified tag value is invalid or inappropriate in the context
574 : * in which the value is being written.
575 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
576 : * If writing the value would exceed the limit on the maximum number of
577 : * bytes specified when the writer was initialized.
578 : * @retval #CHIP_ERROR_NO_MEMORY
579 : * If an attempt to allocate an output buffer failed due to lack of
580 : * memory.
581 : * @retval other Other CHIP or platform-specific errors returned by the configured
582 : * TLVBackingStore.
583 : *
584 : */
585 : CHIP_ERROR PutString(Tag tag, const char * buf, uint32_t len);
586 :
587 : /**
588 : * Encodes a TLV UTF8 string value that's passed in as a Span.
589 : *
590 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
591 : * value should be encoded without a tag. Tag values should be
592 : * constructed with one of the tag definition functions ProfileTag(),
593 : * ContextTag() or CommonTag().
594 : * @param[in] str A Span containing a pointer and a length of the string to be encoded.
595 : *
596 : * @retval #CHIP_NO_ERROR If the method succeeded.
597 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
598 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
599 : * If a container writer has been opened on the current writer and not
600 : * yet closed.
601 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
602 : * If the specified tag value is invalid or inappropriate in the context
603 : * in which the value is being written.
604 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
605 : * If writing the value would exceed the limit on the maximum number of
606 : * bytes specified when the writer was initialized.
607 : * @retval #CHIP_ERROR_NO_MEMORY
608 : * If an attempt to allocate an output buffer failed due to lack of
609 : * memory.
610 : * @retval other Other CHIP or platform-specific errors returned by the configured
611 : * TLVBackingStore.
612 : *
613 : */
614 : CHIP_ERROR PutString(Tag tag, CharSpan str);
615 :
616 : /**
617 : * @brief
618 : * Encode the string output formatted according to the format in the TLV element.
619 : *
620 : * PutStringF is an analog of a sprintf where the output is stored in
621 : * a TLV element as opposed to a character buffer. When extended
622 : * printf functionality is available, the function is able to output
623 : * the result string into a discontinuous underlying storage. The
624 : * implementation supports the following printf enhancements:
625 : *
626 : * -- The platform supplies a callback-based `vcbprintf` that provides
627 : * the ability to call a custom callback in place of putchar.
628 : *
629 : * -- The platform supplies a variant of `vsnprintf` called
630 : * `vsnprintf_ex`, that behaves exactly like vsnprintf except it
631 : * has provisions for omitting the first `n` characters of the
632 : * output.
633 : *
634 : * Note that while the callback-based function may be the simplest and
635 : * use the least amount of code, the `vsprintf_ex` variety of
636 : * functions will consume less stack.
637 : *
638 : * If neither of the above is available, the function will allocate a
639 : * temporary buffer to hold the output, using Platform::MemoryAlloc().
640 : *
641 : * @param[in] tag The TLV tag to be encoded with the value, or @p
642 : * AnonymousTag() if the value should be encoded without
643 : * a tag. Tag values should be constructed with one of
644 : * the tag definition functions ProfileTag(),
645 : * ContextTag() or CommonTag().
646 : *
647 : * @param[in] fmt The format string used to format the argument list.
648 : * Follows the same syntax and rules as the format
649 : * string for `printf` family of functions.
650 : *
651 : * @param[in] ... A list of arguments to be formatted in the output value
652 : * according to fmt.
653 : *
654 : * @retval #CHIP_NO_ERROR If the method succeeded.
655 : *
656 : * @retval other If underlying calls to TLVWriter methods --
657 : * `WriteElementHead` or `GetNewBuffer` -- failed, their
658 : * error is immediately forwarded up the call stack.
659 : */
660 : // The ENFORCE_FORMAT args are "off by one" because this is a class method,
661 : // with an implicit "this" as first arg.
662 : CHIP_ERROR PutStringF(Tag tag, const char * fmt, ...) ENFORCE_FORMAT(3, 4);
663 :
664 : /**
665 : * @brief
666 : * Encode the string output formatted according to the format in the TLV element.
667 : *
668 : * PutStringF is an analog of a sprintf where the output is stored in
669 : * a TLV element as opposed to a character buffer. When extended
670 : * printf functionality is available, the function is able to output
671 : * the result string into a discontinuous underlying storage. The
672 : * implementation supports the following printf enhancements:
673 : *
674 : * -- The platform supplies a callback-based `vcbprintf` that provides
675 : * the ability to call a custom callback in place of putchar.
676 : *
677 : * -- The platform supplies a variant of `vsnprintf` called
678 : * `vsnprintf_ex`, that behaves exactly like vsnprintf except it
679 : * has provisions for omitting the first `n` characters of the
680 : * output.
681 : *
682 : * Note that while the callback-based function may be the simplest and
683 : * use the least amount of code, the `vsprintf_ex` variety of
684 : * functions will consume less stack.
685 : *
686 : * If neither of the above is available, the function will allocate a
687 : * temporary buffer to hold the output, using Platform::MemoryAlloc().
688 : *
689 : * @param[in] tag The TLV tag to be encoded with the value, or @p
690 : * AnonymousTag() if the value should be encoded without
691 : * a tag. Tag values should be constructed with one of
692 : * the tag definition functions ProfileTag(),
693 : * ContextTag() or CommonTag().
694 : *
695 : * @param[in] fmt The format string used to format the argument list.
696 : * Follows the same syntax and rules as the format
697 : * string for `printf` family of functions.
698 : *
699 : * @param[in] ap A list of arguments to be formatted in the output value
700 : * according to fmt.
701 : *
702 : * @retval #CHIP_NO_ERROR If the method succeeded.
703 : *
704 : * @retval other If underlying calls to TLVWriter methods --
705 : * `WriteElementHead` or `GetNewBuffer` -- failed, their
706 : * error is immediately forwarded up the call stack.
707 : */
708 : // The ENFORCE_FORMAT args are "off by one" because this is a class method,
709 : // with an implicit "this" as first arg.
710 : CHIP_ERROR VPutStringF(Tag tag, const char * fmt, va_list ap) ENFORCE_FORMAT(3, 0);
711 :
712 : /**
713 : * Encodes a TLV null value.
714 : *
715 : * @param[in] tag The TLV tag to be encoded with the value, or @p AnonymousTag() if the
716 : * value should be encoded without a tag. Tag values should be
717 : * constructed with one of the tag definition functions ProfileTag(),
718 : * ContextTag() or CommonTag().
719 : *
720 : * @retval #CHIP_NO_ERROR If the method succeeded.
721 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
722 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
723 : * If a container writer has been opened on the current writer and not
724 : * yet closed.
725 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
726 : * If the specified tag value is invalid or inappropriate in the context
727 : * in which the value is being written.
728 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
729 : * If writing the value would exceed the limit on the maximum number of
730 : * bytes specified when the writer was initialized.
731 : * @retval #CHIP_ERROR_NO_MEMORY
732 : * If an attempt to allocate an output buffer failed due to lack of
733 : * memory.
734 : * @retval other Other CHIP or platform-specific errors returned by the configured
735 : * TLVBackingStore.
736 : *
737 : */
738 : CHIP_ERROR PutNull(Tag tag);
739 :
740 : /**
741 : * Copies a TLV element from a reader object into the writer.
742 : *
743 : * The CopyElement() method encodes a new TLV element whose type, tag and value are taken from a TLVReader
744 : * object. When the method is called, the supplied reader object is expected to be positioned on the
745 : * source TLV element. The newly encoded element will have the same type, tag and contents as the input
746 : * container. If the supplied element is a TLV container (structure, array or path), the entire contents
747 : * of the container will be copied.
748 : *
749 : * @note This method requires the supplied TVLReader object to be reading from a single, contiguous
750 : * input buffer that contains the entirety of the underlying TLV encoding. Supplying a reader in any
751 : * other mode has undefined behavior.
752 : *
753 : * @param[in] reader A reference to a TLVReader object identifying a pre-encoded TLV
754 : * element that should be copied.
755 : *
756 : * @retval #CHIP_NO_ERROR If the method succeeded.
757 : * @retval #CHIP_ERROR_INCORRECT_STATE
758 : * If the supplied reader is not positioned on an element or if the writer is not initialized.
759 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
760 : * If a container writer has been opened on the current writer and not
761 : * yet closed.
762 : * @retval #CHIP_ERROR_TLV_UNDERRUN
763 : * If the underlying TLV encoding associated with the supplied reader ended
764 : * prematurely.
765 : * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT
766 : * If the supplied reader encountered an invalid or unsupported TLV element
767 : * type.
768 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
769 : * If the supplied reader encountered a TLV tag in an invalid context,
770 : * or if the supplied tag is invalid or inappropriate in the context in
771 : * which the new container is being written.
772 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
773 : * If writing the value would exceed the limit on the maximum number of
774 : * bytes specified when the writer was initialized.
775 : * @retval #CHIP_ERROR_NO_MEMORY
776 : * If an attempt to allocate an output buffer failed due to lack of
777 : * memory.
778 : * @retval other Other CHIP or platform-specific errors returned by the configured
779 : * GetNewBuffer() or FinalizeBuffer() functions, or by the GetNextBuffer()
780 : * function associated with the reader object.
781 : *
782 : */
783 : CHIP_ERROR CopyElement(TLVReader & reader);
784 :
785 : /**
786 : * Copies a TLV element from a reader object into the writer.
787 : *
788 : * The CopyElement() method encodes a new TLV element whose type and value are taken from a TLVReader
789 : * object. When the method is called, the supplied reader object is expected to be positioned on the
790 : * source TLV element. The newly encoded element will have the same type and contents as the input
791 : * container, however the tag will be set to the specified argument. If the supplied element is a
792 : * TLV container (structure, array or path), the entire contents of the container will be copied.
793 : *
794 : * @note This method requires the supplied TVLReader object to be reading from a single, contiguous
795 : * input buffer that contains the entirety of the underlying TLV encoding. Supplying a reader in any
796 : * other mode has undefined behavior.
797 : *
798 : * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag() if
799 : * the container should be encoded without a tag. Tag values should be
800 : * constructed with one of the tag definition functions ProfileTag(),
801 : * ContextTag() or CommonTag().
802 : * @param[in] reader A reference to a TLVReader object identifying a pre-encoded TLV
803 : * element whose type and value should be copied.
804 : *
805 : * @retval #CHIP_NO_ERROR If the method succeeded.
806 : * @retval #CHIP_ERROR_INCORRECT_STATE
807 : * If the supplied reader is not positioned on an element or if the writer is not initialized.
808 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
809 : * If a container writer has been opened on the current writer and not
810 : * yet closed.
811 : * @retval #CHIP_ERROR_TLV_UNDERRUN
812 : * If the underlying TLV encoding associated with the supplied reader ended
813 : * prematurely.
814 : * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT
815 : * If the supplied reader encountered an invalid or unsupported TLV element
816 : * type.
817 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
818 : * If the supplied reader encountered a TLV tag in an invalid context,
819 : * or if the supplied tag is invalid or inappropriate in the context in
820 : * which the new container is being written.
821 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
822 : * If writing the value would exceed the limit on the maximum number of
823 : * bytes specified when the writer was initialized.
824 : * @retval #CHIP_ERROR_NO_MEMORY
825 : * If an attempt to allocate an output buffer failed due to lack of
826 : * memory.
827 : * @retval other Other CHIP or platform-specific errors returned by the configured
828 : * GetNewBuffer() or FinalizeBuffer() functions, or by the GetNextBuffer()
829 : * function associated with the reader object.
830 : *
831 : */
832 : CHIP_ERROR CopyElement(Tag tag, TLVReader & reader);
833 :
834 : /**
835 : * Begins encoding a new TLV container element.
836 : *
837 : * The StartContainer() method is used to write TLV container elements (structure, arrays or paths)
838 : * to an encoding. The method takes the type and tag (if any) of the new container, and a reference
839 : * to a TLVType value which will be used to save the current context of the writer while it is being
840 : * used to write the container.
841 : *
842 : * Once the StartContainer() method returns, the application should use the current TLVWriter object to
843 : * write the elements of the container. When finish, the application must call the EndContainer()
844 : * method to finish the encoding of the container.
845 : *
846 : * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag() if
847 : * the container should be encoded without a tag. Tag values should be
848 : * constructed with one of the tag definition functions ProfileTag(),
849 : * ContextTag() or CommonTag().
850 : * @param[in] containerType The type of container to encode. Must be one of @p kTLVType_Structure,
851 : * @p kTLVType_Array or @p kTLVType_List.
852 : * @param[out] outerContainerType
853 : * A reference to a TLVType value that will receive the context of the
854 : * writer.
855 : *
856 : * @retval #CHIP_NO_ERROR If the method succeeded.
857 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
858 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE
859 : * If the value specified for containerType is incorrect.
860 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
861 : * If a container writer has been opened on the current writer and not
862 : * yet closed.
863 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
864 : * If the specified tag value is invalid or inappropriate in the context
865 : * in which the value is being written.
866 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
867 : * If writing the value would exceed the limit on the maximum number of
868 : * bytes specified when the writer was initialized.
869 : * @retval #CHIP_ERROR_NO_MEMORY
870 : * If an attempt to allocate an output buffer failed due to lack of
871 : * memory.
872 : * @retval other Other CHIP or platform-specific errors returned by the configured
873 : * TLVBackingStore.
874 : *
875 : */
876 : CHIP_ERROR StartContainer(Tag tag, TLVType containerType, TLVType & outerContainerType);
877 :
878 : /**
879 : * Completes the encoding of a TLV container element.
880 : *
881 : * The EndContainer() method completes the encoding of a TLV container element and restores the state
882 : * of a TLVWrite object after an earlier call to StartContainer(). For every call to StartContainer()
883 : * applications must make a corresponding call to EndContainer(), passing the TLVType value returned
884 : * by the StartContainer() call. When EndContainer() returns, the writer object can be used to write
885 : * additional TLV elements that follow the container element.
886 : *
887 : * @note Any changes made to the configuration of the writer between the calls to StartContainer()
888 : * and EndContainer() are NOT undone by the call to EndContainer(). For example, a change to the
889 : * implicit profile id (@p ImplicitProfileId) will not be reversed when a container is ended. Thus
890 : * it is the application's responsibility to adjust the configuration accordingly at the appropriate
891 : * times.
892 : *
893 : * @param[in] outerContainerType
894 : * The TLVType value that was returned by the StartContainer() method.
895 : *
896 : * @retval #CHIP_NO_ERROR If the method succeeded.
897 : * @retval #CHIP_ERROR_INCORRECT_STATE
898 : * If a corresponding StartContainer() call was not made or if the TLVWriter is not initialized.
899 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
900 : * If a container writer has been opened on the current writer and not
901 : * yet closed.
902 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
903 : * If writing the value would exceed the limit on the maximum number of
904 : * bytes specified when the writer was initialized.
905 : * @retval #CHIP_ERROR_NO_MEMORY
906 : * If an attempt to allocate an output buffer failed due to lack of
907 : * memory.
908 : * @retval other Other CHIP or platform-specific errors returned by the configured
909 : * TLVBackingStore.
910 : *
911 : */
912 : CHIP_ERROR EndContainer(TLVType outerContainerType);
913 :
914 : /**
915 : * Initializes a new TLVWriter object for writing the members of a TLV container element.
916 : *
917 : * The OpenContainer() method is used to write TLV container elements (structure, arrays or paths)
918 : * to an encoding. The method takes the type and tag (if any) of the new container, and a reference
919 : * to a new writer object (the <em>container writer</em>) that will be initialized for the purpose
920 : * of writing the container's elements. Applications write the members of the new container using
921 : * the container writer and then call CloseContainer() to complete the container encoding.
922 : *
923 : * While the container writer is open, applications must not make calls on or otherwise alter the state
924 : * of the parent writer.
925 : *
926 : * The container writer inherits various configuration properties from the parent writer. These are:
927 : *
928 : * @li The implicit profile id (ImplicitProfileId)
929 : * @li The application data pointer (AppData)
930 : * @li The GetNewBuffer and FinalizeBuffer function pointers
931 : *
932 : * @note The StartContainer() method can be used as an alternative to OpenContainer() to write a
933 : * container element without initializing a new writer object.
934 : *
935 : * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag() if
936 : * the container should be encoded without a tag. Tag values should be
937 : * constructed with one of the tag definition functions ProfileTag(),
938 : * ContextTag() or CommonTag().
939 : * @param[in] containerType The type of container to encode. Must be one of @p kTLVType_Structure,
940 : * @p kTLVType_Array or @p kTLVType_List.
941 : * @param[out] containerWriter A reference to a TLVWriter object that will be initialized for
942 : * writing the members of the new container element. Any data
943 : * associated with the supplied object is overwritten.
944 : *
945 : * @retval #CHIP_NO_ERROR If the method succeeded.
946 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
947 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE
948 : * If the value specified for containerType is incorrect.
949 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
950 : * If a container writer has been opened on the current writer and not
951 : * yet closed.
952 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
953 : * If the specified tag value is invalid or inappropriate in the context
954 : * in which the value is being written.
955 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
956 : * If writing the value would exceed the limit on the maximum number of
957 : * bytes specified when the writer was initialized.
958 : * @retval #CHIP_ERROR_NO_MEMORY
959 : * If an attempt to allocate an output buffer failed due to lack of
960 : * memory.
961 : * @retval other Other CHIP or platform-specific errors returned by the configured
962 : * TLVBackingStore.
963 : *
964 : */
965 : CHIP_ERROR OpenContainer(Tag tag, TLVType containerType, TLVWriter & containerWriter);
966 :
967 : /**
968 : * Completes the writing of a TLV container after a call to OpenContainer().
969 : *
970 : * The CloseContainer() method restores the state of a parent TLVWriter object after a call to
971 : * OpenContainer(). For every call to OpenContainer() applications must make a corresponding
972 : * call to CloseContainer(), passing a reference to the same container writer to both methods.
973 : *
974 : * When CloseContainer() returns, applications may continue to use the parent writer to write
975 : * additional TLV elements that appear after the container element. At this point the supplied
976 : * container writer should be considered 'de-initialized' and must not be used without
977 : * re-initialization.
978 : *
979 : * @param[in] containerWriter A reference to the TLVWriter object that was supplied to the
980 : * OpenContainer() method.
981 : *
982 : * @retval #CHIP_NO_ERROR If the method succeeded.
983 : * @retval #CHIP_ERROR_INCORRECT_STATE
984 : * If the supplied container writer is not in the correct state or if the TLVWriter is not
985 : * initialized.
986 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
987 : * If another container writer has been opened on the supplied
988 : * container writer and not yet closed.
989 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
990 : * If completing the encoding of the container would exceed the
991 : * limit on the maximum number of bytes specified when the writer
992 : * was initialized.
993 : * @retval #CHIP_ERROR_NO_MEMORY
994 : * If an attempt to allocate an output buffer failed due to lack
995 : * of memory.
996 : * @retval other Other CHIP or platform-specific errors returned by the
997 : * configured TLVBackingStore.
998 : *
999 : */
1000 : CHIP_ERROR CloseContainer(TLVWriter & containerWriter);
1001 :
1002 : /**
1003 : * Encodes a TLV container element from a pre-encoded set of member elements
1004 : *
1005 : * The PutPreEncodedContainer() method encodes a new TLV container element (a structure, array or path)
1006 : * containing a set of member elements taken from a pre-encoded buffer. The input buffer is expected to
1007 : * contain zero or more full-encoded TLV elements, with tags that conform to the rules associated with
1008 : * the specified container type (e.g. structure members must have tags, while array members must not).
1009 : *
1010 : * The method encodes the entirety of the container element in one call. When PutPreEncodedContainer()
1011 : * returns, the writer object can be used to write additional TLV elements following the container element.
1012 : *
1013 : * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag() if
1014 : * the container should be encoded without a tag. Tag values should be
1015 : * constructed with one of the tag definition functions ProfileTag(),
1016 : * ContextTag() or CommonTag().
1017 : * @param[in] containerType The type of container to encode. Must be one of @p kTLVType_Structure,
1018 : * @p kTLVType_Array or @p kTLVType_List.
1019 : * @param[in] data A pointer to a buffer containing zero of more encoded TLV elements that
1020 : * will become the members of the new container.
1021 : * @param[in] dataLen The number of bytes in the @p data buffer.
1022 : *
1023 : * @retval #CHIP_NO_ERROR If the method succeeded.
1024 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
1025 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE
1026 : * If the value specified for containerType is incorrect.
1027 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
1028 : * If a container writer has been opened on the current writer and not
1029 : * yet closed.
1030 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
1031 : * If the specified tag value is invalid or inappropriate in the context
1032 : * in which the value is being written.
1033 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
1034 : * If writing the value would exceed the limit on the maximum number of
1035 : * bytes specified when the writer was initialized.
1036 : * @retval #CHIP_ERROR_NO_MEMORY
1037 : * If an attempt to allocate an output buffer failed due to lack of
1038 : * memory.
1039 : * @retval other Other CHIP or platform-specific errors returned by the configured
1040 : * TLVBackingStore.
1041 : *
1042 : */
1043 : CHIP_ERROR PutPreEncodedContainer(Tag tag, TLVType containerType, const uint8_t * data, uint32_t dataLen);
1044 :
1045 : /**
1046 : * Copies a TLV container element from TLVReader object
1047 : *
1048 : * The CopyContainer() encodes a new TLV container element by copying a pre-encoded container element
1049 : * located at the current position of a TLVReader object. The method writes the entirety of the new
1050 : * container element in one call, copying the container's type, tag and elements from the source
1051 : * encoding. When the method returns, the writer object can be used to write additional TLV elements
1052 : * following the container element.
1053 : *
1054 : * @note This method requires the supplied TVLReader object to be reading from a single, contiguous
1055 : * input buffer that contains the entirety of the underlying TLV encoding.
1056 : *
1057 : * @param[in] container A reference to a TLVReader object identifying the pre-encoded TLV
1058 : * container to be copied.
1059 : *
1060 : * @retval #CHIP_NO_ERROR If the method succeeded.
1061 : * @retval #CHIP_ERROR_INVALID_ARGUMENT
1062 : * If the supplied reader uses a TLVBackingStore rather than a simple buffer.
1063 : * @retval #CHIP_ERROR_INCORRECT_STATE
1064 : * If the supplied reader is not positioned on a container element or if the TLVWriter was not
1065 : * initialized.
1066 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
1067 : * If a container writer has been opened on the current writer and not
1068 : * yet closed.
1069 : * @retval #CHIP_ERROR_TLV_UNDERRUN
1070 : * If the underlying TLV encoding associated with the supplied reader ended
1071 : * prematurely.
1072 : * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT
1073 : * If the supplied reader encountered an invalid or unsupported TLV element
1074 : * type.
1075 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
1076 : * If the supplied reader encountered a TLV tag in an invalid context,
1077 : * or if the tag associated with the source container is invalid or
1078 : * inappropriate in the context in which the new container is being written.
1079 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
1080 : * If writing the value would exceed the limit on the maximum number of
1081 : * bytes specified when the writer was initialized.
1082 : * @retval #CHIP_ERROR_NO_MEMORY
1083 : * If an attempt to allocate an output buffer failed due to lack of
1084 : * memory.
1085 : * @retval other Other CHIP or platform-specific errors returned by the configured
1086 : * TLVBackingStore.
1087 : *
1088 : */
1089 : CHIP_ERROR CopyContainer(TLVReader & container);
1090 :
1091 : /**
1092 : * Encodes a TLV container element from a pre-encoded set of member elements
1093 : *
1094 : * The CopyContainer() method encodes a new TLV container element (a structure, array or path)
1095 : * containing a set of member elements taken from a TLVReader object. When the method is called, the
1096 : * supplied reader object is expected to be positioned on a TLV container element. The newly encoded
1097 : * container will have the same type and members as the input container. The tag for the new
1098 : * container is specified as an input parameter.
1099 : *
1100 : * When the method returns, the writer object can be used to write additional TLV elements following
1101 : * the container element.
1102 : *
1103 : * @note This method requires the supplied TVLReader object to be reading from a single, contiguous
1104 : * input buffer that contains the entirety of the underlying TLV encoding.
1105 : *
1106 : * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag() if
1107 : * the container should be encoded without a tag. Tag values should be
1108 : * constructed with one of the tag definition functions ProfileTag(),
1109 : * ContextTag() or CommonTag().
1110 : * @param[in] container A reference to a TLVReader object identifying a pre-encoded TLV
1111 : * container whose type and members should be copied.
1112 : *
1113 : * @retval #CHIP_NO_ERROR If the method succeeded.
1114 : * @retval #CHIP_ERROR_INVALID_ARGUMENT
1115 : * If the supplied reader uses a TLVBackingStore rather than a simple buffer.
1116 : * @retval #CHIP_ERROR_INCORRECT_STATE
1117 : * If the supplied reader is not positioned on a container element or of the TLVWriter was not
1118 : * initialized.
1119 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
1120 : * If a container writer has been opened on the current writer and not
1121 : * yet closed.
1122 : * @retval #CHIP_ERROR_TLV_UNDERRUN
1123 : * If the underlying TLV encoding associated with the supplied reader ended
1124 : * prematurely.
1125 : * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT
1126 : * If the supplied reader encountered an invalid or unsupported TLV element
1127 : * type.
1128 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
1129 : * If the supplied reader encountered a TLV tag in an invalid context,
1130 : * or if the supplied tag is invalid or inappropriate in the context in
1131 : * which the new container is being written.
1132 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
1133 : * If writing the value would exceed the limit on the maximum number of
1134 : * bytes specified when the writer was initialized.
1135 : * @retval #CHIP_ERROR_NO_MEMORY
1136 : * If an attempt to allocate an output buffer failed due to lack of
1137 : * memory.
1138 : * @retval other Other CHIP or platform-specific errors returned by the configured
1139 : * TLVBackingStore.
1140 : *
1141 : */
1142 : CHIP_ERROR CopyContainer(Tag tag, TLVReader & container);
1143 :
1144 : /**
1145 : * Encodes a TLV container element that contains member elements from a pre-encoded container
1146 : *
1147 : * The CopyContainer() method encodes a new TLV container element (a structure, array or path)
1148 : * containing a set of member elements taken from the contents of a supplied pre-encoded container.
1149 : * When the method is called, data in the supplied input buffer is parsed as a TLV container element
1150 : * an a new container is written that has the same type and members as the input container. The tag
1151 : * for the new container is specified as an input parameter.
1152 : *
1153 : * When the method returns, the writer object can be used to write additional TLV elements following
1154 : * the container element.
1155 : *
1156 : * @param[in] tag The TLV tag to be encoded with the container, or @p AnonymousTag() if
1157 : * the container should be encoded without a tag. Tag values should be
1158 : * constructed with one of the tag definition functions ProfileTag(),
1159 : * ContextTag() or CommonTag().
1160 : * @param[in] encodedContainer A buffer containing a pre-encoded TLV container whose type and members
1161 : * should be copied.
1162 : * @param[in] encodedContainerLen The length in bytes of the pre-encoded container.
1163 : *
1164 : * @retval #CHIP_NO_ERROR If the method succeeded.
1165 : * @retval #CHIP_ERROR_INCORRECT_STATE If the TLVWriter was not initialized.
1166 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
1167 : * If a container writer has been opened on the current writer and not
1168 : * yet closed.
1169 : * @retval #CHIP_ERROR_TLV_UNDERRUN
1170 : * If the encoded container ended prematurely.
1171 : * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT
1172 : * If the encoded container contained an invalid or unsupported TLV element type.
1173 : * @retval #CHIP_ERROR_INVALID_TLV_TAG
1174 : * If the encoded container contained a TLV tag in an invalid context,
1175 : * or if the supplied tag is invalid or inappropriate in the context in
1176 : * which the new container is being written.
1177 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
1178 : * If writing the value would exceed the limit on the maximum number of
1179 : * bytes specified when the writer was initialized.
1180 : * @retval #CHIP_ERROR_NO_MEMORY
1181 : * If an attempt to allocate an output buffer failed due to lack of
1182 : * memory.
1183 : * @retval other Other CHIP or platform-specific errors returned by the configured
1184 : * TLVBackingStore.
1185 : *
1186 : */
1187 : CHIP_ERROR CopyContainer(Tag tag, const uint8_t * encodedContainer, uint16_t encodedContainerLen);
1188 :
1189 : /**
1190 : * Returns the type of container within which the TLVWriter is currently writing.
1191 : *
1192 : * The GetContainerType() method returns the type of the TLV container within which the TLVWriter
1193 : * is currently writing. If the TLVWriter is not writing elements within a container (i.e. if writing
1194 : * at the outer-most level of an encoding) the method returns kTLVType_NotSpecified.
1195 : *
1196 : * @return The TLVType of the current container, or kTLVType_NotSpecified if the TLVWriter is not
1197 : * writing elements within a container.
1198 : */
1199 : TLVType GetContainerType() const { return mContainerType; }
1200 :
1201 : /**
1202 : * Returns the total number of bytes written since the writer was initialized.
1203 : *
1204 : * @return Total number of bytes written since the writer was initialized.
1205 : */
1206 12438 : uint32_t GetLengthWritten() const { return mLenWritten; }
1207 :
1208 : /**
1209 : * Returns the total remaining number of bytes for current tlv writer
1210 : *
1211 : * @return the total remaining number of bytes.
1212 : */
1213 : uint32_t GetRemainingFreeLength() const { return mRemainingLen; }
1214 :
1215 : /**
1216 : * @brief Returns true if this TLVWriter was properly initialized.
1217 : */
1218 859811 : bool IsInitialized() const { return mInitializationCookie == kExpectedInitializationCookie; }
1219 :
1220 : /**
1221 : * The profile id of tags that should be encoded in implicit form.
1222 : *
1223 : * When a writer is asked to encode a new element, if the profile id of the tag associated with the
1224 : * new element matches the value of the @p ImplicitProfileId member, the writer will encode the tag
1225 : * in implicit form, omitting the profile id in the process.
1226 : *
1227 : * By default, the @p ImplicitProfileId property is set to kProfileIdNotSpecified, which instructs
1228 : * the writer not to emit implicitly encoded tags. Applications can set @p ImplicitProfileId at any
1229 : * time to enable encoding tags in implicit form starting at the current point in the encoding. The
1230 : * appropriate profile id to set is usually dependent on the context of the application or protocol
1231 : * being spoken.
1232 : *
1233 : * @note The value of the @p ImplicitProfileId member affects the encoding of profile-specific
1234 : * tags only; the encoding of context-specific tags is unchanged.
1235 : */
1236 : uint32_t ImplicitProfileId;
1237 :
1238 : /**
1239 : * A pointer field that can be used for application-specific data.
1240 : */
1241 : void * AppData;
1242 :
1243 : protected:
1244 : TLVBackingStore * mBackingStore;
1245 : uint8_t * mBufStart;
1246 : uint8_t * mWritePoint;
1247 : uint32_t mRemainingLen;
1248 : uint32_t mLenWritten;
1249 : uint32_t mMaxLen;
1250 : uint32_t mReservedSize;
1251 : TLVType mContainerType;
1252 : uint16_t mInitializationCookie;
1253 :
1254 : private:
1255 : bool mContainerOpen;
1256 : bool mCloseContainerReserved;
1257 :
1258 : protected:
1259 342239 : bool IsContainerOpen() const { return mContainerOpen; }
1260 115971 : void SetContainerOpen(bool aContainerOpen) { mContainerOpen = aContainerOpen; }
1261 :
1262 : enum
1263 : {
1264 : kEndOfContainerMarkerSize = 1, /**< Size of the EndOfContainer marker, used in reserving space. */
1265 : };
1266 :
1267 : /**
1268 : * @brief
1269 : * Determine whether the container should reserve space for the
1270 : * CloseContainer symbol at the point of starting / opening the
1271 : * container.
1272 : */
1273 161240 : bool IsCloseContainerReserved() const { return mCloseContainerReserved; }
1274 :
1275 : /**
1276 : * @brief
1277 : * Set whether the container should reserve the space for the
1278 : * CloseContainer symbol at the point of starting / opening the
1279 : * container.
1280 : */
1281 28592 : void SetCloseContainerReserved(bool aCloseContainerReserved) { mCloseContainerReserved = aCloseContainerReserved; }
1282 :
1283 : #if CONFIG_HAVE_VCBPRINTF
1284 : static void TLVWriterPutcharCB(uint8_t c, void * appState);
1285 : #endif
1286 : CHIP_ERROR WriteElementHead(TLVElementType elemType, Tag tag, uint64_t lenOrVal);
1287 : CHIP_ERROR WriteElementWithData(TLVType type, Tag tag, const uint8_t * data, uint32_t dataLen);
1288 : CHIP_ERROR WriteData(const uint8_t * p, uint32_t len);
1289 : };
1290 :
1291 : /*
1292 : * A TLVWriter that is backed by a scoped memory buffer that is owned by the writer.
1293 : */
1294 : class ScopedBufferTLVWriter : public TLVWriter
1295 : {
1296 : public:
1297 : /*
1298 : * Construct and initialize the writer by taking ownership of the provided scoped buffer.
1299 : */
1300 1252 : ScopedBufferTLVWriter(Platform::ScopedMemoryBuffer<uint8_t> && buffer, size_t dataLen)
1301 1252 : {
1302 1252 : mBuffer = std::move(buffer);
1303 1252 : Init(mBuffer.Get(), dataLen);
1304 1252 : }
1305 :
1306 : /*
1307 : * Finalize the writer and take back the buffer owned by the writer. This transfers its
1308 : * ownership to the provided buffer reference. This also re-initializes the writer with
1309 : * a null buffer to prevent further inadvertent use of the writer.
1310 : */
1311 1250 : CHIP_ERROR Finalize(Platform::ScopedMemoryBuffer<uint8_t> & buffer)
1312 : {
1313 1250 : ReturnErrorOnFailure(TLVWriter::Finalize());
1314 1250 : buffer = std::move(mBuffer);
1315 1250 : Init(nullptr, 0);
1316 1250 : return CHIP_NO_ERROR;
1317 : }
1318 :
1319 : private:
1320 : Platform::ScopedMemoryBuffer<uint8_t> mBuffer;
1321 : };
1322 :
1323 : } // namespace TLV
1324 : } // namespace chip
|