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 Offset(const char chr)11 Offset::Offset(const char chr) 12 : line(chr == '\n' ? 1 : 0), 13 column(chr == '\n' ? 0 : 1) 14 {} 15 Offset(const char * string)16 Offset::Offset(const char* string) 17 : line(0), column(0) 18 { 19 *this = inc(string, string + strlen(string)); 20 } 21 Offset(const sass::string & text)22 Offset::Offset(const sass::string& text) 23 : line(0), column(0) 24 { 25 *this = inc(text.c_str(), text.c_str() + text.size()); 26 } 27 Offset(const size_t line,const size_t column)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 init(const char * beg,const char * end)32 Offset Offset::init(const char* beg, const char* end) 33 { 34 Offset offset(0, 0); 35 if (end == 0) { 36 end += strlen(beg); 37 } 38 offset.add(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 add(const char * begin,const char * end)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 inc(const char * begin,const char * end) const76 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 operator ==(const Offset & pos) const83 bool Offset::operator== (const Offset &pos) const 84 { 85 return line == pos.line && column == pos.column; 86 } 87 operator !=(const Offset & pos) const88 bool Offset::operator!= (const Offset &pos) const 89 { 90 return line != pos.line || column != pos.column; 91 } 92 operator +=(const Offset & off)93 void Offset::operator+= (const Offset &off) 94 { 95 *this = Offset(line + off.line, off.line > 0 ? off.column : column + off.column); 96 } 97 operator +(const Offset & off) const98 Offset Offset::operator+ (const Offset &off) const 99 { 100 return Offset(line + off.line, off.line > 0 ? off.column : column + off.column); 101 } 102 operator -(const Offset & off) const103 Offset Offset::operator- (const Offset &off) const 104 { 105 return Offset(line - off.line, off.line == line ? column - off.column : column); 106 } 107 Position(const size_t file)108 Position::Position(const size_t file) 109 : Offset(0, 0), file(file) { } 110 Position(const size_t file,const Offset & offset)111 Position::Position(const size_t file, const Offset& offset) 112 : Offset(offset), file(file) { } 113 Position(const size_t line,const size_t column)114 Position::Position(const size_t line, const size_t column) 115 : Offset(line, column), file(-1) { } 116 Position(const size_t file,const size_t line,const size_t column)117 Position::Position(const size_t file, const size_t line, const size_t column) 118 : Offset(line, column), file(file) { } 119 120 SourceSpan(const char * path)121 SourceSpan::SourceSpan(const char* path) 122 : source(SASS_MEMORY_NEW(SynthFile, path)), position(0, 0), offset(0, 0) { } 123 SourceSpan(SourceDataObj source,const Offset & position,const Offset & offset)124 SourceSpan::SourceSpan(SourceDataObj source, const Offset& position, const Offset& offset) 125 : source(source), position(position), offset(offset) { } 126 add(const char * begin,const char * end)127 Position Position::add(const char* begin, const char* end) 128 { 129 Offset::add(begin, end); 130 return *this; 131 } 132 inc(const char * begin,const char * end) const133 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 operator ==(const Position & pos) const140 bool Position::operator== (const Position &pos) const 141 { 142 return file == pos.file && line == pos.line && column == pos.column; 143 } 144 operator !=(const Position & pos) const145 bool Position::operator!= (const Position &pos) const 146 { 147 return file == pos.file || line != pos.line || column != pos.column; 148 } 149 operator +=(const Offset & off)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 operator +(const Offset & off) const155 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 operator -(const Offset & off) const160 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