Update SDP o= and t= lines to use 64 bit unsigned integer (#3565)

This commit is contained in:
Nanang Izzuddin 2023-05-17 10:53:31 +07:00 committed by GitHub
parent 7816d95093
commit 1af96abb89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 198 additions and 18 deletions

View File

@ -47,4 +47,11 @@
/** Minimum value for unsigned long. */
#define PJ_MAXULONG ULONG_MAX
/** Maximum value for generic unsigned integer. */
#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
# define PJ_MAXUINT 0xffffffffffffffffULL
#else
# define PJ_MAXUINT 0xffffffff
#endif
#endif /* __PJ_LIMITS_H__ */

View File

@ -717,6 +717,31 @@ PJ_DECL(unsigned long) pj_strtoul2(const pj_str_t *str, pj_str_t *endptr,
PJ_DECL(pj_status_t) pj_strtoul3(const pj_str_t *str, unsigned long *value,
unsigned base);
/**
* Convert string to generic unsigned integer. The conversion will stop as
* soon as non-digit character is found or all the characters have
* been processed.
*
* @param str The input string.
* @param value Pointer to an unsigned integer to receive the value.
* The value will be a 64 bit unsigned integer if the system
* supports it, otherwise a 32 bit unsigned integer.
* @param base Number base to use.
*
* @return PJ_SUCCESS if successful. Otherwise:
* PJ_ETOOBIG if the value was an impossibly long positive number.
* In this case, *value will be set to ULLONG_MAX (for 64 bit) or
* ULONG_MAX (for 32 bit).
* \n
* PJ_EINVAL if the input string was NULL, the value pointer was NULL
* or the input string could not be parsed at all such as starting
* with a character outside the base character range. In this case,
* *value will be left untouched.
*/
PJ_DECL(pj_status_t) pj_strtoul4(const pj_str_t *str, pj_uint_t *value,
unsigned base);
/**
* Convert string to float.
*
@ -737,6 +762,20 @@ PJ_DECL(float) pj_strtof(const pj_str_t *str);
*/
PJ_DECL(int) pj_utoa(unsigned long val, char *buf);
/**
* Utility to convert generic unsigned integer to string. Note that the
* string will be NULL terminated.
*
* This function will take 64 bit unsigned integer if the system has one,
* otherwise it takes 32 bit unsigned integer.
*
* @param val the unsigned integer value.
* @param buf the buffer
*
* @return the number of characters written
*/
PJ_DECL(int) pj_utoa2(pj_uint_t val, char *buf);
/**
* Convert unsigned integer to string with minimum digits. Note that the
* string will be NULL terminated.
@ -752,6 +791,24 @@ PJ_DECL(int) pj_utoa(unsigned long val, char *buf);
*/
PJ_DECL(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad);
/**
* Convert generic unsigned integer to string with minimum digits. Note that
* the string will be NULL terminated.
*
* This function will take 64 bit unsigned integer if the system has one,
* otherwise it takes 32 bit unsigned integer.
*
* @param val The unsigned integer value.
* @param buf The buffer.
* @param min_dig Minimum digits to be printed, or zero to specify no
* minimum digit.
* @param pad The padding character to be put in front of the string
* when the digits is less than minimum.
*
* @return the number of characters written.
*/
PJ_DECL(int) pj_utoa_pad2( pj_uint_t val, char *buf, int min_dig, int pad);
/**
* Fill the memory location with zero.

View File

@ -108,6 +108,19 @@ typedef pj_int64_t pj_off_t;
typedef pj_ssize_t pj_off_t;
#endif
/**
* Generic unsigned integer types.
*
* This is a 64 bit unsigned integer if the system support it, otherwise
* this is a 32 bit unsigned integer.
*/
#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
typedef pj_uint64_t pj_uint_t;
#else
typedef pj_uint32_t pj_uint_t;
#endif
/* ************************************************************************* */
/*
* Data structure types.

View File

@ -437,6 +437,72 @@ PJ_DEF(pj_status_t) pj_strtoul3(const pj_str_t *str, unsigned long *value,
return PJ_SUCCESS;
}
PJ_DEF(pj_status_t) pj_strtoul4(const pj_str_t *str, pj_uint_t *value,
unsigned base)
{
pj_str_t s;
unsigned i;
PJ_CHECK_STACK();
if (!str || !value) {
return PJ_EINVAL;
}
PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
s = *str;
pj_strltrim(&s);
if (s.slen == 0 || s.ptr[0] < '0' ||
(base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) ||
(base == 16 && !pj_isxdigit(s.ptr[0])))
{
return PJ_EINVAL;
}
*value = 0;
if (base <= 10) {
for (i=0; i<(unsigned)s.slen; ++i) {
unsigned c = s.ptr[i] - '0';
if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) {
break;
}
if (*value > PJ_MAXUINT / base) {
*value = PJ_MAXUINT;
return PJ_ETOOBIG;
}
*value *= base;
if ((PJ_MAXUINT - *value) < c) {
*value = PJ_MAXUINT;
return PJ_ETOOBIG;
}
*value += c;
}
} else if (base == 16) {
for (i=0; i<(unsigned)s.slen; ++i) {
unsigned c = pj_hex_digit_to_val(s.ptr[i]);
if (!pj_isxdigit(s.ptr[i]))
break;
if (*value > PJ_MAXUINT / base) {
*value = PJ_MAXUINT;
return PJ_ETOOBIG;
}
*value *= base;
if ((PJ_MAXUINT - *value) < c) {
*value = PJ_MAXUINT;
return PJ_ETOOBIG;
}
*value += c;
}
} else {
pj_assert(!"Unsupported base");
return PJ_EINVAL;
}
return PJ_SUCCESS;
}
PJ_DEF(float) pj_strtof(const pj_str_t *str)
{
pj_str_t part;
@ -514,6 +580,43 @@ PJ_DEF(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad)
return len;
}
PJ_DEF(int) pj_utoa2(pj_uint_t val, char *buf)
{
return pj_utoa_pad2(val, buf, 0, 0);
}
PJ_DEF(int) pj_utoa_pad2(pj_uint_t val, char *buf, int min_dig, int pad)
{
char *p;
int len;
PJ_CHECK_STACK();
p = buf;
do {
pj_uint_t digval = (pj_uint_t) (val % 10);
val /= 10;
*p++ = (char) (digval + '0');
} while (val > 0);
len = (int)(p-buf);
while (len < min_dig) {
*p++ = (char)pad;
++len;
}
*p-- = '\0';
do {
char temp = *p;
*p = *buf;
*buf = temp;
--p;
++buf;
} while (buf < p);
return len;
}
PJ_DEF(int) pj_ansi_strxcpy(char *dst, const char *src,
pj_size_t dst_size)
{

View File

@ -681,8 +681,8 @@ struct pjmedia_sdp_session
struct
{
pj_str_t user; /**< User */
pj_uint32_t id; /**< Session ID */
pj_uint32_t version; /**< Session version */
pj_uint_t id; /**< Session ID */
pj_uint_t version; /**< Session version */
pj_str_t net_type; /**< Network type ("IN") */
pj_str_t addr_type; /**< Address type ("IP4", "IP6") */
pj_str_t addr; /**< The address. */
@ -697,8 +697,8 @@ struct pjmedia_sdp_session
/** Session time (t= line) */
struct
{
pj_uint32_t start; /**< Start time. */
pj_uint32_t stop; /**< Stop time. */
pj_uint_t start; /**< Start time. */
pj_uint_t stop; /**< Stop time. */
} time;
unsigned attr_count; /**< Number of attributes. */

View File

@ -912,10 +912,10 @@ static int print_session(const pjmedia_sdp_session *ses,
pj_memcpy(p, ses->origin.user.ptr, ses->origin.user.slen);
p += ses->origin.user.slen;
*p++ = ' ';
printed = pj_utoa(ses->origin.id, p);
printed = pj_utoa2(ses->origin.id, p);
p += printed;
*p++ = ' ';
printed = pj_utoa(ses->origin.version, p);
printed = pj_utoa2(ses->origin.version, p);
p += printed;
*p++ = ' ';
pj_memcpy(p, ses->origin.net_type.ptr, ses->origin.net_type.slen);
@ -964,10 +964,10 @@ static int print_session(const pjmedia_sdp_session *ses,
}
*p++ = 't';
*p++ = '=';
printed = pj_utoa(ses->time.start, p);
printed = pj_utoa2(ses->time.start, p);
p += printed;
*p++ = ' ';
printed = pj_utoa(ses->time.stop, p);
printed = pj_utoa2(ses->time.stop, p);
p += printed;
*p++ = '\r';
*p++ = '\n';
@ -1022,7 +1022,7 @@ static void parse_origin(pj_scanner *scanner, pjmedia_sdp_session *ses,
volatile parse_context *ctx)
{
pj_str_t str;
unsigned long ul;
pj_uint_t ui;
ctx->last_error = PJMEDIA_SDP_EINORIGIN;
@ -1041,20 +1041,20 @@ static void parse_origin(pj_scanner *scanner, pjmedia_sdp_session *ses,
/* id */
pj_scan_get_until_ch(scanner, ' ', &str);
if (pj_strtoul3(&str, &ul, 10) != PJ_SUCCESS){
if (pj_strtoul4(&str, &ui, 10) != PJ_SUCCESS){
on_scanner_error(scanner);
return;
}
ses->origin.id = (pj_uint32_t)ul;
ses->origin.id = (pj_uint_t)ui;
pj_scan_get_char(scanner);
/* version */
pj_scan_get_until_ch(scanner, ' ', &str);
if (pj_strtoul3(&str, &ul, 10) != PJ_SUCCESS){
if (pj_strtoul4(&str, &ui, 10) != PJ_SUCCESS){
on_scanner_error(scanner);
return;
}
ses->origin.version = (pj_uint32_t)ul;
ses->origin.version = (pj_uint_t)ui;
pj_scan_get_char(scanner);
/* network-type */
@ -1077,7 +1077,7 @@ static void parse_time(pj_scanner *scanner, pjmedia_sdp_session *ses,
volatile parse_context *ctx)
{
pj_str_t str;
unsigned long ul;
pj_uint_t ui;
ctx->last_error = PJMEDIA_SDP_EINTIME;
@ -1092,21 +1092,21 @@ static void parse_time(pj_scanner *scanner, pjmedia_sdp_session *ses,
/* start time */
pj_scan_get_until_ch(scanner, ' ', &str);
if (pj_strtoul3(&str, &ul, 10) != PJ_SUCCESS){
if (pj_strtoul4(&str, &ui, 10) != PJ_SUCCESS){
on_scanner_error(scanner);
return;
}
ses->time.start = (pj_uint32_t)ul;
ses->time.start = (pj_uint_t)ui;
pj_scan_get_char(scanner);
/* stop time */
pj_scan_get_until_chr(scanner, " \t\r\n", &str);
if (pj_strtoul3(&str, &ul, 10) != PJ_SUCCESS){
if (pj_strtoul4(&str, &ui, 10) != PJ_SUCCESS){
on_scanner_error(scanner);
return;
}
ses->time.stop = (pj_uint32_t)ul;
ses->time.stop = (pj_uint_t)ui;
/* We've got what we're looking for, skip anything until newline */
pj_scan_skip_line(scanner);