aboutsummaryrefslogtreecommitdiffstats
path: root/skeletons/GeneralizedTime.c
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2005-07-03 05:32:40 +0000
committerLev Walkin <vlm@lionet.info>2005-07-03 05:32:40 +0000
commit535612a3f78980f6737bab9fdaf3983a991c1707 (patch)
tree2db18f7607f55539a55709fdaf3f48641ea26642 /skeletons/GeneralizedTime.c
parent026661996e34894c8a8bc9101a4131a3d9412524 (diff)
API extended to support fractions of seconds
Diffstat (limited to 'skeletons/GeneralizedTime.c')
-rw-r--r--skeletons/GeneralizedTime.c166
1 files changed, 110 insertions, 56 deletions
diff --git a/skeletons/GeneralizedTime.c b/skeletons/GeneralizedTime.c
index 770a3043..45a082bd 100644
--- a/skeletons/GeneralizedTime.c
+++ b/skeletons/GeneralizedTime.c
@@ -108,7 +108,7 @@ static time_t timegm(struct tm *tm) {
#endif /* _EMULATE_TIMEGM */
-#ifndef __NO_ASN_TABLE__
+#ifndef __ASN_INTERNAL_TEST_MODE__
/*
* GeneralizedTime basic type description.
@@ -139,7 +139,7 @@ asn_TYPE_descriptor_t asn_DEF_GeneralizedTime = {
0 /* No specifics */
};
-#endif /* __NO_ASN_TABLE__ */
+#endif /* __ASN_INTERNAL_TEST_MODE__ */
/*
* Check that the time looks like the time.
@@ -163,76 +163,70 @@ GeneralizedTime_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
}
asn_enc_rval_t
-GeneralizedTime_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
+GeneralizedTime_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
- GeneralizedTime_t *st = (GeneralizedTime_t *)ptr;
+ GeneralizedTime_t *st = (GeneralizedTime_t *)sptr;
asn_enc_rval_t erval;
+ long fv, fb; /* seconds fraction value and base */
+ struct tm tm;
+ time_t tloc;
- /* If not canonical DER, re-encode into canonical DER. */
- if(st->size && st->buf[st->size-1] != 0x5a) {
- struct tm tm;
- time_t tloc;
+ /*
+ * Encode as a canonical DER.
+ */
+ errno = EPERM;
+ tloc = asn_GT2time_frac(st, &fv, &fb, &tm, 1); /* Recognize time */
+ if(tloc == -1 && errno != EPERM)
+ /* Failed to recognize time. Fail completely. */
+ _ASN_ENCODE_FAILED;
- errno = EPERM;
- tloc = asn_GT2time(st, &tm, 1); /* Recognize time */
- if(tloc == -1 && errno != EPERM) {
- /* Failed to recognize time. Fail completely. */
- erval.encoded = -1;
- erval.failed_type = td;
- erval.structure_ptr = ptr;
- return erval;
- }
- st = asn_time2GT(0, &tm, 1); /* Save time canonically */
- if(!st) {
- /* Memory allocation failure. */
- erval.encoded = -1;
- erval.failed_type = td;
- erval.structure_ptr = ptr;
- return erval;
- }
- }
+ st = asn_time2GT_frac(0, &tm, fv, fb, 1); /* Save time canonically */
+ if(!st) _ASN_ENCODE_FAILED; /* Memory allocation failure. */
erval = OCTET_STRING_encode_der(td, st, tag_mode, tag, cb, app_key);
- if(st != ptr) {
- FREEMEM(st->buf);
- FREEMEM(st);
- }
+ FREEMEM(st->buf);
+ FREEMEM(st);
return erval;
}
+#ifndef __ASN_INTERNAL_TEST_MODE__
+
asn_enc_rval_t
GeneralizedTime_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
- OCTET_STRING_t st;
if(flags & XER_F_CANONICAL) {
- char buf[32];
+ GeneralizedTime_t *gt;
+ asn_enc_rval_t rv;
+ long fv, fb; /* fractional parts */
struct tm tm;
- ssize_t ret;
errno = EPERM;
- if(asn_GT2time((GeneralizedTime_t *)sptr, &tm, 1) == -1
+ if(asn_GT2time_frac((GeneralizedTime_t *)sptr,
+ &fv, &fb, &tm, 1) == -1
&& errno != EPERM)
_ASN_ENCODE_FAILED;
+
+ gt = asn_time2GT_frac(0, &tm, fv, fb, 1);
+ if(!gt) _ASN_ENCODE_FAILED;
- ret = snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02dZ",
- tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
- assert(ret > 0 && ret < (int)sizeof(buf));
-
- st.buf = (uint8_t *)buf;
- st.size = ret;
- sptr = &st;
+ rv = OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
+ cb, app_key);
+ asn_DEF_GeneralizedTime.free_struct(&asn_DEF_GeneralizedTime,
+ gt, 0);
+ return rv;
+ } else {
+ return OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
+ cb, app_key);
}
-
- return OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
- cb, app_key);
}
+#endif /* __ASN_INTERNAL_TEST_MODE__ */
+
int
GeneralizedTime_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
@@ -251,7 +245,7 @@ GeneralizedTime_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
return (cb("<bad-value>", 11, app_key) < 0) ? -1 : 0;
ret = snprintf(buf, sizeof(buf),
- "%04d-%02d-%02d %02d:%02d%02d (GMT)",
+ "%04d-%02d-%02d %02d:%02d:%02d (GMT)",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
assert(ret > 0 && ret < (int)sizeof(buf));
@@ -263,6 +257,11 @@ GeneralizedTime_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
time_t
asn_GT2time(const GeneralizedTime_t *st, struct tm *ret_tm, int as_gmt) {
+ return asn_GT2time_frac(st, 0, 0, ret_tm, as_gmt);
+}
+
+time_t
+asn_GT2time_frac(const GeneralizedTime_t *st, long *frac_value, long *frac_base, struct tm *ret_tm, int as_gmt) {
struct tm tm_s;
uint8_t *buf;
uint8_t *end;
@@ -270,6 +269,8 @@ asn_GT2time(const GeneralizedTime_t *st, struct tm *ret_tm, int as_gmt) {
int gmtoff_m = 0;
int gmtoff = 0; /* h + m */
int offset_specified = 0;
+ long fvalue = 0;
+ long fbase = 1;
time_t tloc;
if(!st || !st->buf) {
@@ -365,13 +366,21 @@ asn_GT2time(const GeneralizedTime_t *st, struct tm *ret_tm, int as_gmt) {
* ^ ^
*/
switch(*buf) {
- case 0x2C: case 0x2E: /* (.|,) */
- /* Fractions of seconds are not supported
- * by time_t or struct tm. Skip them */
+ case 0x2C: case 0x2E: /* (.|,) */
+ /*
+ * Process fractions of seconds.
+ */
for(buf++; buf < end; buf++) {
- switch(*buf) {
+ int v = *buf;
+ switch(v) {
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
+ if((fbase * 10 / fbase) != 10) {
+ /* Not enough precision, ignore */
+ } else {
+ fbase *= 10;
+ fvalue = fvalue * 10 + (v - 0x30);
+ }
continue;
default:
break;
@@ -479,15 +488,29 @@ local_finish:
}
}
+ /* Fractions of seconds */
+ if(frac_value) *frac_value = fvalue;
+ if(frac_base) *frac_base = fbase;
+
return tloc;
}
-
GeneralizedTime_t *
asn_time2GT(GeneralizedTime_t *opt_gt, const struct tm *tm, int force_gmt) {
+ return asn_time2GT_frac(opt_gt, tm, 0, 0, force_gmt);
+}
+
+GeneralizedTime_t *
+asn_time2GT_frac(GeneralizedTime_t *opt_gt, const struct tm *tm, long frac_value, long frac_base, int force_gmt) {
struct tm tm_s;
long gmtoff;
- const unsigned int buf_size = 24; /* 4+2+2 +2+2+2 +4 + cushion */
+ const unsigned int buf_size =
+ 4 + 2 + 2 /* yyyymmdd */
+ + 2 + 2 + 2 /* hhmmss */
+ + 1 + 6 /* .ffffff */
+ + 1 + 4 /* +hhmm */
+ + 1 /* '\0' */
+ ;
char *buf;
char *p;
int size;
@@ -524,17 +547,48 @@ asn_time2GT(GeneralizedTime_t *opt_gt, const struct tm *tm, int force_gmt) {
tm->tm_min,
tm->tm_sec
);
- assert(size == 14);
+ if(size != 14) {
+ /* Could be assert(size == 14); */
+ FREEMEM(buf);
+ errno = EINVAL;
+ return 0;
+ }
p = buf + size;
+
+ /*
+ * Deal with fractions.
+ */
+ if(frac_base >= 10 && frac_value > 0) {
+ char *end = p + 1 + 6; /* '.' + maximum 6 digits */
+ char *z;
+ *p++ = '.';
+ do {
+ int digit;
+ frac_base /= 10;
+ digit = frac_value / frac_base;
+ frac_value %= frac_base;
+ *p++ = digit + 0x30;
+ } while(frac_base >= 10 && frac_value > 0 && p < end);
+ for(z = p - 1; *z == 0x30; --z); /* Strip zeroes */
+ p = z + (*z != '.');
+ size = p - buf;
+ }
+
if(force_gmt) {
*p++ = 0x5a; /* "Z" */
*p++ = 0;
size++;
} else {
- int ret = snprintf(p, buf_size - size, "%+03ld%02ld",
- gmtoff / 3600, gmtoff % 3600);
- assert(ret >= 5 && ret <= 7);
+ int ret;
+ gmtoff %= 86400;
+ ret = snprintf(p, buf_size - size, "%+03ld%02ld",
+ gmtoff / 3600, labs(gmtoff % 3600));
+ if(ret != 5) {
+ FREEMEM(buf);
+ errno = EINVAL;
+ return 0;
+ }
size += ret;
}