//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
//
 
//  This file defines the MemoryBuffer interface.
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_SUPPORT_MEMORYBUFFER_H
 
#define LLVM_SUPPORT_MEMORYBUFFER_H
 
 
 
#include "llvm-c/Types.h"
 
#include "llvm/ADT/ArrayRef.h"
 
#include "llvm/ADT/StringRef.h"
 
#include "llvm/ADT/Twine.h"
 
#include "llvm/Support/Alignment.h"
 
#include "llvm/Support/CBindingWrapping.h"
 
#include "llvm/Support/ErrorOr.h"
 
#include "llvm/Support/MemoryBufferRef.h"
 
#include <cstddef>
 
#include <cstdint>
 
#include <memory>
 
 
 
namespace llvm {
 
namespace sys {
 
namespace fs {
 
// Duplicated from FileSystem.h to avoid a dependency.
 
#if defined(_WIN32)
 
// A Win32 HANDLE is a typedef of void*
 
using file_t = void *;
 
#else
 
using file_t = int;
 
#endif
 
} // namespace fs
 
} // namespace sys
 
 
 
/// This interface provides simple read-only access to a block of memory, and
 
/// provides simple methods for reading files and standard input into a memory
 
/// buffer.  In addition to basic access to the characters in the file, this
 
/// interface guarantees you can read one character past the end of the file,
 
/// and that this character will read as '\0'.
 
///
 
/// The '\0' guarantee is needed to support an optimization -- it's intended to
 
/// be more efficient for clients which are reading all the data to stop
 
/// reading when they encounter a '\0' than to continually check the file
 
/// position to see if it has reached the end of the file.
 
class MemoryBuffer {
 
  const char *BufferStart; // Start of the buffer.
 
  const char *BufferEnd;   // End of the buffer.
 
 
 
protected:
 
  MemoryBuffer() = default;
 
 
 
  void init(const char *BufStart, const char *BufEnd,
 
            bool RequiresNullTerminator);
 
 
 
public:
 
  MemoryBuffer(const MemoryBuffer &) = delete;
 
  MemoryBuffer &operator=(const MemoryBuffer &) = delete;
 
  virtual ~MemoryBuffer();
 
 
 
  const char *getBufferStart() const { return BufferStart; }
 
  const char *getBufferEnd() const   { return BufferEnd; }
 
  size_t getBufferSize() const { return BufferEnd-BufferStart; }
 
 
 
  StringRef getBuffer() const {
 
    return StringRef(BufferStart, getBufferSize());
 
  }
 
 
 
  /// Return an identifier for this buffer, typically the filename it was read
 
  /// from.
 
  virtual StringRef getBufferIdentifier() const { return "Unknown buffer"; }
 
 
 
  /// For read-only MemoryBuffer_MMap, mark the buffer as unused in the near
 
  /// future and the kernel can free resources associated with it. Further
 
  /// access is supported but may be expensive. This calls
 
  /// madvise(MADV_DONTNEED) on read-only file mappings on *NIX systems. This
 
  /// function should not be called on a writable buffer.
 
  virtual void dontNeedIfMmap() {}
 
 
 
  /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer
 
  /// if successful, otherwise returning null.
 
  ///
 
  /// \param IsText Set to true to indicate that the file should be read in
 
  /// text mode.
 
  ///
 
  /// \param IsVolatile Set to true to indicate that the contents of the file
 
  /// can change outside the user's control, e.g. when libclang tries to parse
 
  /// while the user is editing/updating the file or if the file is on an NFS.
 
  ///
 
  /// \param Alignment Set to indicate that the buffer should be aligned to at
 
  /// least the specified alignment.
 
  static ErrorOr<std::unique_ptr<MemoryBuffer>>
 
  getFile(const Twine &Filename, bool IsText = false,
 
          bool RequiresNullTerminator = true, bool IsVolatile = false,
 
          std::optional<Align> Alignment = std::nullopt);
 
 
 
  /// Read all of the specified file into a MemoryBuffer as a stream
 
  /// (i.e. until EOF reached). This is useful for special files that
 
  /// look like a regular file but have 0 size (e.g. /proc/cpuinfo on Linux).
 
  static ErrorOr<std::unique_ptr<MemoryBuffer>>
 
