Line data Source code
1 : // Snap Websites Server -- handle versions and dependencies
2 : // Copyright (c) 2014-2019 Made to Order Software Corp. All Rights Reserved
3 : //
4 : // This program is free software; you can redistribute it and/or modify
5 : // it under the terms of the GNU General Public License as published by
6 : // the Free Software Foundation; either version 2 of the License, or
7 : // (at your option) any later version.
8 : //
9 : // This program is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : // GNU General Public License for more details.
13 : //
14 : // You should have received a copy of the GNU General Public License
15 : // along with this program; if not, write to the Free Software
16 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 : #pragma once
18 :
19 : #include "snapwebsites/snap_exception.h"
20 : #include "snapwebsites/qstring_stream.h"
21 :
22 : #include <QVector>
23 :
24 :
25 : namespace snap
26 : {
27 : namespace snap_version
28 : {
29 :
30 0 : class snap_version_exception : public snap_exception
31 : {
32 : public:
33 0 : explicit snap_version_exception(char const * whatmsg) : snap_exception("snap_version", whatmsg) {}
34 : explicit snap_version_exception(std::string const & whatmsg) : snap_exception("snap_version", whatmsg) {}
35 : explicit snap_version_exception(QString const & whatmsg) : snap_exception("snap_version", whatmsg) {}
36 : };
37 :
38 0 : class snap_version_exception_invalid_extension : public snap_version_exception
39 : {
40 : public:
41 0 : explicit snap_version_exception_invalid_extension(char const * whatmsg) : snap_version_exception(whatmsg) {}
42 : explicit snap_version_exception_invalid_extension(std::string const & whatmsg) : snap_version_exception(whatmsg) {}
43 : explicit snap_version_exception_invalid_extension(QString const & whatmsg) : snap_version_exception(whatmsg) {}
44 : };
45 :
46 :
47 : enum class compare_t : signed int
48 : {
49 : COMPARE_INVALID = -2, // i.e. unordered
50 : COMPARE_SMALLER = -1,
51 : COMPARE_EQUAL = 0,
52 : COMPARE_LARGER = 1
53 : };
54 :
55 : typedef uint32_t basic_version_number_t;
56 :
57 : static basic_version_number_t const SPECIAL_VERSION_ALL = static_cast<basic_version_number_t>(-4); // apply to all branches
58 : static basic_version_number_t const SPECIAL_VERSION_EXTENDED = static_cast<basic_version_number_t>(-3); // revision of .js/.css may be more than one number
59 : static basic_version_number_t const SPECIAL_VERSION_INVALID = static_cast<basic_version_number_t>(-2);
60 : static basic_version_number_t const SPECIAL_VERSION_UNDEFINED = static_cast<basic_version_number_t>(-1);
61 : static basic_version_number_t const SPECIAL_VERSION_MIN = 0;
62 : static basic_version_number_t const SPECIAL_VERSION_SYSTEM_BRANCH = 0;
63 : static basic_version_number_t const SPECIAL_VERSION_USER_FIRST_BRANCH = 1;
64 : static basic_version_number_t const SPECIAL_VERSION_FIRST_REVISION = 0;
65 : static basic_version_number_t const SPECIAL_VERSION_MAX_BRANCH_NUMBER = static_cast<basic_version_number_t>(-5);
66 : static basic_version_number_t const SPECIAL_VERSION_MAX = static_cast<basic_version_number_t>(-1);
67 :
68 : static basic_version_number_t const SPECIAL_VERSION_DEFAULT = SPECIAL_VERSION_UNDEFINED;
69 :
70 : class version_number_t
71 : {
72 : public:
73 0 : version_number_t() noexcept
74 0 : {
75 0 : }
76 :
77 0 : version_number_t(version_number_t const & rhs)
78 0 : : f_version(rhs.f_version)
79 : {
80 0 : }
81 :
82 0 : version_number_t(basic_version_number_t const v)
83 0 : : f_version(v)
84 : {
85 0 : }
86 :
87 0 : version_number_t & operator = (version_number_t const & rhs)
88 : {
89 0 : f_version = rhs.f_version;
90 0 : return *this;
91 : }
92 :
93 0 : version_number_t & operator = (basic_version_number_t const v)
94 : {
95 0 : f_version = v;
96 0 : return *this;
97 : }
98 :
99 0 : /*explicit*/ operator basic_version_number_t () const
100 : {
101 0 : return f_version;
102 : }
103 :
104 : version_number_t & operator -- ()
105 : {
106 : --f_version;
107 : return *this;
108 : }
109 :
110 : version_number_t & operator ++ ()
111 : {
112 : ++f_version;
113 : return *this;
114 : }
115 :
116 : version_number_t operator -- (int)
117 : {
118 : version_number_t const copy(*this);
119 : --f_version;
120 : return copy;
121 : }
122 :
123 : version_number_t operator ++ (int)
124 : {
125 : version_number_t const copy(*this);
126 : ++f_version;
127 : return copy;
128 : }
129 :
130 : private:
131 : basic_version_number_t f_version = SPECIAL_VERSION_UNDEFINED;
132 : };
133 :
134 : typedef QVector<version_number_t> version_numbers_vector_t;
135 :
136 : enum class operator_t
137 : {
138 : /* ?? */ OPERATOR_UNORDERED,
139 : /* == */ OPERATOR_EQUAL,
140 : /* != */ OPERATOR_EXCEPT,
141 : /* < */ OPERATOR_EARLIER,
142 : /* > */ OPERATOR_LATER,
143 : /* <= */ OPERATOR_EARLIER_OR_EQUAL,
144 : /* >= */ OPERATOR_LATER_OR_EQUAL
145 : };
146 :
147 :
148 : char const * find_extension(QString const & filename, char const ** extensions);
149 : bool validate_basic_name(QString const & name, QString & error);
150 : bool validate_name(QString & name, QString & error, QString & namespace_string);
151 : bool validate_version(QString const & version_string, version_numbers_vector_t & version, QString & error);
152 : bool validate_operator(QString const & operator_string, operator_t & op, QString & error);
153 :
154 :
155 0 : class name
156 : {
157 : public:
158 : typedef QVector<name> vector_t;
159 :
160 0 : void clear() { f_name.clear(); f_error.clear(); }
161 : bool set_name(QString const & name_string);
162 0 : QString const & get_name() const { return f_name; }
163 0 : QString const & get_namespace() const { return f_namespace; }
164 0 : bool is_valid() const { return f_error.isEmpty(); }
165 0 : QString get_error() const { return f_error; }
166 :
167 : compare_t compare(name const & rhs) const;
168 :
169 : private:
170 : QString f_name = QString();
171 : QString f_namespace = QString();
172 : QString f_error = QString();
173 : };
174 :
175 :
176 0 : class version_operator
177 : {
178 : public:
179 : bool set_operator_string(QString const & operator_string);
180 : bool set_operator(operator_t op);
181 : char const * get_operator_string() const;
182 0 : operator_t get_operator() const { return f_operator; }
183 0 : bool is_valid() const { return f_error.isEmpty(); }
184 0 : QString const & get_error() const { return f_error; }
185 :
186 : private:
187 : operator_t f_operator = operator_t::OPERATOR_UNORDERED;
188 : QString f_error = QString();
189 : };
190 :
191 :
192 0 : class version
193 : {
194 : public:
195 : typedef QVector<version> vector_t;
196 :
197 : bool set_version_string(QString const & version_string);
198 : void set_version(version_numbers_vector_t const & version);
199 : void set_operator(version_operator const & op);
200 : version_numbers_vector_t const & get_version() const { return f_version; }
201 : QString const & get_version_string() const;
202 : QString get_opversion_string() const;
203 : version_operator const & get_operator() const { return f_operator; }
204 0 : bool is_valid() const { return f_error.isEmpty() && f_operator.is_valid(); }
205 0 : QString get_error() const { return f_error; }
206 :
207 : compare_t compare(version const & rhs) const;
208 :
209 : private:
210 : mutable QString f_version_string = QString();
211 : version_numbers_vector_t f_version = version_numbers_vector_t();
212 : QString f_error = QString();
213 : version_operator f_operator = version_operator();
214 : };
215 :
216 :
217 : class versioned_filename
218 : {
219 : public:
220 :
221 : versioned_filename(QString const & extension);
222 :
223 : bool set_filename(QString const & filename);
224 : bool set_name(QString const & name);
225 : bool set_version(QString const & version_string);
226 :
227 0 : bool is_valid() const { return f_error.isEmpty() && f_name.is_valid() && f_version.is_valid() && f_browser.is_valid(); }
228 :
229 : QString get_error() const { return f_error; }
230 : QString get_filename(bool extension = false) const;
231 : QString const & get_extension() const { return f_extension; }
232 : QString const & get_name() const { return f_name.get_name(); }
233 : QString const & get_version_string() const { return f_version.get_version_string(); } // this was canonicalized
234 : version_numbers_vector_t const & get_version() const { return f_version.get_version(); }
235 : QString const & get_browser() const { return f_browser.get_name(); }
236 :
237 : compare_t compare(versioned_filename const & rhs) const;
238 : bool operator == (versioned_filename const & rhs) const;
239 : bool operator != (versioned_filename const & rhs) const;
240 : bool operator < (versioned_filename const & rhs) const;
241 : bool operator <= (versioned_filename const & rhs) const;
242 : bool operator > (versioned_filename const & rhs) const;
243 : bool operator >= (versioned_filename const & rhs) const;
244 :
245 : operator bool () const { return is_valid(); }
246 : bool operator ! () const { return !is_valid(); }
247 :
248 : private:
249 : QString f_error = QString();
250 : QString f_extension = QString();
251 : name f_name = name();
252 : version f_version = version();
253 : name f_browser = name();
254 : };
255 :
256 :
257 0 : class dependency
258 : {
259 : public:
260 : bool set_dependency(QString const & dependency_string);
261 : QString get_dependency_string() const;
262 : QString const & get_name() const { return f_name.get_name(); }
263 : QString const & get_namespace() const { return f_name.get_namespace(); }
264 : version::vector_t const & get_versions() const { return f_versions; }
265 : name::vector_t const & get_browsers() const { return f_browsers; }
266 : bool is_valid() const;
267 : QString const & get_error() const { return f_error; }
268 :
269 : private:
270 : QString f_error = QString();
271 : name f_name = name();
272 : version::vector_t f_versions = version::vector_t();
273 : name::vector_t f_browsers = name::vector_t();
274 : };
275 : typedef QVector<dependency> dependency_vector_t;
276 :
277 :
278 : class quick_find_version_in_source
279 : {
280 : public:
281 : quick_find_version_in_source();
282 : quick_find_version_in_source(quick_find_version_in_source const & rhs) = delete;
283 : quick_find_version_in_source & operator = (quick_find_version_in_source const & rhs) = delete;
284 :
285 : bool find_version(char const * data, int const size);
286 :
287 : void set_name(QString const & name) { f_name.set_name(name); }
288 : QString const & get_name() const { return f_name.get_name(); }
289 : QString const & get_layout() const { return f_layout.get_name(); }
290 : QString const & get_version_string() const { return f_version.get_version_string(); } // this was canonicalized
291 : version_number_t get_branch() const { if(f_version.get_version().empty()) return SPECIAL_VERSION_UNDEFINED; else return f_version.get_version()[0]; }
292 : version_numbers_vector_t const & get_version() const { return f_version.get_version(); }
293 : name::vector_t const & get_browsers() const { return f_browsers; }
294 : QString const & get_description() const { return f_description; }
295 : dependency_vector_t const & get_depends() const { return f_depends; }
296 : bool is_defined() const { return f_data != nullptr; }
297 : bool is_valid() const;
298 : QString const & get_error() const { return f_error; }
299 :
300 : private:
301 : int getc();
302 : QString get_line();
303 :
304 : char const * f_data = nullptr;
305 : char const * f_end = nullptr;
306 :
307 : name f_name = name();
308 : name f_layout = name();
309 : version f_version = version();
310 : name::vector_t f_browsers = name::vector_t();
311 : QString f_error = QString();
312 : QString f_description = QString();
313 : dependency_vector_t f_depends = dependency_vector_t();
314 : };
315 :
316 :
317 : } // namespace snap_version
318 : } // namespace snap
319 : // vim: ts=4 sw=4 et
|