1+ #if !defined(SOURCE_MAP_HXX)
2+ #define SOURCE_MAP_HXX
3+
4+ #include < vector>
5+ #include < algorithm>
6+ #include " aliases.hxx"
7+ #include " token.hxx"
8+ #include " properties.hxx"
9+
10+ WHEEL_LEXER_NAMESPACE
11+ struct SourceMap {
12+ private:
13+ std::vector<uint32_t > line_starts;
14+
15+ public:
16+ SourceMap () {
17+ line_starts.push_back (0 );
18+ }
19+
20+ WHEEL_ALWAYS_INLINE void build_table (StringView source) noexcept {
21+ line_starts.clear ();
22+ line_starts.push_back (0 );
23+
24+ for (size_t index = 0 ; index < source.size (); ++index) {
25+ char character = source[index];
26+
27+ if (is_crlf_sequence (character, (index > 0 ) ? source[index -1 ] : ' \0 ' )) {
28+ continue ;
29+ }
30+
31+ if (is_newline_like (character)) {
32+ line_starts.push_back (static_cast <uint32_t >(index + 1 ));
33+ }
34+ }
35+ }
36+
37+ WHEEL_ALWAYS_INLINE_NODISCARD SourceLocation source_location (size_t offset) const {
38+ if (offset > UINT32_MAX) {
39+ return SourceLocation {0 , 0 , offset};
40+ }
41+
42+ uint32_t safe_offset = static_cast <uint32_t >(offset);
43+ auto it = std::upper_bound (line_starts.begin (), line_starts.end (), safe_offset);
44+
45+ if (it != line_starts.begin ()) {
46+ --it;
47+ }
48+
49+ size_t line_index = std::distance (line_starts.begin (), it);
50+ uint32_t line_start_offset = line_starts[line_index];
51+ uint32_t column = (safe_offset - line_start_offset) + 1 ;
52+
53+ return SourceLocation {
54+ .line = line_index + 1 ,
55+ .column = column,
56+ .offset = safe_offset
57+ };
58+ }
59+ };
60+
61+ END_NAMESPACE
62+
63+ #endif // SOURCE_MAP_HXX
0 commit comments