1//===-- DataEncoder.h -------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef liblldb_DataEncoder_h_
10#define liblldb_DataEncoder_h_
11
12#if defined(__cplusplus)
13
14#include "lldb/lldb-defines.h"
15#include "lldb/lldb-enumerations.h"
16#include "lldb/lldb-forward.h"
17#include "lldb/lldb-types.h"
18
19#include <stddef.h>
20#include <stdint.h>
21
22namespace lldb_private {
23
24/// \class DataEncoder
25///
26/// An binary data encoding class.
27///
28/// DataEncoder is a class that can encode binary data (swapping if needed) to
29/// a data buffer. The data buffer can be caller owned, or can be shared data
30/// that can be shared between multiple DataEncoder or DataEncoder instances.
31///
32/// \see DataBuffer
33class DataEncoder {
34public:
35  /// Default constructor.
36  ///
37  /// Initialize all members to a default empty state.
38  DataEncoder();
39
40  /// Construct with a buffer that is owned by the caller.
41  ///
42  /// This constructor allows us to use data that is owned by the caller. The
43  /// data must stay around as long as this object is valid.
44  ///
45  /// \param[in] data
46  ///     A pointer to caller owned data.
47  ///
48  /// \param[in] data_length
49  ///     The length in bytes of \a data.
50  ///
51  /// \param[in] byte_order
52  ///     A byte order of the data that we are extracting from.
53  ///
54  /// \param[in] addr_size
55  ///     A new address byte size value.
56  DataEncoder(void *data, uint32_t data_length, lldb::ByteOrder byte_order,
57              uint8_t addr_size);
58
59  /// Construct with shared data.
60  ///
61  /// Copies the data shared pointer which adds a reference to the contained
62  /// in \a data_sp. The shared data reference is reference counted to ensure
63  /// the data lives as long as anyone still has a valid shared pointer to the
64  /// data in \a data_sp.
65  ///
66  /// \param[in] data_sp
67  ///     A shared pointer to data.
68  ///
69  /// \param[in] byte_order
70  ///     A byte order of the data that we are extracting from.
71  ///
72  /// \param[in] addr_size
73  ///     A new address byte size value.
74  DataEncoder(const lldb::DataBufferSP &data_sp, lldb::ByteOrder byte_order,
75              uint8_t addr_size);
76
77  /// Destructor
78  ///
79  /// If this object contains a valid shared data reference, the reference
80  /// count on the data will be decremented, and if zero, the data will be
81  /// freed.
82  ~DataEncoder();
83
84  /// Clears the object state.
85  ///
86  /// Clears the object contents back to a default invalid state, and release
87  /// any references to shared data that this object may contain.
88  void Clear();
89
90  /// Encode an unsigned integer of size \a byte_size to \a offset.
91  ///
92  /// Encode a single integer value at \a offset and return the offset that
93  /// follows the newly encoded integer when the data is successfully encoded
94  /// into the existing data. There must be enough room in the data, else
95  /// UINT32_MAX will be returned to indicate that encoding failed.
96  ///
97  /// \param[in] offset
98  ///     The offset within the contained data at which to put the
99  ///     encoded integer.
100  ///
101  /// \param[in] byte_size
102  ///     The size in byte of the integer to encode.
103  ///
104  /// \param[in] value
105  ///     The integer value to write. The least significant bytes of
106  ///     the integer value will be written if the size is less than
107  ///     8 bytes.
108  ///
109  /// \return
110  ///     The next offset in the bytes of this data if the integer
111  ///     was successfully encoded, UINT32_MAX if the encoding failed.
112  uint32_t PutUnsigned(uint32_t offset, uint32_t byte_size, uint64_t value);
113
114  /// Encode an arbitrary number of bytes.
115  ///
116  /// \param[in] offset
117  ///     The offset in bytes into the contained data at which to
118  ///     start encoding.
119  ///
120  /// \param[in] src
121  ///     The buffer that contains the bytes to encode.
122  ///
123  /// \param[in] src_len
124  ///     The number of bytes to encode.
125  ///
126  /// \return
127  ///     The next valid offset within data if the put operation
128  ///     was successful, else UINT32_MAX to indicate the put failed.
129  uint32_t PutData(uint32_t offset, const void *src, uint32_t src_len);
130
131  /// Encode an address in the existing buffer at \a offset bytes into the
132  /// buffer.
133  ///
134  /// Encode a single address (honoring the m_addr_size member) to the data
135  /// and return the next offset where subsequent data would go. pointed to by
136  /// \a offset_ptr. The size of the extracted address comes from the \a
137  /// m_addr_size member variable and should be set correctly prior to
138  /// extracting any address values.
139  ///
140  /// \param[in] offset
141  ///     The offset where to encode the address.
142  ///
143  /// \param[in] addr
144  ///     The address to encode.
145  ///
146  /// \return
147  ///     The next valid offset within data if the put operation
148  ///     was successful, else UINT32_MAX to indicate the put failed.
149  uint32_t PutAddress(uint32_t offset, lldb::addr_t addr);
150
151  /// Put a C string to \a offset.
152  ///
153  /// Encodes a C string into the existing data including the terminating
154  ///
155  /// \param[in] offset
156  ///     The offset where to encode the string.
157  ///
158  /// \param[in] cstr
159  ///     The string to encode.
160  ///
161  /// \return
162  ///     A pointer to the C string value in the data. If the offset
163  ///     pointed to by \a offset_ptr is out of bounds, or if the
164  ///     offset plus the length of the C string is out of bounds,
165  ///     NULL will be returned.
166  uint32_t PutCString(uint32_t offset, const char *cstr);
167
168private:
169  uint32_t PutU8(uint32_t offset, uint8_t value);
170  uint32_t PutU16(uint32_t offset, uint16_t value);
171  uint32_t PutU32(uint32_t offset, uint32_t value);
172  uint32_t PutU64(uint32_t offset, uint64_t value);
173
174  uint32_t BytesLeft(uint32_t offset) const {
175    const uint32_t size = GetByteSize();
176    if (size > offset)
177      return size - offset;
178    return 0;
179  }
180
181  /// Test the availability of \a length bytes of data from \a offset.
182  ///
183  /// \return
184  ///     \b true if \a offset is a valid offset and there are \a
185  ///     length bytes available at that offset, \b false otherwise.
186  bool ValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const {
187    return length <= BytesLeft(offset);
188  }
189
190  /// Adopt a subset of shared data in \a data_sp.
191  ///
192  /// Copies the data shared pointer which adds a reference to the contained
193  /// in \a data_sp. The shared data reference is reference counted to ensure
194  /// the data lives as long as anyone still has a valid shared pointer to the
195  /// data in \a data_sp. The byte order and address byte size settings remain
196  /// the same. If \a offset is not a valid offset in \a data_sp, then no
197  /// reference to the shared data will be added. If there are not \a length
198  /// bytes available in \a data starting at \a offset, the length will be
199  /// truncated to contains as many bytes as possible.
200  ///
201  /// \param[in] data_sp
202  ///     A shared pointer to data.
203  ///
204  /// \param[in] offset
205  ///     The offset into \a data_sp at which the subset starts.
206  ///
207  /// \param[in] length
208  ///     The length in bytes of the subset of \a data_sp.
209  ///
210  /// \return
211  ///     The number of bytes that this object now contains.
212  uint32_t SetData(const lldb::DataBufferSP &data_sp, uint32_t offset = 0,
213                   uint32_t length = UINT32_MAX);
214
215  /// Test the validity of \a offset.
216  ///
217  /// \return
218  ///     \b true if \a offset is a valid offset into the data in this
219  ///     object, \b false otherwise.
220  bool ValidOffset(uint32_t offset) const { return offset < GetByteSize(); }
221
222  /// Get the number of bytes contained in this object.
223  ///
224  /// \return
225  ///     The total number of bytes of data this object refers to.
226  size_t GetByteSize() const { return m_end - m_start; }
227
228private:
229  /// A pointer to the first byte of data.
230  uint8_t *m_start;
231
232  /// A pointer to the byte that is past the end of the data.
233  uint8_t *m_end;
234
235  /// The byte order of the data we are extracting from.
236  lldb::ByteOrder m_byte_order;
237
238  /// The address size to use when extracting pointers or
239  /// addresses
240  uint8_t m_addr_size;
241
242  /// The shared pointer to data that can
243  /// be shared among multiple instances
244  mutable lldb::DataBufferSP m_data_sp;
245
246  DISALLOW_COPY_AND_ASSIGN(DataEncoder);
247};
248
249} // namespace lldb_private
250
251#endif // #if defined (__cplusplus)
252#endif // #ifndef liblldb_DataEncoder_h_
253