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