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 LLDB_UTILITY_DATAENCODER_H
10 #define LLDB_UTILITY_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 
22 namespace 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
33 class DataEncoder {
34 public:
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 
168 private:
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 
228   /// A pointer to the first byte of data.
229   uint8_t *m_start;
230 
231   /// A pointer to the byte that is past the end of the data.
232   uint8_t *m_end;
233 
234   /// The byte order of the data we are extracting from.
235   lldb::ByteOrder m_byte_order;
236 
237   /// The address size to use when extracting pointers or
238   /// addresses
239   uint8_t m_addr_size;
240 
241   /// The shared pointer to data that can
242   /// be shared among multiple instances
243   mutable lldb::DataBufferSP m_data_sp;
244 
245   DataEncoder(const DataEncoder &) = delete;
246   const DataEncoder &operator=(const DataEncoder &) = delete;
247 };
248 
249 } // namespace lldb_private
250 
251 #endif // #if defined (__cplusplus)
252 #endif // LLDB_UTILITY_DATAENCODER_H
253