-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsource.cpp
More file actions
82 lines (67 loc) · 2.6 KB
/
Copy pathsource.cpp
File metadata and controls
82 lines (67 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include "source.hpp"
#include <algorithm>
#include <fstream>
#include <sstream>
namespace rs {
Source::Source(std::string name, std::string text)
: name_(std::move(name)), text_(std::move(text)) {
// UTF-8 BOM'u at. Dosyadan gelen icerikte de, boru ile gelen girdide de
// olabiliyor -- o yuzden fromFile'da degil KURUCUDA yapiliyor.
// Lexer BOM'u cok baytli bir karakter sanip ilk tanimlayiciya yapistiriyordu.
if (text_.size() >= 3 && static_cast<unsigned char>(text_[0]) == 0xEF &&
static_cast<unsigned char>(text_[1]) == 0xBB &&
static_cast<unsigned char>(text_[2]) == 0xBF) {
text_.erase(0, 3);
}
lineStarts_.push_back(0);
for (std::size_t i = 0; i < text_.size(); ++i) {
if (text_[i] == '\n') {
lineStarts_.push_back(static_cast<std::uint32_t>(i + 1));
}
}
}
std::optional<Source> Source::fromFile(const std::filesystem::path& yol) {
std::ifstream f(yol, std::ios::binary);
if (!f) {
return std::nullopt;
}
std::ostringstream ss;
ss << f.rdbuf();
std::string icerik = ss.str();
// CRLF -> LF. Windows'ta yazılmış dosyalar lexer'a hep temiz gelsin.
// (BOM kırpma artık Source kurucusunda yapılıyor.)
icerik.erase(std::remove(icerik.begin(), icerik.end(), '\r'), icerik.end());
return Source(yol.string(), std::move(icerik));
}
Source::LineCol Source::lineCol(std::uint32_t offset) const {
if (offset > size()) {
offset = size();
}
// lineStarts_ sıralı; offset'ten büyük ilk girişin bir öncesi bizim satırımız.
const auto it = std::upper_bound(lineStarts_.begin(), lineStarts_.end(), offset);
const auto idx = static_cast<std::uint32_t>(std::distance(lineStarts_.begin(), it) - 1);
const std::uint32_t satirBasi = lineStarts_[idx];
// Sütunu UTF-8 karakter cinsinden say: devam baytlarını (10xxxxxx) atla.
std::uint32_t sutun = 1;
for (std::uint32_t i = satirBasi; i < offset; ++i) {
const auto b = static_cast<unsigned char>(text_[i]);
if ((b & 0xC0) != 0x80) {
++sutun;
}
}
return LineCol{idx + 1, sutun};
}
std::string_view Source::lineText(std::uint32_t line) const {
if (line == 0 || line > lineCount()) {
return {};
}
const std::uint32_t bas = lineStarts_[line - 1];
const std::uint32_t son = (line < lineCount()) ? lineStarts_[line] : size();
std::uint32_t uzunluk = son - bas;
// Sondaki \n'i kes.
if (uzunluk > 0 && text_[bas + uzunluk - 1] == '\n') {
--uzunluk;
}
return std::string_view(text_).substr(bas, uzunluk);
}
} // namespace rs