| //===--- llvm/Support/DataStream.cpp - Lazy streamed data -----------------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file implements DataStreamer, which fetches bytes of Data from | |
| // a stream source. It provides support for streaming (lazy reading) of | |
| // bitcode. An example implementation of streaming from a file or stdin | |
| // is included. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/Support/DataStream.h" | |
| #include "llvm/ADT/STLExtras.h" | |
| #include "llvm/ADT/Statistic.h" | |
| #include "llvm/Support/FileSystem.h" | |
| #include "llvm/Support/Program.h" | |
| #include <string> | |
| #include <system_error> | |
| #if !defined(_MSC_VER) && !defined(__MINGW32__) | |
| #include <unistd.h> | |
| #else | |
| #include <io.h> | |
| #endif | |
| using namespace llvm; | |
| #define DEBUG_TYPE "Data-stream" | |
| // Interface goals: | |
| // * StreamingMemoryObject doesn't care about complexities like using | |
| // threads/async callbacks to actually overlap download+compile | |
| // * Don't want to duplicate Data in memory | |
| // * Don't need to know total Data len in advance | |
| // Non-goals: | |
| // StreamingMemoryObject already has random access so this interface only does | |
| // in-order streaming (no arbitrary seeking, else we'd have to buffer all the | |
| // Data here in addition to MemoryObject). This also means that if we want | |
| // to be able to to free Data, BitstreamBytes/BitcodeReader will implement it | |
| STATISTIC(NumStreamFetches, "Number of calls to Data stream fetch"); | |
| namespace llvm { | |
| DataStreamer::~DataStreamer() {} | |
| } // namespace llvm | |
| namespace { | |
| // Very simple stream backed by a file. Mostly useful for stdin and debugging; | |
| // actual file access is probably still best done with mmap. | |
| class DataFileStreamer : public DataStreamer { | |
| int Fd; | |
| public: | |
| DataFileStreamer() : Fd(0) {} | |
| ~DataFileStreamer() override { close(Fd); } | |
| size_t GetBytes(unsigned char *buf, size_t len) override { | |
| NumStreamFetches++; | |
| return read(Fd, buf, len); | |
| } | |
| std::error_code OpenFile(const std::string &Filename) { | |
| if (Filename == "-") { | |
| Fd = 0; | |
| sys::ChangeStdinToBinary(); | |
| return std::error_code(); | |
| } | |
| return sys::fs::openFileForRead(Filename, Fd); | |
| } | |
| }; | |
| } // namespace | |
| std::unique_ptr<DataStreamer> | |
| llvm::getDataFileStreamer(const std::string &Filename, std::string *StrError) { | |
| std::unique_ptr<DataFileStreamer> s = make_unique<DataFileStreamer>(); | |
| if (std::error_code e = s->OpenFile(Filename)) { | |
| *StrError = | |
| std::string("Could not open ") + Filename + ": " + e.message() + "\n"; | |
| return nullptr; | |
| } | |
| return std::move(s); | |
| } |