Skip to content

Commit

Permalink
Improve custom printf
Browse files Browse the repository at this point in the history
- add `is_lower_ascii()` and `to_lower_ascii()`
- fix compilation warnings
- simplify `unicode_to_utf8()`
- add `digits36_upper`
- add floating point conversions
- add wide string conversions
- improve string conversions
  • Loading branch information
chqrlie committed May 7, 2024
1 parent 075f4bc commit c31580b
Show file tree
Hide file tree
Showing 5 changed files with 931 additions and 307 deletions.
189 changes: 107 additions & 82 deletions cutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,19 @@
#include "cutils.h"

#undef NANOSEC
#define NANOSEC ((uint64_t) 1e9)
#define NANOSEC 1000000000

#pragma GCC visibility push(default)

void pstrcpy(char *buf, int buf_size, const char *str)
void pstrcpy(char *buf, size_t buf_size, const char *str)
{
int c;
char *q = buf;

if (buf_size <= 0)
return;

for(;;) {
c = *str++;
char c = *str++;
if (c == 0 || q >= buf + buf_size - 1)
break;
*q++ = c;
Expand All @@ -57,10 +56,9 @@ void pstrcpy(char *buf, int buf_size, const char *str)
}

/* strcat and truncate. */
char *pstrcat(char *buf, int buf_size, const char *s)
char *pstrcat(char *buf, size_t buf_size, const char *s)
{
int len;
len = strlen(buf);
size_t len = strlen(buf);
if (len < buf_size)
pstrcpy(buf + len, buf_size - len, s);
return buf;
Expand Down Expand Up @@ -189,15 +187,16 @@ static int dbuf_vprintf_default(DynBuf *s, const char *fmt, va_list ap)
va_end(arg);

if (len >= 0) {
if ((size_t)len >= avail) {
if (dbuf_realloc(s, s->size + len + 1))
size_t ulen = (size_t)len;
if (ulen >= avail) {
if (dbuf_realloc(s, s->size + ulen + 1))
return -1;
avail = s->allocated_size - s->size;
va_copy(arg, ap);
vsnprintf((char *)(s->buf + s->size), avail, fmt, arg);
va_end(arg);
}
s->size += len;
s->size += ulen;
}
return len;
}
Expand Down Expand Up @@ -231,42 +230,55 @@ void dbuf_free(DynBuf *s)

/* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes
are output. */
int unicode_to_utf8(uint8_t *buf, unsigned int c)
size_t unicode_to_utf8(uint8_t *buf, unsigned int c)
{
uint8_t *q = buf;

if (c < 0x80) {
*q++ = c;
} else {
if (c < 0x800) {
*q++ = (c >> 6) | 0xc0;
} else {
if (c < 0x10000) {
*q++ = (c >> 12) | 0xe0;
} else {
if (c < 0x00200000) {
*q++ = (c >> 18) | 0xf0;
} else {
if (c < 0x04000000) {
*q++ = (c >> 24) | 0xf8;
} else if (c < 0x80000000) {
*q++ = (c >> 30) | 0xfc;
*q++ = ((c >> 24) & 0x3f) | 0x80;
} else {
return 0;
}
*q++ = ((c >> 18) & 0x3f) | 0x80;
}
*q++ = ((c >> 12) & 0x3f) | 0x80;
}
*q++ = ((c >> 6) & 0x3f) | 0x80;
}
*q++ = (c & 0x3f) | 0x80;
buf[0] = (uint8_t)c;
return 1;
}
if (c < 0x800) {
buf[0] = (uint8_t)((c >> 6) | 0xc0);
buf[1] = (uint8_t)((c & 0x3f) | 0x80);
return 2;
}
return q - buf;
if (c < 0x10000) {
buf[0] = (uint8_t)((c >> 12) | 0xe0);
buf[1] = (uint8_t)(((c >> 6) & 0x3f) | 0x80);
buf[2] = (uint8_t)((c & 0x3f) | 0x80);
return 3;
}
if (c < 0x00200000) {
buf[0] = (uint8_t)((c >> 18) | 0xf0);
buf[1] = (uint8_t)(((c >> 12) & 0x3f) | 0x80);
buf[2] = (uint8_t)(((c >> 6) & 0x3f) | 0x80);
buf[3] = (uint8_t)((c & 0x3f) | 0x80);
return 4;
}
#if 0
if (c < 0x04000000) {
buf[0] = (uint8_t)((c >> 24) | 0xf8);
buf[1] = (uint8_t)(((c >> 18) & 0x3f) | 0x80);
buf[2] = (uint8_t)(((c >> 12) & 0x3f) | 0x80);
buf[3] = (uint8_t)(((c >> 6) & 0x3f) | 0x80);
buf[4] = (uint8_t)((c & 0x3f) | 0x80);
return 5;
}
buf[0] = (uint8_t)((c >> 30) | 0xfc);
buf[1] = (uint8_t)(((c >> 24) & 0x3f) | 0x80);
buf[2] = (uint8_t)(((c >> 18) & 0x3f) | 0x80);
buf[3] = (uint8_t)(((c >> 12) & 0x3f) | 0x80);
buf[4] = (uint8_t)(((c >> 6) & 0x3f) | 0x80);
buf[5] = (uint8_t)((c & 0x3f) | 0x80);
return 6;
#else
buf[0] = (uint8_t)((0xFFFD >> 12) | 0xe0);
buf[1] = (uint8_t)(((0xFFFD >> 6) & 0x3f) | 0x80);
buf[2] = (uint8_t)((0xFFFD & 0x3f) | 0x80);
return 3;
#endif
}

static const unsigned int utf8_min_code[5] = {
static const int utf8_min_code[5] = {
0x80, 0x800, 0x10000, 0x00200000, 0x04000000,
};

Expand Down Expand Up @@ -342,6 +354,7 @@ int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp)

/* 2 <= base <= 36 */
char const digits36[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
char const digits36_upper[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

/* using u32toa_shift variant */

Expand All @@ -350,7 +363,7 @@ char const digits36[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
else \
buf = (buf << 8) | (c)

size_t u7toa_shift(char dest[minimum_length(8)], uint32_t n)
static size_t u7toa_shift(char dest[minimum_length(8)], uint32_t n)
{
size_t len = 1;
uint64_t buf = 0;
Expand All @@ -365,7 +378,7 @@ size_t u7toa_shift(char dest[minimum_length(8)], uint32_t n)
return len;
}

size_t u07toa_shift(char dest[minimum_length(8)], uint32_t n, size_t len)
static size_t u07toa_shift(char dest[minimum_length(8)], uint32_t n, size_t len)
{
size_t i;
dest += len;
Expand All @@ -389,39 +402,41 @@ size_t u32toa(char buf[minimum_length(11)], uint32_t n)
#define TEN_POW_7 10000000
if (n >= TEN_POW_7) {
uint32_t quo = n / TEN_POW_7;
size_t len;
n %= TEN_POW_7;
size_t len = u7toa_shift(buf, quo);
len = u7toa_shift(buf, quo);
return u07toa_shift(buf, n, len);
}
return u7toa_shift(buf, n);
}

size_t u64toa(char buf[minimum_length(21)], uint64_t n)
{
size_t len;

if (likely(n < 0x100000000))
return u32toa(buf, n);
return u32toa(buf, (uint32_t)n);

size_t len;
if (n >= TEN_POW_7) {
uint64_t n1 = n / TEN_POW_7;
n %= TEN_POW_7;
if (n1 >= TEN_POW_7) {
uint32_t quo = n1 / TEN_POW_7;
uint32_t quo = (uint32_t)(n1 / TEN_POW_7);
n1 %= TEN_POW_7;
len = u7toa_shift(buf, quo);
len = u07toa_shift(buf, n1, len);
len = u07toa_shift(buf, (uint32_t)n1, len);
} else {
len = u7toa_shift(buf, n1);
len = u7toa_shift(buf, (uint32_t)n1);
}
return u07toa_shift(buf, n, len);
return u07toa_shift(buf, (uint32_t)n, len);
}
return u7toa_shift(buf, n);
return u7toa_shift(buf, (uint32_t)n);
}

size_t i32toa(char buf[minimum_length(12)], int32_t n)
{
if (likely(n >= 0))
return u32toa(buf, n);
return u32toa(buf, (uint32_t)n);

buf[0] = '-';
return 1 + u32toa(buf + 1, -(uint32_t)n);
Expand All @@ -430,7 +445,7 @@ size_t i32toa(char buf[minimum_length(12)], int32_t n)
size_t i64toa(char buf[minimum_length(22)], int64_t n)
{
if (likely(n >= 0))
return u64toa(buf, n);
return u64toa(buf, (uint64_t)n);

buf[0] = '-';
return 1 + u64toa(buf + 1, -(uint64_t)n);
Expand All @@ -447,6 +462,9 @@ static uint8_t const radix_shift[64] = {

size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned base)
{
int shift;
char *end;

#ifdef USE_SPECIAL_RADIX_10
if (likely(base == 10))
return u32toa(buf, n);
Expand All @@ -456,13 +474,13 @@ size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned base)
buf[1] = '\0';
return 1;
}
int shift = radix_shift[base & 63];
shift = radix_shift[base & 63];
if (shift) {
uint32_t mask = (1 << shift) - 1;
size_t len = (32 - clz32(n) + shift - 1) / shift;
size_t len = (size_t)((32 - clz32(n) + shift - 1) / shift);
size_t last = n & mask;
n /= base;
char *end = buf + len;
end = buf + len;
n >>= shift;
*end-- = '\0';
*end-- = digits36[last];
while (n >= base) {
Expand All @@ -474,14 +492,14 @@ size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned base)
return len;
} else {
size_t len = 2;
uint32_t nbase = base;
size_t last = n % base;
n /= base;
uint32_t nbase = base;
while (n >= nbase) {
nbase *= base;
len++;
}
char *end = buf + len;
end = buf + len;
*end-- = '\0';
*end-- = digits36[last];
while (n >= base) {
Expand All @@ -496,22 +514,24 @@ size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned base)

size_t u64toa_radix(char buf[minimum_length(65)], uint64_t n, unsigned base)
{
#ifdef USE_SPECIAL_RADIX_10
if (likely(base == 10))
int shift;
char *end;

if (n < base) {
buf[0] = digits36[n];
buf[1] = '\0';
return 1;
}
if (likely(base == 10)) {
return u64toa(buf, n);
#endif
int shift = radix_shift[base & 63];
}
shift = radix_shift[base & 63];
if (shift) {
if (n < base) {
buf[0] = digits36[n];
buf[1] = '\0';
return 1;
}
uint64_t mask = (1 << shift) - 1;
size_t len = (64 - clz64(n) + shift - 1) / shift;
size_t len = (size_t)((64 - clz64(n) + shift - 1) / shift);
size_t last = n & mask;
n /= base;
char *end = buf + len;
end = buf + len;
n >>= shift;
*end-- = '\0';
*end-- = digits36[last];
while (n >= base) {
Expand All @@ -521,18 +541,19 @@ size_t u64toa_radix(char buf[minimum_length(65)], uint64_t n, unsigned base)
}
*end = digits36[n];
return len;
} else
if (likely(n < 0x100000000)) {
return u32toa_radix(buf, (uint32_t)n, base);
} else {
if (likely(n < 0x100000000))
return u32toa_radix(buf, n, base);
size_t last = n % base;
n /= base;
uint64_t nbase = base;
size_t len = 2;
n /= base;
while (n >= nbase) {
nbase *= base;
len++;
}
char *end = buf + len;
end = buf + len;
*end-- = '\0';
*end-- = digits36[last];
while (n >= base) {
Expand All @@ -548,7 +569,7 @@ size_t u64toa_radix(char buf[minimum_length(65)], uint64_t n, unsigned base)
size_t i64toa_radix(char buf[minimum_length(66)], int64_t n, unsigned int base)
{
if (likely(n >= 0))
return u64toa_radix(buf, n, base);
return u64toa_radix(buf, (uint64_t)n, base);

buf[0] = '-';
return 1 + u64toa_radix(buf + 1, -(uint64_t)n, base);
Expand Down Expand Up @@ -738,7 +759,14 @@ static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque)
/* pointer based version with local stack and insertion sort threshhold */
void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
{
struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack;
struct {
uint8_t *base;
size_t count;
int depth;
#if SIZE_MAX > UINT_MAX
int pad;
#endif
} stack[50], *sp = stack;
uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m;
size_t m4, i, lt, gt, span, span2;
int c, depth;
Expand Down Expand Up @@ -1121,12 +1149,9 @@ int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) {
if (r == 0)
return 0;

if (r == ETIMEDOUT)
return -1;

abort();
if (r != ETIMEDOUT)
abort();

/* Pacify some compilers. */
return -1;
}

Expand Down
Loading

0 comments on commit c31580b

Please sign in to comment.