Xerces 3 revisions.
[shibboleth/cpp-xmltooling.git] / xmltooling / util / DateTime.h
1 /*
2  *  Copyright 2001-2007 Internet2
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 /**
18  * @file xmltooling/util/DateTime.h
19  *
20  * Manipulation of XML date/time data.
21  */
22
23 #ifndef __xmltool_datetime_h__
24 #define __xmltool_datetime_h__
25
26 #include <xmltooling/base.h>
27
28 #if defined (_MSC_VER)
29     #pragma warning( push )
30     #pragma warning( disable : 4244 )
31 #endif
32
33 #include <xercesc/util/XMLDateTime.hpp>
34
35 #if defined (_MSC_VER)
36     #pragma warning( pop )
37 #endif
38
39 namespace xmltooling
40 {
41     /**
42      * Class for manipulating XML date/time information.
43      *
44      * This is mostly copied from Xerces-C, but they haven't produced a usable date/time
45      * class, so we had to incorporate a version of it for now. It can't be inherited
46      * since the fields needed are private.
47      */
48     class XMLTOOL_API DateTime
49     {
50     public:
51         /// @cond OFF
52         DateTime();
53         DateTime(const XMLCh* const);
54         DateTime(time_t epoch, bool duration=false);
55         DateTime(const DateTime&);
56         DateTime& operator=(const DateTime&);
57         ~DateTime();
58
59         inline void setBuffer(const XMLCh* const);
60
61         const XMLCh* getRawData() const;
62         const XMLCh* getFormattedString() const;
63         int getSign() const;
64
65         XMLCh* getDateTimeCanonicalRepresentation() const;
66         XMLCh* getTimeCanonicalRepresentation() const;
67
68         void parseDateTime();
69         void parseDate();
70         void parseTime();
71         void parseDay();
72         void parseMonth();
73         void parseYear();
74         void parseMonthDay();
75         void parseYearMonth();
76         void parseDuration();
77
78         static int compare(const DateTime* const, const DateTime* const);
79         static int compare(const DateTime* const, const DateTime* const, bool);
80         static int compareOrder(const DateTime* const, const DateTime* const);
81
82         int getYear() const {return fValue[CentYear];}
83         int getMonth() const {return fValue[Month];}
84         int getDay() const {return fValue[Day];}
85         int getHour() const {return fValue[Hour];}
86         int getMinute() const {return fValue[Minute];}
87         int getSecond() const {return fValue[Second];}
88         time_t getEpoch(bool duration=false) const;
89
90         /// @endcond
91     private:
92         enum valueIndex {
93             CentYear   = 0,
94             Month      ,
95             Day        ,
96             Hour       ,
97             Minute     ,
98             Second     ,
99             MiliSecond ,  //not to be used directly
100             utc        ,
101             TOTAL_SIZE
102         };
103
104         enum utcType {
105             UTC_UNKNOWN = 0,
106             UTC_STD        ,          // set in parse() or normalize()
107             UTC_POS        ,          // set in parse()
108             UTC_NEG                   // set in parse()
109         };
110
111         enum timezoneIndex {
112             hh = 0,
113             mm ,
114             TIMEZONE_ARRAYSIZE
115         };
116
117         static int compareResult(int, int, bool);
118         static void addDuration(DateTime* pDuration, const DateTime* const pBaseDate, int index);
119         static int compareResult(const DateTime* const, const DateTime* const, bool, int);
120         static inline int getRetVal(int, int);
121
122         inline void reset();
123         //inline void assertBuffer() const;
124         inline void copy(const DateTime&);
125
126         inline void initParser();
127         inline bool isNormalized() const;
128
129         void getDate();
130         void getTime();
131         void getYearMonth();
132         void getTimeZone(const int);
133         void parseTimeZone();
134
135         int findUTCSign(const int start);
136         int indexOf(const int start, const int end, const XMLCh ch) const;
137         int parseInt(const int start, const int end) const;
138         int parseIntYear(const int end) const;
139         double parseMiliSecond(const int start, const int end) const;
140
141         void validateDateTime() const;
142         void normalize();
143         void fillString(XMLCh*& ptr, valueIndex ind, int expLen) const;
144         int  fillYearString(XMLCh*& ptr, valueIndex ind) const;
145         void searchMiliSeconds(XMLCh*& miliStartPtr, XMLCh*& miliEndPtr) const;
146
147         bool operator==(const DateTime& toCompare) const;
148
149         static const int DATETIMES[][TOTAL_SIZE];
150         int fValue[TOTAL_SIZE];
151         int fTimeZone[TIMEZONE_ARRAYSIZE];
152         int fStart;
153         int fEnd;
154         int fBufferMaxLen;
155         XMLCh* fBuffer;
156
157         double fMiliSecond;
158         bool fHasTime;
159     };
160
161     inline void DateTime::setBuffer(const XMLCh* const aString)
162     {
163         reset();
164         fEnd = (int) xercesc::XMLString::stringLen(aString);
165         if (fEnd > 0) {
166             if (fEnd > fBufferMaxLen) {
167                 delete[] fBuffer;
168                 fBufferMaxLen = fEnd + 8;
169                 fBuffer = new XMLCh[fBufferMaxLen+1];
170             }
171             memcpy(fBuffer, aString, (fEnd+1) * sizeof(XMLCh));
172         }
173     }
174
175     inline void DateTime::reset()
176     {
177         for ( int i=0; i < xercesc::XMLDateTime::TOTAL_SIZE; i++ )
178             fValue[i] = 0;
179
180         fMiliSecond   = 0;
181         fHasTime      = false;
182         fTimeZone[hh] = fTimeZone[mm] = 0;
183         fStart = fEnd = 0;
184
185         if (fBuffer)
186             *fBuffer = 0;
187     }
188
189     inline void DateTime::copy(const DateTime& rhs)
190     {
191         for ( int i = 0; i < xercesc::XMLDateTime::TOTAL_SIZE; i++ )
192             fValue[i] = rhs.fValue[i];
193
194         fMiliSecond   = rhs.fMiliSecond;
195         fHasTime      = rhs.fHasTime;
196         fTimeZone[hh] = rhs.fTimeZone[hh];
197         fTimeZone[mm] = rhs.fTimeZone[mm];
198         fStart = rhs.fStart;
199         fEnd   = rhs.fEnd;
200
201         if (fEnd > 0) {
202             if (fEnd > fBufferMaxLen) {
203                 delete[] fBuffer;
204                 fBufferMaxLen = rhs.fBufferMaxLen;
205                 fBuffer = new XMLCh[fBufferMaxLen+1];
206             }
207             memcpy(fBuffer, rhs.fBuffer, (fEnd+1) * sizeof(XMLCh));
208         }
209     }
210
211     inline void DateTime::initParser()
212     {
213         fStart = 0;   // to ensure scan from the very first beginning
214                       // in case the pointer is updated accidentally by someone else.
215     }
216
217     inline bool DateTime::isNormalized() const
218     {
219         return (fValue[xercesc::XMLDateTime::utc] == xercesc::XMLDateTime::UTC_STD ? true : false);
220     }
221
222     inline int DateTime::getRetVal(int c1, int c2)
223     {
224         if ((c1 == xercesc::XMLDateTime::LESS_THAN && c2 == xercesc::XMLDateTime::GREATER_THAN) ||
225             (c1 == xercesc::XMLDateTime::GREATER_THAN && c2 == xercesc::XMLDateTime::LESS_THAN))
226             return xercesc::XMLDateTime::INDETERMINATE;
227
228         return (c1 != xercesc::XMLDateTime::INDETERMINATE) ? c1 : c2;
229     }
230
231 }
232
233 #endif /* __xmltool_datetime_h__ */