10b57cec5SDimitry Andric //===-- DataExtractor.h -----------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_SUPPORT_DATAEXTRACTOR_H
100b57cec5SDimitry Andric #define LLVM_SUPPORT_DATAEXTRACTOR_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
130b57cec5SDimitry Andric #include "llvm/Support/DataTypes.h"
148bcb0991SDimitry Andric #include "llvm/Support/Error.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric namespace llvm {
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric /// An auxiliary type to facilitate extraction of 3-byte entities.
190b57cec5SDimitry Andric struct Uint24 {
200b57cec5SDimitry Andric   uint8_t Bytes[3];
Uint24Uint24210b57cec5SDimitry Andric   Uint24(uint8_t U) {
220b57cec5SDimitry Andric     Bytes[0] = Bytes[1] = Bytes[2] = U;
230b57cec5SDimitry Andric   }
Uint24Uint24240b57cec5SDimitry Andric   Uint24(uint8_t U0, uint8_t U1, uint8_t U2) {
250b57cec5SDimitry Andric     Bytes[0] = U0; Bytes[1] = U1; Bytes[2] = U2;
260b57cec5SDimitry Andric   }
getAsUint32Uint24270b57cec5SDimitry Andric   uint32_t getAsUint32(bool IsLittleEndian) const {
280b57cec5SDimitry Andric     int LoIx = IsLittleEndian ? 0 : 2;
290b57cec5SDimitry Andric     return Bytes[LoIx] + (Bytes[1] << 8) + (Bytes[2-LoIx] << 16);
300b57cec5SDimitry Andric   }
310b57cec5SDimitry Andric };
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using uint24_t = Uint24;
340b57cec5SDimitry Andric static_assert(sizeof(uint24_t) == 3, "sizeof(uint24_t) != 3");
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric /// Needed by swapByteOrder().
getSwappedBytes(uint24_t C)370b57cec5SDimitry Andric inline uint24_t getSwappedBytes(uint24_t C) {
380b57cec5SDimitry Andric   return uint24_t(C.Bytes[2], C.Bytes[1], C.Bytes[0]);
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric class DataExtractor {
420b57cec5SDimitry Andric   StringRef Data;
430b57cec5SDimitry Andric   uint8_t IsLittleEndian;
440b57cec5SDimitry Andric   uint8_t AddressSize;
450b57cec5SDimitry Andric public:
468bcb0991SDimitry Andric   /// A class representing a position in a DataExtractor, as well as any error
478bcb0991SDimitry Andric   /// encountered during extraction. It enables one to extract a sequence of
488bcb0991SDimitry Andric   /// values without error-checking and then checking for errors in bulk at the
498bcb0991SDimitry Andric   /// end. The class holds an Error object, so failing to check the result of
508bcb0991SDimitry Andric   /// the parse will result in a runtime error. The error flag is sticky and
518bcb0991SDimitry Andric   /// will cause all subsequent extraction functions to fail without even
528bcb0991SDimitry Andric   /// attempting to parse and without updating the Cursor offset. After clearing
538bcb0991SDimitry Andric   /// the error flag, one can again use the Cursor object for parsing.
548bcb0991SDimitry Andric   class Cursor {
558bcb0991SDimitry Andric     uint64_t Offset;
568bcb0991SDimitry Andric     Error Err;
578bcb0991SDimitry Andric 
588bcb0991SDimitry Andric     friend class DataExtractor;
598bcb0991SDimitry Andric 
608bcb0991SDimitry Andric   public:
618bcb0991SDimitry Andric     /// Construct a cursor for extraction from the given offset.
Cursor(uint64_t Offset)628bcb0991SDimitry Andric     explicit Cursor(uint64_t Offset) : Offset(Offset), Err(Error::success()) {}
638bcb0991SDimitry Andric 
648bcb0991SDimitry Andric     /// Checks whether the cursor is valid (i.e. no errors were encountered). In
658bcb0991SDimitry Andric     /// case of errors, this does not clear the error flag -- one must call
668bcb0991SDimitry Andric     /// takeError() instead.
678bcb0991SDimitry Andric     explicit operator bool() { return !Err; }
688bcb0991SDimitry Andric 
698bcb0991SDimitry Andric     /// Return the current position of this Cursor. In the error state this is
708bcb0991SDimitry Andric     /// the position of the Cursor before the first error was encountered.
tell()718bcb0991SDimitry Andric     uint64_t tell() const { return Offset; }
728bcb0991SDimitry Andric 
73349cc55cSDimitry Andric     /// Set the cursor to the new offset. This does not impact the error state.
seek(uint64_t NewOffSet)74349cc55cSDimitry Andric     void seek(uint64_t NewOffSet) { Offset = NewOffSet; }
75349cc55cSDimitry Andric 
768bcb0991SDimitry Andric     /// Return error contained inside this Cursor, if any. Clears the internal
778bcb0991SDimitry Andric     /// Cursor state.
takeError()788bcb0991SDimitry Andric     Error takeError() { return std::move(Err); }
798bcb0991SDimitry Andric   };
808bcb0991SDimitry Andric 
810b57cec5SDimitry Andric   /// Construct with a buffer that is owned by the caller.
820b57cec5SDimitry Andric   ///
830b57cec5SDimitry Andric   /// This constructor allows us to use data that is owned by the
840b57cec5SDimitry Andric   /// caller. The data must stay around as long as this object is
850b57cec5SDimitry Andric   /// valid.
DataExtractor(StringRef Data,bool IsLittleEndian,uint8_t AddressSize)860b57cec5SDimitry Andric   DataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize)
870b57cec5SDimitry Andric     : Data(Data), IsLittleEndian(IsLittleEndian), AddressSize(AddressSize) {}
DataExtractor(ArrayRef<uint8_t> Data,bool IsLittleEndian,uint8_t AddressSize)888bcb0991SDimitry Andric   DataExtractor(ArrayRef<uint8_t> Data, bool IsLittleEndian,
898bcb0991SDimitry Andric                 uint8_t AddressSize)
908bcb0991SDimitry Andric       : Data(StringRef(reinterpret_cast<const char *>(Data.data()),
918bcb0991SDimitry Andric                        Data.size())),
928bcb0991SDimitry Andric         IsLittleEndian(IsLittleEndian), AddressSize(AddressSize) {}
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   /// Get the data pointed to by this extractor.
getData()950b57cec5SDimitry Andric   StringRef getData() const { return Data; }
960b57cec5SDimitry Andric   /// Get the endianness for this extractor.
isLittleEndian()970b57cec5SDimitry Andric   bool isLittleEndian() const { return IsLittleEndian; }
980b57cec5SDimitry Andric   /// Get the address size for this extractor.
getAddressSize()990b57cec5SDimitry Andric   uint8_t getAddressSize() const { return AddressSize; }
1000b57cec5SDimitry Andric   /// Set the address size for this extractor.
setAddressSize(uint8_t Size)1010b57cec5SDimitry Andric   void setAddressSize(uint8_t Size) { AddressSize = Size; }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   /// Extract a C string from \a *offset_ptr.
1040b57cec5SDimitry Andric   ///
1050b57cec5SDimitry Andric   /// Returns a pointer to a C String from the data at the offset
1060b57cec5SDimitry Andric   /// pointed to by \a offset_ptr. A variable length NULL terminated C
1070b57cec5SDimitry Andric   /// string will be extracted and the \a offset_ptr will be
1080b57cec5SDimitry Andric   /// updated with the offset of the byte that follows the NULL
1090b57cec5SDimitry Andric   /// terminator byte.
1100b57cec5SDimitry Andric   ///
1115ffd83dbSDimitry Andric   /// @param[in,out] OffsetPtr
1120b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
1130b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
1140b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
1150b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
1160b57cec5SDimitry Andric   ///     unmodified.
1170b57cec5SDimitry Andric   ///
1185ffd83dbSDimitry Andric   /// @param[in,out] Err
1195ffd83dbSDimitry Andric   ///     A pointer to an Error object. Upon return the Error object is set to
1205ffd83dbSDimitry Andric   ///     indicate the result (success/failure) of the function. If the Error
1215ffd83dbSDimitry Andric   ///     object is already set when calling this function, no extraction is
1225ffd83dbSDimitry Andric   ///     performed.
1235ffd83dbSDimitry Andric   ///
1240b57cec5SDimitry Andric   /// @return
1250b57cec5SDimitry Andric   ///     A pointer to the C string value in the data. If the offset
1260b57cec5SDimitry Andric   ///     pointed to by \a offset_ptr is out of bounds, or if the
1270b57cec5SDimitry Andric   ///     offset plus the length of the C string is out of bounds,
1280b57cec5SDimitry Andric   ///     NULL will be returned.
1295ffd83dbSDimitry Andric   const char *getCStr(uint64_t *OffsetPtr, Error *Err = nullptr) const {
1305ffd83dbSDimitry Andric     return getCStrRef(OffsetPtr, Err).data();
1315ffd83dbSDimitry Andric   }
1325ffd83dbSDimitry Andric 
1335ffd83dbSDimitry Andric   /// Extract a C string from the location given by the cursor. In case of an
1345ffd83dbSDimitry Andric   /// extraction error, or if the cursor is already in an error state, a
1355ffd83dbSDimitry Andric   /// nullptr is returned.
getCStr(Cursor & C)1365ffd83dbSDimitry Andric   const char *getCStr(Cursor &C) const { return getCStrRef(C).data(); }
1370b57cec5SDimitry Andric 
1388bcb0991SDimitry Andric   /// Extract a C string from \a *offset_ptr.
1390b57cec5SDimitry Andric   ///
1400b57cec5SDimitry Andric   /// Returns a StringRef for the C String from the data at the offset
1418bcb0991SDimitry Andric   /// pointed to by \a offset_ptr. A variable length NULL terminated C
1428bcb0991SDimitry Andric   /// string will be extracted and the \a offset_ptr will be
1430b57cec5SDimitry Andric   /// updated with the offset of the byte that follows the NULL
1440b57cec5SDimitry Andric   /// terminator byte.
1450b57cec5SDimitry Andric   ///
1465ffd83dbSDimitry Andric   /// \param[in,out] OffsetPtr
1470b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
1480b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
1490b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
1500b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
1510b57cec5SDimitry Andric   ///     unmodified.
1520b57cec5SDimitry Andric   ///
1535ffd83dbSDimitry Andric   /// @param[in,out] Err
1545ffd83dbSDimitry Andric   ///     A pointer to an Error object. Upon return the Error object is set to
1555ffd83dbSDimitry Andric   ///     indicate the result (success/failure) of the function. If the Error
1565ffd83dbSDimitry Andric   ///     object is already set when calling this function, no extraction is
1575ffd83dbSDimitry Andric   ///     performed.
1585ffd83dbSDimitry Andric   ///
1590b57cec5SDimitry Andric   /// \return
1600b57cec5SDimitry Andric   ///     A StringRef for the C string value in the data. If the offset
1618bcb0991SDimitry Andric   ///     pointed to by \a offset_ptr is out of bounds, or if the
1620b57cec5SDimitry Andric   ///     offset plus the length of the C string is out of bounds,
1630b57cec5SDimitry Andric   ///     a default-initialized StringRef will be returned.
1645ffd83dbSDimitry Andric   StringRef getCStrRef(uint64_t *OffsetPtr, Error *Err = nullptr) const;
1655ffd83dbSDimitry Andric 
1665ffd83dbSDimitry Andric   /// Extract a C string (as a StringRef) from the location given by the cursor.
1675ffd83dbSDimitry Andric   /// In case of an extraction error, or if the cursor is already in an error
1685ffd83dbSDimitry Andric   /// state, a default-initialized StringRef is returned.
getCStrRef(Cursor & C)1695ffd83dbSDimitry Andric   StringRef getCStrRef(Cursor &C) const {
1705ffd83dbSDimitry Andric     return getCStrRef(&C.Offset, &C.Err);
1715ffd83dbSDimitry Andric   }
1725ffd83dbSDimitry Andric 
1735ffd83dbSDimitry Andric   /// Extract a fixed length string from \a *OffsetPtr and consume \a Length
1745ffd83dbSDimitry Andric   /// bytes.
1755ffd83dbSDimitry Andric   ///
1765ffd83dbSDimitry Andric   /// Returns a StringRef for the string from the data at the offset
1775ffd83dbSDimitry Andric   /// pointed to by \a OffsetPtr. A fixed length C string will be extracted
1785ffd83dbSDimitry Andric   /// and the \a OffsetPtr will be advanced by \a Length bytes.
1795ffd83dbSDimitry Andric   ///
1805ffd83dbSDimitry Andric   /// \param[in,out] OffsetPtr
1815ffd83dbSDimitry Andric   ///     A pointer to an offset within the data that will be advanced
1825ffd83dbSDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
1835ffd83dbSDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
1845ffd83dbSDimitry Andric   ///     enough bytes to extract this value, the offset will be left
1855ffd83dbSDimitry Andric   ///     unmodified.
1865ffd83dbSDimitry Andric   ///
1875ffd83dbSDimitry Andric   /// \param[in] Length
1885ffd83dbSDimitry Andric   ///     The length of the fixed length string to extract. If there are not
1895ffd83dbSDimitry Andric   ///     enough bytes in the data to extract the full string, the offset will
1905ffd83dbSDimitry Andric   ///     be left unmodified.
1915ffd83dbSDimitry Andric   ///
1925ffd83dbSDimitry Andric   /// \param[in] TrimChars
1935ffd83dbSDimitry Andric   ///     A set of characters to trim from the end of the string. Fixed length
1945ffd83dbSDimitry Andric   ///     strings are commonly either NULL terminated by one or more zero
1955ffd83dbSDimitry Andric   ///     bytes. Some clients have one or more spaces at the end of the string,
1965ffd83dbSDimitry Andric   ///     but a good default is to trim the NULL characters.
1975ffd83dbSDimitry Andric   ///
1985ffd83dbSDimitry Andric   /// \return
1995ffd83dbSDimitry Andric   ///     A StringRef for the C string value in the data. If the offset
2005ffd83dbSDimitry Andric   ///     pointed to by \a OffsetPtr is out of bounds, or if the
2015ffd83dbSDimitry Andric   ///     offset plus the length of the C string is out of bounds,
2025ffd83dbSDimitry Andric   ///     a default-initialized StringRef will be returned.
2035ffd83dbSDimitry Andric   StringRef getFixedLengthString(uint64_t *OffsetPtr,
2045ffd83dbSDimitry Andric       uint64_t Length, StringRef TrimChars = {"\0", 1}) const;
2055ffd83dbSDimitry Andric 
2065ffd83dbSDimitry Andric   /// Extract a fixed number of bytes from the specified offset.
2075ffd83dbSDimitry Andric   ///
2085ffd83dbSDimitry Andric   /// Returns a StringRef for the bytes from the data at the offset
2095ffd83dbSDimitry Andric   /// pointed to by \a OffsetPtr. A fixed length C string will be extracted
2105ffd83dbSDimitry Andric   /// and the \a OffsetPtr will be advanced by \a Length bytes.
2115ffd83dbSDimitry Andric   ///
2125ffd83dbSDimitry Andric   /// \param[in,out] OffsetPtr
2135ffd83dbSDimitry Andric   ///     A pointer to an offset within the data that will be advanced
2145ffd83dbSDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
2155ffd83dbSDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
2165ffd83dbSDimitry Andric   ///     enough bytes to extract this value, the offset will be left
2175ffd83dbSDimitry Andric   ///     unmodified.
2185ffd83dbSDimitry Andric   ///
2195ffd83dbSDimitry Andric   /// \param[in] Length
2205ffd83dbSDimitry Andric   ///     The number of bytes to extract. If there are not enough bytes in the
2215ffd83dbSDimitry Andric   ///     data to extract all of the bytes, the offset will be left unmodified.
2225ffd83dbSDimitry Andric   ///
2235ffd83dbSDimitry Andric   /// @param[in,out] Err
2245ffd83dbSDimitry Andric   ///     A pointer to an Error object. Upon return the Error object is set to
2255ffd83dbSDimitry Andric   ///     indicate the result (success/failure) of the function. If the Error
2265ffd83dbSDimitry Andric   ///     object is already set when calling this function, no extraction is
2275ffd83dbSDimitry Andric   ///     performed.
2285ffd83dbSDimitry Andric   ///
2295ffd83dbSDimitry Andric   /// \return
2305ffd83dbSDimitry Andric   ///     A StringRef for the extracted bytes. If the offset pointed to by
2315ffd83dbSDimitry Andric   ///     \a OffsetPtr is out of bounds, or if the offset plus the length
2325ffd83dbSDimitry Andric   ///     is out of bounds, a default-initialized StringRef will be returned.
2335ffd83dbSDimitry Andric   StringRef getBytes(uint64_t *OffsetPtr, uint64_t Length,
2345ffd83dbSDimitry Andric                      Error *Err = nullptr) const;
2355ffd83dbSDimitry Andric 
2365ffd83dbSDimitry Andric   /// Extract a fixed number of bytes from the location given by the cursor. In
2375ffd83dbSDimitry Andric   /// case of an extraction error, or if the cursor is already in an error
2385ffd83dbSDimitry Andric   /// state, a default-initialized StringRef is returned.
getBytes(Cursor & C,uint64_t Length)2395ffd83dbSDimitry Andric   StringRef getBytes(Cursor &C, uint64_t Length) {
2405ffd83dbSDimitry Andric     return getBytes(&C.Offset, Length, &C.Err);
2415ffd83dbSDimitry Andric   }
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   /// Extract an unsigned integer of size \a byte_size from \a
2440b57cec5SDimitry Andric   /// *offset_ptr.
2450b57cec5SDimitry Andric   ///
2460b57cec5SDimitry Andric   /// Extract a single unsigned integer value and update the offset
2470b57cec5SDimitry Andric   /// pointed to by \a offset_ptr. The size of the extracted integer
2480b57cec5SDimitry Andric   /// is specified by the \a byte_size argument. \a byte_size should
2490b57cec5SDimitry Andric   /// have a value greater than or equal to one and less than or equal
2500b57cec5SDimitry Andric   /// to eight since the return value is 64 bits wide. Any
2510b57cec5SDimitry Andric   /// \a byte_size values less than 1 or greater than 8 will result in
2520b57cec5SDimitry Andric   /// nothing being extracted, and zero being returned.
2530b57cec5SDimitry Andric   ///
2540b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
2550b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
2560b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
2570b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
2580b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
2590b57cec5SDimitry Andric   ///     unmodified.
2600b57cec5SDimitry Andric   ///
2610b57cec5SDimitry Andric   /// @param[in] byte_size
2620b57cec5SDimitry Andric   ///     The size in byte of the integer to extract.
2630b57cec5SDimitry Andric   ///
2648bcb0991SDimitry Andric   /// @param[in,out] Err
2658bcb0991SDimitry Andric   ///     A pointer to an Error object. Upon return the Error object is set to
2668bcb0991SDimitry Andric   ///     indicate the result (success/failure) of the function. If the Error
2678bcb0991SDimitry Andric   ///     object is already set when calling this function, no extraction is
2688bcb0991SDimitry Andric   ///     performed.
2698bcb0991SDimitry Andric   ///
2700b57cec5SDimitry Andric   /// @return
2710b57cec5SDimitry Andric   ///     The unsigned integer value that was extracted, or zero on
2720b57cec5SDimitry Andric   ///     failure.
2738bcb0991SDimitry Andric   uint64_t getUnsigned(uint64_t *offset_ptr, uint32_t byte_size,
2748bcb0991SDimitry Andric                        Error *Err = nullptr) const;
2758bcb0991SDimitry Andric 
2768bcb0991SDimitry Andric   /// Extract an unsigned integer of the given size from the location given by
2778bcb0991SDimitry Andric   /// the cursor. In case of an extraction error, or if the cursor is already in
2788bcb0991SDimitry Andric   /// an error state, zero is returned.
getUnsigned(Cursor & C,uint32_t Size)2798bcb0991SDimitry Andric   uint64_t getUnsigned(Cursor &C, uint32_t Size) const {
2808bcb0991SDimitry Andric     return getUnsigned(&C.Offset, Size, &C.Err);
2818bcb0991SDimitry Andric   }
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric   /// Extract an signed integer of size \a byte_size from \a *offset_ptr.
2840b57cec5SDimitry Andric   ///
2850b57cec5SDimitry Andric   /// Extract a single signed integer value (sign extending if required)
2860b57cec5SDimitry Andric   /// and update the offset pointed to by \a offset_ptr. The size of
2870b57cec5SDimitry Andric   /// the extracted integer is specified by the \a byte_size argument.
2880b57cec5SDimitry Andric   /// \a byte_size should have a value greater than or equal to one
2890b57cec5SDimitry Andric   /// and less than or equal to eight since the return value is 64
2900b57cec5SDimitry Andric   /// bits wide. Any \a byte_size values less than 1 or greater than
2910b57cec5SDimitry Andric   /// 8 will result in nothing being extracted, and zero being returned.
2920b57cec5SDimitry Andric   ///
2930b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
2940b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
2950b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
2960b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
2970b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
2980b57cec5SDimitry Andric   ///     unmodified.
2990b57cec5SDimitry Andric   ///
3000b57cec5SDimitry Andric   /// @param[in] size
3010b57cec5SDimitry Andric   ///     The size in bytes of the integer to extract.
3020b57cec5SDimitry Andric   ///
3030b57cec5SDimitry Andric   /// @return
3040b57cec5SDimitry Andric   ///     The sign extended signed integer value that was extracted,
3050b57cec5SDimitry Andric   ///     or zero on failure.
3068bcb0991SDimitry Andric   int64_t getSigned(uint64_t *offset_ptr, uint32_t size) const;
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   //------------------------------------------------------------------
3090b57cec5SDimitry Andric   /// Extract an pointer from \a *offset_ptr.
3100b57cec5SDimitry Andric   ///
3110b57cec5SDimitry Andric   /// Extract a single pointer from the data and update the offset
3120b57cec5SDimitry Andric   /// pointed to by \a offset_ptr. The size of the extracted pointer
3130b57cec5SDimitry Andric   /// is \a getAddressSize(), so the address size has to be
3140b57cec5SDimitry Andric   /// set correctly prior to extracting any pointer values.
3150b57cec5SDimitry Andric   ///
3160b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
3170b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
3180b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
3190b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
3200b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
3210b57cec5SDimitry Andric   ///     unmodified.
3220b57cec5SDimitry Andric   ///
3230b57cec5SDimitry Andric   /// @return
3240b57cec5SDimitry Andric   ///     The extracted pointer value as a 64 integer.
getAddress(uint64_t * offset_ptr)3258bcb0991SDimitry Andric   uint64_t getAddress(uint64_t *offset_ptr) const {
3260b57cec5SDimitry Andric     return getUnsigned(offset_ptr, AddressSize);
3270b57cec5SDimitry Andric   }
3280b57cec5SDimitry Andric 
3298bcb0991SDimitry Andric   /// Extract a pointer-sized unsigned integer from the location given by the
3308bcb0991SDimitry Andric   /// cursor. In case of an extraction error, or if the cursor is already in
3318bcb0991SDimitry Andric   /// an error state, zero is returned.
getAddress(Cursor & C)3328bcb0991SDimitry Andric   uint64_t getAddress(Cursor &C) const { return getUnsigned(C, AddressSize); }
3338bcb0991SDimitry Andric 
3340b57cec5SDimitry Andric   /// Extract a uint8_t value from \a *offset_ptr.
3350b57cec5SDimitry Andric   ///
3360b57cec5SDimitry Andric   /// Extract a single uint8_t from the binary data at the offset
3370b57cec5SDimitry Andric   /// pointed to by \a offset_ptr, and advance the offset on success.
3380b57cec5SDimitry Andric   ///
3390b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
3400b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
3410b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
3420b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
3430b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
3440b57cec5SDimitry Andric   ///     unmodified.
3450b57cec5SDimitry Andric   ///
3468bcb0991SDimitry Andric   /// @param[in,out] Err
3478bcb0991SDimitry Andric   ///     A pointer to an Error object. Upon return the Error object is set to
3488bcb0991SDimitry Andric   ///     indicate the result (success/failure) of the function. If the Error
3498bcb0991SDimitry Andric   ///     object is already set when calling this function, no extraction is
3508bcb0991SDimitry Andric   ///     performed.
3518bcb0991SDimitry Andric   ///
3520b57cec5SDimitry Andric   /// @return
3530b57cec5SDimitry Andric   ///     The extracted uint8_t value.
3548bcb0991SDimitry Andric   uint8_t getU8(uint64_t *offset_ptr, Error *Err = nullptr) const;
3558bcb0991SDimitry Andric 
3568bcb0991SDimitry Andric   /// Extract a single uint8_t value from the location given by the cursor. In
3578bcb0991SDimitry Andric   /// case of an extraction error, or if the cursor is already in an error
3588bcb0991SDimitry Andric   /// state, zero is returned.
getU8(Cursor & C)3598bcb0991SDimitry Andric   uint8_t getU8(Cursor &C) const { return getU8(&C.Offset, &C.Err); }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   /// Extract \a count uint8_t values from \a *offset_ptr.
3620b57cec5SDimitry Andric   ///
3630b57cec5SDimitry Andric   /// Extract \a count uint8_t values from the binary data at the
3640b57cec5SDimitry Andric   /// offset pointed to by \a offset_ptr, and advance the offset on
3650b57cec5SDimitry Andric   /// success. The extracted values are copied into \a dst.
3660b57cec5SDimitry Andric   ///
3670b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
3680b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
3690b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
3700b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
3710b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
3720b57cec5SDimitry Andric   ///     unmodified.
3730b57cec5SDimitry Andric   ///
3740b57cec5SDimitry Andric   /// @param[out] dst
3750b57cec5SDimitry Andric   ///     A buffer to copy \a count uint8_t values into. \a dst must
3760b57cec5SDimitry Andric   ///     be large enough to hold all requested data.
3770b57cec5SDimitry Andric   ///
3780b57cec5SDimitry Andric   /// @param[in] count
3790b57cec5SDimitry Andric   ///     The number of uint8_t values to extract.
3800b57cec5SDimitry Andric   ///
3810b57cec5SDimitry Andric   /// @return
3820b57cec5SDimitry Andric   ///     \a dst if all values were properly extracted and copied,
3830b57cec5SDimitry Andric   ///     NULL otherise.
3848bcb0991SDimitry Andric   uint8_t *getU8(uint64_t *offset_ptr, uint8_t *dst, uint32_t count) const;
3858bcb0991SDimitry Andric 
3868bcb0991SDimitry Andric   /// Extract \a Count uint8_t values from the location given by the cursor and
3878bcb0991SDimitry Andric   /// store them into the destination buffer. In case of an extraction error, or
3888bcb0991SDimitry Andric   /// if the cursor is already in an error state, a nullptr is returned and the
3898bcb0991SDimitry Andric   /// destination buffer is left unchanged.
3908bcb0991SDimitry Andric   uint8_t *getU8(Cursor &C, uint8_t *Dst, uint32_t Count) const;
3918bcb0991SDimitry Andric 
3928bcb0991SDimitry Andric   /// Extract \a Count uint8_t values from the location given by the cursor and
3938bcb0991SDimitry Andric   /// store them into the destination vector. The vector is resized to fit the
3948bcb0991SDimitry Andric   /// extracted data. In case of an extraction error, or if the cursor is
3958bcb0991SDimitry Andric   /// already in an error state, the destination vector is left unchanged and
3968bcb0991SDimitry Andric   /// cursor is placed into an error state.
getU8(Cursor & C,SmallVectorImpl<uint8_t> & Dst,uint32_t Count)3978bcb0991SDimitry Andric   void getU8(Cursor &C, SmallVectorImpl<uint8_t> &Dst, uint32_t Count) const {
3988bcb0991SDimitry Andric     if (isValidOffsetForDataOfSize(C.Offset, Count))
3998bcb0991SDimitry Andric       Dst.resize(Count);
4008bcb0991SDimitry Andric 
4018bcb0991SDimitry Andric     // This relies on the fact that getU8 will not attempt to write to the
4028bcb0991SDimitry Andric     // buffer if isValidOffsetForDataOfSize(C.Offset, Count) is false.
4038bcb0991SDimitry Andric     getU8(C, Dst.data(), Count);
4048bcb0991SDimitry Andric   }
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric   //------------------------------------------------------------------
4070b57cec5SDimitry Andric   /// Extract a uint16_t value from \a *offset_ptr.
4080b57cec5SDimitry Andric   ///
4090b57cec5SDimitry Andric   /// Extract a single uint16_t from the binary data at the offset
4100b57cec5SDimitry Andric   /// pointed to by \a offset_ptr, and update the offset on success.
4110b57cec5SDimitry Andric   ///
4120b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
4130b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
4140b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
4150b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
4160b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
4170b57cec5SDimitry Andric   ///     unmodified.
4180b57cec5SDimitry Andric   ///
4198bcb0991SDimitry Andric   /// @param[in,out] Err
4208bcb0991SDimitry Andric   ///     A pointer to an Error object. Upon return the Error object is set to
4218bcb0991SDimitry Andric   ///     indicate the result (success/failure) of the function. If the Error
4228bcb0991SDimitry Andric   ///     object is already set when calling this function, no extraction is
4238bcb0991SDimitry Andric   ///     performed.
4248bcb0991SDimitry Andric   ///
4250b57cec5SDimitry Andric   /// @return
4260b57cec5SDimitry Andric   ///     The extracted uint16_t value.
4270b57cec5SDimitry Andric   //------------------------------------------------------------------
4288bcb0991SDimitry Andric   uint16_t getU16(uint64_t *offset_ptr, Error *Err = nullptr) const;
4298bcb0991SDimitry Andric 
4308bcb0991SDimitry Andric   /// Extract a single uint16_t value from the location given by the cursor. In
4318bcb0991SDimitry Andric   /// case of an extraction error, or if the cursor is already in an error
4328bcb0991SDimitry Andric   /// state, zero is returned.
getU16(Cursor & C)4338bcb0991SDimitry Andric   uint16_t getU16(Cursor &C) const { return getU16(&C.Offset, &C.Err); }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   /// Extract \a count uint16_t values from \a *offset_ptr.
4360b57cec5SDimitry Andric   ///
4370b57cec5SDimitry Andric   /// Extract \a count uint16_t values from the binary data at the
4380b57cec5SDimitry Andric   /// offset pointed to by \a offset_ptr, and advance the offset on
4390b57cec5SDimitry Andric   /// success. The extracted values are copied into \a dst.
4400b57cec5SDimitry Andric   ///
4410b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
4420b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
4430b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
4440b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
4450b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
4460b57cec5SDimitry Andric   ///     unmodified.
4470b57cec5SDimitry Andric   ///
4480b57cec5SDimitry Andric   /// @param[out] dst
4490b57cec5SDimitry Andric   ///     A buffer to copy \a count uint16_t values into. \a dst must
4500b57cec5SDimitry Andric   ///     be large enough to hold all requested data.
4510b57cec5SDimitry Andric   ///
4520b57cec5SDimitry Andric   /// @param[in] count
4530b57cec5SDimitry Andric   ///     The number of uint16_t values to extract.
4540b57cec5SDimitry Andric   ///
4550b57cec5SDimitry Andric   /// @return
4560b57cec5SDimitry Andric   ///     \a dst if all values were properly extracted and copied,
4570b57cec5SDimitry Andric   ///     NULL otherise.
4588bcb0991SDimitry Andric   uint16_t *getU16(uint64_t *offset_ptr, uint16_t *dst, uint32_t count) const;
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric   /// Extract a 24-bit unsigned value from \a *offset_ptr and return it
4610b57cec5SDimitry Andric   /// in a uint32_t.
4620b57cec5SDimitry Andric   ///
4630b57cec5SDimitry Andric   /// Extract 3 bytes from the binary data at the offset pointed to by
4640b57cec5SDimitry Andric   /// \a offset_ptr, construct a uint32_t from them and update the offset
4650b57cec5SDimitry Andric   /// on success.
4660b57cec5SDimitry Andric   ///
4675ffd83dbSDimitry Andric   /// @param[in,out] OffsetPtr
4680b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
4690b57cec5SDimitry Andric   ///     by the 3 bytes if the value is extracted correctly. If the offset
4700b57cec5SDimitry Andric   ///     is out of bounds or there are not enough bytes to extract this value,
4710b57cec5SDimitry Andric   ///     the offset will be left unmodified.
4720b57cec5SDimitry Andric   ///
4735ffd83dbSDimitry Andric   /// @param[in,out] Err
4745ffd83dbSDimitry Andric   ///     A pointer to an Error object. Upon return the Error object is set to
4755ffd83dbSDimitry Andric   ///     indicate the result (success/failure) of the function. If the Error
4765ffd83dbSDimitry Andric   ///     object is already set when calling this function, no extraction is
4775ffd83dbSDimitry Andric   ///     performed.
4785ffd83dbSDimitry Andric   ///
4790b57cec5SDimitry Andric   /// @return
4800b57cec5SDimitry Andric   ///     The extracted 24-bit value represented in a uint32_t.
4815ffd83dbSDimitry Andric   uint32_t getU24(uint64_t *OffsetPtr, Error *Err = nullptr) const;
4825ffd83dbSDimitry Andric 
4835ffd83dbSDimitry Andric   /// Extract a single 24-bit unsigned value from the location given by the
4845ffd83dbSDimitry Andric   /// cursor. In case of an extraction error, or if the cursor is already in an
4855ffd83dbSDimitry Andric   /// error state, zero is returned.
getU24(Cursor & C)4865ffd83dbSDimitry Andric   uint32_t getU24(Cursor &C) const { return getU24(&C.Offset, &C.Err); }
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   /// Extract a uint32_t value from \a *offset_ptr.
4890b57cec5SDimitry Andric   ///
4900b57cec5SDimitry Andric   /// Extract a single uint32_t from the binary data at the offset
4910b57cec5SDimitry Andric   /// pointed to by \a offset_ptr, and update the offset on success.
4920b57cec5SDimitry Andric   ///
4930b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
4940b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
4950b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
4960b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
4970b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
4980b57cec5SDimitry Andric   ///     unmodified.
4990b57cec5SDimitry Andric   ///
5008bcb0991SDimitry Andric   /// @param[in,out] Err
5018bcb0991SDimitry Andric   ///     A pointer to an Error object. Upon return the Error object is set to
5028bcb0991SDimitry Andric   ///     indicate the result (success/failure) of the function. If the Error
5038bcb0991SDimitry Andric   ///     object is already set when calling this function, no extraction is
5048bcb0991SDimitry Andric   ///     performed.
5058bcb0991SDimitry Andric   ///
5060b57cec5SDimitry Andric   /// @return
5070b57cec5SDimitry Andric   ///     The extracted uint32_t value.
5088bcb0991SDimitry Andric   uint32_t getU32(uint64_t *offset_ptr, Error *Err = nullptr) const;
5098bcb0991SDimitry Andric 
5108bcb0991SDimitry Andric   /// Extract a single uint32_t value from the location given by the cursor. In
5118bcb0991SDimitry Andric   /// case of an extraction error, or if the cursor is already in an error
5128bcb0991SDimitry Andric   /// state, zero is returned.
getU32(Cursor & C)5138bcb0991SDimitry Andric   uint32_t getU32(Cursor &C) const { return getU32(&C.Offset, &C.Err); }
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   /// Extract \a count uint32_t values from \a *offset_ptr.
5160b57cec5SDimitry Andric   ///
5170b57cec5SDimitry Andric   /// Extract \a count uint32_t values from the binary data at the
5180b57cec5SDimitry Andric   /// offset pointed to by \a offset_ptr, and advance the offset on
5190b57cec5SDimitry Andric   /// success. The extracted values are copied into \a dst.
5200b57cec5SDimitry Andric   ///
5210b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
5220b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
5230b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
5240b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
5250b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
5260b57cec5SDimitry Andric   ///     unmodified.
5270b57cec5SDimitry Andric   ///
5280b57cec5SDimitry Andric   /// @param[out] dst
5290b57cec5SDimitry Andric   ///     A buffer to copy \a count uint32_t values into. \a dst must
5300b57cec5SDimitry Andric   ///     be large enough to hold all requested data.
5310b57cec5SDimitry Andric   ///
5320b57cec5SDimitry Andric   /// @param[in] count
5330b57cec5SDimitry Andric   ///     The number of uint32_t values to extract.
5340b57cec5SDimitry Andric   ///
5350b57cec5SDimitry Andric   /// @return
5360b57cec5SDimitry Andric   ///     \a dst if all values were properly extracted and copied,
5370b57cec5SDimitry Andric   ///     NULL otherise.
5388bcb0991SDimitry Andric   uint32_t *getU32(uint64_t *offset_ptr, uint32_t *dst, uint32_t count) const;
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric   /// Extract a uint64_t value from \a *offset_ptr.
5410b57cec5SDimitry Andric   ///
5420b57cec5SDimitry Andric   /// Extract a single uint64_t from the binary data at the offset
5430b57cec5SDimitry Andric   /// pointed to by \a offset_ptr, and update the offset on success.
5440b57cec5SDimitry Andric   ///
5450b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
5460b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
5470b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
5480b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
5490b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
5500b57cec5SDimitry Andric   ///     unmodified.
5510b57cec5SDimitry Andric   ///
5528bcb0991SDimitry Andric   /// @param[in,out] Err
5538bcb0991SDimitry Andric   ///     A pointer to an Error object. Upon return the Error object is set to
5548bcb0991SDimitry Andric   ///     indicate the result (success/failure) of the function. If the Error
5558bcb0991SDimitry Andric   ///     object is already set when calling this function, no extraction is
5568bcb0991SDimitry Andric   ///     performed.
5578bcb0991SDimitry Andric   ///
5580b57cec5SDimitry Andric   /// @return
5590b57cec5SDimitry Andric   ///     The extracted uint64_t value.
5608bcb0991SDimitry Andric   uint64_t getU64(uint64_t *offset_ptr, Error *Err = nullptr) const;
5618bcb0991SDimitry Andric 
5628bcb0991SDimitry Andric   /// Extract a single uint64_t value from the location given by the cursor. In
5638bcb0991SDimitry Andric   /// case of an extraction error, or if the cursor is already in an error
5648bcb0991SDimitry Andric   /// state, zero is returned.
getU64(Cursor & C)5658bcb0991SDimitry Andric   uint64_t getU64(Cursor &C) const { return getU64(&C.Offset, &C.Err); }
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric   /// Extract \a count uint64_t values from \a *offset_ptr.
5680b57cec5SDimitry Andric   ///
5690b57cec5SDimitry Andric   /// Extract \a count uint64_t values from the binary data at the
5700b57cec5SDimitry Andric   /// offset pointed to by \a offset_ptr, and advance the offset on
5710b57cec5SDimitry Andric   /// success. The extracted values are copied into \a dst.
5720b57cec5SDimitry Andric   ///
5730b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
5740b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
5750b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
5760b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
5770b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
5780b57cec5SDimitry Andric   ///     unmodified.
5790b57cec5SDimitry Andric   ///
5800b57cec5SDimitry Andric   /// @param[out] dst
5810b57cec5SDimitry Andric   ///     A buffer to copy \a count uint64_t values into. \a dst must
5820b57cec5SDimitry Andric   ///     be large enough to hold all requested data.
5830b57cec5SDimitry Andric   ///
5840b57cec5SDimitry Andric   /// @param[in] count
5850b57cec5SDimitry Andric   ///     The number of uint64_t values to extract.
5860b57cec5SDimitry Andric   ///
5870b57cec5SDimitry Andric   /// @return
5880b57cec5SDimitry Andric   ///     \a dst if all values were properly extracted and copied,
5890b57cec5SDimitry Andric   ///     NULL otherise.
5908bcb0991SDimitry Andric   uint64_t *getU64(uint64_t *offset_ptr, uint64_t *dst, uint32_t count) const;
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   /// Extract a signed LEB128 value from \a *offset_ptr.
5930b57cec5SDimitry Andric   ///
5940b57cec5SDimitry Andric   /// Extracts an signed LEB128 number from this object's data
5950b57cec5SDimitry Andric   /// starting at the offset pointed to by \a offset_ptr. The offset
5960b57cec5SDimitry Andric   /// pointed to by \a offset_ptr will be updated with the offset of
5970b57cec5SDimitry Andric   /// the byte following the last extracted byte.
5980b57cec5SDimitry Andric   ///
5995ffd83dbSDimitry Andric   /// @param[in,out] OffsetPtr
6000b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
6010b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
6020b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
6030b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
6040b57cec5SDimitry Andric   ///     unmodified.
6050b57cec5SDimitry Andric   ///
6065ffd83dbSDimitry Andric   /// @param[in,out] Err
6075ffd83dbSDimitry Andric   ///     A pointer to an Error object. Upon return the Error object is set to
6085ffd83dbSDimitry Andric   ///     indicate the result (success/failure) of the function. If the Error
6095ffd83dbSDimitry Andric   ///     object is already set when calling this function, no extraction is
6105ffd83dbSDimitry Andric   ///     performed.
6115ffd83dbSDimitry Andric   ///
6120b57cec5SDimitry Andric   /// @return
6130b57cec5SDimitry Andric   ///     The extracted signed integer value.
6145ffd83dbSDimitry Andric   int64_t getSLEB128(uint64_t *OffsetPtr, Error *Err = nullptr) const;
6155ffd83dbSDimitry Andric 
6165ffd83dbSDimitry Andric   /// Extract an signed LEB128 value from the location given by the cursor.
6175ffd83dbSDimitry Andric   /// In case of an extraction error, or if the cursor is already in an error
6185ffd83dbSDimitry Andric   /// state, zero is returned.
getSLEB128(Cursor & C)6195ffd83dbSDimitry Andric   int64_t getSLEB128(Cursor &C) const { return getSLEB128(&C.Offset, &C.Err); }
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   /// Extract a unsigned LEB128 value from \a *offset_ptr.
6220b57cec5SDimitry Andric   ///
6230b57cec5SDimitry Andric   /// Extracts an unsigned LEB128 number from this object's data
6240b57cec5SDimitry Andric   /// starting at the offset pointed to by \a offset_ptr. The offset
6250b57cec5SDimitry Andric   /// pointed to by \a offset_ptr will be updated with the offset of
6260b57cec5SDimitry Andric   /// the byte following the last extracted byte.
6270b57cec5SDimitry Andric   ///
6280b57cec5SDimitry Andric   /// @param[in,out] offset_ptr
6290b57cec5SDimitry Andric   ///     A pointer to an offset within the data that will be advanced
6300b57cec5SDimitry Andric   ///     by the appropriate number of bytes if the value is extracted
6310b57cec5SDimitry Andric   ///     correctly. If the offset is out of bounds or there are not
6320b57cec5SDimitry Andric   ///     enough bytes to extract this value, the offset will be left
6330b57cec5SDimitry Andric   ///     unmodified.
6340b57cec5SDimitry Andric   ///
6358bcb0991SDimitry Andric   /// @param[in,out] Err
6368bcb0991SDimitry Andric   ///     A pointer to an Error object. Upon return the Error object is set to
6378bcb0991SDimitry Andric   ///     indicate the result (success/failure) of the function. If the Error
6388bcb0991SDimitry Andric   ///     object is already set when calling this function, no extraction is
6398bcb0991SDimitry Andric   ///     performed.
6408bcb0991SDimitry Andric   ///
6410b57cec5SDimitry Andric   /// @return
6420b57cec5SDimitry Andric   ///     The extracted unsigned integer value.
6438bcb0991SDimitry Andric   uint64_t getULEB128(uint64_t *offset_ptr, llvm::Error *Err = nullptr) const;
6448bcb0991SDimitry Andric 
6455ffd83dbSDimitry Andric   /// Extract an unsigned LEB128 value from the location given by the cursor.
6468bcb0991SDimitry Andric   /// In case of an extraction error, or if the cursor is already in an error
6478bcb0991SDimitry Andric   /// state, zero is returned.
getULEB128(Cursor & C)6488bcb0991SDimitry Andric   uint64_t getULEB128(Cursor &C) const { return getULEB128(&C.Offset, &C.Err); }
6498bcb0991SDimitry Andric 
6508bcb0991SDimitry Andric   /// Advance the Cursor position by the given number of bytes. No-op if the
6518bcb0991SDimitry Andric   /// cursor is in an error state.
6528bcb0991SDimitry Andric   void skip(Cursor &C, uint64_t Length) const;
6538bcb0991SDimitry Andric 
6548bcb0991SDimitry Andric   /// Return true iff the cursor is at the end of the buffer, regardless of the
6558bcb0991SDimitry Andric   /// error state of the cursor. The only way both eof and error states can be
6568bcb0991SDimitry Andric   /// true is if one attempts a read while the cursor is at the very end of the
6578bcb0991SDimitry Andric   /// data buffer.
eof(const Cursor & C)658480093f4SDimitry Andric   bool eof(const Cursor &C) const { return size() == C.Offset; }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric   /// Test the validity of \a offset.
6610b57cec5SDimitry Andric   ///
6620b57cec5SDimitry Andric   /// @return
6630b57cec5SDimitry Andric   ///     \b true if \a offset is a valid offset into the data in this
6640b57cec5SDimitry Andric   ///     object, \b false otherwise.
isValidOffset(uint64_t offset)665480093f4SDimitry Andric   bool isValidOffset(uint64_t offset) const { return size() > offset; }
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric   /// Test the availability of \a length bytes of data from \a offset.
6680b57cec5SDimitry Andric   ///
6690b57cec5SDimitry Andric   /// @return
6700b57cec5SDimitry Andric   ///     \b true if \a offset is a valid offset and there are \a
6710b57cec5SDimitry Andric   ///     length bytes available at that offset, \b false otherwise.
isValidOffsetForDataOfSize(uint64_t offset,uint64_t length)6728bcb0991SDimitry Andric   bool isValidOffsetForDataOfSize(uint64_t offset, uint64_t length) const {
6730b57cec5SDimitry Andric     return offset + length >= offset && isValidOffset(offset + length - 1);
6740b57cec5SDimitry Andric   }
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric   /// Test the availability of enough bytes of data for a pointer from
6770b57cec5SDimitry Andric   /// \a offset. The size of a pointer is \a getAddressSize().
6780b57cec5SDimitry Andric   ///
6790b57cec5SDimitry Andric   /// @return
6800b57cec5SDimitry Andric   ///     \b true if \a offset is a valid offset and there are enough
6810b57cec5SDimitry Andric   ///     bytes for a pointer available at that offset, \b false
6820b57cec5SDimitry Andric   ///     otherwise.
isValidOffsetForAddress(uint64_t offset)6838bcb0991SDimitry Andric   bool isValidOffsetForAddress(uint64_t offset) const {
6840b57cec5SDimitry Andric     return isValidOffsetForDataOfSize(offset, AddressSize);
6850b57cec5SDimitry Andric   }
6868bcb0991SDimitry Andric 
687480093f4SDimitry Andric   /// Return the number of bytes in the underlying buffer.
size()688480093f4SDimitry Andric   size_t size() const { return Data.size(); }
689480093f4SDimitry Andric 
6908bcb0991SDimitry Andric protected:
6918bcb0991SDimitry Andric   // Make it possible for subclasses to access these fields without making them
6928bcb0991SDimitry Andric   // public.
getOffset(Cursor & C)6938bcb0991SDimitry Andric   static uint64_t &getOffset(Cursor &C) { return C.Offset; }
getError(Cursor & C)6948bcb0991SDimitry Andric   static Error &getError(Cursor &C) { return C.Err; }
6955ffd83dbSDimitry Andric 
6965ffd83dbSDimitry Andric private:
6975ffd83dbSDimitry Andric   /// If it is possible to read \a Size bytes at offset \a Offset, returns \b
6985ffd83dbSDimitry Andric   /// true. Otherwise, returns \b false. If \a E is not nullptr, also sets the
6995ffd83dbSDimitry Andric   /// error object to indicate an error.
7005ffd83dbSDimitry Andric   bool prepareRead(uint64_t Offset, uint64_t Size, Error *E) const;
7015ffd83dbSDimitry Andric 
7025ffd83dbSDimitry Andric   template <typename T> T getU(uint64_t *OffsetPtr, Error *Err) const;
7035ffd83dbSDimitry Andric   template <typename T>
7045ffd83dbSDimitry Andric   T *getUs(uint64_t *OffsetPtr, T *Dst, uint32_t Count, Error *Err) const;
7050b57cec5SDimitry Andric };
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric } // namespace llvm
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric #endif
710