  getFileAsStream(const Twine &Filename);
 
 
 
  /// Given an already-open file descriptor, map some slice of it into a
 
  /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize.
 
  /// Since this is in the middle of a file, the buffer is not null terminated.
 
  static ErrorOr<std::unique_ptr<MemoryBuffer>>
 
  getOpenFileSlice(sys::fs::file_t FD, const Twine &Filename, uint64_t MapSize,
 
                   int64_t Offset, bool IsVolatile = false,
 
                   std::optional<Align> Alignment = std::nullopt);
 
 
 
  /// Given an already-open file descriptor, read the file and return a
 
  /// MemoryBuffer.
 
  ///
 
  /// \param IsVolatile Set to true to indicate that the contents of the file
 
  /// can change outside the user's control, e.g. when libclang tries to parse
 
  /// while the user is editing/updating the file or if the file is on an NFS.
 
  ///
 
  /// \param Alignment Set to indicate that the buffer should be aligned to at
 
  /// least the specified alignment.
 
  static ErrorOr<std::unique_ptr<MemoryBuffer>>
 
  getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
 
              bool RequiresNullTerminator = true, bool IsVolatile = false,
 
              std::optional<Align> Alignment = std::nullopt);
 
 
 
  /// Open the specified memory range as a MemoryBuffer. Note that InputData
 
  /// must be null terminated if RequiresNullTerminator is true.
 
  static std::unique_ptr<MemoryBuffer>
 
  getMemBuffer(StringRef InputData, StringRef BufferName = "",
 
               bool RequiresNullTerminator = true);
 
 
 
  static std::unique_ptr<MemoryBuffer>
 
  getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true);
 
 
 
  /// Open the specified memory range as a MemoryBuffer, copying the contents
 
  /// and taking ownership of it. InputData does not have to be null terminated.
 
  static std::unique_ptr<MemoryBuffer>
 
  getMemBufferCopy(StringRef InputData, const Twine &BufferName = "");
 
 
 
  /// Read all of stdin into a file buffer, and return it.
 
  static ErrorOr<std::unique_ptr<MemoryBuffer>> getSTDIN();
 
 
 
  /// Open the specified file as a MemoryBuffer, or open stdin if the Filename
 
  /// is "-".
 
  static ErrorOr<std::unique_ptr<MemoryBuffer>>
 
  getFileOrSTDIN(const Twine &Filename, bool IsText = false,
 
                 bool RequiresNullTerminator = true,
 
                 std::optional<Align> Alignment = std::nullopt);
 
 
 
  /// Map a subrange of the specified file as a MemoryBuffer.
 
  static ErrorOr<std::unique_ptr<MemoryBuffer>>
 
  getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset,
 
               bool IsVolatile = false,
 
               std::optional<Align> Alignment = std::nullopt);
 
 
 
  //===--------------------------------------------------------------------===//
 
  // Provided for performance analysis.
 
  //===--------------------------------------------------------------------===//
 
 
 
  /// The kind of memory backing used to support the MemoryBuffer.
 
  enum BufferKind {
 
    MemoryBuffer_Malloc,
 
    MemoryBuffer_MMap
 
  };
 
 
 
  /// Return information on the memory mechanism used to support the
 
  /// MemoryBuffer.
 
  virtual BufferKind getBufferKind() const = 0;
 
 
 
  MemoryBufferRef getMemBufferRef() const;
 
};
 
 
 
/// This class is an extension of MemoryBuffer, which allows copy-on-write
 
/// access to the underlying contents.  It only supports creation methods that
 
/// are guaranteed to produce a writable buffer.  For example, mapping a file
 
/// read-only is not supported.
 
class WritableMemoryBuffer : public MemoryBuffer {
 
protected:
 
  WritableMemoryBuffer() = default;
 
 
 
public:
 
  using MemoryBuffer::getBuffer;
 
  using MemoryBuffer::getBufferEnd;
 
  using MemoryBuffer::getBufferStart;
 
 
 
  // const_cast is well-defined here, because the underlying buffer is
 
  // guaranteed to have been initialized with a mutable buffer.
 
  char *getBufferStart() {
 
    return const_cast<char *>(MemoryBuffer::getBufferStart());
 
  }
 
