//===--- SourceManager.cpp - Track and cache source files -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SourceManager interface.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
#include "clang/Basic/FileManager.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include <algorithm>
using namespace clang;
using namespace SrcMgr;
using llvm::MemoryBuffer;
//===----------------------------------------------------------------------===//
// SourceManager Helper Classes
//===----------------------------------------------------------------------===//
ContentCache::~ContentCache() {
delete Buffer;
}
/// getSizeBytesMapped - Returns the number of bytes actually mapped for
/// this ContentCache. This can be 0 if the MemBuffer was not actually
/// instantiated.
unsigned ContentCache::getSizeBytesMapped() const {
return Buffer ? Buffer->getBufferSize() : 0;
}
/// getSize - Returns the size of the content encapsulated by this ContentCache.
/// This can be the size of the source file or the size of an arbitrary
/// scratch buffer. If the ContentCache encapsulates a source file, that
/// file is not lazily brought in from disk to satisfy this query unless it
/// needs to be truncated due to a truncateAt() call.
unsigned ContentCache::getSize() const {
return Buffer ? Buffer->getBufferSize() : Entry->getSize();
}
const llvm::MemoryBuffer *ContentCache::getBuffer(std::string *ErrorStr) const {
// Lazily create the Buffer for ContentCaches that wrap files.
if (!Buffer && Entry) {
// FIXME: Should we support a way to not have to do this check over
// and over if we cannot open the file?
Buffer = MemoryBuffer::getFile(Entry->getName(), ErrorStr,Entry->getSize());
if (isTruncated())
const_cast<ContentCache *>(this)->truncateAt(TruncateAtLine,
TruncateAtColumn);
}
return Buffer;
}
void ContentCache::truncateAt(unsigned Line, unsigned Column) {
TruncateAtLine = Line;
TruncateAtColumn = Column;
if (!isTruncated() || !Buffer)
return;
// Find the byte position of the truncation point.
const char *Position = Buffer->getBufferStart();
for (unsigned Line = 1; Line < TruncateAtLine; ++Line) {
for (; *Position; ++Position) {
if (*Position != '\r' && *Position != '\n')
continue;
// Eat \r\n or \n\r as a single line.
if ((Position[1] == '\r' || Position[1] == '\n') &&
Position[0] != Position[1])
++Position;
++Position;
break;
}
}
for (unsigned Column = 1; Column < TruncateAtColumn; ++Column, ++Position) {
if (!*Position)
break;
if (*Position == '\t')
Column += 7;
}
// Truncate the buffer.
if (Position != Buffer->getBufferEnd()) {
MemoryBuffer *TruncatedBuffer
= MemoryBuffer::getMemBufferCopy(Buffer->getBufferStart(), Position,
Buffer->getBufferIdentifier());
delete Buffer;
Buffer = TruncatedBuffer;
}
}
unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) {
// Look up the filename in the string table, returning the pre-existing value
// if it exists.
llvm::StringMapEntry<unsigned&g