blob: 5ba33e47f0b68a4e1cf15a68cf82ec2a94c616b5 [file] [log] [blame]
//===-- AST Abstract Data Source Class --------------------------*- C++ -*-===//
//
// High Level Virtual Machine (HLVM)
//
// Copyright (C) 2006 Reid Spencer. All Rights Reserved.
//
// This software is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or (at
// your option) any later version.
//
// This software is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library in the file named LICENSE.txt; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
// MA 02110-1301 USA
//
//===----------------------------------------------------------------------===//
/// @file hlvm/Base/Source.cpp
/// @author Reid Spencer <reid@reidspencer.com> (original author)
/// @date 2006/05/04
/// @since 0.1.0
/// @brief Defines the class hlvm::Source
//===----------------------------------------------------------------------===//
#include <hlvm/Base/Source.h>
#include <hlvm/AST/URI.h>
#include <llvm/System/MappedFile.h>
#include <iostream>
#include <ios>
using namespace hlvm;
namespace
{
class MappedFileSource : public Source
{
public:
MappedFileSource(llvm::sys::MappedFile& mf)
: mf_(mf), at_(0), end_(0), was_mapped_(false), read_len_(0)
{
}
virtual void prepare(intptr_t block_len)
{
was_mapped_ = mf_.isMapped();
if (!was_mapped_)
mf_.map();
at_ = mf_.charBase();
end_ = at_ + mf_.size();
read_len_ = block_len;
}
virtual bool more()
{
return at_ < end_;
}
virtual const char* read(intptr_t& actual_len)
{
if (at_ >= end_) {
actual_len = 0;
return 0;
}
const char* result = at_;
if (read_len_ < end_ - at_) {
actual_len = read_len_;
at_ += read_len_;
} else {
actual_len = end_ - at_;
at_ = end_;
}
return result;
}
virtual void finish()
{
if (!was_mapped_)
mf_.unmap();
at_ = 0;
end_ = 0;
was_mapped_ = false;
read_len_ = 0;
}
virtual std::string systemId() const
{
return mf_.path().toString();
}
virtual std::string publicId() const
{
return "file://" + systemId();
}
private:
llvm::sys::MappedFile& mf_;
const char* at_;
const char* end_;
bool was_mapped_;
intptr_t read_len_;
};
class StreamSource : public Source
{
public:
StreamSource(std::istream& strm, std::string sysId, size_t bsize) : s_(strm)
{
s_.seekg(0, std::ios::end);
len_ = s_.tellg();
s_.seekg(0, std::ios::beg);
if (bsize > 1024*1024)
buffSize = 1024*1024;
else
buffSize = bsize;
buffer = new char[buffSize+1];
}
virtual ~StreamSource()
{
delete buffer;
}
virtual void prepare(intptr_t block_len)
{
s_.seekg(0,std::ios::beg);
}
virtual bool more()
{
return ! s_.bad() && !s_.eof();
}
virtual const char* read(intptr_t& actual_len)
{
if (more())
{
size_t pos = s_.tellg();
if (len_ - pos > buffSize)
actual_len = buffSize;
else
actual_len = len_ - pos;
s_.read(buffer, actual_len);
buffer[actual_len] = 0;
return buffer;
}
else
{
buffer[0] = 0;
actual_len = 0;
return buffer;
}
}
virtual void finish()
{
}
virtual std::string systemId() const
{
return sysId;
}
virtual std::string publicId() const
{
return "file:///" + systemId();
}
private:
std::string sysId;
std::istream& s_;
size_t len_;
char* buffer;
size_t buffSize;
};
class URISource : public Source
{
private:
const hlvm::URI* uri_;
llvm::sys::MappedFile* mf_;
MappedFileSource* mfs_;
public:
URISource(const URI* uri )
: uri_(uri)
, mf_(0)
, mfs_(0)
{
mf_ = new llvm::sys::MappedFile();
mf_->open(llvm::sys::Path(uri_->resolveToFile()));
mfs_ = new MappedFileSource(*mf_);
}
virtual ~URISource() {}
virtual void prepare(intptr_t block_len) { mfs_->prepare(block_len); }
virtual bool more() { return mfs_->more(); }
virtual const char* read(intptr_t& actual_len)
{ return mfs_->read(actual_len); }
virtual void finish() { mfs_->finish(); }
virtual std::string systemId() const { return mfs_->systemId(); }
virtual std::string publicId() const { return "file://" + mfs_->systemId(); }
};
}
namespace hlvm {
Source::~Source()
{
}
Source*
new_MappedFileSource(llvm::sys::MappedFile& mf)
{
return new MappedFileSource(mf);
}
Source*
new_StreamSource(std::istream& strm, std::string sysId, size_t bSize)
{
return new StreamSource(strm, sysId, bSize);
}
Source*
new_URISource(const URI* uri)
{
return new URISource(uri);
}
} // end hlvm namespace