1234285Sdim//===--- llvm/Support/DataStream.cpp - Lazy streamed data -----------------===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10234285Sdim// This file implements DataStreamer, which fetches bytes of Data from 11234285Sdim// a stream source. It provides support for streaming (lazy reading) of 12234285Sdim// bitcode. An example implementation of streaming from a file or stdin 13234285Sdim// is included. 14234285Sdim// 15234285Sdim//===----------------------------------------------------------------------===// 16234285Sdim 17234285Sdim#define DEBUG_TYPE "Data-stream" 18249423Sdim#include "llvm/Support/DataStream.h" 19234285Sdim#include "llvm/ADT/Statistic.h" 20234285Sdim#include "llvm/Support/Program.h" 21234285Sdim#include "llvm/Support/system_error.h" 22234285Sdim#include <cerrno> 23234285Sdim#include <cstdio> 24249423Sdim#include <string> 25234285Sdim#if !defined(_MSC_VER) && !defined(__MINGW32__) 26234285Sdim#include <unistd.h> 27234285Sdim#else 28234285Sdim#include <io.h> 29234285Sdim#endif 30234285Sdim#include <fcntl.h> 31234285Sdimusing namespace llvm; 32234285Sdim 33234285Sdim// Interface goals: 34234285Sdim// * StreamableMemoryObject doesn't care about complexities like using 35234285Sdim// threads/async callbacks to actually overlap download+compile 36234285Sdim// * Don't want to duplicate Data in memory 37234285Sdim// * Don't need to know total Data len in advance 38234285Sdim// Non-goals: 39234285Sdim// StreamableMemoryObject already has random access so this interface only does 40234285Sdim// in-order streaming (no arbitrary seeking, else we'd have to buffer all the 41234285Sdim// Data here in addition to MemoryObject). This also means that if we want 42234285Sdim// to be able to to free Data, BitstreamBytes/BitcodeReader will implement it 43234285Sdim 44234285SdimSTATISTIC(NumStreamFetches, "Number of calls to Data stream fetch"); 45234285Sdim 46234285Sdimnamespace llvm { 47234285SdimDataStreamer::~DataStreamer() {} 48234285Sdim} 49234285Sdim 50234285Sdimnamespace { 51234285Sdim 52234285Sdim// Very simple stream backed by a file. Mostly useful for stdin and debugging; 53234285Sdim// actual file access is probably still best done with mmap. 54234285Sdimclass DataFileStreamer : public DataStreamer { 55234285Sdim int Fd; 56234285Sdimpublic: 57234285Sdim DataFileStreamer() : Fd(0) {} 58234285Sdim virtual ~DataFileStreamer() { 59234285Sdim close(Fd); 60234285Sdim } 61243830Sdim virtual size_t GetBytes(unsigned char *buf, size_t len) LLVM_OVERRIDE { 62234285Sdim NumStreamFetches++; 63234285Sdim return read(Fd, buf, len); 64234285Sdim } 65234285Sdim 66234285Sdim error_code OpenFile(const std::string &Filename) { 67234285Sdim if (Filename == "-") { 68234285Sdim Fd = 0; 69234285Sdim sys::Program::ChangeStdinToBinary(); 70234285Sdim return error_code::success(); 71234285Sdim } 72234285Sdim 73234285Sdim int OpenFlags = O_RDONLY; 74234285Sdim#ifdef O_BINARY 75234285Sdim OpenFlags |= O_BINARY; // Open input file in binary mode on win32. 76234285Sdim#endif 77234285Sdim Fd = ::open(Filename.c_str(), OpenFlags); 78234285Sdim if (Fd == -1) 79234285Sdim return error_code(errno, posix_category()); 80234285Sdim return error_code::success(); 81234285Sdim } 82234285Sdim}; 83234285Sdim 84234285Sdim} 85234285Sdim 86234285Sdimnamespace llvm { 87234285SdimDataStreamer *getDataFileStreamer(const std::string &Filename, 88234285Sdim std::string *StrError) { 89234285Sdim DataFileStreamer *s = new DataFileStreamer(); 90234285Sdim if (error_code e = s->OpenFile(Filename)) { 91234285Sdim *StrError = std::string("Could not open ") + Filename + ": " + 92234285Sdim e.message() + "\n"; 93234285Sdim return NULL; 94234285Sdim } 95234285Sdim return s; 96234285Sdim} 97234285Sdim 98234285Sdim} 99