@ -22,6 +22,8 @@
*/
*/
# include <strings.h>
# include <strings.h>
# include <sys/time.h>
# include <time.h>
# include "parseutils.h"
# include "parseutils.h"
# include "libavutil/avutil.h"
# include "libavutil/avutil.h"
# include "libavutil/eval.h"
# include "libavutil/eval.h"
@ -371,6 +373,241 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
return 0 ;
return 0 ;
}
}
/* get a positive number between n_min and n_max, for a maximum length
of len_max . Return - 1 if error . */
static int date_get_num ( const char * * pp ,
int n_min , int n_max , int len_max )
{
int i , val , c ;
const char * p ;
p = * pp ;
val = 0 ;
for ( i = 0 ; i < len_max ; i + + ) {
c = * p ;
if ( ! isdigit ( c ) )
break ;
val = ( val * 10 ) + c - ' 0 ' ;
p + + ;
}
/* no number read ? */
if ( p = = * pp )
return - 1 ;
if ( val < n_min | | val > n_max )
return - 1 ;
* pp = p ;
return val ;
}
/* small strptime for ffmpeg */
static
const char * small_strptime ( const char * p , const char * fmt ,
struct tm * dt )
{
int c , val ;
for ( ; ; ) {
c = * fmt + + ;
if ( c = = ' \0 ' ) {
return p ;
} else if ( c = = ' % ' ) {
c = * fmt + + ;
switch ( c ) {
case ' H ' :
val = date_get_num ( & p , 0 , 23 , 2 ) ;
if ( val = = - 1 )
return NULL ;
dt - > tm_hour = val ;
break ;
case ' M ' :
val = date_get_num ( & p , 0 , 59 , 2 ) ;
if ( val = = - 1 )
return NULL ;
dt - > tm_min = val ;
break ;
case ' S ' :
val = date_get_num ( & p , 0 , 59 , 2 ) ;
if ( val = = - 1 )
return NULL ;
dt - > tm_sec = val ;
break ;
case ' Y ' :
val = date_get_num ( & p , 0 , 9999 , 4 ) ;
if ( val = = - 1 )
return NULL ;
dt - > tm_year = val - 1900 ;
break ;
case ' m ' :
val = date_get_num ( & p , 1 , 12 , 2 ) ;
if ( val = = - 1 )
return NULL ;
dt - > tm_mon = val - 1 ;
break ;
case ' d ' :
val = date_get_num ( & p , 1 , 31 , 2 ) ;
if ( val = = - 1 )
return NULL ;
dt - > tm_mday = val ;
break ;
case ' % ' :
goto match ;
default :
return NULL ;
}
} else {
match :
if ( c ! = * p )
return NULL ;
p + + ;
}
}
return p ;
}
static time_t mktimegm ( struct tm * tm )
{
time_t t ;
int y = tm - > tm_year + 1900 , m = tm - > tm_mon + 1 , d = tm - > tm_mday ;
if ( m < 3 ) {
m + = 12 ;
y - - ;
}
t = 86400 *
( d + ( 153 * m - 457 ) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469 ) ;
t + = 3600 * tm - > tm_hour + 60 * tm - > tm_min + tm - > tm_sec ;
return t ;
}
int av_parse_time ( int64_t * timeval , const char * datestr , int duration )
{
const char * p ;
int64_t t ;
struct tm dt ;
int i ;
static const char * const date_fmt [ ] = {
" %Y-%m-%d " ,
" %Y%m%d " ,
} ;
static const char * const time_fmt [ ] = {
" %H:%M:%S " ,
" %H%M%S " ,
} ;
const char * q ;
int is_utc , len ;
char lastch ;
int negative = 0 ;
# undef time
time_t now = time ( 0 ) ;
len = strlen ( datestr ) ;
if ( len > 0 )
lastch = datestr [ len - 1 ] ;
else
lastch = ' \0 ' ;
is_utc = ( lastch = = ' z ' | | lastch = = ' Z ' ) ;
memset ( & dt , 0 , sizeof ( dt ) ) ;
p = datestr ;
q = NULL ;
if ( ! duration ) {
if ( ! strncasecmp ( datestr , " now " , len ) ) {
* timeval = ( int64_t ) now * 1000000 ;
return 0 ;
}
/* parse the year-month-day part */
for ( i = 0 ; i < FF_ARRAY_ELEMS ( date_fmt ) ; i + + ) {
q = small_strptime ( p , date_fmt [ i ] , & dt ) ;
if ( q ) {
break ;
}
}
/* if the year-month-day part is missing, then take the
* current year - month - day time */
if ( ! q ) {
if ( is_utc ) {
dt = * gmtime ( & now ) ;
} else {
dt = * localtime ( & now ) ;
}
dt . tm_hour = dt . tm_min = dt . tm_sec = 0 ;
} else {
p = q ;
}
if ( * p = = ' T ' | | * p = = ' t ' | | * p = = ' ' )
p + + ;
/* parse the hour-minute-second part */
for ( i = 0 ; i < FF_ARRAY_ELEMS ( time_fmt ) ; i + + ) {
q = small_strptime ( p , time_fmt [ i ] , & dt ) ;
if ( q ) {
break ;
}
}
} else {
/* parse datestr as a duration */
if ( p [ 0 ] = = ' - ' ) {
negative = 1 ;
+ + p ;
}
/* parse datestr as HH:MM:SS */
q = small_strptime ( p , time_fmt [ 0 ] , & dt ) ;
if ( ! q ) {
/* parse datestr as S+ */
dt . tm_sec = strtol ( p , ( char * * ) & q , 10 ) ;
if ( q = = p ) {
/* the parsing didn't succeed */
* timeval = INT64_MIN ;
return AVERROR ( EINVAL ) ;
}
dt . tm_min = 0 ;
dt . tm_hour = 0 ;
}
}
/* Now we have all the fields that we can get */
if ( ! q ) {
* timeval = INT64_MIN ;
return AVERROR ( EINVAL ) ;
}
if ( duration ) {
t = dt . tm_hour * 3600 + dt . tm_min * 60 + dt . tm_sec ;
} else {
dt . tm_isdst = - 1 ; /* unknown */
if ( is_utc ) {
t = mktimegm ( & dt ) ;
} else {
t = mktime ( & dt ) ;
}
}
t * = 1000000 ;
/* parse the .m... part */
if ( * q = = ' . ' ) {
int val , n ;
q + + ;
for ( val = 0 , n = 100000 ; n > = 1 ; n / = 10 , q + + ) {
if ( ! isdigit ( * q ) )
break ;
val + = n * ( * q - ' 0 ' ) ;
}
t + = val ;
}
* timeval = negative ? - t : t ;
return 0 ;
}
# ifdef TEST
# ifdef TEST
# undef printf
# undef printf