Matter SDK Coverage Report
Current view: top level - lib/core - TLVReader.h (source / functions) Coverage Total Hit
Test: SHA:209dc18e4021e7d0dff8120ccc585909391dd862 Lines: 100.0 % 44 44
Test Date: 2026-06-16 07:34:53 Functions: 91.7 % 96 88

            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
        

Generated by: LCOV version 2.0-1