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 : #pragma once
28 :
29 : #include <stddef.h>
30 : #include <stdint.h>
31 : #include <type_traits>
32 : #include <utility>
33 :
34 : #include <lib/core/CHIPError.h>
35 : #include <lib/core/DataModelTypes.h>
36 : #include <lib/core/Optional.h>
37 : #include <lib/core/TLVBackingStore.h>
38 : #include <lib/core/TLVTags.h>
39 : #include <lib/core/TLVTypes.h>
40 : #include <lib/support/BitFlags.h>
41 : #include <lib/support/BitMask.h>
42 : #include <lib/support/CodeUtils.h>
43 : #include <lib/support/DLLUtil.h>
44 : #include <lib/support/ScopedMemoryBuffer.h>
45 : #include <lib/support/Span.h>
46 :
47 : /**
48 : * @namespace chip::TLV
49 : *
50 : * Definitions for working with data encoded in CHIP TLV format.
51 : *
52 : * CHIP TLV is a generalized encoding method for simple structured data. It shares many properties
53 : * with the commonly used JSON serialization format while being considerably more compact over the wire.
54 : */
55 :
56 : namespace chip {
57 : namespace TLV {
58 :
59 : /**
60 : * Provides a memory efficient parser for data encoded in CHIP TLV format.
61 : *
62 : * TLVReader implements a forward-only, “pull-style” parser for CHIP TLV data. The TLVReader
63 : * object operates as a cursor that can be used to iterate over a sequence of TLV elements
64 : * and interpret their contents. When positioned on an element, applications can make calls
65 : * to the reader's Get() methods to query the current element’s type and tag, and to extract
66 : * any associated value. The reader’s Next() method is used to advance from element to element.
67 : *
68 : * A TLVReader object is always positioned either before, on or after a TLV element. When first
69 : * initialized, a TLVReader is positioned immediately before the first element of the encoding.
70 : * To begin reading, an application must make an initial call to the Next() method to position
71 : * the reader on the first element. When a container element is encountered--either a structure,
72 : * an array or a path--the OpenContainer() or EnterContainer() methods can be used to iterate
73 : * through the contents of the container.
74 : *
75 : * When the reader reaches the end of a TLV encoding, or the last element within a container,
76 : * it signals the application by returning a CHIP_END_OF_TLV error from the Next() method.
77 : * The reader will continue to return CHIP_END_OF_TLV until it is reinitialized, or the current
78 : * container is exited (via CloseContainer() / ExitContainer()).
79 : *
80 : * A TLVReader object can parse data directly from a fixed input buffer, or from memory provided
81 : * by a TLVBackingStore.
82 : */
83 : class DLL_EXPORT TLVReader
84 : {
85 : friend class TLVWriter;
86 : friend class TLVUpdater;
87 :
88 : #if CHIP_CONFIG_TEST
89 : // Test seam: lets unit tests drive GetLocalizedStringIdentifierImpl with the strict
90 : // UTF-8 check forced on, independent of CHIP_CONFIG_TLV_VALIDATE_CHAR_STRING_ON_READ.
91 : friend CHIP_ERROR GetLocalizedStringIdentifierForTest(TLVReader & reader, Optional<LocalizedStringIdentifier> & lsid,
92 : bool validateCharString);
93 : #endif // CHIP_CONFIG_TEST
94 :
95 : public:
96 : TLVReader();
97 :
98 : /**
99 : * Initializes a TLVReader object from another TLVReader object.
100 : *
101 : * @param[in] aReader A read-only reference to the TLVReader to initialize
102 : * this from.
103 : *
104 : */
105 : void Init(const TLVReader & aReader);
106 :
107 : /**
108 : * Initializes a TLVReader object to read from a single input buffer.
109 : *
110 : * @param[in] data A pointer to a buffer containing the TLV data to be parsed.
111 : * @param[in] dataLen The length of the TLV data to be parsed.
112 : *
113 : */
114 : void Init(const uint8_t * data, size_t dataLen);
115 :
116 : /**
117 : * Initializes a TLVReader object to read from a single input buffer
118 : * represented as a span.
119 : *
120 : * @param[in] data A byte span to read from
121 : *
122 : */
123 5914 : void Init(const ByteSpan & data) { Init(data.data(), data.size()); }
124 :
125 : /**
126 : * Initializes a TLVReader object to read from a single input buffer
127 : * represented as byte array.
128 : *
129 : * @param[in] data A byte buffer to read from
130 : *
131 : */
132 : template <size_t N>
133 1647475 : void Init(const uint8_t (&data)[N])
134 : {
135 1647475 : Init(data, N);
136 1647475 : }
137 :
138 : /**
139 : * Initializes a TLVReader object to read from a TLVBackingStore.
140 : *
141 : * Parsing begins at the backing store's start position and continues until the
142 : * end of the data in the buffer, or maxLen bytes have been parsed.
143 : *
144 : * @param[in] backingStore A reference to a TLVBackingStore providing the TLV data to be parsed.
145 : * @param[in] maxLen The maximum number of bytes to parse. Defaults to the amount of data
146 : * in the input buffer.
147 : *
148 : * @retval #CHIP_NO_ERROR If the method succeeded.
149 : * @retval other Other error codes returned by TLVBackingStore::OnInit().
150 : */
151 : CHIP_ERROR Init(TLVBackingStore & backingStore, uint32_t maxLen = UINT32_MAX);
152 :
153 : /**
154 : * Advances the TLVReader object to the next TLV element to be read.
155 : *
156 : * The Next() method positions the reader object on the next element in a TLV encoding that resides
157 : * in the same containment context. In particular, if the reader is positioned at the outer-most
158 : * level of a TLV encoding, calling Next() will advance the reader to the next, top-most element.
159 : * If the reader is positioned within a TLV container element (a structure, array or path), calling
160 : * Next() will advance the reader to the next member element of the container.
161 : *
162 : * Since Next() constrains reader motion to the current containment context, calling Next() when
163 : * the reader is positioned on a container element will advance @em over the container, skipping
164 : * its member elements (and the members of any nested containers) until it reaches the first element
165 : * after the container.
166 : *
167 : * When there are no further elements within a particular containment context the Next() method will
168 : * return a #CHIP_END_OF_TLV error and the position of the reader will remain unchanged.
169 : *
170 : * @retval #CHIP_NO_ERROR If the reader was successfully positioned on a new element.
171 : * @retval #CHIP_END_OF_TLV If no further elements are available.
172 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely.
173 : * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT
174 : * If the reader encountered an invalid or unsupported TLV element
175 : * type.
176 : * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context.
177 : * @retval #CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG
178 : * If the reader encountered a implicitly-encoded TLV tag for which
179 : * the corresponding profile id is unknown.
180 : * @retval other Other CHIP or platform error codes returned by the configured
181 : * TLVBackingStore.
182 : *
183 : */
184 : CHIP_ERROR Next();
185 :
186 : /**
187 : * Advances the TLVReader object to the next TLV element to be read, asserting the tag of
188 : * the new element.
189 : *
190 : * This is a convenience method that combines the behavior of Next() and Expect(...).
191 : *
192 : * Note that if this method returns an error, the reader may or may not have been advanced already.
193 : * In use cases where this is important, separate calls to Next() and Expect(...) should be made.
194 : *
195 : * @retval #CHIP_NO_ERROR If the reader was successfully positioned on a new element
196 : * matching the expected parameters.
197 : * @retval other See return values of Next() and Expect().
198 : */
199 : CHIP_ERROR Next(Tag expectedTag);
200 :
201 : /**
202 : * Checks that the TLV reader is positioned at an element with the expected tag.
203 : *
204 : * @retval #CHIP_NO_ERROR If the reader is positioned on the expected element.
205 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the reader is not positioned on an element.
206 : * @retval #CHIP_ERROR_UNEXPECTED_TLV_ELEMENT
207 : * If the tag associated with the new element does not match the
208 : * value of the @p expectedTag argument.
209 : */
210 : CHIP_ERROR Expect(Tag expectedTag);
211 :
212 : /**
213 : * Advances the TLVReader object to the next TLV element to be read, asserting the type and tag of
214 : * the new element.
215 : *
216 : * This is a convenience method that combines the behavior of Next() and Expect(...).
217 : *
218 : * Note that if this method returns an error, the reader may or may not have been advanced already.
219 : * In use cases where this is important, separate calls to Next() and Expect(...) should be made.
220 : *
221 : * @retval #CHIP_NO_ERROR If the reader was successfully positioned on a new element
222 : * matching the expected parameters.
223 : * @retval other See return values of Next() and Expect().
224 : */
225 : CHIP_ERROR Next(TLVType expectedType, Tag expectedTag);
226 :
227 : /**
228 : * Checks that the TLV reader is positioned at an element with the expected type and tag.
229 : *
230 : * @param[in] expectedType The expected data type for the next element.
231 : * @param[in] expectedTag The expected tag for the next element.
232 : *
233 : * @retval #CHIP_NO_ERROR If the reader is positioned on the expected element.
234 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the type of the new element does not match the value
235 : * of the @p expectedType argument.
236 : * @retval #CHIP_ERROR_UNEXPECTED_TLV_ELEMENT
237 : * If the tag associated with the new element does not match the
238 : * value of the @p expectedTag argument.
239 : */
240 : CHIP_ERROR Expect(TLVType expectedType, Tag expectedTag);
241 :
242 : /**
243 : * Returns the type of the current TLV element.
244 : *
245 : * @return A TLVType value describing the data type of the current TLV element. If the reader
246 : * is not positioned on a TLV element, the return value will be kTLVType_NotSpecified.
247 : */
248 : TLVType GetType() const;
249 :
250 : /**
251 : * Returns the tag associated with current TLV element.
252 : *
253 : * The value returned by GetTag() can be used with the tag utility functions (IsProfileTag(),
254 : * IsContextTag(), ProfileIdFromTag(), etc.) to determine the type of tag and to extract various tag
255 : * field values.
256 : *
257 : * @note If the reader is not positioned on a TLV element when GetTag() is called, the return value
258 : * is undefined. Therefore whenever the position of the reader is uncertain applications should call
259 : * GetType() to determine if the reader is position on an element (GetType() != kTLVType_NotSpecified)
260 : * before calling GetTag().
261 : *
262 : * @return An unsigned integer containing information about the tag associated with the current
263 : * TLV element.
264 : */
265 10109935 : Tag GetTag() const { return mElemTag; }
266 :
267 : /**
268 : * Returns the length of data associated with current TLV element.
269 : *
270 : * Data length only applies to elements of type UTF8 string or byte string. For UTF8 strings, the
271 : * value returned is the number of bytes in the string, not the number of characters.
272 : *
273 : * @return The length (in bytes) of data associated with the current TLV element, or 0 if the
274 : * current element is not a UTF8 string or byte string, or if the reader is not
275 : * positioned on an element.
276 : */
277 : uint32_t GetLength() const;
278 :
279 : /**
280 : * Returns the control byte associated with current TLV element.
281 : *
282 : * Ideally, nobody ever needs to know about the control byte and only the
283 : * internal implementation of TLV should have access to it. But, nevertheless,
284 : * having access to the control byte is helpful for debugging purposes by the
285 : * TLV Debug Utilities (that try to decode the tag control byte when pretty
286 : * printing the TLV buffer contents).
287 : *
288 : * @note Unless you really know what you are doing, please refrain from using
289 : * this method and the associated control byte information.
290 : *
291 : * @return An unsigned integer containing the control byte associated with
292 : * the current TLV element. kTLVControlByte_NotSpecified is
293 : * returned if the reader is not positioned @em on an element.
294 : */
295 1344 : uint16_t GetControlByte() const { return mControlByte; }
296 :
297 : /**
298 : * Get the value of the current element as a bool type.
299 : *
300 : * @param[out] v Receives the value associated with current TLV element.
301 : *
302 : * @retval #CHIP_NO_ERROR If the method succeeded.
303 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV boolean type, or the
304 : * reader is not positioned on an element.
305 : */
306 : CHIP_ERROR Get(bool & v) const;
307 :
308 : /**
309 : * Get the value of the current element as an 8-bit signed integer.
310 : *
311 : * If the encoded integer value is larger than the output data type the resultant value will be
312 : * truncated.
313 : *
314 : * @param[out] v Receives the value associated with current TLV element.
315 : *
316 : * @retval #CHIP_NO_ERROR If the method succeeded.
317 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or
318 : * unsigned), or the reader is not positioned on an element.
319 : *
320 : */
321 : CHIP_ERROR Get(int8_t & v) const;
322 :
323 : /**
324 : * Get the value of the current element as a 16-bit signed integer.
325 : *
326 : * If the encoded integer value is larger than the output data type the resultant value will be
327 : * truncated.
328 : *
329 : * @param[out] v Receives the value associated with current TLV element.
330 : *
331 : * @retval #CHIP_NO_ERROR If the method succeeded.
332 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or
333 : * unsigned), or the reader is not positioned on an element.
334 : *
335 : */
336 : CHIP_ERROR Get(int16_t & v) const;
337 :
338 : /**
339 : * Get the value of the current element as a 32-bit signed integer.
340 : *
341 : * If the encoded integer value is larger than the output data type the resultant value will be
342 : * truncated.
343 : *
344 : * @param[out] v Receives the value associated with current TLV element.
345 : *
346 : * @retval #CHIP_NO_ERROR If the method succeeded.
347 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or
348 : * unsigned), or the reader is not positioned on an element.
349 : *
350 : */
351 : CHIP_ERROR Get(int32_t & v) const;
352 :
353 : /**
354 : * Get the value of the current element as a 64-bit signed integer.
355 : *
356 : * If the encoded integer value is larger than the output data type the resultant value will be
357 : * truncated.
358 : *
359 : * @param[out] v Receives the value associated with current TLV element.
360 : *
361 : * @retval #CHIP_NO_ERROR If the method succeeded.
362 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or
363 : * unsigned), or the reader is not positioned on an element.
364 : *
365 : */
366 : CHIP_ERROR Get(int64_t & v) const;
367 :
368 : /**
369 : * Get the value of the current element as an 8-bit unsigned integer.
370 : *
371 : * If the encoded integer value is larger than the output data type the resultant value will be
372 : * truncated. Similarly, if the encoded integer value is negative, the value will be converted
373 : * to unsigned.
374 : *
375 : * @param[out] v Receives the value associated with current TLV element.
376 : *
377 : * @retval #CHIP_NO_ERROR If the method succeeded.
378 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or
379 : * unsigned), or the reader is not positioned on an element.
380 : *
381 : */
382 : CHIP_ERROR Get(uint8_t & v) const;
383 :
384 : /**
385 : * Get the value of the current element as a 16-bit unsigned integer.
386 : *
387 : * If the encoded integer value is larger than the output data type the resultant value will be
388 : * truncated. Similarly, if the encoded integer value is negative, the value will be converted
389 : * to unsigned.
390 : *
391 : * @param[out] v Receives the value associated with current TLV element.
392 : *
393 : * @retval #CHIP_NO_ERROR If the method succeeded.
394 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or
395 : * unsigned), or the reader is not positioned on an element.
396 : *
397 : */
398 : CHIP_ERROR Get(uint16_t & v) const;
399 :
400 : /**
401 : * Get the value of the current element as a 32-bit unsigned integer.
402 : *
403 : * If the encoded integer value is larger than the output data type the resultant value will be
404 : * truncated. Similarly, if the encoded integer value is negative, the value will be converted
405 : * to unsigned.
406 : *
407 : * @param[out] v Receives the value associated with current TLV element.
408 : *
409 : * @retval #CHIP_NO_ERROR If the method succeeded.
410 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or
411 : unsigned), or the reader is not positioned on an element.
412 : *
413 : */
414 : CHIP_ERROR Get(uint32_t & v) const;
415 :
416 : /**
417 : * Get the value of the current element as a 64-bit unsigned integer.
418 : *
419 : * If the encoded integer value is negative, the value will be converted to unsigned.
420 : *
421 : * @param[out] v Receives the value associated with current TLV element.
422 : *
423 : * @retval #CHIP_NO_ERROR If the method succeeded.
424 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV integer type (signed or
425 : * unsigned), or the reader is not positioned on an element.
426 : *
427 : */
428 : CHIP_ERROR Get(uint64_t & v) const;
429 :
430 : /**
431 : * Get the value of the current element as a double-precision floating point number.
432 : *
433 : * @param[out] v Receives the value associated with current TLV element.
434 : *
435 : * @retval #CHIP_NO_ERROR If the method succeeded.
436 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV floating point type, or
437 : * the reader is not positioned on an element.
438 : *
439 : */
440 : CHIP_ERROR Get(double & v) const;
441 :
442 : /**
443 : * Get the value of the current element as a single-precision floating point number.
444 : *
445 : * @param[out] v Receives the value associated with current TLV element.
446 : *
447 : * @retval #CHIP_NO_ERROR If the method succeeded.
448 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV floating point type, or
449 : * the reader is not positioned on an element.
450 : *
451 : */
452 : CHIP_ERROR Get(float & v) const;
453 :
454 : /**
455 : * Get the value of the current element as a ByteSpan
456 : *
457 : * @param[out] v Receives the value associated with current TLV element.
458 : *
459 : * @retval #CHIP_NO_ERROR If the method succeeded.
460 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV bytes array, or
461 : * the reader is not positioned on an element.
462 : *
463 : */
464 : CHIP_ERROR Get(ByteSpan & v) const;
465 :
466 : /**
467 : * Get the value of the current element as a FixedByteSpan
468 : *
469 : * @param[out] v Receives the value associated with current TLV element.
470 : *
471 : * @retval #CHIP_NO_ERROR If the method succeeded.
472 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV bytes array, or
473 : * the reader is not positioned on an element.
474 : *
475 : */
476 : template <size_t N>
477 15006 : CHIP_ERROR Get(FixedByteSpan<N> & v) const
478 : {
479 : const uint8_t * val;
480 15006 : ReturnErrorOnFailure(GetDataPtr(val));
481 15006 : VerifyOrReturnError(GetLength() == N, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
482 14988 : v = FixedByteSpan<N>(val);
483 14988 : return CHIP_NO_ERROR;
484 : }
485 :
486 : /**
487 : * Get the value of the current element as a CharSpan
488 : *
489 : * @param[out] v Receives the value associated with current TLV element.
490 : *
491 : * @retval #CHIP_NO_ERROR If the method succeeded.
492 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV character string, or
493 : * the reader is not positioned on an element.
494 : *
495 : */
496 : CHIP_ERROR Get(CharSpan & v) const;
497 :
498 : /**
499 : * Get the Localized String Identifier contained in the current element..
500 : *
501 : * The method takes what's after the first Information Separator 1 <IS1>, and until end of string
502 : * or second <IS1>, and return the hex-decoded string identifier, if one was there.
503 : *
504 : * @param[out] lsid Optional Localized String Identifier. Returns empty
505 : * if the value is not found or it was invalidly encoded.
506 : *
507 : * @retval #CHIP_NO_ERROR If the method succeeded.
508 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV character string, or
509 : * the reader is not positioned on an element.
510 : * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT If the Localized String Identifier is malformed.
511 : */
512 : CHIP_ERROR Get(Optional<LocalizedStringIdentifier> & lsid);
513 :
514 : private:
515 : // Shared implementation of Get(Optional<LocalizedStringIdentifier>&). When
516 : // validateCharString is true, the entire on-wire char string is run through the
517 : // shared conformance predicate (see ValidateCharString in TLVReader.cpp) so this
518 : // overload's verdict matches Get(CharSpan&)'s on the same bytes; when false, the
519 : // string is decoded leniently. Decoupling the check from
520 : // CHIP_CONFIG_TLV_VALIDATE_CHAR_STRING_ON_READ lets unit tests exercise the strict
521 : // path at runtime via GetLocalizedStringIdentifierForTest below.
522 : CHIP_ERROR GetLocalizedStringIdentifierImpl(Optional<LocalizedStringIdentifier> & lsid, bool validateCharString);
523 :
524 : public:
525 : /**
526 : * Get the value of the current element as an enum value, if it's an integer
527 : * value that fits in the enum type.
528 : *
529 : * @param[out] v Receives the value associated with current TLV element.
530 : */
531 : template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
532 5969 : CHIP_ERROR Get(T & v)
533 : {
534 : std::underlying_type_t<T> val;
535 5969 : ReturnErrorOnFailure(Get(val));
536 5969 : v = static_cast<T>(val);
537 5969 : return CHIP_NO_ERROR;
538 : }
539 :
540 : /**
541 : * Get the value of the current element as a BitFlags value, if it's an integer
542 : * value that fits in the BitFlags type.
543 : *
544 : * @param[out] v Receives the value associated with current TLV element.
545 : */
546 : template <typename T>
547 113 : CHIP_ERROR Get(BitFlags<T> & v)
548 : {
549 : std::underlying_type_t<T> val;
550 113 : ReturnErrorOnFailure(Get(val));
551 113 : v.SetRaw(val);
552 113 : return CHIP_NO_ERROR;
553 : }
554 :
555 : /**
556 : * Get the value of the current element as a BitMask value, if it's an integer
557 : * value that fits in the BitMask type.
558 : *
559 : * @param[out] v Receives the value associated with current TLV element.
560 : */
561 : template <typename T>
562 : CHIP_ERROR Get(BitMask<T> & v)
563 : {
564 : std::underlying_type_t<T> val;
565 : ReturnErrorOnFailure(Get(val));
566 : v.SetRaw(val);
567 : return CHIP_NO_ERROR;
568 : }
569 :
570 : /**
571 : * Get the value of the current byte or UTF8 string element.
572 : *
573 : * To determine the required input buffer size, call the GetLength() method before calling GetBytes().
574 : *
575 : * @note The data output by this method is NOT null-terminated.
576 : *
577 : * @param[in] buf A pointer to a buffer to receive the string data.
578 : * @param[in] bufSize The size in bytes of the buffer pointed to by @p buf.
579 : *
580 : * @retval #CHIP_NO_ERROR If the method succeeded.
581 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or
582 : * the reader is not positioned on an element.
583 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
584 : * If the supplied buffer is too small to hold the data associated
585 : * with the current element.
586 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely.
587 : * @retval other Other CHIP or platform error codes returned by the configured
588 : * TLVBackingStore.
589 : *
590 : */
591 : CHIP_ERROR GetBytes(uint8_t * buf, size_t bufSize);
592 :
593 : /**
594 : * Allocates and returns a buffer containing the value of the current byte or UTF8 string.
595 : *
596 : * This method creates a buffer for and returns a copy of the data associated with the byte
597 : * or UTF-8 string element at the current position. Memory for the buffer is obtained with
598 : * Platform::MemoryAlloc() and should be freed with Platform::MemoryFree() by the caller when
599 : * it is no longer needed.
600 : *
601 : * @note The data returned by this method is NOT null-terminated.
602 : *
603 : * @param[out] buf A reference to a pointer to which a heap-allocated buffer of
604 : * @p dataLen bytes will be assigned on success.
605 : * @param[out] dataLen A reference to storage for the size, in bytes, of @p buf on
606 : * success.
607 : *
608 : * @retval #CHIP_NO_ERROR If the method succeeded.
609 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or
610 : * the reader is not positioned on an element.
611 : * @retval #CHIP_ERROR_NO_MEMORY If memory could not be allocated for the output buffer.
612 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely.
613 : * @retval other Other CHIP or platform error codes returned by the configured
614 : * TLVBackingStore.
615 : *
616 : */
617 : CHIP_ERROR DupBytes(uint8_t *& buf, uint32_t & dataLen);
618 :
619 : /**
620 : * Get the value of the current byte or UTF8 string element as a null terminated string.
621 : *
622 : * To determine the required input buffer size, call the GetLength() method before calling GetBytes().
623 : * The input buffer should be at least one byte bigger than the string length to accommodate the null
624 : * character.
625 : *
626 : * @param[in] buf A pointer to a buffer to receive the byte string data.
627 : * @param[in] bufSize The size in bytes of the buffer pointed to by @p buf.
628 : *
629 : * @retval #CHIP_NO_ERROR If the method succeeded.
630 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or
631 : * the reader is not positioned on an element.
632 : * @retval #CHIP_ERROR_BUFFER_TOO_SMALL
633 : * If the supplied buffer is too small to hold the data associated
634 : * with the current element.
635 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely.
636 : * @retval other Other CHIP or platform error codes returned by the configured
637 : * TLVBackingStore.
638 : *
639 : */
640 : CHIP_ERROR GetString(char * buf, size_t bufSize);
641 :
642 : /**
643 : * Allocates and returns a buffer containing the null-terminated value of the current byte or UTF8
644 : * string.
645 : *
646 : * This method creates a buffer for and returns a null-terminated copy of the data associated with
647 : * the byte or UTF-8 string element at the current position. Memory for the buffer is obtained with
648 : * Platform::MemoryAlloc() and should be freed with chip::Platform::MemoryFree() by the caller when
649 : * it is no longer needed.
650 : *
651 : * @param[out] buf A reference to a pointer to which a heap-allocated buffer of
652 : * will be assigned on success.
653 : *
654 : * @retval #CHIP_NO_ERROR If the method succeeded.
655 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or
656 : * the reader is not positioned on an element.
657 : * @retval #CHIP_ERROR_NO_MEMORY If memory could not be allocated for the output buffer.
658 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely.
659 : * @retval other Other CHIP or platform error codes returned by the configured
660 : * TLVBackingStore.
661 : *
662 : */
663 : CHIP_ERROR DupString(char *& buf);
664 :
665 : /**
666 : * Get a pointer to the initial encoded byte of a TLV byte or UTF8 string element.
667 : *
668 : * This method returns a direct pointer to the encoded string value within the underlying input buffer
669 : * as fetched by `Next`. To succeed, the method requires that the entirety of the
670 : * string value be present in a single buffer.
671 : *
672 : * If no string data is present (i.e the length is zero), data shall be updated to point to null.
673 : *
674 : * @param[out] data A reference to a const pointer that will receive a pointer to
675 : * the underlying string data.
676 : *
677 : * @retval #CHIP_NO_ERROR If the method succeeded.
678 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV byte or UTF8 string, or the
679 : * reader is not positioned on an element.
680 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely or the value
681 : * of the current string element is not contained within a single
682 : * contiguous buffer.
683 : * @retval other Other CHIP or platform error codes returned by the configured
684 : * TLVBackingStore.
685 : *
686 : */
687 : CHIP_ERROR GetDataPtr(const uint8_t *& data) const;
688 :
689 : /**
690 : * Prepares a TLVReader object for reading the members of TLV container element.
691 : *
692 : * The EnterContainer() method prepares the current TLVReader object to begin reading the member
693 : * elements of a TLV container (a structure, array or path). For every call to EnterContainer()
694 : * applications must make a corresponding call to ExitContainer().
695 : *
696 : * When EnterContainer() is called the TLVReader object must be positioned on the container element
697 : * to be read. The method takes as an argument a reference to a TLVType value which will be used
698 : * to save the context of the reader while it is reading the container.
699 : *
700 : * When the EnterContainer() method returns, the reader is positioned immediately @em before the
701 : * first member of the container. Repeatedly calling Next() will advance the reader through the members
702 : * of the collection until the end is reached, at which point the reader will return CHIP_END_OF_TLV.
703 : *
704 : * Once the application has finished reading a container it can continue reading the elements after
705 : * the container by calling the ExitContainer() method.
706 : *
707 : * @param[out] outerContainerType A reference to a TLVType value that will receive the context
708 : * of the reader.
709 : *
710 : * @retval #CHIP_NO_ERROR If the method succeeded.
711 : * @retval #CHIP_ERROR_INCORRECT_STATE If the current element is not positioned on a container element.
712 : *
713 : */
714 : CHIP_ERROR EnterContainer(TLVType & outerContainerType);
715 :
716 : /**
717 : * Completes the reading of a TLV container and prepares a TLVReader object to read elements
718 : * after the container.
719 : *
720 : * The ExitContainer() method restores the state of a TLVReader object after a call to
721 : * EnterContainer(). For every call to EnterContainer() applications must make a corresponding
722 : * call to ExitContainer(), passing the context value returned by the EnterContainer() method.
723 : *
724 : * When ExitContainer() returns, the reader is positioned immediately before the first element that
725 : * follows the container. From this point an application can use the Next() method to advance
726 : * through any remaining elements.
727 : *
728 : * Once EnterContainer() has been called, applications can call ExitContainer() on a reader at any
729 : * point in time, regardless of whether all elements in the underlying container have been read.
730 : *
731 : * @note Any changes made to the configuration of the reader between the calls to EnterContainer()
732 : * and ExitContainer() are NOT undone by the call to ExitContainer(). For example, a change to the
733 : * implicit profile id (@p ImplicitProfileId) will not be reversed when a container is exited. Thus
734 : * it is the application's responsibility to adjust the configuration accordingly at the appropriate
735 : * times.
736 : *
737 : * @param[in] outerContainerType The TLVType value that was returned by the EnterContainer() method.
738 : *
739 : * @retval #CHIP_NO_ERROR If the method succeeded.
740 : * @retval #CHIP_ERROR_INCORRECT_STATE If OpenContainer() has not been called on the reader, or if
741 : * the container reader does not match the one passed to the
742 : * OpenContainer() method.
743 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely.
744 : * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT
745 : * If the reader encountered an invalid or unsupported TLV element type.
746 : * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context.
747 : * @retval other Other CHIP or platform error codes returned by the configured
748 : * TLVBackingStore.
749 : *
750 : */
751 : CHIP_ERROR ExitContainer(TLVType outerContainerType);
752 :
753 : /**
754 : * Initializes a new TLVReader object for reading the members of a TLV container element.
755 : *
756 : * The OpenContainer() method initializes a new TLVReader object for reading the member elements of a
757 : * TLV container (a structure, array or path). When OpenContainer() is called, the current TLVReader
758 : * object must be positioned on the container element to be read. The method takes as its sole argument
759 : * a reference to a new reader that will be initialized to read the container. This reader is known as
760 : * the <em>container reader</em> while the reader on which OpenContainer() is called is known as the <em>parent
761 : * reader</em>.
762 : *
763 : * When the OpenContainer() method returns, the container reader is positioned immediately before the
764 : * first member of the container. Calling Next() on the container reader will advance through the members
765 : * of the collection until the end is reached, at which point the reader will return CHIP_END_OF_TLV.
766 : *
767 : * While the container reader is open, applications must not make calls on or otherwise alter the state
768 : * of the parent reader. Once an application has finished using the container reader it must close it
769 : * by calling CloseContainer() on the parent reader, passing the container reader as an argument.
770 : * Applications may close the container reader at any point, with or without reading all elements
771 : * contained in the underlying container. After the container reader is closed, applications may
772 : * continue their use of the parent reader.
773 : *
774 : * The container reader inherits various configuration properties from the parent reader. These are:
775 : *
776 : * @li The implicit profile id (ImplicitProfileId)
777 : * @li The application data pointer (AppData)
778 : * @li The GetNextBuffer function pointer
779 : *
780 : * @note The EnterContainer() method can be used as an alternative to OpenContainer() to read a
781 : * container element without initializing a new reader object.
782 : *
783 : * @param[out] containerReader A reference to a TLVReader object that will be initialized for
784 : * reading the members of the current container element. Any data
785 : * associated with the supplied object is overwritten.
786 : *
787 : * @retval #CHIP_NO_ERROR If the method succeeded.
788 : * @retval #CHIP_ERROR_INCORRECT_STATE If the current element is not positioned on a container element.
789 : *
790 : */
791 : CHIP_ERROR OpenContainer(TLVReader & containerReader);
792 :
793 : /**
794 : * Completes the reading of a TLV container after a call to OpenContainer().
795 : *
796 : * The CloseContainer() method restores the state of a parent TLVReader object after a call to
797 : * OpenContainer(). For every call to OpenContainer() applications must make a corresponding
798 : * call to CloseContainer(), passing a reference to the same container reader to both methods.
799 : *
800 : * When CloseContainer() returns, the parent reader is positioned immediately before the first
801 : * element that follows the container. From this point an application can use the Next() method
802 : * to advance through any remaining elements.
803 : *
804 : * Applications can call close CloseContainer() on a parent reader at any point in time, regardless
805 : * of whether all elements in the underlying container have been read. After CloseContainer() has
806 : * been called, the application should consider the container reader 'de-initialized' and must not
807 : * use it further without re-initializing it.
808 : *
809 : * @param[in] containerReader A reference to the TLVReader object that was supplied to the
810 : * OpenContainer() method.
811 : *
812 : * @retval #CHIP_NO_ERROR If the method succeeded.
813 : * @retval #CHIP_ERROR_INCORRECT_STATE If OpenContainer() has not been called on the reader, or if
814 : * the container reader does not match the one passed to the
815 : * OpenContainer() method.
816 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely.
817 : * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT
818 : * If the reader encountered an invalid or unsupported TLV
819 : * element type.
820 : * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context.
821 : * @retval other Other CHIP or platform error codes returned by the configured
822 : * TLVBackingStore.
823 : *
824 : */
825 : CHIP_ERROR CloseContainer(TLVReader & containerReader);
826 :
827 : /**
828 : * Returns the type of the container within which the TLVReader is currently reading.
829 : *
830 : * The GetContainerType() method returns the type of the TLV container within which the TLVReader
831 : * is reading. If the TLVReader is positioned at the outer-most level of a TLV encoding (i.e. before,
832 : * on or after the outer-most TLV element), the method will return kTLVType_NotSpecified.
833 : *
834 : * @return The TLVType of the current container, or kTLVType_NotSpecified if the TLVReader is not
835 : * positioned within a container.
836 : */
837 13138 : TLVType GetContainerType() const { return mContainerType; }
838 :
839 : /**
840 : * Verifies that the TLVReader object is at the end of a TLV container.
841 : *
842 : * The VerifyEndOfContainer() method verifies that there are no further TLV elements to be read
843 : * within the current TLV container. This is a convenience method that is equivalent to calling
844 : * Next() and checking for a return value of CHIP_END_OF_TLV.
845 : *
846 : * @note When there are more TLV elements in the collection, this method will change the position
847 : * of the reader.
848 : *
849 : * @retval #CHIP_NO_ERROR If there are no further TLV elements to be read.
850 : * @retval #CHIP_ERROR_UNEXPECTED_TLV_ELEMENT
851 : * If another TLV element was found in the collection.
852 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely.
853 : * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT
854 : * If the reader encountered an invalid or unsupported TLV element
855 : * type.
856 : * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context.
857 : * @retval other Other CHIP or platform error codes returned by the configured
858 : * TLVBackingStore.
859 : *
860 : */
861 : CHIP_ERROR VerifyEndOfContainer();
862 :
863 : /**
864 : * Returns the total number of bytes read since the reader was initialized.
865 : *
866 : * @return Total number of bytes read since the reader was initialized.
867 : */
868 58295 : uint32_t GetLengthRead() const { return mLenRead; }
869 :
870 : /**
871 : * Returns the total number of bytes that can be read until the max read length is reached.
872 : *
873 : * @return Total number of bytes that can be read until the max read length is reached.
874 : */
875 46 : uint32_t GetRemainingLength() const { return mMaxLen - mLenRead; }
876 :
877 : /**
878 : * Return the total number of bytes for the TLV data
879 : * @return the total number of bytes for the TLV data
880 : */
881 184 : uint32_t GetTotalLength() const { return mMaxLen; }
882 :
883 : /**
884 : * Returns the stored backing store.
885 : *
886 : * @return the stored backing store.
887 : */
888 5 : TLVBackingStore * GetBackingStore() { return mBackingStore; }
889 :
890 : /**
891 : * Returns true if the current TLV element type is a double.
892 : */
893 54 : bool IsElementDouble() { return ElementType() == TLVElementType::FloatingPointNumber64; }
894 :
895 : /**
896 : * Gets the point in the underlying input buffer that corresponds to the reader's current position.
897 : *
898 : * @note Depending on the type of the current element, GetReadPoint() will return a pointer that
899 : * is some number of bytes *after* the first byte of the element. For string types (UTF8 and byte
900 : * strings), the pointer will point to the first byte of the string's value. For container types
901 : * (structures, arrays and paths), the pointer will point to the first member element within the
902 : * container. For all other types, the pointer will point to the byte immediately after the element's
903 : * encoding.
904 : *
905 : * @return A pointer into underlying input buffer that corresponds to the reader's current position.
906 : */
907 1642 : const uint8_t * GetReadPoint() const { return mReadPoint; }
908 :
909 : /**
910 : * Advances the TLVReader object to immediately after the current TLV element.
911 : *
912 : * The Skip() method positions the reader object immediately @em after the current TLV element, such
913 : * that a subsequent call to Next() will advance the reader to the following element. Like Next(),
914 : * if the reader is positioned on a container element at the time of the call, the members of the
915 : * container will be skipped. If the reader is not positioned on any element, its position remains
916 : * unchanged.
917 : *
918 : * @retval #CHIP_NO_ERROR If the reader was successfully positioned on a new element.
919 : * @retval #CHIP_END_OF_TLV If no further elements are available.
920 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely.
921 : * @retval #CHIP_ERROR_INVALID_TLV_ELEMENT
922 : * If the reader encountered an invalid or unsupported TLV
923 : * element type.
924 : * @retval #CHIP_ERROR_INVALID_TLV_TAG If the reader encountered a TLV tag in an invalid context.
925 : * @retval other Other CHIP or platform error codes returned by the configured
926 : * TLVBackingStore.
927 : *
928 : */
929 : CHIP_ERROR Skip();
930 :
931 : /**
932 : * Position the destination reader on the next element with the given tag within this reader's current container context
933 : *
934 : * @param[in] tagInApiForm The destination context tag value
935 : * @param[in] destReader The destination TLV reader value that was located by given tag
936 : *
937 : * @retval #CHIP_NO_ERROR If the reader was successfully positioned at the given tag
938 : * @retval #CHIP_END_OF_TLV If the given tag cannot be found
939 : * @retval other Other CHIP or platform error codes
940 : */
941 : CHIP_ERROR FindElementWithTag(Tag tagInApiForm, TLVReader & destReader) const;
942 :
943 : /**
944 : * Count how many elements remain in the currently-open container. Will
945 : * fail with CHIP_ERROR_INCORRECT_STATE if not currently in a container.
946 : *
947 : * @param[out] size On success, set to the number of items following the
948 : * current reader position in the container.
949 : */
950 : CHIP_ERROR CountRemainingInContainer(size_t * size) const;
951 :
952 : /**
953 : * The profile id to be used for profile tags encoded in implicit form.
954 : *
955 : * When the reader encounters a profile-specific tag that has been encoded in implicit form, it
956 : * uses the value of the @p ImplicitProfileId property as the assumed profile id for the tag.
957 : *
958 : * By default, the @p ImplicitProfileId property is set to kProfileIdNotSpecified. When decoding
959 : * TLV that contains implicitly-encoded tags, applications must set @p ImplicitProfileId prior
960 : * to reading any TLV elements having such tags. The appropriate profile id is usually dependent
961 : * on the context of the application or protocol being spoken.
962 : *
963 : * If an implicitly-encoded tag is encountered while @p ImplicitProfileId is set to
964 : * kProfileIdNotSpecified, the reader will return a #CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG error.
965 : */
966 : uint32_t ImplicitProfileId;
967 :
968 : /**
969 : * A pointer field that can be used for application-specific data.
970 : */
971 : void * AppData;
972 :
973 : protected:
974 : Tag mElemTag;
975 : uint64_t mElemLenOrVal;
976 : TLVBackingStore * mBackingStore;
977 : const uint8_t * mReadPoint;
978 : const uint8_t * mBufEnd;
979 : uint32_t mLenRead;
980 : uint32_t mMaxLen;
981 : TLVType mContainerType;
982 : uint16_t mControlByte;
983 :
984 : private:
985 : bool mContainerOpen;
986 :
987 : protected:
988 799887 : bool IsContainerOpen() const { return mContainerOpen; }
989 7075374 : void SetContainerOpen(bool aContainerOpen) { mContainerOpen = aContainerOpen; }
990 :
991 : CHIP_ERROR ReadElement();
992 : void ClearElementState();
993 : CHIP_ERROR SkipData();
994 : CHIP_ERROR SkipToEndOfContainer();
995 : CHIP_ERROR VerifyElement();
996 : Tag ReadTag(TLVTagControl tagControl, const uint8_t *& p) const;
997 : CHIP_ERROR EnsureData(CHIP_ERROR noDataErr);
998 : CHIP_ERROR ReadData(uint8_t * buf, uint32_t len);
999 : CHIP_ERROR GetElementHeadLength(uint8_t & elemHeadBytes) const;
1000 : TLVElementType ElementType() const;
1001 : };
1002 :
1003 : /*
1004 : * A TLVReader that is backed by a scoped memory buffer that is owned by the reader
1005 : */
1006 : class ScopedBufferTLVReader : public TLVReader
1007 : {
1008 : public:
1009 : /*
1010 : * Construct and initialize the reader by taking ownership of the provided scoped buffer.
1011 : */
1012 475 : ScopedBufferTLVReader(Platform::ScopedMemoryBuffer<uint8_t> && buffer, size_t dataLen) { Init(std::move(buffer), dataLen); }
1013 :
1014 1351 : ScopedBufferTLVReader() {}
1015 :
1016 : /*
1017 : * Initialize the reader by taking ownership of a passed in scoped buffer.
1018 : */
1019 1826 : void Init(Platform::ScopedMemoryBuffer<uint8_t> && buffer, size_t dataLen)
1020 : {
1021 1826 : mBuffer = std::move(buffer);
1022 1826 : TLVReader::Init(mBuffer.Get(), dataLen);
1023 1826 : }
1024 :
1025 : /*
1026 : * Take back the buffer owned by the reader and transfer its ownership to
1027 : * the provided buffer reference. This also re-initializes the reader with
1028 : * a null buffer to prevent further use of the reader.
1029 : */
1030 1 : void TakeBuffer(Platform::ScopedMemoryBuffer<uint8_t> & buffer)
1031 : {
1032 1 : buffer = std::move(mBuffer);
1033 1 : TLVReader::Init(nullptr, 0);
1034 1 : }
1035 :
1036 : private:
1037 : Platform::ScopedMemoryBuffer<uint8_t> mBuffer;
1038 : };
1039 :
1040 : /**
1041 : * A TLVReader that is guaranteed to be backed by a single contiguous buffer.
1042 : * This allows it to expose some additional methods that allow consumers to
1043 : * directly access the data in that buffer in a safe way that is guaranteed to
1044 : * work as long as the reader object stays in scope.
1045 : */
1046 : class ContiguousBufferTLVReader : public TLVReader
1047 : {
1048 : public:
1049 22400 : ContiguousBufferTLVReader() : TLVReader() {}
1050 :
1051 : /**
1052 : * Init with input buffer as ptr + length pair.
1053 : */
1054 24835 : void Init(const uint8_t * data, size_t dataLen) { TLVReader::Init(data, dataLen); }
1055 :
1056 : /**
1057 : * Init with input buffer as ByteSpan.
1058 : */
1059 640 : void Init(const ByteSpan & data) { Init(data.data(), data.size()); }
1060 :
1061 : /**
1062 : * Init with input buffer as byte array.
1063 : */
1064 : template <size_t N>
1065 10 : void Init(const uint8_t (&data)[N])
1066 : {
1067 10 : Init(data, N);
1068 10 : }
1069 :
1070 : /**
1071 : * Allow opening a container, with a new ContiguousBufferTLVReader reading
1072 : * that container. See TLVReader::OpenContainer for details.
1073 : */
1074 : CHIP_ERROR OpenContainer(ContiguousBufferTLVReader & containerReader);
1075 :
1076 : /**
1077 : * Get the value of the current UTF8 string as a Span<const char> pointing
1078 : * into the TLV data. Consumers may need to copy the data elsewhere as
1079 : * needed (e.g. before releasing the reader and its backing buffer if they
1080 : * plan to use the data after that point).
1081 : *
1082 : * @param[out] data A Span<const char> representing the string data.
1083 : *
1084 : * @retval #CHIP_NO_ERROR If the method succeeded.
1085 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV UTF8 string, or
1086 : * the reader is not positioned on an element.
1087 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely (i.e. the string length was "too big").
1088 : *
1089 : */
1090 : CHIP_ERROR GetStringView(Span<const char> & data);
1091 :
1092 : /**
1093 : * Get the value of the current octet string as a ByteSpan pointing into the
1094 : * TLV data. Consumers may need to copy the data elsewhere as needed
1095 : * (e.g. before releasing the reader and its backing buffer if they plan to
1096 : * use the data after that point).
1097 : *
1098 : * @param[out] data A ByteSpan representing the string data.
1099 : *
1100 : * @retval #CHIP_NO_ERROR If the method succeeded.
1101 : * @retval #CHIP_ERROR_WRONG_TLV_TYPE If the current element is not a TLV octet string, or
1102 : * the reader is not positioned on an element.
1103 : * @retval #CHIP_ERROR_TLV_UNDERRUN If the underlying TLV encoding ended prematurely (i.e. the string length was "too big").
1104 : *
1105 : */
1106 : CHIP_ERROR GetByteView(ByteSpan & data);
1107 : };
1108 :
1109 : #if CHIP_CONFIG_TEST
1110 : /**
1111 : * Test-only shim around the file-scope ValidateCharString predicate in TLVReader.cpp.
1112 : * Lets unit tests pin the predicate's verdict on hand-built byte sequences without
1113 : * routing through a TLVReader. See ValidateCharString in TLVReader.cpp for semantics.
1114 : */
1115 : CHIP_ERROR ValidateCharStringForTest(const CharSpan & str);
1116 :
1117 : /**
1118 : * Test-only entry point that runs TLVReader::Get(Optional<LocalizedStringIdentifier>&)'s
1119 : * shared implementation with UTF-8 conformance forced on or off, independent of
1120 : * CHIP_CONFIG_TLV_VALIDATE_CHAR_STRING_ON_READ. Lets unit tests exercise the strict
1121 : * path at runtime without a flag-on build of the SDK.
1122 : */
1123 : CHIP_ERROR GetLocalizedStringIdentifierForTest(TLVReader & reader, Optional<LocalizedStringIdentifier> & lsid,
1124 : bool validateCharString);
1125 : #endif // CHIP_CONFIG_TEST
1126 :
1127 : } // namespace TLV
1128 : } // namespace chip
|