Flowdock
marshal_load(p1) private

No documentation

This method has no description. You can help the Ruby community by adding new notes.

Hide source
static VALUE
time_mload(VALUE time, VALUE str)
{
    struct time_object *tobj;
    unsigned long p, s;
    time_t sec;
    long usec;
    unsigned char *buf;
    struct vtm vtm;
    int i, gmt;
    long nsec;
    VALUE submicro, nano_num, nano_den, offset, zone;
    wideval_t timew;

    time_modify(time);

#define get_attr(attr, iffound) \
    attr = rb_attr_delete(str, id_##attr); \
    if (!NIL_P(attr)) { \
        iffound; \
    }

    get_attr(nano_num, {});
    get_attr(nano_den, {});
    get_attr(submicro, {});
    get_attr(offset, (offset = rb_rescue(validate_utc_offset, offset, NULL, Qnil)));
    get_attr(zone, (zone = rb_rescue(validate_zone_name, zone, NULL, Qnil)));

#undef get_attr

    rb_copy_generic_ivar(time, str);

    StringValue(str);
    buf = (unsigned char *)RSTRING_PTR(str);
    if (RSTRING_LEN(str) != 8) {
        rb_raise(rb_eTypeError, "marshaled time format differ");
    }

    p = s = 0;
    for (i=0; i<4; i++) {
        p |= (unsigned long)buf[i]<<(8*i);
    }
    for (i=4; i<8; i++) {
        s |= (unsigned long)buf[i]<<(8*(i-4));
    }

    if ((p & (1UL<<31)) == 0) {
        gmt = 0;
        offset = Qnil;
        sec = p;
        usec = s;
        nsec = usec * 1000;
        timew = wadd(rb_time_magnify(TIMET2WV(sec)), wmulquoll(WINT2FIXWV(usec), TIME_SCALE, 1000000));
    }
    else {
        p &= ~(1UL<<31);
        gmt        = (int)((p >> 30) & 0x1);

        vtm.year = INT2FIX(((int)(p >> 14) & 0xffff) + 1900);
        vtm.mon  = ((int)(p >> 10) & 0xf) + 1;
        vtm.mday = (int)(p >>  5) & 0x1f;
        vtm.hour = (int) p        & 0x1f;
        vtm.min  = (int)(s >> 26) & 0x3f;
        vtm.sec  = (int)(s >> 20) & 0x3f;
        vtm.utc_offset = INT2FIX(0);
        vtm.yday = vtm.wday = 0;
        vtm.isdst = 0;
        vtm.zone = "";

        usec = (long)(s & 0xfffff);
        nsec = usec * 1000;


        vtm.subsecx = mulquov(LONG2FIX(nsec), INT2FIX(TIME_SCALE), LONG2FIX(1000000000));
        if (nano_num != Qnil) {
            VALUE nano = quov(num_exact(nano_num), num_exact(nano_den));
            vtm.subsecx = addv(vtm.subsecx, mulquov(nano, INT2FIX(TIME_SCALE), LONG2FIX(1000000000)));
        }
        else if (submicro != Qnil) { /* for Ruby 1.9.1 compatibility */
            unsigned char *ptr;
            long len;
            int digit;
            ptr = (unsigned char*)StringValuePtr(submicro);
            len = RSTRING_LEN(submicro);
            nsec = 0;
            if (0 < len) {
                if (10 <= (digit = ptr[0] >> 4)) goto end_submicro;
                nsec += digit * 100;
                if (10 <= (digit = ptr[0] & 0xf)) goto end_submicro;
                nsec += digit * 10;
            }
            if (1 < len) {
                if (10 <= (digit = ptr[1] >> 4)) goto end_submicro;
                nsec += digit;
            }
            vtm.subsecx = addv(vtm.subsecx, mulquov(LONG2FIX(nsec), INT2FIX(TIME_SCALE), LONG2FIX(1000000000)));
end_submicro: ;
        }
        timew = timegmw(&vtm);
    }

    GetNewTimeval(time, tobj);
    tobj->gmt = 0;
    tobj->tm_got = 0;
    tobj->timew = timew;
    if (gmt) {
        TIME_SET_UTC(tobj);
    }
    else if (!NIL_P(offset)) {
        time_set_utc_offset(time, offset);
        time_fixoff(time);
    }
    if (!NIL_P(zone)) {
        if (TIME_FIXOFF_P(tobj)) TIME_SET_LOCALTIME(tobj);
        zone = rb_fstring(zone);
        tobj->vtm.zone = StringValueCStr(zone);
        rb_ivar_set(time, id_zone, zone);
    }

    return time;
}
Register or log in to add new notes.