1317027Sdim//===-- DataEncoder.h -------------------------------------------*- C++ -*-===// 2317027Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6317027Sdim// 7317027Sdim//===----------------------------------------------------------------------===// 8317027Sdim 9317027Sdim#ifndef liblldb_DataEncoder_h_ 10317027Sdim#define liblldb_DataEncoder_h_ 11317027Sdim 12317027Sdim#if defined(__cplusplus) 13317027Sdim 14344779Sdim#include "lldb/lldb-defines.h" 15344779Sdim#include "lldb/lldb-enumerations.h" 16344779Sdim#include "lldb/lldb-forward.h" 17344779Sdim#include "lldb/lldb-types.h" 18317027Sdim 19344779Sdim#include <stddef.h> 20317027Sdim#include <stdint.h> 21317027Sdim 22317027Sdimnamespace lldb_private { 23317027Sdim 24360784Sdim/// \class DataEncoder 25317027Sdim/// 26360784Sdim/// An binary data encoding class. 27360784Sdim/// 28341825Sdim/// DataEncoder is a class that can encode binary data (swapping if needed) to 29341825Sdim/// a data buffer. The data buffer can be caller owned, or can be shared data 30341825Sdim/// that can be shared between multiple DataEncoder or DataEncoder instances. 31317027Sdim/// 32353358Sdim/// \see DataBuffer 33317027Sdimclass DataEncoder { 34317027Sdimpublic: 35317027Sdim /// Default constructor. 36317027Sdim /// 37317027Sdim /// Initialize all members to a default empty state. 38317027Sdim DataEncoder(); 39317027Sdim 40317027Sdim /// Construct with a buffer that is owned by the caller. 41317027Sdim /// 42341825Sdim /// This constructor allows us to use data that is owned by the caller. The 43341825Sdim /// data must stay around as long as this object is valid. 44317027Sdim /// 45353358Sdim /// \param[in] data 46317027Sdim /// A pointer to caller owned data. 47317027Sdim /// 48353358Sdim /// \param[in] data_length 49317027Sdim /// The length in bytes of \a data. 50317027Sdim /// 51353358Sdim /// \param[in] byte_order 52317027Sdim /// A byte order of the data that we are extracting from. 53317027Sdim /// 54353358Sdim /// \param[in] addr_size 55317027Sdim /// A new address byte size value. 56317027Sdim DataEncoder(void *data, uint32_t data_length, lldb::ByteOrder byte_order, 57317027Sdim uint8_t addr_size); 58317027Sdim 59317027Sdim /// Construct with shared data. 60317027Sdim /// 61341825Sdim /// Copies the data shared pointer which adds a reference to the contained 62341825Sdim /// in \a data_sp. The shared data reference is reference counted to ensure 63341825Sdim /// the data lives as long as anyone still has a valid shared pointer to the 64341825Sdim /// data in \a data_sp. 65317027Sdim /// 66353358Sdim /// \param[in] data_sp 67317027Sdim /// A shared pointer to data. 68317027Sdim /// 69353358Sdim /// \param[in] byte_order 70317027Sdim /// A byte order of the data that we are extracting from. 71317027Sdim /// 72353358Sdim /// \param[in] addr_size 73317027Sdim /// A new address byte size value. 74317027Sdim DataEncoder(const lldb::DataBufferSP &data_sp, lldb::ByteOrder byte_order, 75317027Sdim uint8_t addr_size); 76317027Sdim 77317027Sdim /// Destructor 78317027Sdim /// 79341825Sdim /// If this object contains a valid shared data reference, the reference 80341825Sdim /// count on the data will be decremented, and if zero, the data will be 81341825Sdim /// freed. 82317027Sdim ~DataEncoder(); 83317027Sdim 84317027Sdim /// Clears the object state. 85317027Sdim /// 86341825Sdim /// Clears the object contents back to a default invalid state, and release 87341825Sdim /// any references to shared data that this object may contain. 88317027Sdim void Clear(); 89317027Sdim 90317027Sdim /// Encode an unsigned integer of size \a byte_size to \a offset. 91317027Sdim /// 92341825Sdim /// Encode a single integer value at \a offset and return the offset that 93341825Sdim /// follows the newly encoded integer when the data is successfully encoded 94341825Sdim /// into the existing data. There must be enough room in the data, else 95341825Sdim /// UINT32_MAX will be returned to indicate that encoding failed. 96317027Sdim /// 97353358Sdim /// \param[in] offset 98317027Sdim /// The offset within the contained data at which to put the 99317027Sdim /// encoded integer. 100317027Sdim /// 101353358Sdim /// \param[in] byte_size 102317027Sdim /// The size in byte of the integer to encode. 103317027Sdim /// 104353358Sdim /// \param[in] value 105317027Sdim /// The integer value to write. The least significant bytes of 106317027Sdim /// the integer value will be written if the size is less than 107317027Sdim /// 8 bytes. 108317027Sdim /// 109353358Sdim /// \return 110317027Sdim /// The next offset in the bytes of this data if the integer 111317027Sdim /// was successfully encoded, UINT32_MAX if the encoding failed. 112360784Sdim uint32_t PutUnsigned(uint32_t offset, uint32_t byte_size, uint64_t value); 113317027Sdim 114317027Sdim /// Encode an arbitrary number of bytes. 115317027Sdim /// 116353358Sdim /// \param[in] offset 117317027Sdim /// The offset in bytes into the contained data at which to 118317027Sdim /// start encoding. 119317027Sdim /// 120353358Sdim /// \param[in] src 121317027Sdim /// The buffer that contains the bytes to encode. 122317027Sdim /// 123353358Sdim /// \param[in] src_len 124317027Sdim /// The number of bytes to encode. 125317027Sdim /// 126353358Sdim /// \return 127317027Sdim /// The next valid offset within data if the put operation 128317027Sdim /// was successful, else UINT32_MAX to indicate the put failed. 129317027Sdim uint32_t PutData(uint32_t offset, const void *src, uint32_t src_len); 130317027Sdim 131341825Sdim /// Encode an address in the existing buffer at \a offset bytes into the 132341825Sdim /// buffer. 133317027Sdim /// 134341825Sdim /// Encode a single address (honoring the m_addr_size member) to the data 135341825Sdim /// and return the next offset where subsequent data would go. pointed to by 136341825Sdim /// \a offset_ptr. The size of the extracted address comes from the \a 137341825Sdim /// m_addr_size member variable and should be set correctly prior to 138341825Sdim /// extracting any address values. 139317027Sdim /// 140360784Sdim /// \param[in] offset 141360784Sdim /// The offset where to encode the address. 142317027Sdim /// 143360784Sdim /// \param[in] addr 144360784Sdim /// The address to encode. 145360784Sdim /// 146353358Sdim /// \return 147317027Sdim /// The next valid offset within data if the put operation 148317027Sdim /// was successful, else UINT32_MAX to indicate the put failed. 149317027Sdim uint32_t PutAddress(uint32_t offset, lldb::addr_t addr); 150317027Sdim 151317027Sdim /// Put a C string to \a offset. 152317027Sdim /// 153341825Sdim /// Encodes a C string into the existing data including the terminating 154317027Sdim /// 155360784Sdim /// \param[in] offset 156360784Sdim /// The offset where to encode the string. 157317027Sdim /// 158360784Sdim /// \param[in] cstr 159360784Sdim /// The string to encode. 160360784Sdim /// 161353358Sdim /// \return 162317027Sdim /// A pointer to the C string value in the data. If the offset 163317027Sdim /// pointed to by \a offset_ptr is out of bounds, or if the 164317027Sdim /// offset plus the length of the C string is out of bounds, 165317027Sdim /// NULL will be returned. 166360784Sdim uint32_t PutCString(uint32_t offset, const char *cstr); 167317027Sdim 168360784Sdimprivate: 169360784Sdim uint32_t PutU8(uint32_t offset, uint8_t value); 170360784Sdim uint32_t PutU16(uint32_t offset, uint16_t value); 171360784Sdim uint32_t PutU32(uint32_t offset, uint32_t value); 172360784Sdim uint32_t PutU64(uint32_t offset, uint64_t value); 173317027Sdim 174360784Sdim uint32_t BytesLeft(uint32_t offset) const { 175360784Sdim const uint32_t size = GetByteSize(); 176360784Sdim if (size > offset) 177360784Sdim return size - offset; 178360784Sdim return 0; 179360784Sdim } 180317027Sdim 181360784Sdim /// Test the availability of \a length bytes of data from \a offset. 182317027Sdim /// 183353358Sdim /// \return 184360784Sdim /// \b true if \a offset is a valid offset and there are \a 185360784Sdim /// length bytes available at that offset, \b false otherwise. 186360784Sdim bool ValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const { 187360784Sdim return length <= BytesLeft(offset); 188360784Sdim } 189317027Sdim 190317027Sdim /// Adopt a subset of shared data in \a data_sp. 191317027Sdim /// 192341825Sdim /// Copies the data shared pointer which adds a reference to the contained 193341825Sdim /// in \a data_sp. The shared data reference is reference counted to ensure 194341825Sdim /// the data lives as long as anyone still has a valid shared pointer to the 195341825Sdim /// data in \a data_sp. The byte order and address byte size settings remain 196341825Sdim /// the same. If \a offset is not a valid offset in \a data_sp, then no 197341825Sdim /// reference to the shared data will be added. If there are not \a length 198341825Sdim /// bytes available in \a data starting at \a offset, the length will be 199341825Sdim /// truncated to contains as many bytes as possible. 200317027Sdim /// 201353358Sdim /// \param[in] data_sp 202317027Sdim /// A shared pointer to data. 203317027Sdim /// 204353358Sdim /// \param[in] offset 205317027Sdim /// The offset into \a data_sp at which the subset starts. 206317027Sdim /// 207353358Sdim /// \param[in] length 208317027Sdim /// The length in bytes of the subset of \a data_sp. 209317027Sdim /// 210353358Sdim /// \return 211317027Sdim /// The number of bytes that this object now contains. 212317027Sdim uint32_t SetData(const lldb::DataBufferSP &data_sp, uint32_t offset = 0, 213317027Sdim uint32_t length = UINT32_MAX); 214317027Sdim 215317027Sdim /// Test the validity of \a offset. 216317027Sdim /// 217353358Sdim /// \return 218317027Sdim /// \b true if \a offset is a valid offset into the data in this 219317027Sdim /// object, \b false otherwise. 220317027Sdim bool ValidOffset(uint32_t offset) const { return offset < GetByteSize(); } 221317027Sdim 222360784Sdim /// Get the number of bytes contained in this object. 223317027Sdim /// 224353358Sdim /// \return 225360784Sdim /// The total number of bytes of data this object refers to. 226360784Sdim size_t GetByteSize() const { return m_end - m_start; } 227317027Sdim 228360784Sdimprivate: 229360784Sdim /// A pointer to the first byte of data. 230360784Sdim uint8_t *m_start; 231317027Sdim 232360784Sdim /// A pointer to the byte that is past the end of the data. 233360784Sdim uint8_t *m_end; 234317027Sdim 235360784Sdim /// The byte order of the data we are extracting from. 236360784Sdim lldb::ByteOrder m_byte_order; 237360784Sdim 238360784Sdim /// The address size to use when extracting pointers or 239360784Sdim /// addresses 240360784Sdim uint8_t m_addr_size; 241360784Sdim 242360784Sdim /// The shared pointer to data that can 243360784Sdim /// be shared among multiple instances 244360784Sdim mutable lldb::DataBufferSP m_data_sp; 245360784Sdim 246317027Sdim DISALLOW_COPY_AND_ASSIGN(DataEncoder); 247317027Sdim}; 248317027Sdim 249317027Sdim} // namespace lldb_private 250317027Sdim 251317027Sdim#endif // #if defined (__cplusplus) 252317027Sdim#endif // #ifndef liblldb_DataEncoder_h_ 253