LCOV - code coverage report
Current view: top level - lib/core - TLVReader.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 32 37 86.5 %
Date: 2024-02-15 08:20:41 Functions: 28 32 87.5 %

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

Generated by: LCOV version 1.14