source: XIOS/trunk/src/duration.cpp @ 539

Last change on this file since 539 was 539, checked in by rlacroix, 9 years ago

Fix a possible infinite loop in the duration parser and make parsing stricter.

  • Some malformed duration strings could cause an infinite loop in the parser.
  • Invalid duration strings will now cause an error message to be displayed.
  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
File size: 5.9 KB
Line 
1#include "duration.hpp"
2#include "date.hpp"
3#include "calendar.hpp"
4
5namespace xios
6{
7      /// ////////////////////// Définitions ////////////////////// ///
8      const CDuration Year   = {1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
9                      Month  = {0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0},
10                      Week   = {0.0, 0.0, 7.0, 0.0, 0.0, 0.0, 0.0},
11                      Day    = {0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0},
12                      Hour   = {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0},
13                      Minute = {0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0},
14                      Second = {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0},
15                      NoneDu = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
16                      TimeStep = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0};
17
18      ///---------------------------------------------------------------
19
20      CDuration & CDuration::operator=(const CDuration & duration)
21      {
22         year = duration.year;  month  = duration.month ; day    = duration.day;
23         hour = duration.hour;  minute = duration.minute; second = duration.second; timestep=duration.timestep ;
24         return (*this);
25      }
26
27      StdOStream & operator<<(StdOStream & out, const CDuration & duration)
28      {
29         StdOStringStream sout;
30         bool testValue = true;
31         if(duration.year   != 0.0) { testValue = false; sout << duration.year   << "y " ; }
32         if(duration.month  != 0.0) { testValue = false; sout << duration.month  << "mo "; }
33         if(duration.day    != 0.0) { testValue = false; sout << duration.day    << "d " ; }
34         if(duration.hour   != 0.0) { testValue = false; sout << duration.hour   << "h " ; }
35         if(duration.minute != 0.0) { testValue = false; sout << duration.minute << "mi "; }
36         if(duration.second != 0.0) { testValue = false; sout << duration.second << "s " ; }
37         if(duration.timestep != 0.0 || testValue)       { sout << duration.timestep << "ts " ; }
38
39         // << suppression de l'espace en fin de chaîne.
40         out << (sout.str().substr(0, sout.str().size()-1));
41         return (out);
42      }
43
44      StdIStream& operator>>(StdIStream& in , CDuration& duration)
45      {
46        duration = NoneDu;
47        double v = 1.0;
48        char   c = '/';
49        bool   invalidUnit = false;
50
51        do
52        {
53          in >> v >> c;
54          if (in.fail())
55            ERROR("StdIStream& operator>>(StdIStream& in , CDuration& duration)",
56                  << "Bad duration format: impossible to read a pair (value, unit).");
57
58          switch (c)
59          {
60            case 'y': duration.year   = v; break;
61            case 'd': duration.day    = v; break;
62            case 'h': duration.hour   = v; break;
63            case 's': duration.second = v; break;
64            case 'm':
65            {
66              in >> c;
67              if      (c == 'i') duration.minute = v;
68              else if (c == 'o') duration.month  = v;
69              else invalidUnit = true;
70              break;
71            }
72            case 't':
73            {
74              in >> c;
75              if (c == 's') duration.timestep = v;
76              else invalidUnit = true;
77              break;
78            }
79            default:
80              invalidUnit = true; 
81              break;
82          }
83
84          if (invalidUnit)
85            ERROR("StdIStream& operator>>(StdIStream& in , CDuration& duration)",
86                  << "Bad duration format: invalid unit, unexpected '" << c << "' character.");
87        } while (in.peek() != EOF); // check whether there is a next character to read
88
89        return in;
90      }
91
92      //-----------------------------------------------------------------
93
94      bool CDuration::isNone(void) const
95      {
96         if ((year == 0) && (month  == 0) && (day    == 0) &&
97             (hour == 0) && (minute == 0) && (second == 0) && (timestep == 0))
98            return (true);
99         return (false);
100      }
101
102      //-----------------------------------------------------------------
103      CDuration & CDuration::solveTimeStep(const CCalendar & c)
104      {
105        CDuration timeStep=c.getTimeStep() ;
106        second +=timestep*timeStep.second ; 
107        minute +=timestep*timeStep.minute ; 
108        hour +=timestep*timeStep.hour ; 
109        day +=timestep*timeStep.day ; 
110        month +=timestep*timeStep.month ; 
111        year +=timestep*timeStep.year ; 
112        timestep = 0 ;
113
114      }
115               
116       
117      CDuration & CDuration::resolve(const CCalendar & c)
118      {
119         // Simplification de l'écriture des minutes.
120         second += modf(minute, &minute) * (float)c.getMinuteLength();
121         minute += int(second)/c.getMinuteLength(); second = int(second)%c.getMinuteLength();
122
123         // Simplification de l'écriture des heures.
124         minute += modf(hour , &hour) * (float)c.getHourLength();
125         hour   += int(minute)/c.getHourLength(); minute = int(minute)%c.getHourLength();
126
127         // Simplification de l'écriture des jours.
128         hour   += modf(day, &day) * (float)c.getDayLength();
129         day    += int(hour)  /c.getDayLength(); hour   = int(hour)%c.getDayLength();
130
131         // > Aucune équivalence jour - mois fixée par avance. //
132
133         // Simplification de l'écriture des années.
134         month  += modf(year, &year) * (float)c.getYearLength();
135         year   += int(month) /c.getYearLength(); month  = int(month)%c.getYearLength();
136         return (*this);
137      }
138
139      //-----------------------------------------------------------------
140
141      StdString CDuration::toString(void) const
142      {
143         const  CDuration & own = *this;
144         StdOStringStream oss; oss << own;
145         return (oss.str());
146      }
147
148      CDuration CDuration::FromString(const StdString & str)
149      {
150         CDuration dr = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
151         StdIStringStream iss(str); iss >> dr;
152         return (dr);
153      }
154
155      ///---------------------------------------------------------------
156
157
158} // namespace xios
159
Note: See TracBrowser for help on using the repository browser.