Matter SDK Coverage Report
Current view: top level - lib/core - TLVWriter.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 100.0 % 30 30
Test Date: 2025-01-17 19:00:11 Functions: 95.2 % 21 20

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

Generated by: LCOV version 2.0-1