  char *getBufferEnd() {
 
    return const_cast<char *>(MemoryBuffer::getBufferEnd());
 
  }
 
  MutableArrayRef<char> getBuffer() {
 
    return {getBufferStart(), getBufferEnd()};
 
  }
 
 
 
  static ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
 
  getFile(const Twine &Filename, bool IsVolatile = false,
 
          std::optional<Align> Alignment = std::nullopt);
 
 
 
  /// Map a subrange of the specified file as a WritableMemoryBuffer.
 
  static ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
 
  getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset,
 
               bool IsVolatile = false,
 
               std::optional<Align> Alignment = std::nullopt);
 
 
 
  /// Allocate a new MemoryBuffer of the specified size that is not initialized.
 
  /// Note that the caller should initialize the memory allocated by this
 
  /// method. The memory is owned by the MemoryBuffer object.
 
  ///
 
  /// \param Alignment Set to indicate that the buffer should be aligned to at
 
  /// least the specified alignment.
 
  static std::unique_ptr<WritableMemoryBuffer>
 
  getNewUninitMemBuffer(size_t Size, const Twine &BufferName = "",
 
                        std::optional<Align> Alignment = std::nullopt);
 
 
 
  /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note
 
  /// that the caller need not initialize the memory allocated by this method.
 
  /// The memory is owned by the MemoryBuffer object.
 
  static std::unique_ptr<WritableMemoryBuffer>
 
  getNewMemBuffer(size_t Size, const Twine &BufferName = "");
 
 
 
private:
 
  // Hide these base class factory function so one can't write
 
  //   WritableMemoryBuffer::getXXX()
 
  // and be surprised that he got a read-only Buffer.
 
  using MemoryBuffer::getFileAsStream;
 
  using MemoryBuffer::getFileOrSTDIN;
 
  using MemoryBuffer::getMemBuffer;
 
  using MemoryBuffer::getMemBufferCopy;
 
  using MemoryBuffer::getOpenFile;
 
  using MemoryBuffer::getOpenFileSlice;
 
  using MemoryBuffer::getSTDIN;
 
};
 
 
 
/// This class is an extension of MemoryBuffer, which allows write access to
 
/// the underlying contents and committing those changes to the original source.
 
/// It only supports creation methods that are guaranteed to produce a writable
 
/// buffer.  For example, mapping a file read-only is not supported.
 
class WriteThroughMemoryBuffer : public MemoryBuffer {
 
protected:
 
  WriteThroughMemoryBuffer() = default;
 
 
 
public:
 
  using MemoryBuffer::getBuffer;
 
  using MemoryBuffer::getBufferEnd;
 
  using MemoryBuffer::getBufferStart;
 
 
 
  // const_cast is well-defined here, because the underlying buffer is
 
  // guaranteed to have been initialized with a mutable buffer.
 
  char *getBufferStart() {
 
    return const_cast<char *>(MemoryBuffer::getBufferStart());
 
  }
 
  char *getBufferEnd() {
 
    return const_cast<char *>(MemoryBuffer::getBufferEnd());
 
  }
 
  MutableArrayRef<char> getBuffer() {
 
    return {getBufferStart(), getBufferEnd()};
 
  }
 
 
 
  static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
 
  getFile(const Twine &Filename, int64_t FileSize = -1);
 
 
 
  /// Map a subrange of the specified file as a ReadWriteMemoryBuffer.
 
  static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
 
  getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset);
 
 
 
private:
 
  // Hide these base class factory function so one can't write
 
  //   WritableMemoryBuffer::getXXX()
 
  // and be surprised that he got a read-only Buffer.
 
  using MemoryBuffer::getFileAsStream;
 
  using MemoryBuffer::getFileOrSTDIN;
 
  using MemoryBuffer::getMemBuffer;
 
  using MemoryBuffer::getMemBufferCopy;
 
  using MemoryBuffer::getOpenFile;
 
  using MemoryBuffer::getOpenFileSlice;
 
  using MemoryBuffer::getSTDIN;
 
};
 
 
 
// Create wrappers for C Binding types (see CBindingWrapping.h).
 
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef)
 
 
 
} // end namespace llvm
 
 
 
#endif // LLVM_SUPPORT_MEMORYBUFFER_H