blob: dfa53e7e5654202aff081caa77b1d430d7e2c4c2 [file] [log] [blame]
//===-- InMemoryOutputFileSystem.h - Collects outputs in memory -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_INMEMORYOUTPUTFILESYSTEM_H_
#define LLVM_CLANG_BASIC_INMEMORYOUTPUTFILESYSTEM_H_
#include <memory>
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/VirtualFileSystem.h"
namespace clang {
/// Collects output files in memory, and provides a `llvm::vfs::FileSystem`
/// interface for accessing those files.
///
/// This class is threadsafe. Unsynchronized calls from multiple threads will
/// not corrupt the internal state, and operations occur atomically and
/// sequentially consistently from the point of view of all threads.
class InMemoryOutputFileSystem : public llvm::vfs::FileSystem {
public:
InMemoryOutputFileSystem() : OutputFiles(new llvm::vfs::InMemoryFileSystem())
{}
/// Creates a temporary buffer that collects data for a file that may
/// eventually appear on the `llvm::vfs::FileSystem` interface.
/// `InMemoryOutputFileSystem` owns the buffer, which will not be released
/// until `DeleteTemporaryFile` or `FinalizeTemporaryFile` is called.
/// \param OutputPath the path of the file that may eventually be created.
/// \param TemporaryPath must be non-null. Pointee will be set to a unique
// string identifying this particular temporary buffer.
// \returns A stream that can be used to write to the buffer.
std::unique_ptr<llvm::raw_pwrite_stream> CreateTemporaryBuffer(
llvm::StringRef OutputPath,
std::string *TemporaryPath);
/// Releases the buffer underlying the temporary file.
/// \param TemporaryPath the unique string from `CreateTemporaryFile`.
void DeleteTemporaryBuffer(llvm::StringRef TemporaryPath);
/// Makes the contents of the specified temporary buffer visible on the
/// `llvm::vfs::FileSystem` interface, and releases the temporary buffer. If
/// the file already exists on the `llvm::vfs::FileSystem` interface, then
/// the new contents is silently ignored.
/// \param OutputPath the path of the file to create.
/// \param TemporaryPath the unique string from `CreateTemporaryFile`.
void FinalizeTemporaryBuffer(llvm::StringRef OutputPath,
llvm::StringRef TemporaryPath);
// MARK: - `llvm::vfs::FileSystem` overrides
llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine& relpath) override {
llvm::MutexGuard locked(Mu);
return OutputFiles->status(relpath);
}
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>> openFileForRead(
const llvm::Twine& relpath) override {
llvm::MutexGuard locked(Mu);
return OutputFiles->openFileForRead(relpath);
}
llvm::vfs::directory_iterator dir_begin(const llvm::Twine& reldir,
std::error_code& err) override {
llvm::MutexGuard locked(Mu);
return OutputFiles->dir_begin(reldir, err);
}
std::error_code setCurrentWorkingDirectory(const llvm::Twine& path) override {
llvm::MutexGuard locked(Mu);
return OutputFiles->setCurrentWorkingDirectory(path);
}
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
llvm::MutexGuard locked(Mu);
return OutputFiles->getCurrentWorkingDirectory();
}
std::error_code getRealPath(
const llvm::Twine& path,
llvm::SmallVectorImpl<char>& output) const override {
llvm::MutexGuard locked(Mu);
return OutputFiles->getRealPath(path, output);
}
private:
mutable llvm::sys::Mutex Mu;
llvm::StringMap<llvm::SmallVector<char, 0>> TemporaryBuffers;
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> OutputFiles;
};
} // namespace clang
#endif // LLVM_CLANG_BASIC_INMEMORYOUTPUTFILESYSTEM_H_