LCOV - code coverage report
Current view: top level - lib/core - TLVWriter.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 30 30 100.0 %
Date: 2024-02-15 08:20:41 Functions: 19 20 95.0 %

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

Generated by: LCOV version 1.14