| 1 | //===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- 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 | //  This file defines the MemoryBuffer interface. | 
| 10 | // | 
| 11 | //===----------------------------------------------------------------------===// | 
| 12 |  | 
| 13 | #ifndef LLVM_SUPPORT_MEMORYBUFFER_H | 
| 14 | #define LLVM_SUPPORT_MEMORYBUFFER_H | 
| 15 |  | 
| 16 | #include "llvm-c/Types.h" | 
| 17 | #include "llvm/ADT/ArrayRef.h" | 
| 18 | #include "llvm/ADT/StringRef.h" | 
| 19 | #include "llvm/ADT/Twine.h" | 
| 20 | #include "llvm/Support/Alignment.h" | 
| 21 | #include "llvm/Support/CBindingWrapping.h" | 
| 22 | #include "llvm/Support/ErrorOr.h" | 
| 23 | #include "llvm/Support/MemoryBufferRef.h" | 
| 24 | #include <cstddef> | 
| 25 | #include <cstdint> | 
| 26 | #include <memory> | 
| 27 |  | 
| 28 | namespace llvm { | 
| 29 | namespace sys { | 
| 30 | namespace fs { | 
| 31 | // Duplicated from FileSystem.h to avoid a dependency. | 
| 32 | #if defined(_WIN32) | 
| 33 | // A Win32 HANDLE is a typedef of void* | 
| 34 | using file_t = void *; | 
| 35 | #else | 
| 36 | using file_t = int; | 
| 37 | #endif | 
| 38 | } // namespace fs | 
| 39 | } // namespace sys | 
| 40 |  | 
| 41 | /// This interface provides simple read-only access to a block of memory, and | 
| 42 | /// provides simple methods for reading files and standard input into a memory | 
| 43 | /// buffer.  In addition to basic access to the characters in the file, this | 
| 44 | /// interface guarantees you can read one character past the end of the file, | 
| 45 | /// and that this character will read as '\0'. | 
| 46 | /// | 
| 47 | /// The '\0' guarantee is needed to support an optimization -- it's intended to | 
| 48 | /// be more efficient for clients which are reading all the data to stop | 
| 49 | /// reading when they encounter a '\0' than to continually check the file | 
| 50 | /// position to see if it has reached the end of the file. | 
| 51 | class MemoryBuffer { | 
| 52 |   const char *BufferStart; // Start of the buffer. | 
| 53 |   const char *BufferEnd;   // End of the buffer. | 
| 54 |  | 
| 55 | protected: | 
| 56 |   MemoryBuffer() = default; | 
| 57 |  | 
| 58 |   void init(const char *BufStart, const char *BufEnd, | 
| 59 |             bool RequiresNullTerminator); | 
| 60 |  | 
| 61 | public: | 
| 62 |   MemoryBuffer(const MemoryBuffer &) = delete; | 
| 63 |   MemoryBuffer &operator=(const MemoryBuffer &) = delete; | 
| 64 |   virtual ~MemoryBuffer(); | 
| 65 |  | 
| 66 |   const char *getBufferStart() const { return BufferStart; } | 
| 67 |   const char *getBufferEnd() const   { return BufferEnd; } | 
| 68 |   size_t getBufferSize() const { return BufferEnd-BufferStart; } | 
| 69 |  | 
| 70 |   StringRef getBuffer() const { | 
| 71 |     return StringRef(BufferStart, getBufferSize()); | 
| 72 |   } | 
| 73 |  | 
| 74 |   /// Return an identifier for this buffer, typically the filename it was read | 
| 75 |   /// from. | 
| 76 |   virtual StringRef getBufferIdentifier() const { return "Unknown buffer" ; } | 
| 77 |  | 
| 78 |   /// For read-only MemoryBuffer_MMap, mark the buffer as unused in the near | 
| 79 |   /// future and the kernel can free resources associated with it. Further | 
| 80 |   /// access is supported but may be expensive. This calls | 
| 81 |   /// madvise(MADV_DONTNEED) on read-only file mappings on *NIX systems. This | 
| 82 |   /// function should not be called on a writable buffer. | 
| 83 |   virtual void dontNeedIfMmap() {} | 
| 84 |  | 
| 85 |   /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer | 
| 86 |   /// if successful, otherwise returning null. | 
| 87 |   /// | 
| 88 |   /// \param IsText Set to true to indicate that the file should be read in | 
| 89 |   /// text mode. | 
| 90 |   /// | 
| 91 |   /// \param IsVolatile Set to true to indicate that the contents of the file | 
| 92 |   /// can change outside the user's control, e.g. when libclang tries to parse | 
| 93 |   /// while the user is editing/updating the file or if the file is on an NFS. | 
| 94 |   /// | 
| 95 |   /// \param Alignment Set to indicate that the buffer should be aligned to at | 
| 96 |   /// least the specified alignment. | 
| 97 |   static ErrorOr<std::unique_ptr<MemoryBuffer>> | 
| 98 |   getFile(const Twine &Filename, bool IsText = false, | 
| 99 |           bool RequiresNullTerminator = true, bool IsVolatile = false, | 
| 100 |           std::optional<Align> Alignment = std::nullopt); | 
| 101 |  | 
| 102 |   /// Read all of the specified file into a MemoryBuffer as a stream | 
| 103 |   /// (i.e. until EOF reached). This is useful for special files that | 
| 104 |   /// look like a regular file but have 0 size (e.g. /proc/cpuinfo on Linux). | 
| 105 |   static ErrorOr<std::unique_ptr<MemoryBuffer>> | 
| 106 |   getFileAsStream(const Twine &Filename); | 
| 107 |  | 
| 108 |   /// Given an already-open file descriptor, map some slice of it into a | 
| 109 |   /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. | 
| 110 |   /// Since this is in the middle of a file, the buffer is not null terminated. | 
| 111 |   static ErrorOr<std::unique_ptr<MemoryBuffer>> | 
| 112 |   getOpenFileSlice(sys::fs::file_t FD, const Twine &Filename, uint64_t MapSize, | 
| 113 |                    int64_t Offset, bool IsVolatile = false, | 
| 114 |                    std::optional<Align> Alignment = std::nullopt); | 
| 115 |  | 
| 116 |   /// Given an already-open file descriptor, read the file and return a | 
| 117 |   /// MemoryBuffer. | 
| 118 |   /// | 
| 119 |   /// \param IsVolatile Set to true to indicate that the contents of the file | 
| 120 |   /// can change outside the user's control, e.g. when libclang tries to parse | 
| 121 |   /// while the user is editing/updating the file or if the file is on an NFS. | 
| 122 |   /// | 
| 123 |   /// \param Alignment Set to indicate that the buffer should be aligned to at | 
| 124 |   /// least the specified alignment. | 
| 125 |   static ErrorOr<std::unique_ptr<MemoryBuffer>> | 
| 126 |   getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, | 
| 127 |               bool RequiresNullTerminator = true, bool IsVolatile = false, | 
| 128 |               std::optional<Align> Alignment = std::nullopt); | 
| 129 |  | 
| 130 |   /// Open the specified memory range as a MemoryBuffer. Note that InputData | 
| 131 |   /// must be null terminated if RequiresNullTerminator is true. | 
| 132 |   static std::unique_ptr<MemoryBuffer> | 
| 133 |   getMemBuffer(StringRef InputData, StringRef BufferName = "" , | 
| 134 |                bool RequiresNullTerminator = true); | 
| 135 |  | 
| 136 |   static std::unique_ptr<MemoryBuffer> | 
| 137 |   getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true); | 
| 138 |  | 
| 139 |   /// Open the specified memory range as a MemoryBuffer, copying the contents | 
| 140 |   /// and taking ownership of it. InputData does not have to be null terminated. | 
| 141 |   static std::unique_ptr<MemoryBuffer> | 
| 142 |   getMemBufferCopy(StringRef InputData, const Twine &BufferName = "" ); | 
| 143 |  | 
| 144 |   /// Read all of stdin into a file buffer, and return it. | 
| 145 |   static ErrorOr<std::unique_ptr<MemoryBuffer>> getSTDIN(); | 
| 146 |  | 
| 147 |   /// Open the specified file as a MemoryBuffer, or open stdin if the Filename | 
| 148 |   /// is "-". | 
| 149 |   static ErrorOr<std::unique_ptr<MemoryBuffer>> | 
| 150 |   getFileOrSTDIN(const Twine &Filename, bool IsText = false, | 
| 151 |                  bool RequiresNullTerminator = true, | 
| 152 |                  std::optional<Align> Alignment = std::nullopt); | 
| 153 |  | 
| 154 |   /// Map a subrange of the specified file as a MemoryBuffer. | 
| 155 |   static ErrorOr<std::unique_ptr<MemoryBuffer>> | 
| 156 |   getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset, | 
| 157 |                bool IsVolatile = false, | 
| 158 |                std::optional<Align> Alignment = std::nullopt); | 
| 159 |  | 
| 160 |   //===--------------------------------------------------------------------===// | 
| 161 |   // Provided for performance analysis. | 
| 162 |   //===--------------------------------------------------------------------===// | 
| 163 |  | 
| 164 |   /// The kind of memory backing used to support the MemoryBuffer. | 
| 165 |   enum BufferKind { | 
| 166 |     MemoryBuffer_Malloc, | 
| 167 |     MemoryBuffer_MMap | 
| 168 |   }; | 
| 169 |  | 
| 170 |   /// Return information on the memory mechanism used to support the | 
| 171 |   /// MemoryBuffer. | 
| 172 |   virtual BufferKind getBufferKind() const = 0; | 
| 173 |  | 
| 174 |   MemoryBufferRef getMemBufferRef() const; | 
| 175 | }; | 
| 176 |  | 
| 177 | /// This class is an extension of MemoryBuffer, which allows copy-on-write | 
| 178 | /// access to the underlying contents.  It only supports creation methods that | 
| 179 | /// are guaranteed to produce a writable buffer.  For example, mapping a file | 
| 180 | /// read-only is not supported. | 
| 181 | class WritableMemoryBuffer : public MemoryBuffer { | 
| 182 | protected: | 
| 183 |   WritableMemoryBuffer() = default; | 
| 184 |  | 
| 185 | public: | 
| 186 |   using MemoryBuffer::getBuffer; | 
| 187 |   using MemoryBuffer::getBufferEnd; | 
| 188 |   using MemoryBuffer::getBufferStart; | 
| 189 |  | 
| 190 |   // const_cast is well-defined here, because the underlying buffer is | 
| 191 |   // guaranteed to have been initialized with a mutable buffer. | 
| 192 |   char *getBufferStart() { | 
| 193 |     return const_cast<char *>(MemoryBuffer::getBufferStart()); | 
| 194 |   } | 
| 195 |   char *getBufferEnd() { | 
| 196 |     return const_cast<char *>(MemoryBuffer::getBufferEnd()); | 
| 197 |   } | 
| 198 |   MutableArrayRef<char> getBuffer() { | 
| 199 |     return {getBufferStart(), getBufferEnd()}; | 
| 200 |   } | 
| 201 |  | 
| 202 |   static ErrorOr<std::unique_ptr<WritableMemoryBuffer>> | 
| 203 |   getFile(const Twine &Filename, bool IsVolatile = false, | 
| 204 |           std::optional<Align> Alignment = std::nullopt); | 
| 205 |  | 
| 206 |   /// Map a subrange of the specified file as a WritableMemoryBuffer. | 
| 207 |   static ErrorOr<std::unique_ptr<WritableMemoryBuffer>> | 
| 208 |   getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset, | 
| 209 |                bool IsVolatile = false, | 
| 210 |                std::optional<Align> Alignment = std::nullopt); | 
| 211 |  | 
| 212 |   /// Allocate a new MemoryBuffer of the specified size that is not initialized. | 
| 213 |   /// Note that the caller should initialize the memory allocated by this | 
| 214 |   /// method. The memory is owned by the MemoryBuffer object. | 
| 215 |   /// | 
| 216 |   /// \param Alignment Set to indicate that the buffer should be aligned to at | 
| 217 |   /// least the specified alignment. | 
| 218 |   static std::unique_ptr<WritableMemoryBuffer> | 
| 219 |   getNewUninitMemBuffer(size_t Size, const Twine &BufferName = "" , | 
| 220 |                         std::optional<Align> Alignment = std::nullopt); | 
| 221 |  | 
| 222 |   /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note | 
| 223 |   /// that the caller need not initialize the memory allocated by this method. | 
| 224 |   /// The memory is owned by the MemoryBuffer object. | 
| 225 |   static std::unique_ptr<WritableMemoryBuffer> | 
| 226 |   getNewMemBuffer(size_t Size, const Twine &BufferName = "" ); | 
| 227 |  | 
| 228 | private: | 
| 229 |   // Hide these base class factory function so one can't write | 
| 230 |   //   WritableMemoryBuffer::getXXX() | 
| 231 |   // and be surprised that he got a read-only Buffer. | 
| 232 |   using MemoryBuffer::getFileAsStream; | 
| 233 |   using MemoryBuffer::getFileOrSTDIN; | 
| 234 |   using MemoryBuffer::getMemBuffer; | 
| 235 |   using MemoryBuffer::getMemBufferCopy; | 
| 236 |   using MemoryBuffer::getOpenFile; | 
| 237 |   using MemoryBuffer::getOpenFileSlice; | 
| 238 |   using MemoryBuffer::getSTDIN; | 
| 239 | }; | 
| 240 |  | 
| 241 | /// This class is an extension of MemoryBuffer, which allows write access to | 
| 242 | /// the underlying contents and committing those changes to the original source. | 
| 243 | /// It only supports creation methods that are guaranteed to produce a writable | 
| 244 | /// buffer.  For example, mapping a file read-only is not supported. | 
| 245 | class WriteThroughMemoryBuffer : public MemoryBuffer { | 
| 246 | protected: | 
| 247 |   WriteThroughMemoryBuffer() = default; | 
| 248 |  | 
| 249 | public: | 
| 250 |   using MemoryBuffer::getBuffer; | 
| 251 |   using MemoryBuffer::getBufferEnd; | 
| 252 |   using MemoryBuffer::getBufferStart; | 
| 253 |  | 
| 254 |   // const_cast is well-defined here, because the underlying buffer is | 
| 255 |   // guaranteed to have been initialized with a mutable buffer. | 
| 256 |   char *getBufferStart() { | 
| 257 |     return const_cast<char *>(MemoryBuffer::getBufferStart()); | 
| 258 |   } | 
| 259 |   char *getBufferEnd() { | 
| 260 |     return const_cast<char *>(MemoryBuffer::getBufferEnd()); | 
| 261 |   } | 
| 262 |   MutableArrayRef<char> getBuffer() { | 
| 263 |     return {getBufferStart(), getBufferEnd()}; | 
| 264 |   } | 
| 265 |  | 
| 266 |   static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>> | 
| 267 |   getFile(const Twine &Filename, int64_t FileSize = -1); | 
| 268 |  | 
| 269 |   /// Map a subrange of the specified file as a ReadWriteMemoryBuffer. | 
| 270 |   static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>> | 
| 271 |   getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset); | 
| 272 |  | 
| 273 | private: | 
| 274 |   // Hide these base class factory function so one can't write | 
| 275 |   //   WritableMemoryBuffer::getXXX() | 
| 276 |   // and be surprised that he got a read-only Buffer. | 
| 277 |   using MemoryBuffer::getFileAsStream; | 
| 278 |   using MemoryBuffer::getFileOrSTDIN; | 
| 279 |   using MemoryBuffer::getMemBuffer; | 
| 280 |   using MemoryBuffer::getMemBufferCopy; | 
| 281 |   using MemoryBuffer::getOpenFile; | 
| 282 |   using MemoryBuffer::getOpenFileSlice; | 
| 283 |   using MemoryBuffer::getSTDIN; | 
| 284 | }; | 
| 285 |  | 
| 286 | // Create wrappers for C Binding types (see CBindingWrapping.h). | 
| 287 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef) | 
| 288 |  | 
| 289 | } // end namespace llvm | 
| 290 |  | 
| 291 | #endif // LLVM_SUPPORT_MEMORYBUFFER_H | 
| 292 |  |