This machine mirrors various open-source projects.
20 Gbit/s uplink.
If there are any issues or you want another project mirrored, please contact
mirror-service -=AT=- netcologne DOT de !
00001 //===-- basic/TextProvider.cpp -------------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2008-2009, Stephen Wilson 00006 // 00007 //===----------------------------------------------------------------------===// 00008 00009 #include "comma/basic/TextProvider.h" 00010 #include <ostream> 00011 #include <cstdlib> 00012 #include <cstring> 00013 #include <cassert> 00014 00015 using namespace comma; 00016 00017 TextProvider::TextProvider(const llvm::sys::Path &path) 00018 { 00019 memBuffer = llvm::MemoryBuffer::getFileOrSTDIN(path.c_str()); 00020 00021 // Perhaps it would be better to simply return an empty TextProvider in this 00022 // case. 00023 if (!memBuffer) abort(); 00024 00025 buffer = memBuffer->getBufferStart(); 00026 00027 identity = path.getLast(); 00028 00029 // If we are reading from stdin, update identity to a more meningful string. 00030 if (identity.compare("-") == 0) 00031 identity = "<stdin>"; 00032 00033 initializeLinevec(); 00034 } 00035 00036 TextProvider::TextProvider(const char *raw, size_t length) 00037 { 00038 memBuffer = llvm::MemoryBuffer::getMemBufferCopy(raw, raw + length); 00039 buffer = memBuffer->getBufferStart(); 00040 initializeLinevec(); 00041 } 00042 00043 TextProvider::TextProvider(const std::string &str) 00044 { 00045 const char *start = str.c_str(); 00046 const char *end = start + str.size(); 00047 memBuffer = llvm::MemoryBuffer::getMemBufferCopy(start, end); 00048 buffer = memBuffer->getBufferStart(); 00049 initializeLinevec(); 00050 } 00051 00052 TextProvider::~TextProvider() 00053 { 00054 delete memBuffer; 00055 } 00056 00057 Location TextProvider::getLocation(const TextIterator &ti) const 00058 { 00059 return indexOf(ti.cursor); 00060 } 00061 00062 SourceLocation TextProvider::getSourceLocation(const TextIterator &ti) const 00063 { 00064 unsigned line = getLine(ti); 00065 unsigned column = getColumn(ti); 00066 return SourceLocation(line, column, this); 00067 } 00068 00069 SourceLocation TextProvider::getSourceLocation(const Location loc) const 00070 { 00071 unsigned line = getLine(loc); 00072 unsigned column = getColumn(loc); 00073 return SourceLocation(line, column, this); 00074 } 00075 00076 TextIterator TextProvider::begin() const 00077 { 00078 return TextIterator(buffer); 00079 } 00080 00081 TextIterator TextProvider::end() const 00082 { 00083 return TextIterator(memBuffer->getBufferEnd()); 00084 } 00085 00086 std::string TextProvider::extract(Location start, Location end) const 00087 { 00088 std::string str; 00089 unsigned x = start.getOffset(); 00090 unsigned y = end.getOffset(); 00091 assert(x <= y && "Inconsistent Location range!"); 00092 assert(y < indexOf(memBuffer->getBufferEnd()) && "Locations out of range!"); 00093 str.insert(0, &buffer[x], y - x + 1); 00094 return str; 00095 } 00096 00097 std::string TextProvider::extract(const TextIterator &s, 00098 const TextIterator &e) const 00099 { 00100 std::string str; 00101 unsigned length = e.cursor - s.cursor; 00102 str.insert(0, s.cursor, length); 00103 return str; 00104 } 00105 00106 std::string TextProvider::extract(const SourceLocation &sloc) const 00107 { 00108 assert(sloc.getTextProvider() == this && 00109 "SourceLocation not associated with this TextProvider!"); 00110 00111 std::string str; 00112 unsigned line = sloc.getLine(); 00113 unsigned start = lines[line - 1]; 00114 unsigned end = lines[line]; 00115 str.insert(0, &buffer[start], end - start); 00116 return str; 00117 } 00118 00119 unsigned TextProvider::extract(const TextIterator &s, 00120 const TextIterator &e, 00121 char *buff, size_t size) const 00122 { 00123 unsigned length = e.cursor - s.cursor; 00124 00125 if (buff == 0) return length; 00126 00127 if (length >= size) { 00128 ::memcpy(buff, s.cursor, size); 00129 return size; 00130 } 00131 00132 ::memcpy(buff, s.cursor, length); 00133 buff[length] = 0; 00134 return length; 00135 } 00136 00137 void TextProvider::initializeLinevec() 00138 { 00139 lines.push_back(0); 00140 maxLineIndex = 0; 00141 } 00142 00143 unsigned TextProvider::getLine(Location loc) const 00144 { 00145 assert(loc < indexOf(memBuffer->getBufferEnd())); 00146 00147 // Check that loc is within the known range of the line vector. If not, 00148 // extend the vector with all lines upto this location. 00149 if (loc >= maxLineIndex) { 00150 unsigned line; 00151 const char* cursor = &buffer[lines.back()]; 00152 while (cursor != &buffer[loc]) { 00153 switch (*cursor++) { 00154 case '\r': 00155 if (*cursor == '\n') 00156 cursor++; 00157 case '\n': 00158 case '\f': 00159 lines.push_back(indexOf(cursor)); 00160 } 00161 } 00162 // By returning the length of the vector, we provide a 1-based line 00163 // number. 00164 line = lines.size(); 00165 00166 // Continue scanning until the end of the current line is found. 00167 while (cursor != memBuffer->getBufferEnd()) { 00168 switch (*cursor++) { 00169 case '\r': 00170 if (*cursor == '\n') 00171 cursor++; 00172 case '\n': 00173 case '\f': 00174 lines.push_back(indexOf(cursor)); 00175 maxLineIndex = indexOf(cursor); 00176 return line; 00177 } 00178 } 00179 // We have hit the end of the buffer. 00180 lines.push_back(indexOf(cursor)); 00181 maxLineIndex = indexOf(cursor); 00182 return line; 00183 } 00184 00185 // Otherwise, perform a binary search over the existing line vector. 00186 int max = lines.size(); 00187 int start = 0; 00188 int end = max - 1; 00189 while (start <= end) { 00190 int mid = (start + end) >> 1; 00191 Location candidate = lines[mid]; 00192 if (candidate <= loc) { 00193 if (mid + 1 < max) { 00194 if (lines[mid + 1] <= loc) { 00195 start = ++mid; 00196 continue; 00197 } 00198 return ++mid; 00199 } 00200 return mid; 00201 } 00202 end = --mid; 00203 } 00204 assert(false && "Bad offset into chunk map."); 00205 return 0; 00206 } 00207 00208 unsigned TextProvider::getColumn(Location loc) const 00209 { 00210 unsigned start = lines[getLine(loc) - 1]; 00211 return loc - start; 00212 } 00213 00214 std::pair<unsigned, unsigned> TextProvider::getLineOf(Location loc) const 00215 { 00216 unsigned line = getLine(loc) - 1; 00217 unsigned start = lines[line]; 00218 unsigned end = lines[line + 1]; 00219 00220 return std::pair<unsigned, unsigned>(start, end); 00221 } 00222