Initialize Tizen 2.3
[framework/web/wrt-commons.git] / modules_wearable / utils / src / widget_version.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file    widget_version.cpp
18  * @author  Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version 1.0
20  * @brief   Implementation file for widget version
21  */
22 #include <stddef.h>
23 #include <dpl/utils/widget_version.h>
24 #include <dpl/assert.h>
25 #include <dpl/log/log.h>
26 #include <ctype.h>
27 #include <list>
28
29 namespace // anonymous
30 {
31 size_t WAC_CERTIFY_MANDATORY_PART_LOW_COUNT = 2;
32 size_t WAC_CERTIFY_MANDATORY_PART_HIGH_COUNT = 3;
33 size_t WAC_CERTIFY_MANDATORY_PART_MAJOR_INDEX = 0;
34 size_t WAC_CERTIFY_MANDATORY_PART_MINOR_INDEX = 1;
35 size_t WAC_CERTIFY_MANDATORY_PART_MICRO_INDEX = 2;
36 DPL::String::value_type WAC_CERTIFY_MANDATORY_VS_OPTIONAL_SPLIT_CHAR = L' ';
37 DPL::String::value_type WAC_CERTIFY_MANDATORY_NUMBER_PART_SPLIT_CHAR = L'.';
38 DPL::String::value_type LEADING_ZERO_CHAR = L'0';
39
40 //
41 // [ABNF]
42 // Augmented BNF for Syntax Specifications: ABNF. RFC5234. D. Crocker and P.
43 // Overell. January 2008.
44 //
45 // ALPHA          =  %x41-5A / %x61-7A
46 inline bool IsAlpha(int c)
47 {
48     return (c >= 0x41 && c <= 0x5A) ||
49            (c >= 0x61 && c <= 0x7A);
50 }
51
52 // DIGIT          =  %x30-39
53 inline bool IsDigit(int c)
54 {
55     return c >= 0x30 && c <= 0x39;
56 }
57
58 // SP             =  %x20
59 inline bool IsSp(int c)
60 {
61     return c == 0x20;
62 }
63
64 DPL::String RemoveLeadingZeroes(const DPL::String &str)
65 {
66     Assert(!str.empty());
67
68     if (str[0] != LEADING_ZERO_CHAR) {
69         return str;
70     }
71
72     size_t pos = 0;
73
74     while (pos + 1 < str.size()) {
75         ++pos;
76
77         if (str[pos] != LEADING_ZERO_CHAR)
78             break;
79     }
80
81     return str.substr(pos);
82 }
83
84 // operator <
85 bool NumberLessOperator(const DPL::String &left,
86                         const DPL::String &right)
87 {
88     // Assume: No leading zeroes
89     if (left.size() < right.size()) {
90         return true;
91     }
92
93     if (left.size() > right.size()) {
94         return false;
95     }
96
97     // Now: left.size() == right.size()
98     for (ssize_t i = static_cast<ssize_t>(left.size()) - 1; i >= 0; --i) {
99         if (left[i] < right[i]) {
100             return true;
101         }
102
103         if (left[i] > right[i]) {
104             return false;
105         }
106     }
107
108     // Equal
109     return false;
110 }
111
112 bool WacCertifyNumberString(const DPL::String &str)
113 {
114     for (DPL::String::const_iterator i = str.begin(); i != str.end(); ++i) {
115         if (!IsDigit(*i)) {
116             return false;
117         }
118     }
119
120     return true;
121 }
122
123 bool WacCertifyAlphaNumberStringSpace(const DPL::String &str)
124 {
125     for (DPL::String::const_iterator i = str.begin(); i != str.end(); ++i) {
126         if (!IsDigit(*i) && !IsAlpha(*i) && !IsSp(*i)) {
127             return false;
128         }
129     }
130
131     return true;
132 }
133 } // anonymous
134
135 WidgetVersion::WidgetVersion(const DPL::String &str) :
136     m_isWac(false),
137     m_raw(str)
138 {
139     LogDebug("Parsing version string: " << str);
140
141     // Split optional an mandatory parts
142     size_t optionalPartPosition = str.find(
143             WAC_CERTIFY_MANDATORY_VS_OPTIONAL_SPLIT_CHAR);
144
145     DPL::String mandatoryPart;
146     DPL::Optional<DPL::String> optionalPart;
147
148     if (optionalPartPosition == DPL::String::npos) {
149         mandatoryPart = str;
150     } else {
151         mandatoryPart = str.substr(0, optionalPartPosition);
152         optionalPart = str.substr(optionalPartPosition + 1, DPL::String::npos);
153     }
154
155     LogDebug("Mandatory part is: " << mandatoryPart);
156     LogDebug("Optional part is: " << optionalPart);
157
158     // Split string and construct version
159     std::vector<DPL::String> parts;
160     DPL::Tokenize(mandatoryPart,
161                   WAC_CERTIFY_MANDATORY_NUMBER_PART_SPLIT_CHAR,
162                   std::back_inserter(parts),
163                   false);
164
165     LogDebug("Tokenized mandatory parts: " << parts.size());
166
167     if (parts.size() != WAC_CERTIFY_MANDATORY_PART_LOW_COUNT &&
168         parts.size() != WAC_CERTIFY_MANDATORY_PART_HIGH_COUNT)
169     {
170         return;
171     }
172
173     DPL::String major;
174     DPL::String minor;
175     DPL::Optional<DPL::String> micro;
176
177     // Certify for Wac
178     major = parts[WAC_CERTIFY_MANDATORY_PART_MAJOR_INDEX];
179     minor = parts[WAC_CERTIFY_MANDATORY_PART_MINOR_INDEX];
180
181     if (parts.size() == WAC_CERTIFY_MANDATORY_PART_HIGH_COUNT) {
182         micro = parts[WAC_CERTIFY_MANDATORY_PART_MICRO_INDEX];
183     }
184
185     WacCertify(major, minor, micro, optionalPart);
186 }
187
188 WidgetVersion::WidgetVersion(const DPL::String &major,
189                              const DPL::String &minor,
190                              const DPL::Optional<DPL::String> &micro,
191                              const DPL::Optional<DPL::String> &optional) :
192     m_isWac(false)
193 {
194     // Create Raw version
195     m_raw += major;
196     m_raw += WAC_CERTIFY_MANDATORY_NUMBER_PART_SPLIT_CHAR;
197     m_raw += minor;
198
199     if (!!micro) {
200         m_raw += WAC_CERTIFY_MANDATORY_NUMBER_PART_SPLIT_CHAR;
201         m_raw += *micro;
202     }
203
204     if (!!optional) {
205         m_raw += WAC_CERTIFY_MANDATORY_VS_OPTIONAL_SPLIT_CHAR;
206         m_raw += *optional;
207     }
208
209     // Certify for Wac
210     WacCertify(major, minor, micro, optional);
211 }
212
213 void WidgetVersion::WacCertify(const DPL::String &major,
214                                const DPL::String &minor,
215                                const DPL::Optional<DPL::String> &micro,
216                                const DPL::Optional<DPL::String> &optional)
217 {
218     LogDebug("Certyfing...");
219
220     LogDebug("Major candidate: " << major);
221     LogDebug("Minor candidate: " << minor);
222     LogDebug("Micro candidate: " << micro);
223     LogDebug("Optional candidate: " << optional);
224
225     // Check strings
226     if (major.empty() || !WacCertifyNumberString(major)) {
227         LogDebug("Major version not certified!");
228         return;
229     }
230
231     if (minor.empty() || !WacCertifyNumberString(minor)) {
232         LogDebug("Minor version not certified!");
233         return;
234     }
235
236     if (!!micro && (micro->empty() || !WacCertifyNumberString(*micro))) {
237         LogDebug("Microversion not certified!");
238         return;
239     }
240
241     if (!!optional &&
242         (optional->empty() || !WacCertifyAlphaNumberStringSpace(*optional)))
243     {
244         LogDebug("Optional version not certified!");
245         return;
246     }
247
248     // OK
249     m_major = major;
250     m_minor = minor;
251     m_micro = micro;
252     m_optional = optional;
253
254     m_isWac = true;
255
256     LogDebug("Certified.");
257 }
258
259 bool WidgetVersion::IsWac() const
260 {
261     return m_isWac;
262 }
263
264 const DPL::String &WidgetVersion::Raw() const
265 {
266     return m_raw;
267 }
268
269 const DPL::String &WidgetVersion::Major() const
270 {
271     return m_major;
272 }
273
274 const DPL::String &WidgetVersion::Minor() const
275 {
276     return m_minor;
277 }
278
279 const DPL::Optional<DPL::String> &WidgetVersion::Micro() const
280 {
281     return m_micro;
282 }
283
284 const DPL::Optional<DPL::String> &WidgetVersion::Optional() const
285 {
286     return m_optional;
287 }
288
289 bool operator<(const WidgetVersion &left,
290                const WidgetVersion &right)
291 {
292     AssertMsg(
293         left.IsWac() && right.IsWac(),
294         "Only WAC version strings are comparable!");
295
296     if (NumberLessOperator(RemoveLeadingZeroes(left.Major()),
297                            RemoveLeadingZeroes(right.Major())))
298     {
299         return true;
300     }
301     if (NumberLessOperator(RemoveLeadingZeroes(right.Major()),
302                            RemoveLeadingZeroes(left.Major())))
303     {
304         return false;
305     }
306
307     if (NumberLessOperator(RemoveLeadingZeroes(left.Minor()),
308                            RemoveLeadingZeroes(right.Minor())))
309     {
310         return true;
311     }
312     if (NumberLessOperator(RemoveLeadingZeroes(right.Minor()),
313                            RemoveLeadingZeroes(left.Minor())))
314     {
315         return false;
316     }
317
318     if (!!left.Micro() && !!right.Micro() &&
319         NumberLessOperator(RemoveLeadingZeroes(*left.Micro()),
320                            RemoveLeadingZeroes(*right.Micro())))
321     {
322         return true;
323     }
324     if (!left.Micro() && !!right.Micro()) {
325         return true;
326     }
327
328     return false;
329 }
330
331 bool operator<=(const WidgetVersion &left,
332                 const WidgetVersion &right)
333 {
334     AssertMsg(
335         left.IsWac() && right.IsWac(),
336         "Only WAC version strings are comparable!");
337
338     return (left == right) || (left < right);
339 }
340
341 bool operator>(const WidgetVersion &left,
342                const WidgetVersion &right)
343 {
344     AssertMsg(
345         left.IsWac() && right.IsWac(),
346         "Only WAC version strings are comparable!");
347
348     return !(left <= right);
349 }
350
351 bool operator>=(const WidgetVersion &left,
352                 const WidgetVersion &right)
353 {
354     AssertMsg(
355         left.IsWac() && right.IsWac(),
356         "Only WAC version strings are comparable!");
357
358     return (left == right) || (left > right);
359 }
360
361 bool operator==(const WidgetVersion &left,
362                 const WidgetVersion &right)
363 {
364     AssertMsg(
365         left.IsWac() && right.IsWac(),
366         "Only WAC version strings are comparable!");
367
368     //Major are equal
369     //and
370     //Minor are equal
371     //and
372     //Both Micro exist and are equal
373     //or both Micro do not exist
374     return RemoveLeadingZeroes(left.Major()) ==
375            RemoveLeadingZeroes(right.Major()) &&
376            RemoveLeadingZeroes(left.Minor()) ==
377            RemoveLeadingZeroes(right.Minor()) &&
378            (
379                (!!left.Micro() && !!right.Micro() &&
380                 RemoveLeadingZeroes(*left.Micro()) ==
381                 RemoveLeadingZeroes(*right.Micro())) ||
382                (!left.Micro() && !right.Micro())
383            );
384 }
385
386 bool operator!=(const WidgetVersion &left,
387                 const WidgetVersion &right)
388 {
389     AssertMsg(
390         left.IsWac() && right.IsWac(),
391         "Only WAC version strings are comparable!");
392
393     return !(left == right);
394 }
395
396 std::ostream & operator<<(std::ostream& stream,
397                           const WidgetVersion& version)
398 {
399     stream << version.Raw();
400     return stream;
401 }