[CID# 1350626] Slint: add initialization for SciFile class
[scilab.git] / scilab / modules / slint / src / cpp / SciFile.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #include "SciFile.hxx"
17
18 extern "C"
19 {
20 #include "sci_malloc.h"
21 }
22
23 namespace slint
24 {
25
26 SciFile::SciFile() : code(nullptr), tree(nullptr), main(nullptr), codeLength(0)
27 {
28     initLines();
29 }
30
31 SciFile::SciFile(const std::wstring & _filename, const wchar_t * _code, const ast::Exp * _tree) : filename(_filename), code(_code), tree(_tree), main(nullptr)
32 {
33     initLines();
34     analyzeTree();
35 }
36
37 SciFile::~SciFile()
38 {
39     FREE(const_cast<wchar_t *>(code));
40     delete tree;
41 }
42
43 const std::wstring & SciFile::getFilename() const
44 {
45     return filename;
46 }
47
48 const wchar_t * SciFile::getCode() const
49 {
50     return code;
51 }
52
53 unsigned int SciFile::getCodeLength() const
54 {
55     return codeLength;
56 }
57
58 const ast::Exp * SciFile::getTree() const
59 {
60     return tree;
61 }
62
63 bool SciFile::getPosition(const Location & loc, std::pair<unsigned int, unsigned int> & out) const
64 {
65     if (loc.first_line > lines.size() || loc.last_line > lines.size())
66     {
67         return false;
68     }
69     out.first = lines[loc.first_line - 1].first + loc.first_column - 1;
70     out.second = lines[loc.last_line - 1].first + loc.last_column - 1;
71
72     return out.first <= codeLength && out.second <= codeLength;
73 }
74
75 bool SciFile::getFromPositionToEOL(const Location & loc, std::pair<unsigned int, unsigned int> & out) const
76 {
77     if (loc.first_line + 1 > lines.size())
78     {
79         return false;
80     }
81     out.first = lines[loc.first_line - 1].first + loc.first_column - 1;
82     out.second = lines[loc.last_line - 1].second + 1;
83
84     return out.first <= codeLength;
85 }
86
87 bool SciFile::checkLineLength(const unsigned int max, std::vector<unsigned int> & out) const
88 {
89     unsigned int i = 1;
90     for (const auto & line : lines)
91     {
92         if (line.second - line.first + 1 > max)
93         {
94             out.push_back(i);
95         }
96         ++i;
97     }
98     return out.empty();
99 }
100
101 unsigned int SciFile::countLines() const
102 {
103     unsigned int i = 0;
104     for (const auto & line : lines)
105     {
106         if (line.first < line.second && !isEmptyLine(code + line.first, line.second - line.first + 1))
107         {
108             ++i;
109         }
110     }
111     return i;
112 }
113
114 unsigned int SciFile::countLines(const unsigned from, const unsigned to) const
115 {
116     unsigned int i = 0;
117     for (unsigned j = from; j <= to; ++j)
118     {
119         const auto & line = lines[j - 1];
120         if (line.first < line.second && !isEmptyLine(code + line.first, line.second - line.first + 1))
121         {
122             ++i;
123         }
124     }
125     return i;
126 }
127
128 void SciFile::initLines()
129 {
130     lines.clear();
131     codeLength = 0;
132     if (code)
133     {
134         const wchar_t * p = code;
135         lines.emplace_back(0, 0);
136         while (*p)
137         {
138             if (*p == L'\n') // Unix EOL
139             {
140                 lines.back().second = p - code - 1;
141                 lines.emplace_back(p - code + 1, 0);
142                 ++p;
143             }
144             else if (*p == L'\r')
145             {
146                 if (*(p + 1) == L'\n') // Windows EOL
147                 {
148                     lines.back().second = p - code - 1;
149                     lines.emplace_back(p - code + 2, 0);
150                     p += 2;
151                 }
152                 else // Old mac EOL
153                 {
154                     lines.back().second = p - code - 1;
155                     lines.emplace_back(p - code + 1, 0);
156                     ++p;
157                 }
158             }
159             else
160             {
161                 ++p;
162             }
163         }
164
165         lines.back().second = p - code - 1;
166         codeLength = p - code;
167     }
168
169     /*for (const auto & line : lines)
170       {
171       std::wcerr << line.first << "->" << line.second << std::endl;
172       }*/
173 }
174
175 bool SciFile::isEmptyLine(const wchar_t * line, const unsigned len) const
176 {
177     // An empty line is (^[\t ]*//) or (^[\t ]*$)
178     for (unsigned i = 0; i < len; ++i)
179     {
180         const wchar_t c = line[i];
181         if (c == L' ' || c == L'\t')
182         {
183             continue;
184         }
185         else if (c == L'/' && (i < len - 1) && line[i + 1] == L'/')
186         {
187             return true;
188         }
189         else
190         {
191             return false;
192         }
193     }
194     return true;
195 }
196
197 void SciFile::analyzeTree()
198 {
199     if (tree && tree->isSeqExp())
200     {
201         bool first = true;
202         const ast::SeqExp * se = static_cast<const ast::SeqExp *>(tree);
203         for (const auto e : se->getExps())
204         {
205             if (e->isFunctionDec())
206             {
207                 const ast::FunctionDec * fd = static_cast<const ast::FunctionDec *>(e);
208                 if (first)
209                 {
210                     main = fd;
211                     first = false;
212                 }
213                 else
214                 {
215                     privateFunctions.emplace(fd->getSymbol().getName(), fd);
216                 }
217             }
218         }
219     }
220 }
221
222 bool SciFile::isPrivateFunction(const symbol::Symbol & sym) const
223 {
224     return privateFunctions.find(sym.getName()) != privateFunctions.end();
225 }
226
227 const ast::FunctionDec * SciFile::getPrivateFunction(const std::wstring & name) const
228 {
229     auto i = privateFunctions.find(name);
230     if (i != privateFunctions.end())
231     {
232         return i->second;
233     }
234     return nullptr;
235 }
236
237 const ast::FunctionDec * SciFile::getMain() const
238 {
239     return main;
240 }
241
242 } // namespace slint