Convert-Binary-C

 view release on metacpan or  search on metacpan

tests/include/pdclib/functions/_tzcode/_PDCLIB_tzload.c  view on Meta::CPAN

    return result;
}

static int_fast64_t detzcode64( const char * codep )
{
    uint_fast64_t result;
    int           i;
    int_fast64_t  one = 1;
    int_fast64_t  halfmaxval = one << ( 64 - 2 );
    int_fast64_t  maxval = halfmaxval - 1 + halfmaxval;
    int_fast64_t  minval = - _PDCLIB_TWOS_COMPLEMENT - maxval;

    result = codep[ 0 ] & 0x7f;

    for ( i = 1; i < 8; ++i )
    {
        result = ( result << 8 ) | ( codep[ i ] & 0xff );
    }

    if ( codep[ 0 ] & 0x80 )
    {
        /* Do two's-complement negation even on non-two's-complement machines.
           If the result would be minval - 1, return minval.
        */
      result -= ! _PDCLIB_TWOS_COMPLEMENT && result != 0;
      result += minval;
    }

    return result;
}

static bool differ_by_repeat( const time_t t1, const time_t t0 )
{
    if ( ( sizeof( time_t ) * _PDCLIB_CHAR_BIT ) - _PDCLIB_TYPE_SIGNED( time_t ) < SECSPERREPEAT_BITS )
    {
        return 0;
    }

    return ( t1 - t0 ) == SECSPERREPEAT;
}

static bool typesequiv( const struct state * sp, int a, int b )
{
    bool result;

    if ( sp == NULL ||
         a < 0 || a >= sp->typecnt ||
         b < 0 || b >= sp->typecnt )
    {
        result = false;
    }
    else
    {
        const struct ttinfo *  ap = &sp->ttis[ a ];
        const struct ttinfo *  bp = &sp->ttis[ b ];

        result = ( ap->utoff == bp->utoff &&
                   ap->isdst == bp->isdst &&
                   ap->ttisstd == bp->ttisstd &&
                   ap->ttisut == bp->ttisut &&
                   ( strcmp( &sp->chars[ ap->desigidx ], &sp->chars[ bp->desigidx ] ) == 0 )
                 );
    }

    return result;
}

#define TZ_MAGIC "TZif"

struct tzhead
{
    char tzh_magic[ 4 ];       /* TZ_MAGIC */
    char tzh_version[ 1 ];     /* '\0' or '2' or '3' as of 2013 */
    char tzh_reserved[ 15 ];   /* reserved; must be zero */
    char tzh_ttisutcnt[ 4 ];   /* coded number of trans. time flags */
    char tzh_ttisstdcnt[ 4 ];  /* coded number of trans. time flags */
    char tzh_leapcnt[ 4 ];     /* coded number of leap seconds */
    char tzh_timecnt[ 4 ];     /* coded number of transition times */
    char tzh_typecnt[ 4 ];     /* coded number of local time types */
    char tzh_charcnt[ 4 ];     /* coded number of abbr. chars */
};

/* Input buffer for data read from a compiled tz file.  */
union input_buffer
{
    /* The first part of the buffer, interpreted as a header.  */
    struct tzhead tzhead;

    /* The entire buffer.  */
    char buf[ 2 * sizeof ( struct tzhead ) + 2 * sizeof ( struct state ) + 4 * TZ_MAX_TIMES ];
};

/* _PDCLIB_TZDIR with a trailing '/' rather than a trailing '\0'.  */
static char const tzdirslash[ sizeof _PDCLIB_TZDIR + 1 ] = _PDCLIB_TZDIR "/";

/* Local storage needed for 'tzloadbody'.  */
union local_storage
{
    /* The results of analyzing the file's contents after it is opened.  */
    struct file_analysis
    {
        /* The input buffer.  */
        union input_buffer u;

        /* A temporary state used for parsing a TZ string in the file.  */
        struct state st;
    } u;

    /* The file name to be opened.  */
    char fullname[ BIGGEST ( sizeof ( struct file_analysis ), sizeof tzdirslash + 1024 ) ];
};

