1 | // sass.hpp must go before all system headers to get the |
2 | // __EXTENSIONS__ fix on Solaris. |
3 | #include "sass.hpp" |
4 | |
5 | #include "position.hpp" |
6 | #include "source.hpp" |
7 | |
8 | namespace Sass { |
9 | |
10 | |
11 | Offset::Offset(const char chr) |
12 | : line(chr == '\n' ? 1 : 0), |
13 | column(chr == '\n' ? 0 : 1) |
14 | {} |
15 | |
16 | Offset::Offset(const char* string) |
17 | : line(0), column(0) |
18 | { |
19 | *this = inc(begin: string, end: string + strlen(s: string)); |
20 | } |
21 | |
22 | Offset::Offset(const sass::string& text) |
23 | : line(0), column(0) |
24 | { |
25 | *this = inc(begin: text.c_str(), end: text.c_str() + text.size()); |
26 | } |
27 | |
28 | Offset::Offset(const size_t line, const size_t column) |
29 | : line(line), column(column) { } |
30 | |
31 | // init/create instance from const char substring |
32 | Offset Offset::init(const char* beg, const char* end) |
33 | { |
34 | Offset offset(0, 0); |
35 | if (end == 0) { |
36 | end += strlen(s: beg); |
37 | } |
38 | offset.add(begin: beg, end); |
39 | return offset; |
40 | } |
41 | |
42 | // increase offset by given string (mostly called by lexer) |
43 | // increase line counter and count columns on the last line |
44 | Offset Offset::add(const char* begin, const char* end) |
45 | { |
46 | if (end == 0) return *this; |
47 | while (begin < end && *begin) { |
48 | if (*begin == '\n') { |
49 | ++ line; |
50 | // start new line |
51 | column = 0; |
52 | } else { |
53 | // do not count any utf8 continuation bytes |
54 | // https://stackoverflow.com/a/9356203/1550314 |
55 | // https://en.wikipedia.org/wiki/UTF-8#Description |
56 | unsigned char chr = *begin; |
57 | // skip over 10xxxxxx |
58 | // is 1st bit not set |
59 | if ((chr & 128) == 0) { |
60 | // regular ASCII char |
61 | column += 1; |
62 | } |
63 | // is 2nd bit not set |
64 | else if ((chr & 64) == 0) { |
65 | // first utf8 byte |
66 | column += 1; |
67 | } |
68 | } |
69 | ++ begin; |
70 | } |
71 | return *this; |
72 | } |
73 | |
74 | // increase offset by given string (mostly called by lexer) |
75 | // increase line counter and count columns on the last line |
76 | Offset Offset::inc(const char* begin, const char* end) const |
77 | { |
78 | Offset offset(line, column); |
79 | offset.add(begin, end); |
80 | return offset; |
81 | } |
82 | |
83 | bool Offset::operator== (const Offset &pos) const |
84 | { |
85 | return line == pos.line && column == pos.column; |
86 | } |
87 | |
88 | bool Offset::operator!= (const Offset &pos) const |
89 | { |
90 | return line != pos.line || column != pos.column; |
91 | } |
92 | |
93 | void Offset::operator+= (const Offset &off) |
94 | { |
95 | *this = Offset(line + off.line, off.line > 0 ? off.column : column + off.column); |
96 | } |
97 | |
98 | Offset Offset::operator+ (const Offset &off) const |
99 | { |
100 | return Offset(line + off.line, off.line > 0 ? off.column : column + off.column); |
101 | } |
102 | |
103 | Offset Offset::operator- (const Offset &off) const |
104 | { |
105 | return Offset(line - off.line, off.line == line ? column - off.column : column); |
106 | } |
107 | |
108 | Position::Position(const size_t file) |
109 | : Offset(0, 0), file(file) { } |
110 | |
111 | Position::Position(const size_t file, const Offset& offset) |
112 | : Offset(offset), file(file) { } |
113 | |
114 | Position::Position(const size_t line, const size_t column) |
115 | : Offset(line, column), file(-1) { } |
116 | |
117 | Position::Position(const size_t file, const size_t line, const size_t column) |
118 | : Offset(line, column), file(file) { } |
119 | |
120 | |
121 | SourceSpan::SourceSpan(const char* path) |
122 | : source(SASS_MEMORY_NEW(SynthFile, path)), position(0, 0), offset(0, 0) { } |
123 | |
124 | SourceSpan::SourceSpan(SourceDataObj source, const Offset& position, const Offset& offset) |
125 | : source(source), position(position), offset(offset) { } |
126 | |
127 | Position Position::add(const char* begin, const char* end) |
128 | { |
129 | Offset::add(begin, end); |
130 | return *this; |
131 | } |
132 | |
133 | Position Position::inc(const char* begin, const char* end) const |
134 | { |
135 | Offset offset(line, column); |
136 | offset = offset.inc(begin, end); |
137 | return Position(file, offset); |
138 | } |
139 | |
140 | bool Position::operator== (const Position &pos) const |
141 | { |
142 | return file == pos.file && line == pos.line && column == pos.column; |
143 | } |
144 | |
145 | bool Position::operator!= (const Position &pos) const |
146 | { |
147 | return file == pos.file || line != pos.line || column != pos.column; |
148 | } |
149 | |
150 | void Position::operator+= (const Offset &off) |
151 | { |
152 | *this = Position(file, line + off.line, off.line > 0 ? off.column : column + off.column); |
153 | } |
154 | |
155 | const Position Position::operator+ (const Offset &off) const |
156 | { |
157 | return Position(file, line + off.line, off.line > 0 ? off.column : column + off.column); |
158 | } |
159 | |
160 | const Offset Position::operator- (const Offset &off) const |
161 | { |
162 | return Offset(line - off.line, off.line == line ? column - off.column : column); |
163 | } |
164 | |
165 | } |
166 | |