6bd46c434e7a2ae4bf622b877990d3d799ee2103
[profile/ivi/qtxmlpatterns.git] / src / xmlpatterns / data / qabstractduration.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QStringList>
43
44 #include "qbuiltintypes_p.h"
45 #include "qpatternistlocale_p.h"
46 #include "qvalidationerror_p.h"
47
48 #include "qabstractduration_p.h"
49
50 QT_BEGIN_NAMESPACE
51
52 using namespace QPatternist;
53
54 AbstractDuration::AbstractDuration(const bool isPos) : m_isPositive(isPos)
55 {
56 }
57
58 #define error(msg) return ValidationError::createError(msg);
59 #define getCapt(sym)        ((captTable.sym == -1) ? QString() : capts.at(captTable.sym))
60
61 AtomicValue::Ptr AbstractDuration::create(const CaptureTable &captTable,
62                                           const QString &lexical,
63                                           bool *isPositive,
64                                           YearProperty *years,
65                                           MonthProperty *months,
66                                           DayCountProperty *days,
67                                           HourProperty *hours,
68                                           MinuteProperty *minutes,
69                                           SecondProperty *seconds,
70                                           MSecondProperty *mseconds)
71 {
72     /* We don't directly write into the arguments(eg @p years) but uses these
73      * because the arguments are intended for normalized values, and therefore
74      * can cause overflows. */
75     MonthCountProperty monthCount = 0;
76     MinuteCountProperty minCount = 0;
77     HourCountProperty hourCount = 0;
78     SecondCountProperty secCount = 0;
79
80     Q_ASSERT(isPositive);
81     QRegExp myExp(captTable.regExp); /* Copy, in order to stay thread safe. */
82
83     if(!myExp.exactMatch(lexical))
84     {
85         error(QString());
86     }
87
88     const QStringList capts(myExp.capturedTexts());
89
90
91     if(days)
92     {
93         if(getCapt(tDelimiter).isEmpty())
94         {
95             if((years && getCapt(year).isEmpty() && getCapt(month).isEmpty() && getCapt(day).isEmpty())
96                 ||
97                (!years && getCapt(day).isEmpty()))
98             {
99                 error(QtXmlPatterns::tr("At least one component must be present."));
100             }
101         }
102         else if(getCapt(hour).isEmpty() &&
103                 getCapt(minutes).isEmpty() &&
104                 getCapt(seconds).isEmpty() &&
105                 getCapt(mseconds).isEmpty())
106         {
107             error(QtXmlPatterns::tr("At least one time component must appear "
108                                     "after the %1-delimiter.")
109                                     .arg(formatKeyword("T")));
110         }
111     }
112     else if(getCapt(year).isEmpty() && getCapt(month).isEmpty()) /* This checks xs:yearMonthDuration. */
113     {
114         error(QtXmlPatterns::tr("At least one component must be present."));
115     }
116
117     /* If we got no '-', we are positive. */
118     *isPositive = capts.at(1).isEmpty();
119
120     if(days)
121     {
122         Q_ASSERT(hours);
123         Q_ASSERT(minutes);
124         Q_ASSERT(seconds);
125         Q_ASSERT(mseconds);
126
127         *days = getCapt(day).toInt();
128         hourCount = getCapt(hour).toInt();
129         minCount = getCapt(minutes).toInt();
130         secCount = getCapt(seconds).toInt();
131
132         const QString msecondsStr(getCapt(mseconds));
133         if(!msecondsStr.isEmpty())
134             *mseconds = msecondsStr.leftJustified(3, QLatin1Char('0')).toInt();
135         else
136             *mseconds = msecondsStr.toInt();
137
138         if(secCount > 59)
139         {
140             minCount += secCount / 60;
141             *seconds = secCount % 60;
142         }
143         else
144             *seconds = secCount;
145
146         if(minCount > 59)
147         {
148             hourCount += minCount / 60;
149             *minutes = minCount % 60;
150         }
151         else
152             *minutes = minCount;
153
154         if(hourCount > 23)
155         {
156             *days += hourCount / 24;
157             *hours = hourCount % 24;
158         }
159         else
160             *hours = hourCount;
161     }
162
163     if(!years)
164         return AtomicValue::Ptr();
165
166     /* We're supposed to handle years/months. */
167     Q_ASSERT(months);
168
169     *years = getCapt(year).toInt();
170     monthCount = getCapt(month).toInt();
171
172     if(monthCount > 11)
173     {
174         *years += monthCount / 12;
175         *months = monthCount % 12;
176     }
177     else
178         *months = monthCount;
179
180     return AtomicValue::Ptr();
181 }
182 #undef error
183 #undef getCapt
184
185 bool AbstractDuration::operator==(const AbstractDuration &other) const
186 {
187     if(years() == other.years()
188        && months() == other.months()
189        && days() == other.days()
190        && hours() == other.hours()
191        && minutes() == other.minutes()
192        && seconds() == other.seconds()
193        && mseconds() == other.mseconds())
194     {
195         if(isPositive() == other.isPositive())
196             return true;
197         else if(years() == 0
198                 && months() == 0
199                 && days() == 0
200                 && hours() == 0
201                 && minutes() == 0
202                 && seconds () == 0
203                 && mseconds() == 0)
204         {
205             return true; /* Signedness doesn't matter if all are zero. */
206         }
207     }
208
209     return false;
210 }
211
212 QString AbstractDuration::serializeMSeconds(const MSecondProperty mseconds)
213 {
214     QString retval;
215     retval.append(QLatin1Char('.'));
216     int div = 100;
217     MSecondProperty msecs = mseconds;
218
219     while(msecs > 0)
220     {
221         int d = msecs / div;
222         retval.append(QLatin1Char(d + '0'));
223         msecs = msecs % div;
224         div = div / 10;
225     }
226
227     return retval;
228 }
229
230 bool AbstractDuration::isPositive() const
231 {
232     return m_isPositive;
233 }
234
235 QT_END_NAMESPACE