Skip to content

Commit af0d024

Browse files
past-dueFabrice Bellard
andcommitted
Port bellard/quickjs dtoa library commits
added new dtoa library to print and parse float64 numbers. It is necessary to fix corner cases (e.g. radix != 10) and to have correct behavior regardless of the libc implementation. Port of: bellard/quickjs@9936606 bellard/quickjs@dbbca3d Includes alternative fix for bellard/quickjs@638ec8c from 0191aea Update CMakeLists.txt and meson.build Co-Authored-By: Fabrice Bellard <[email protected]>
1 parent 5299e09 commit af0d024

File tree

8 files changed

+1986
-949
lines changed

8 files changed

+1986
-949
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ endmacro()
227227

228228
set(qjs_sources
229229
cutils.c
230+
dtoa.c
230231
libregexp.c
231232
libunicode.c
232233
quickjs.c

cutils.c

Lines changed: 0 additions & 252 deletions
Original file line numberDiff line numberDiff line change
@@ -586,258 +586,6 @@ size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_
586586
return j;
587587
}
588588

589-
/*--- integer to string conversions --*/
590-
591-
/* All conversion functions:
592-
- require a destination array `buf` of sufficient length
593-
- write the string representation at the beginning of `buf`
594-
- null terminate the string
595-
- return the string length
596-
*/
597-
598-
/* 2 <= base <= 36 */
599-
char const digits36[36] = {
600-
'0','1','2','3','4','5','6','7','8','9',
601-
'a','b','c','d','e','f','g','h','i','j',
602-
'k','l','m','n','o','p','q','r','s','t',
603-
'u','v','w','x','y','z'
604-
};
605-
606-
607-
#define USE_SPECIAL_RADIX_10 1 // special case base 10 radix conversions
608-
#define USE_SINGLE_CASE_FAST 1 // special case single digit numbers
609-
610-
/* using u32toa_shift variant */
611-
612-
#define gen_digit(buf, c) if (is_be()) \
613-
buf = (buf >> 8) | ((uint64_t)(c) << ((sizeof(buf) - 1) * 8)); \
614-
else \
615-
buf = (buf << 8) | (c)
616-
617-
static size_t u7toa_shift(char dest[minimum_length(8)], uint32_t n)
618-
{
619-
size_t len = 1;
620-
uint64_t buf = 0;
621-
while (n >= 10) {
622-
uint32_t quo = n % 10;
623-
n /= 10;
624-
gen_digit(buf, '0' + quo);
625-
len++;
626-
}
627-
gen_digit(buf, '0' + n);
628-
memcpy(dest, &buf, sizeof buf);
629-
return len;
630-
}
631-
632-
static size_t u07toa_shift(char dest[minimum_length(8)], uint32_t n, size_t len)
633-
{
634-
size_t i;
635-
dest += len;
636-
dest[7] = '\0';
637-
for (i = 7; i-- > 1;) {
638-
uint32_t quo = n % 10;
639-
n /= 10;
640-
dest[i] = (char)('0' + quo);
641-
}
642-
dest[i] = (char)('0' + n);
643-
return len + 7;
644-
}
645-
646-
size_t u32toa(char buf[minimum_length(11)], uint32_t n)
647-
{
648-
#ifdef USE_SINGLE_CASE_FAST /* 10% */
649-
if (n < 10) {
650-
buf[0] = (char)('0' + n);
651-
buf[1] = '\0';
652-
return 1;
653-
}
654-
#endif
655-
#define TEN_POW_7 10000000
656-
if (n >= TEN_POW_7) {
657-
uint32_t quo = n / TEN_POW_7;
658-
n %= TEN_POW_7;
659-
size_t len = u7toa_shift(buf, quo);
660-
return u07toa_shift(buf, n, len);
661-
}
662-
return u7toa_shift(buf, n);
663-
}
664-
665-
size_t u64toa(char buf[minimum_length(21)], uint64_t n)
666-
{
667-
if (likely(n < 0x100000000))
668-
return u32toa(buf, n);
669-
670-
size_t len;
671-
if (n >= TEN_POW_7) {
672-
uint64_t n1 = n / TEN_POW_7;
673-
n %= TEN_POW_7;
674-
if (n1 >= TEN_POW_7) {
675-
uint32_t quo = n1 / TEN_POW_7;
676-
n1 %= TEN_POW_7;
677-
len = u7toa_shift(buf, quo);
678-
len = u07toa_shift(buf, n1, len);
679-
} else {
680-
len = u7toa_shift(buf, n1);
681-
}
682-
return u07toa_shift(buf, n, len);
683-
}
684-
return u7toa_shift(buf, n);
685-
}
686-
687-
size_t i32toa(char buf[minimum_length(12)], int32_t n)
688-
{
689-
if (likely(n >= 0))
690-
return u32toa(buf, n);
691-
692-
buf[0] = '-';
693-
return 1 + u32toa(buf + 1, -(uint32_t)n);
694-
}
695-
696-
size_t i64toa(char buf[minimum_length(22)], int64_t n)
697-
{
698-
if (likely(n >= 0))
699-
return u64toa(buf, n);
700-
701-
buf[0] = '-';
702-
return 1 + u64toa(buf + 1, -(uint64_t)n);
703-
}
704-
705-
/* using u32toa_radix_length variant */
706-
707-
static uint8_t const radix_shift[64] = {
708-
0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
709-
4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
710-
5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
711-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
712-
};
713-
714-
size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned base)
715-
{
716-
int shift;
717-
718-
#ifdef USE_SPECIAL_RADIX_10
719-
if (likely(base == 10))
720-
return u32toa(buf, n);
721-
#endif
722-
if (n < base) {
723-
buf[0] = digits36[n];
724-
buf[1] = '\0';
725-
return 1;
726-
}
727-
shift = radix_shift[base & 63];
728-
if (shift) {
729-
uint32_t mask = (1 << shift) - 1;
730-
size_t len = (32 - clz32(n) + shift - 1) / shift;
731-
size_t last = n & mask;
732-
char *end = buf + len;
733-
n >>= shift;
734-
*end-- = '\0';
735-
*end-- = digits36[last];
736-
while (n >= base) {
737-
size_t quo = n & mask;
738-
n >>= shift;
739-
*end-- = digits36[quo];
740-
}
741-
*end = digits36[n];
742-
return len;
743-
} else {
744-
size_t len = 2;
745-
size_t last = n % base;
746-
n /= base;
747-
uint32_t nbase = base;
748-
while (n >= nbase) {
749-
nbase *= base;
750-
len++;
751-
}
752-
char *end = buf + len;
753-
*end-- = '\0';
754-
*end-- = digits36[last];
755-
while (n >= base) {
756-
size_t quo = n % base;
757-
n /= base;
758-
*end-- = digits36[quo];
759-
}
760-
*end = digits36[n];
761-
return len;
762-
}
763-
}
764-
765-
size_t u64toa_radix(char buf[minimum_length(65)], uint64_t n, unsigned base)
766-
{
767-
int shift;
768-
769-
#ifdef USE_SPECIAL_RADIX_10
770-
if (likely(base == 10))
771-
return u64toa(buf, n);
772-
#endif
773-
shift = radix_shift[base & 63];
774-
if (shift) {
775-
if (n < base) {
776-
buf[0] = digits36[n];
777-
buf[1] = '\0';
778-
return 1;
779-
}
780-
uint64_t mask = (1 << shift) - 1;
781-
size_t len = (64 - clz64(n) + shift - 1) / shift;
782-
size_t last = n & mask;
783-
char *end = buf + len;
784-
n >>= shift;
785-
*end-- = '\0';
786-
*end-- = digits36[last];
787-
while (n >= base) {
788-
size_t quo = n & mask;
789-
n >>= shift;
790-
*end-- = digits36[quo];
791-
}
792-
*end = digits36[n];
793-
return len;
794-
} else {
795-
if (likely(n < 0x100000000))
796-
return u32toa_radix(buf, n, base);
797-
size_t last = n % base;
798-
n /= base;
799-
uint64_t nbase = base;
800-
size_t len = 2;
801-
while (n >= nbase) {
802-
nbase *= base;
803-
len++;
804-
}
805-
char *end = buf + len;
806-
*end-- = '\0';
807-
*end-- = digits36[last];
808-
while (n >= base) {
809-
size_t quo = n % base;
810-
n /= base;
811-
*end-- = digits36[quo];
812-
}
813-
*end = digits36[n];
814-
return len;
815-
}
816-
}
817-
818-
size_t i32toa_radix(char buf[minimum_length(34)], int32_t n, unsigned int base)
819-
{
820-
if (likely(n >= 0))
821-
return u32toa_radix(buf, n, base);
822-
823-
buf[0] = '-';
824-
return 1 + u32toa_radix(buf + 1, -(uint32_t)n, base);
825-
}
826-
827-
size_t i64toa_radix(char buf[minimum_length(66)], int64_t n, unsigned int base)
828-
{
829-
if (likely(n >= 0))
830-
return u64toa_radix(buf, n, base);
831-
832-
buf[0] = '-';
833-
return 1 + u64toa_radix(buf + 1, -(uint64_t)n, base);
834-
}
835-
836-
#undef gen_digit
837-
#undef TEN_POW_7
838-
#undef USE_SPECIAL_RADIX_10
839-
#undef USE_SINGLE_CASE_FAST
840-
841589
/*---- sorting with opaque argument ----*/
842590

843591
typedef void (*exchange_f)(void *a, void *b, size_t size);

cutils.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -543,16 +543,6 @@ static inline uint8_t to_upper_ascii(uint8_t c) {
543543
return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c;
544544
}
545545

546-
extern char const digits36[36];
547-
size_t u32toa(char buf[minimum_length(11)], uint32_t n);
548-
size_t i32toa(char buf[minimum_length(12)], int32_t n);
549-
size_t u64toa(char buf[minimum_length(21)], uint64_t n);
550-
size_t i64toa(char buf[minimum_length(22)], int64_t n);
551-
size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned int base);
552-
size_t i32toa_radix(char buf[minimum_length(34)], int32_t n, unsigned base);
553-
size_t u64toa_radix(char buf[minimum_length(65)], uint64_t n, unsigned int base);
554-
size_t i64toa_radix(char buf[minimum_length(66)], int64_t n, unsigned int base);
555-
556546
void rqsort(void *base, size_t nmemb, size_t size,
557547
int (*cmp)(const void *, const void *, void *),
558548
void *arg);

0 commit comments

Comments
 (0)