/*
* Conversions.cpp
*****************************************************************************
* Copyright © 2015 - VideoLAN and VLC Authors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "Conversions.hpp"
#include <vlc_charset.h>
#include <sstream>
/*
Decodes a duration as defined by ISO 8601
http://en.wikipedia.org/wiki/ISO_8601#Durations
@param str A nullptr-terminated string to convert
@return: The duration in seconds. -1 if an error occurred.
Example input string: "PT0H9M56.46S"
*/
static vlc_tick_t str_duration( const char *psz_duration )
{
bool timeDesignatorReached = false;
vlc_tick_t res = 0;
char* end_ptr;
if ( psz_duration == nullptr )
return -1;
if ( ( *(psz_duration++) ) != 'P' )
return -1;
do
{
double number = vlc_strtod_c( psz_duration, &end_ptr );
double mul = 0;
if ( psz_duration != end_ptr )
psz_duration = end_ptr;
switch( *psz_duration )
{
case 'M':
{
//M can mean month or minutes, if the 'T' flag has been reached.
//We don't handle months though.
if ( timeDesignatorReached == true )
mul = 60.0;
break ;
}
case 'Y':
case 'W':
break ; //Don't handle this duration.
case 'D':
mul = 86400.0;
break ;
case 'T':
timeDesignatorReached = true;
break ;
case 'H':
mul = 3600.0;
break ;
case 'S':
mul = 1.0;
break ;
default:
break ;
}
res += vlc_tick_from_sec(mul * number);
if ( *psz_duration )
psz_duration++;
} while ( *psz_duration );
return res;
}
IsoTime::IsoTime(const std::string &str)
{
time = str_duration(str.c_str());
}
IsoTime::operator vlc_tick_t () const
{
return time;
}
UTCTime::UTCTime(const std::string &str)
{
enum { UTCTIME_YEAR = 0, UTCTIME_MON, UTCTIME_DAY, UTCTIME_HOUR, UTCTIME_MIN,
UTCTIME_SEC, UTCTIME_FRAC_NUM, UTCTIME_FRAC_DEN, UTCTIME_TZ };
int values[9] = {0};
std::istringstream in(str);
in.imbue(std::locale("C"));
try
{
/* Date */
for(int i=UTCTIME_YEAR;i<=UTCTIME_DAY && in.good();i++)
{
if(i!=UTCTIME_YEAR)
in.ignore(1);
if(in.good())
in >> values[i];
}
/* Time */
if (in.good() && in.peek() == 'T')
{
for(int i=UTCTIME_HOUR;i<=UTCTIME_SEC && in.good();i++)
{
in.ignore(1);
if(in.good())
in >> values[i];
}
}
if(in.good() && in.peek() == '.')
{
in.ignore(1);
values[UTCTIME_FRAC_NUM] = 0;
values[UTCTIME_FRAC_DEN] = 1;
int c = in.peek();
while(c >= '0' && c <= '9')
{
values[UTCTIME_FRAC_NUM] = values[UTCTIME_FRAC_NUM] * 10 + (c - '0');
values[UTCTIME_FRAC_DEN] *= 10;
in.ignore(1);
if(!in.good())
break;
c = in.peek();
}
}
/* Timezone */
if(in.good() && in.peek() == 'Z')
{
in.ignore(1);
}
else if (in.good() && (in.peek() == '+' || in.peek() == '-'))
{
int sign = (in.peek() == '+') ? 1 : -1;
int tz = 0;
in.ignore(1);
if(in.good())
{
std::string tzspec;
in >> tzspec;
if(!in.fail())
{
if(tzspec.length() >= 4)
{
tz = sign * std::stoul(tzspec.substr(0, 2)) * 60;
if(tzspec.length() == 5 && tzspec.find(':') == 2)
tz += sign * std::stoul(tzspec.substr(3, 2));
else
tz += sign * std::stoul(tzspec.substr(2, 2));
}
else
{
tz = sign * std::stoul(tzspec) * 60;
}
values[UTCTIME_TZ] = tz;
}
}
}
if (!in.fail()) {
struct tm tm;
tm.tm_year = values[UTCTIME_YEAR] - 1900;
tm.tm_mon = values[UTCTIME_MON] - 1;
tm.tm_mday = values[UTCTIME_DAY];
tm.tm_hour = values[UTCTIME_HOUR];
tm.tm_min = values[UTCTIME_MIN];
tm.tm_sec = values[UTCTIME_SEC];
tm.tm_isdst = 0;
int64_t mst = timegm( &tm );
mst += values[UTCTIME_TZ] * -60;
mst *= 1000;
t = VLC_TICK_FROM_MS(mst);
if(values[UTCTIME_FRAC_DEN] > 0)
t += vlc_tick_from_samples(values[UTCTIME_FRAC_NUM], values[UTCTIME_FRAC_DEN]);
} else {
// Failure parsing time string
t = 0;
}
} catch(...) {
t = 0;
}
}
UTCTime::operator vlc_tick_t () const
{
return t;
}
¤ Dauer der Verarbeitung: 0.4 Sekunden
¤
*© Formatika GbR, Deutschland