1 /* 2 * Copyright (c) 2021, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file defines OpenThread `Appender` class. 32 */ 33 34 #ifndef APPENDER_HPP_ 35 #define APPENDER_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/const_cast.hpp" 40 #include "common/data.hpp" 41 #include "common/frame_builder.hpp" 42 #include "common/message.hpp" 43 #include "common/type_traits.hpp" 44 45 namespace ot { 46 47 /** 48 * The `Appender` class acts as a wrapper over either a `Message` or a data buffer and provides different flavors of 49 * `Append()` method. 50 * 51 * Helps in construction of message content where the destination can be either a `Message` or a buffer. 52 * 53 */ 54 class Appender 55 { 56 public: 57 /** 58 * Represent the `Appender` Type (whether appending to a `Message` or data buffer). 59 * 60 */ 61 enum Type : uint8_t 62 { 63 kMessage, ///< `Appender` appends to a `Message` 64 kBuffer, ///< `Appender` appends to a buffer. 65 }; 66 67 /** 68 * Initializes the `Appender` to append to a `Message`. 69 * 70 * New content is appended to the end of @p aMessage, growing its length. 71 * 72 * @param[in] aMessage The message to append to. 73 * 74 */ 75 explicit Appender(Message &aMessage); 76 77 /** 78 * Initializes the `Appender` to append in a given a buffer 79 * 80 * New content is append in the buffer starting from @p aBuffer up to is size @p aSize. `Appender` does not allow 81 * content to be appended beyond the size of the buffer. 82 * 83 * @param[in] aBuffer A pointer to start of buffer. 84 * @param[in] aSize The maximum size of @p aBuffer (number of available bytes in buffer). 85 * 86 */ 87 Appender(uint8_t *aBuffer, uint16_t aSize); 88 89 /** 90 * Indicates the `Appender` type (whether appending to a `Message` or data buffer). 91 * 92 * @returns The type of `Appender`. 93 * 94 */ GetType(void) const95 Type GetType(void) const { return mType; } 96 97 /** 98 * Appends bytes to the `Appender` object 99 * 100 * @param[in] aBuffer A pointer to a data buffer (MUST NOT be `nullptr`) to append. 101 * @param[in] aLength The number of bytes to append. 102 * 103 * @retval kErrorNone Successfully appended the bytes. 104 * @retval kErrorNoBufs Insufficient available buffers. 105 * 106 */ 107 Error AppendBytes(const void *aBuffer, uint16_t aLength); 108 109 /** 110 * Appends an object to the end of the `Appender` object. 111 * 112 * @tparam ObjectType The object type to append to the message. 113 * 114 * @param[in] aObject A reference to the object to append to the message. 115 * 116 * @retval kErrorNone Successfully appended the object. 117 * @retval kErrorNoBufs Insufficient available buffers to append @p aObject. 118 * 119 */ Append(const ObjectType & aObject)120 template <typename ObjectType> Error Append(const ObjectType &aObject) 121 { 122 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); 123 124 return AppendBytes(&aObject, sizeof(ObjectType)); 125 } 126 127 /** 128 * Returns the number of bytes appended so far using `Appender` methods. 129 * 130 * Can be used independent of the `Type` of `Appender`. 131 * 132 * @returns The number of byes appended so far. 133 * 134 */ 135 uint16_t GetAppendedLength(void) const; 136 137 /** 138 * Returns the `Message` associated with `Appender`. 139 * 140 * MUST be used when `GetType() == kMessage`. Otherwise its behavior is undefined. 141 * 142 * @returns The `Message` instance associated with `Appender`. 143 * 144 */ GetMessage(void) const145 Message &GetMessage(void) const { return *mShared.mMessage.mMessage; } 146 147 /** 148 * Returns a pointer to the start of the data buffer associated with `Appender`. 149 * 150 * MUST be used when `GetType() == kBuffer`. Otherwise its behavior is undefined. 151 * 152 * @returns A pointer to the start of the data buffer associated with `Appender`. 153 * 154 */ GetBufferStart(void) const155 uint8_t *GetBufferStart(void) const { return AsNonConst(mShared.mFrameBuilder.GetBytes()); } 156 157 /** 158 * Gets the data buffer associated with `Appender` as a `Data`. 159 * 160 * MUST be used when `GetType() == kBuffer`. Otherwise its behavior is undefined. 161 * 162 * @pram[out] aData A reference to a `Data` to output the data buffer. 163 * 164 */ 165 void GetAsData(Data<kWithUint16Length> &aData) const; 166 167 private: 168 Type mType; 169 union 170 { 171 struct 172 { 173 Message *mMessage; 174 uint16_t mStartOffset; 175 } mMessage; 176 177 FrameBuilder mFrameBuilder; 178 } mShared; 179 }; 180 181 } // namespace ot 182 183 #endif // APPENDER_HPP_ 184