[vlc-devel] [Patch] Adding an helper to convert iso8601 durations to seconds

Rémi Denis-Courmont remi at remlab.net
Tue Dec 6 14:59:04 CET 2011


Le mardi 6 décembre 2011 14:11:10 Hugo Beauzée-Luyssen, vous avez écrit :
> On Wed, Nov 30, 2011 at 4:41 PM, Hugo Beauzée-Luyssen
> 
> <beauze.h at gmail.com> wrote:
> > On Wed, Nov 30, 2011 at 2:45 PM, Hugo Beauzée-Luyssen
> > 
> > <beauze.h at gmail.com> wrote:
> >> On Wed, Nov 30, 2011 at 2:08 PM, Tobias Güntner <fatbull at web.de> wrote:
> >>> Am 30.11.2011 11:05, schrieb Hugo Beauzée-Luyssen:
> >>>> +/*
> >>>> +  Decodes a duration as defined by ISO 8601
> >>>> +  http://en.wikipedia.org/wiki/ISO_8601#Durations
> >>>> +  @param str A null-terminated string to convert
> >>> 
> >>> Perhaps a short example of a valid input string would be useful, so
> >>> readers can see at first glance what kind of data this function
> >>> expects, without looking it up.
> >> 
> >> Yep I'm going to write some tests in a this afternoon or tomorrow, but
> >> I could add a link to the format description and an exemple in the
> >> comments.
> >> 
> >>>> +  @return: The duration in seconds. 0 if an error occured.
> >>> 
> >>> This function usually does not return 0 if the input is invalid.
> >> 
> >> Yep i'm going to change the return type as a signed int 64, so -1 is an
> >> error.
> >> 
> >>>> + */
> >>>> +uint64_t str_iso8601_duration_to_seconds( const char *psz_duration )
> >>>> +{
> >>>> +    bool        timeDesignatorReached = false;
> >>>> +    double      mul = 0;
> >>> 
> >>> I think an integer should be fine.
> >> 
> >> Well in the exemple file I've got
> >> (http://www-itec.uni-klu.ac.at/ftp/datasets/mmsys12/Selected_VLC_Plugin_
> >> MPDs/BigBuckBunny_15s_DASH_VLC_Compatible_4-Representations_720p.mpd)
> >> there are some decimal values, so I try to reduce the loss of
> >> precision when converting by using doubles.
> >> 
> >>>> +    mtime_t     res = 0;
> >>> 
> >>> Shouldn't this type and the return type be the same?
> >> 
> >> I was using mtime_t at first, it seems I forgot to change this one, my
> >> bad.
> >> 
> >> Since the line below is a direct pointer dereferencement without any
> >> prior check, this was intended, but a check could be added.
> >> 
> >>>> +
> >>>> +    if ( *psz_duration++ != 'P' )
> >>>> +        return 0;
> >>>> +    for ( const char* nptr = psz_duration; *psz_duration;
> >>>> ++psz_duration ) +    {
> >>>> +        switch( *psz_duration )
> >>>> +        {
> >>>> +            case 'M':
> >>>> +            {
> >>> 
> >>> I find this a little confusing because letters normally follow numbers
> >>> in the input, yet you somehow parse letters first. ;)
> >> 
> >> That is absolutely right...
> >> 
> >>>> +                //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.
> >>> 
> >>> Maybe return an error here?
> >> 
> >> I don't really know... warning should be mandatory, an error may be to
> >> agressive...
> >> 
> >>>> +            case 'D':
> >>>> +                mul = 86400.0;
> >>>> +                break ;
> >>>> +            case 'T':
> >>>> +                timeDesignatorReached = true;
> >>>> +                break ;
> >>>> +            case 'H':
> >>>> +                mul = 3600.0;
> >>>> +                break ;
> >>>> +            case 'S':
> >>>> +                mul = 1.0;
> >>>> +                break ;
> >>>> +            default:
> >>>> +                continue ;
> >>>> +        }
> >>>> +        //It means we went trough some digits. So we must compute a
> >>>> number +        if ( nptr != psz_duration )
> >>>> +        {
> >>>> +            double tmp = strtold( nptr, NULL );
> >>> 
> >>> I think you can achieve a slightly cleaner design if you utilize the
> >>> second parameter of that function. The strtoX functions store the
> >>> address of the first invalid character in there, so all you have to do
> >> 
> >>> is basically:
> >> Yep since I'm doing it in the wrong way, using the second parameter
> >> makes a lot of sense now :D
> >> 
> >>> 1. Call strtoul(psz_duration, &endptr, 10)
> >>> 2. Check the character at *endptr
> >>> 3. Repeat with psz_duration = endptr + 1
> >>> 
> >>>> +            res += (uint64_t)(tmp * mul);
> >>>> +            nptr = psz_duration;
> >>>> +        }
> >>>> +        nptr++;
> >>>> +    }
> >>>> +    return res;
> >>>> +}
> >>> 
> >>> Regards,
> >>> Tobias
> >> 
> >> Thanks for the review!
> >> Regards,
> > 
> > Here is a new version, along with some unit tests.
> > 
> > Regards,
> 
> Hi,
> 
> Could somebody review these patches?


+    if ( *psz_duration++ != 'P' )
+        return -1;

With *three* independent operators (dereference, increment and inequality) on 
psz_duration in a single expression, you really need more explicit parenthesis 
IMHO.

Also, the test case name is very poor IMHO.

-- 
Rémi Denis-Courmont
http://www.remlab.net/
http://fi.linkedin.com/in/remidenis



More information about the vlc-devel mailing list