static uint8_t *ccder_encode_nanoseconds(CFAbsoluteTime at, const uint8_t *der, uint8_t *der_end) { int dotoff; int sign; char *end; char *str = __dtoa(at, 0, 0, &dotoff, &sign, &end); char *begin = str + (dotoff < 0 ? 0 : dotoff); // Compute 1.0000000 - fraction in ascii space if (at < 0.0 && begin < end) { char *p = end - 1; // Borrow for last digit *p = ('9' + 1) - (*p - '0'); while (p-- > begin) { // Every other digit is a 9 since we borrowed from the last one *p = '9' - (*p - '0'); } } ptrdiff_t len = end - str; if (len > dotoff) { if (dotoff < 0) { assert(-1.0 < at && at < 1.0); der_end = ccder_encode_body(len, (const uint8_t *)str, der, der_end); der_end = ccder_encode_body_nocopy(-dotoff, der, der_end); if (der_end) memset(der_end, at < 0.0 ? '9' : '0', -dotoff); } else { der_end = ccder_encode_body(len - dotoff, (const uint8_t *)(str + dotoff), der, der_end); } der_end = ccder_encode_byte('.', der, der_end); } __freedtoa(str); return der_end; }
/* Encode generalized zulu time YYYYMMDDhhmmss[.ssss]Z */ uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; if (!SecAbsoluteTimeGetGregorianDate(at, &year, &month, &day, &hour, &minute, &second, error)) return NULL; return ccder_encode_decimal_quad(year, der, ccder_encode_decimal_pair(month, der, ccder_encode_decimal_pair(day, der, ccder_encode_decimal_pair(hour, der, ccder_encode_decimal_pair(minute, der, ccder_encode_decimal_pair(second, der, ccder_encode_nanoseconds(at, der, ccder_encode_byte('Z', der, der_end)))))))); }
/* Encode generalized zulu time YYYYMMDDhhmmss[.ssss]Z */ uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { CFGregorianDate g = SecCFAbsoluteTimeGetGregorianDate(floor(at), 0.0, error); if (g.year == 0) return NULL; return ccder_encode_decimal_quad(g.year, der, ccder_encode_decimal_pair(g.month, der, ccder_encode_decimal_pair(g.day, der, ccder_encode_decimal_pair(g.hour, der, ccder_encode_decimal_pair(g.minute, der, ccder_encode_decimal_pair(g.second, der, ccder_encode_nanoseconds(at, der, ccder_encode_byte('Z', der, der_end)))))))); }