mirror of https://gerrit.osmocom.org/asn1c
API extended to support fractions of seconds
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@925 59561ff5-6e30-0410-9f3c-9617f08c8826
This commit is contained in:
parent
d960a86991
commit
5ea810e1af
|
@ -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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
|
||||
cb, app_key);
|
||||
gt = asn_time2GT_frac(0, &tm, fv, fb, 1);
|
||||
if(!gt) _ASN_ENCODE_FAILED;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,14 +32,21 @@ struct tm; /* <time.h> */
|
|||
time_t asn_GT2time(const GeneralizedTime_t *, struct tm *_optional_tm4fill,
|
||||
int as_gmt);
|
||||
|
||||
/* A version of the above function also returning the fractions of seconds */
|
||||
time_t asn_GT2time_frac(const GeneralizedTime_t *,
|
||||
long *frac_value, long *frac_base, /* (value/base) */
|
||||
struct tm *_optional_tm4fill, int as_gmt);
|
||||
|
||||
/*
|
||||
* Convert a struct tm into GeneralizedTime.
|
||||
* If __opt_gt is not given, this function will try to allocate one.
|
||||
* If _optional_gt is not given, this function will try to allocate one.
|
||||
* If force_gmt is given, the resulting GeneralizedTime will be forced
|
||||
* into a GMT time zone (encoding ends with a "Z").
|
||||
* On error, this function returns 0 and sets errno.
|
||||
*/
|
||||
GeneralizedTime_t *asn_time2GT(GeneralizedTime_t *__opt_gt, const struct tm *,
|
||||
int force_gmt);
|
||||
GeneralizedTime_t *asn_time2GT(GeneralizedTime_t *_optional_gt,
|
||||
const struct tm *, int force_gmt);
|
||||
GeneralizedTime_t *asn_time2GT_frac(GeneralizedTime_t *_optional_gt,
|
||||
const struct tm *, long frac_value, long frac_base, int force_gmt);
|
||||
|
||||
#endif /* _GeneralizedTime_H_ */
|
||||
|
|
|
@ -1,31 +1,34 @@
|
|||
#define __NO_ASN_TABLE__
|
||||
#define __ASN_INTERNAL_TEST_MODE__
|
||||
#include <GeneralizedTime.c>
|
||||
#include <constraints.c>
|
||||
|
||||
static void
|
||||
check(char *time_str, time_t expect, int as_gmt) {
|
||||
recognize(char *time_str, time_t expect, int as_gmt) {
|
||||
GeneralizedTime_t gt;
|
||||
struct tm tm;
|
||||
time_t tloc;
|
||||
long fv, fb;
|
||||
|
||||
gt.buf = time_str;
|
||||
gt.buf = (uint8_t *)time_str;
|
||||
gt.size = strlen(time_str);
|
||||
|
||||
tloc = asn_GT2time(>, &tm, as_gmt);
|
||||
tloc = asn_GT2time_frac(>, &fv, &fb, &tm, as_gmt);
|
||||
printf("%s: [%s] -> %ld == %ld\n",
|
||||
as_gmt?"GMT":"ofs", time_str, (long)tloc, (long)expect);
|
||||
|
||||
if(tloc != -1) {
|
||||
printf("\t%04d-%02d-%02dT%02d:%02d:%02d%+03ld%02ld\n",
|
||||
printf("\t%04d-%02d-%02dT%02d:%02d:%02d(.%ld/%ld)%+03ld%02ld\n",
|
||||
tm.tm_year + 1900,
|
||||
tm.tm_mon + 1,
|
||||
tm.tm_mday,
|
||||
tm.tm_hour,
|
||||
tm.tm_min,
|
||||
tm.tm_sec,
|
||||
fv, fb,
|
||||
(GMTOFF(tm) / 3600),
|
||||
labs(GMTOFF(tm) % 3600)
|
||||
);
|
||||
assert(fb < 100 || (fb % 100) == 0);
|
||||
}
|
||||
assert(tloc == expect);
|
||||
|
||||
|
@ -33,11 +36,11 @@ check(char *time_str, time_t expect, int as_gmt) {
|
|||
assert(tloc == -1 || as_gmt == 0 || GMTOFF(tm) == 0);
|
||||
#endif
|
||||
|
||||
if(!as_gmt) check(time_str, expect, 1);
|
||||
if(!as_gmt) recognize(time_str, expect, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
rcheck(time_t tloc, const char *expect, int force_gmt) {
|
||||
encode(time_t tloc, const char *expect, int force_gmt) {
|
||||
GeneralizedTime_t *gt;
|
||||
struct tm tm, *tmp;
|
||||
|
||||
|
@ -49,51 +52,97 @@ rcheck(time_t tloc, const char *expect, int force_gmt) {
|
|||
assert(expect);
|
||||
printf("[%s] vs [%s] (%d)\n",
|
||||
gt->buf, expect, force_gmt);
|
||||
assert(gt->size == (int)strlen(gt->buf));
|
||||
assert(!strcmp(gt->buf, expect));
|
||||
assert(gt->size == (int)strlen((char *)gt->buf));
|
||||
assert(!strcmp((char *)gt->buf, expect));
|
||||
} else {
|
||||
assert(!expect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
recode(char *time_str, const char *expect) {
|
||||
long frac_value, frac_base;
|
||||
GeneralizedTime_t gt;
|
||||
struct tm tm;
|
||||
time_t tloc;
|
||||
|
||||
gt.buf = (uint8_t *)time_str;
|
||||
gt.size = strlen(time_str);
|
||||
|
||||
tloc = asn_GT2time_frac(>, &frac_value, &frac_base, &tm, 1);
|
||||
assert(tloc != -1);
|
||||
|
||||
gt.buf = 0;
|
||||
asn_time2GT_frac(>, &tm, frac_value, frac_base, 1);
|
||||
assert(gt.buf);
|
||||
|
||||
printf("[%s] => [%s] == [%s]\n", time_str, gt.buf, expect);
|
||||
|
||||
assert(strcmp((char *)gt.buf, expect) == 0);
|
||||
FREEMEM(gt.buf);
|
||||
}
|
||||
|
||||
int
|
||||
main(int ac, char **av) {
|
||||
|
||||
(void)av;
|
||||
|
||||
check("200401250", -1, 0);
|
||||
check("2004012509300", -1, 0);
|
||||
check("20040125093000-", -1, 0);
|
||||
check("20040125093007-0", -1, 0);
|
||||
check("20040125093007-080", -1, 0);
|
||||
check("200401250930.01Z", -1, 0);
|
||||
recognize("200401250", -1, 0);
|
||||
recognize("2004012509300", -1, 0);
|
||||
recognize("20040125093000-", -1, 0);
|
||||
recognize("20040125093007-0", -1, 0);
|
||||
recognize("20040125093007-080", -1, 0);
|
||||
recognize("200401250930.01Z", -1, 0);
|
||||
|
||||
/* These six are from X.690:11.7.5 */
|
||||
check("19920520240000Z", -1, 0); /* midnight represented incorrectly */
|
||||
//check("19920622123421.0Z", -1, 0); /* spurious trailing zeros */
|
||||
//check("19920722132100.30Z", -1, 0); /* spurious trailing zeros */
|
||||
check("19920521000000Z", 706406400, 0);
|
||||
check("19920622123421Z", 709216461, 0);
|
||||
check("19920722132100.3Z", 711811260, 0);
|
||||
recognize("19920520240000Z", -1, 0); /* midnight represented incorrectly */
|
||||
recognize("19920622123421.0Z", 709216461, 0); /* spurious trailing zeros */
|
||||
recognize("19920722132100.30Z", 711811260, 0); /* spurious trailing zeros */
|
||||
recognize("19920521000000Z", 706406400, 0);
|
||||
recognize("19920622123421Z", 709216461, 0);
|
||||
recognize("19920722132100.3Z", 711811260, 0);
|
||||
|
||||
check("20040125093007Z", 1075023007, 0);
|
||||
check("20040125093007+00", 1075023007, 0);
|
||||
check("20040125093007.01+0000", 1075023007, 0);
|
||||
check("20040125093007,1+0000", 1075023007, 0);
|
||||
check("20040125093007-0800", 1075051807, 0);
|
||||
recognize("20040125093007Z", 1075023007, 0);
|
||||
recognize("20040125093007+00", 1075023007, 0);
|
||||
recognize("20040125093007.01+0000", 1075023007, 0);
|
||||
recognize("20040125093007,1+0000", 1075023007, 0);
|
||||
recognize("20040125093007-0800", 1075051807, 0);
|
||||
|
||||
rcheck(1075023007, "20040125093007Z", 1);
|
||||
recognize("19920722132100.123000123Z", 711811260, 0);
|
||||
recognize("19920722132100.1230000123Z", 711811260, 0);
|
||||
recognize("19920722132100.12300000123Z", 711811260, 0);
|
||||
|
||||
encode(1075023007, "20040125093007Z", 1);
|
||||
|
||||
if(ac > 1) {
|
||||
/* These will be valid only inside PST time zone */
|
||||
check("20040125093007", 1075051807, 0);
|
||||
check("200401250930", 1075051800, 0);
|
||||
check("20040125093000,01", 1075051800, 0);
|
||||
check("20040125093000,1234", 1075051800, 0);
|
||||
recognize("20040125093007", 1075051807, 0);
|
||||
recognize("200401250930", 1075051800, 0);
|
||||
recognize("20040125093000,01", 1075051800, 0);
|
||||
recognize("20040125093000,1234", 1075051800, 0);
|
||||
|
||||
rcheck(1075023007, "20040125013007-0800", 0);
|
||||
encode(1075023007, "20040125013007-0800", 0);
|
||||
recode("20050702123312", "20050702193312Z");
|
||||
}
|
||||
|
||||
recode("20050702123312Z", "20050702123312Z");
|
||||
recode("20050702123312+01", "20050702113312Z");
|
||||
recode("20050702123312,0+01", "20050702113312Z");
|
||||
recode("20050702123312,1+01", "20050702113312.1Z");
|
||||
recode("20050702123312.01+01", "20050702113312.01Z");
|
||||
recode("20050702123312.00+01", "20050702113312Z");
|
||||
recode("20050702123312.30+01", "20050702113312.3Z");
|
||||
recode("20050702123312,30000+01", "20050702113312.3Z");
|
||||
recode("20050702123312,300000000+01", "20050702113312.3Z");
|
||||
recode("20050702123312.123456+01", "20050702113312.123456Z");
|
||||
recode("20050702123312.1234567+01", "20050702113312.123456Z");
|
||||
recode("20050702123312.12345678+01", "20050702113312.123456Z");
|
||||
recode("20050702123312.123456789+01", "20050702113312.123456Z");
|
||||
recode("20050702123312.000001+01", "20050702113312.000001Z");
|
||||
recode("20050702123312.0000001Z", "20050702123312Z");
|
||||
recode("20050702123312.0080010+1056", "20050702013712.008001Z");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#define __NO_ASN_TABLE__
|
||||
#define __ASN_INTERNAL_TEST_MODE__
|
||||
#include <GeneralizedTime.c>
|
||||
#define __NO_ASN_TABLE__
|
||||
#include <UTCTime.c>
|
||||
#include <constraints.c>
|
||||
|
||||
|
@ -10,7 +9,7 @@ check(char *time_str, time_t sample, int as_gmt) {
|
|||
struct tm tm;
|
||||
time_t tloc;
|
||||
|
||||
gt.buf = time_str;
|
||||
gt.buf = (uint8_t *)time_str;
|
||||
gt.size = strlen(time_str);
|
||||
|
||||
tloc = asn_UT2time(>, &tm, as_gmt);
|
||||
|
|
|
@ -43,7 +43,7 @@ check_speed() {
|
|||
int ret;
|
||||
int i;
|
||||
|
||||
st.buf = long_test;
|
||||
st.buf = (uint8_t *)long_test;
|
||||
st.size = sizeof(long_test) - 1;
|
||||
|
||||
ret = UTF8String_length(&st);
|
||||
|
|
Loading…
Reference in New Issue