static int_fast64_t leapcorr( struct state const * sp, time_t t )
{
    struct lsinfo const * lp;
    int i;

    i = sp->leapcnt;

    while ( --i >= 0 )
    {

tests/include/pdclib/functions/_tzcode/_PDCLIB_tzload.c  view on Meta::CPAN


        sp->leapcnt = leapcnt;
        sp->timecnt = timecnt;
        sp->typecnt = typecnt;
        sp->charcnt = charcnt;

        /* Read transitions, discarding those out of time_t range.
           But pretend the last transition before _PDCLIB_TIME_MIN
           occurred at _PDCLIB_TIME_MIN.
        */
        timecnt = 0;

        for ( i = 0; i < sp->timecnt; ++i )
        {
            int_fast64_t at = stored == 4 ? detzcode( p ) : detzcode64( p );
            sp->types[ i ] = at <= _PDCLIB_TIME_MAX;

            if ( sp->types[ i ] )
            {
                time_t attime = ( ( _PDCLIB_TYPE_SIGNED( time_t ) ? at < _PDCLIB_TIME_MIN : at < 0 ) ? _PDCLIB_TIME_MIN : at );

                if ( timecnt && attime <= sp->ats[ timecnt - 1 ] )
                {
                    if ( attime < sp->ats[ timecnt - 1 ] )
                    {
                        return _PDCLIB_EINVAL;
                    }

                    sp->types[ i - 1 ] = 0;
                    timecnt--;
                }

                sp->ats[ timecnt++ ] = attime;
            }

            p += stored;
        }

        timecnt = 0;

        for ( i = 0; i < sp->timecnt; ++i )
        {
            unsigned char typ = *p++;

            if ( sp->typecnt <= typ )
            {
                return _PDCLIB_EINVAL;
            }

            if ( sp->types[ i ] )
            {
                sp->types[ timecnt++ ] = typ;
            }
        }

        sp->timecnt = timecnt;

        for ( i = 0; i < sp->typecnt; ++i )
        {
            struct ttinfo * ttisp;
            unsigned char isdst, desigidx;

            ttisp = &sp->ttis[ i ];
            ttisp->utoff = detzcode( p );
            p += 4;
            isdst = *p++;

            if ( ! ( isdst < 2 ) )
            {
                return _PDCLIB_EINVAL;
            }

            ttisp->isdst = isdst;
            desigidx = *p++;

            if ( ! ( desigidx < sp->charcnt ) )
            {
                return _PDCLIB_EINVAL;
            }

            ttisp->desigidx = desigidx;
        }

        for ( i = 0; i < sp->charcnt; ++i )
        {
            sp->chars[ i ] = *p++;
        }

        sp->chars[ i ] = '\0';    /* ensure '\0' at end */

        /* Read leap seconds, discarding those out of time_t range.  */
        leapcnt = 0;

        for ( i = 0; i < sp->leapcnt; ++i )
        {
            int_fast64_t tr = stored == 4 ? detzcode( p ) : detzcode64( p );
            int_fast32_t corr = detzcode( p + stored );
            p += stored + 4;

            /* Leap seconds cannot occur before the Epoch.  */
            if ( tr < 0 )
            {
                return _PDCLIB_EINVAL;
            }

            if ( tr <= _PDCLIB_TIME_MAX )
            {
                /* Leap seconds cannot occur more than once per UTC month,
                   and UTC months are at least 28 days long (minus 1
                   second for a negative leap second).  Each leap second's
                   correction must differ from the previous one's by 1
                   second.
                */
                if ( tr - prevtr < 28 * SECSPERDAY - 1 || ( corr != prevcorr - 1 && corr != prevcorr + 1 ) )
                {
                    return _PDCLIB_EINVAL;
                }

                sp->lsis[ leapcnt ].trans = prevtr = tr;
                sp->lsis[ leapcnt ].corr = prevcorr = corr;
                ++leapcnt;
            }
        }

        sp->leapcnt = leapcnt;

        for ( i = 0; i < sp->typecnt; ++i )
        {
            struct ttinfo * ttisp;

            ttisp = &sp->ttis[ i ];

            if ( ttisstdcnt == 0 )
            {
                ttisp->ttisstd = false;
            }
            else
            {
                if ( *p != true && *p != false )
                {
                    return _PDCLIB_EINVAL;
                }

                ttisp->ttisstd = *p++;
            }
        }

        for ( i = 0; i < sp->typecnt; ++i )
        {
            struct ttinfo * ttisp;

            ttisp = &sp->ttis[ i ];

            if ( ttisutcnt == 0 )
            {
                ttisp->ttisut = false;
            }
            else
            {
                if ( *p != true && *p != false )
                {
                    return _PDCLIB_EINVAL;
                }

                ttisp->ttisut = *p++;
            }
        }

        /* If this is an old file, we're done. */
        if ( up->tzhead.tzh_version[ 0 ] == '\0' )
        {
            break;
        }

        nread -= p - up->buf;
        memmove( up->buf, p, nread );
    }

    if ( doextend && nread > 2 && up->buf[ 0 ] == '\n' && up->buf[ nread - 1 ] == '\n' && sp->typecnt + 2 <= TZ_MAX_TYPES )
    {
        struct state    *ts = &lsp->u.st;

        up->buf[ nread - 1 ] = '\0';

        if ( _PDCLIB_tzparse( &up->buf[ 1 ], ts, false ) )
        {
            /* Attempt to reuse existing abbreviations.
               Without this, America/Anchorage would be right on
               the edge after 2037 when TZ_MAX_CHARS is 50, as
               sp->charcnt equals 40 (for LMT AST AWT APT AHST
               AHDT YST AKDT AKST) and ts->charcnt equals 10
               (for AKST AKDT).  Reusing means sp->charcnt can
               stay 40 in this example.  */
            int gotabbr = 0;
            int charcnt = sp->charcnt;

            for ( i = 0; i < ts->typecnt; ++i )
            {
                char * tsabbr = ts->chars + ts->ttis[ i ].desigidx;
                int j;

                for ( j = 0; j < charcnt; ++j )
                {
                    if ( strcmp( sp->chars + j, tsabbr ) == 0 )
                    {
                        ts->ttis[ i ].desigidx = j;
                        ++gotabbr;
                        break;
                    }
                }

                if ( ! ( j < charcnt ) )
                {
                    int tsabbrlen = strlen( tsabbr );

                    if ( j + tsabbrlen < TZ_MAX_CHARS )
                    {
                        strcpy( sp->chars + j, tsabbr );
                        charcnt = j + tsabbrlen + 1;
                        ts->ttis[ i ].desigidx = j;
                        ++gotabbr;
                    }
                }
            }

            if ( gotabbr == ts->typecnt )
            {
                sp->charcnt = charcnt;

                /* Ignore any trailing, no-op transitions generated
                   by zic as they don't help here and can run afoul
                   of bugs in zic 2016j or earlier.  */
                while ( 1 < sp->timecnt && ( sp->types[ sp->timecnt - 1 ] == sp->types[ sp->timecnt - 2 ] ) )
                {
                    sp->timecnt--;
                }

                for ( i = 0; i < ts->timecnt; ++i )
                {
                    if ( sp->timecnt == 0 || ( sp->ats[ sp->timecnt - 1 ] < ts->ats[ i ] + leapcorr( sp, ts->ats[ i ] ) ) )
                    {
                        break;
                    }
                }

                while ( i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES )
                {
                    sp->ats[ sp->timecnt ] = ts->ats[ i ] + leapcorr( sp, ts->ats[ i ] );
                    sp->types[ sp->timecnt ] = ( sp->typecnt + ts->types[ i ] );
                    sp->timecnt++;
                    ++i;
                }

                for ( i = 0; i < ts->typecnt; ++i )
                {
                    sp->ttis[ sp->typecnt++ ] = ts->ttis[ i ];
                }
            }
        }
    }

    if ( sp->typecnt == 0 )
    {
        return _PDCLIB_EINVAL;
    }

    if ( sp->timecnt > 1 )
    {
        for ( i = 1; i < sp->timecnt; ++i )
        {
            if ( typesequiv( sp, sp->types[ i ], sp->types[ 0 ] ) && differ_by_repeat( sp->ats[ i ], sp->ats[ 0 ] ) )
            {
                sp->goback = true;
                break;
            }
        }

        for ( i = sp->timecnt - 2; i >= 0; --i )
        {
            if ( typesequiv( sp, sp->types[ sp->timecnt - 1 ], sp->types[ i ] ) && differ_by_repeat( sp->ats[ sp->timecnt - 1 ], sp->ats[ i ] ) )



( run in 0.516 second using v1.01-cache-2.11-cpan-5735350b133 )