mirror of
https://github.com/janet-lang/janet
synced 2025-02-26 12:50:02 +00:00
Add 64 bit integer support to printf and other formatting functions.
This commit is contained in:
parent
c8974fffbe
commit
ef7afeb2ea
@ -2,6 +2,8 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## ??? - Unreleased
|
## ??? - Unreleased
|
||||||
|
- Add the `u` format specifier to printf family functions.
|
||||||
|
- Allow printing 64 integer types in `printf` and `string/format` family functions.
|
||||||
- Allow importing modules from custom directories more easily with the `@` prefix
|
- Allow importing modules from custom directories more easily with the `@` prefix
|
||||||
to module paths. For example, if there is a dynamic binding :custom-modules that
|
to module paths. For example, if there is a dynamic binding :custom-modules that
|
||||||
is a file system path to a directory of modules, import from that directory with
|
is a file system path to a directory of modules, import from that directory with
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
/* Implements a pretty printer for Janet. The pretty printer
|
/* Implements a pretty printer for Janet. The pretty printer
|
||||||
* is simple and not that flexible, but fast. */
|
* is simple and not that flexible, but fast. */
|
||||||
@ -750,14 +752,41 @@ static void pushtypes(JanetBuffer *buffer, int types) {
|
|||||||
|
|
||||||
#define MAX_ITEM 256
|
#define MAX_ITEM 256
|
||||||
#define FMT_FLAGS "-+ #0"
|
#define FMT_FLAGS "-+ #0"
|
||||||
|
#define FMT_REPLACE_INTTYPES "diouxX"
|
||||||
#define MAX_FORMAT 32
|
#define MAX_FORMAT 32
|
||||||
|
|
||||||
|
struct FmtMapping {
|
||||||
|
char c;
|
||||||
|
const char *mapping;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Janet uses fixed with integer types for most things, so map
|
||||||
|
* format specifiers to these fixed sizes */
|
||||||
|
static const struct FmtMapping format_mappings[] = {
|
||||||
|
{'d', PRId64},
|
||||||
|
{'i', PRIi64},
|
||||||
|
{'o', PRIo64},
|
||||||
|
{'u', PRIu64},
|
||||||
|
{'x', PRIx64},
|
||||||
|
{'X', PRIX64},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *get_fmt_mapping(char c) {
|
||||||
|
for (size_t i = 0; i < (sizeof(format_mappings) / sizeof(struct FmtMapping)); i++) {
|
||||||
|
if (format_mappings[i].c == c)
|
||||||
|
return format_mappings[i].mapping;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *scanformat(
|
static const char *scanformat(
|
||||||
const char *strfrmt,
|
const char *strfrmt,
|
||||||
char *form,
|
char *form,
|
||||||
char width[3],
|
char width[3],
|
||||||
char precision[3]) {
|
char precision[3]) {
|
||||||
const char *p = strfrmt;
|
const char *p = strfrmt;
|
||||||
|
|
||||||
|
/* Parse strfrmt */
|
||||||
memset(width, '\0', 3);
|
memset(width, '\0', 3);
|
||||||
memset(precision, '\0', 3);
|
memset(precision, '\0', 3);
|
||||||
while (*p != '\0' && strchr(FMT_FLAGS, *p) != NULL)
|
while (*p != '\0' && strchr(FMT_FLAGS, *p) != NULL)
|
||||||
@ -776,10 +805,22 @@ static const char *scanformat(
|
|||||||
}
|
}
|
||||||
if (isdigit((int)(*p)))
|
if (isdigit((int)(*p)))
|
||||||
janet_panic("invalid format (width or precision too long)");
|
janet_panic("invalid format (width or precision too long)");
|
||||||
|
|
||||||
|
/* Write to form - replace characters with fixed size stuff */
|
||||||
*(form++) = '%';
|
*(form++) = '%';
|
||||||
memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char));
|
const char *p2 = strfrmt;
|
||||||
form += (p - strfrmt) + 1;
|
while (p2 <= p) {
|
||||||
|
if (strchr(FMT_REPLACE_INTTYPES, *p2) != NULL) {
|
||||||
|
const char *mapping = get_fmt_mapping(*p2++);
|
||||||
|
size_t len = strlen(mapping);
|
||||||
|
strcpy(form, mapping);
|
||||||
|
form += len;
|
||||||
|
} else {
|
||||||
|
*(form++) = *(p2++);
|
||||||
|
}
|
||||||
|
}
|
||||||
*form = '\0';
|
*form = '\0';
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -804,11 +845,16 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i':
|
case 'i': {
|
||||||
case 'o':
|
int64_t n = va_arg(args, long);
|
||||||
|
nb = snprintf(item, MAX_ITEM, form, n);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X': {
|
case 'X':
|
||||||
int32_t n = va_arg(args, long);
|
case 'o':
|
||||||
|
case 'u': {
|
||||||
|
uint64_t n = va_arg(args, unsigned long);
|
||||||
nb = snprintf(item, MAX_ITEM, form, n);
|
nb = snprintf(item, MAX_ITEM, form, n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -962,11 +1008,16 @@ void janet_buffer_format(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i':
|
case 'i': {
|
||||||
case 'o':
|
int64_t n = janet_getinteger64(argv, arg);
|
||||||
|
nb = snprintf(item, MAX_ITEM, form, n);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X': {
|
case 'X':
|
||||||
int32_t n = janet_getinteger(argv, arg);
|
case 'o':
|
||||||
|
case 'u': {
|
||||||
|
uint64_t n = janet_getuinteger64(argv, arg);
|
||||||
nb = snprintf(item, MAX_ITEM, form, n);
|
nb = snprintf(item, MAX_ITEM, form, n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user