forked from microsoft/devicescript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstrformat.c
More file actions
95 lines (78 loc) · 2.92 KB
/
strformat.c
File metadata and controls
95 lines (78 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "devs_internal.h"
static int numvalue(char c) {
if ('0' <= c && c <= '9')
return c - '0';
c |= 0x20;
if ('a' <= c && c <= 'z')
return c - 'a' + 10;
return -1;
}
#define WR(c) \
do { \
char tmp = (c); \
if (numskip == 0) { \
if (dp < dstlen) \
dst[dp] = tmp; \
dp++; \
} else \
numskip--; \
} while (0)
size_t devs_strformat(devs_ctx_t *ctx, const char *fmt, size_t fmtlen, char *dst, size_t dstlen,
value_t *args, size_t numargs, size_t numskip) {
size_t fp = 0;
size_t dp = 0;
if (dstlen)
dst[0] = 0; // in case numskip prevents us from writing anything
while (fp <= fmtlen) {
char c = fp == fmtlen ? (fp++, 0) : fmt[fp++];
if (c != '{' || fp >= fmtlen) {
// if we see "}}" we treat it as a single "}"
if (c == '}' && fp < fmtlen && fmt[fp] == '}')
fp++;
goto write_c;
}
c = fmt[fp++];
if (c == '{')
goto write_c;
int pos = numvalue(c);
if (pos < 0) {
c = '!';
goto write_c;
}
size_t nextp = fp;
while (nextp < fmtlen && fmt[nextp] != '}')
nextp++;
int precision = -1;
if (fp < nextp)
precision = numvalue(fmt[fp++]);
fp = nextp + 1;
if (pos >= (int)numargs) {
c = '?';
goto write_c;
}
if (precision < 0)
precision = 6;
unsigned sz;
const char *s;
value_t v = args[pos];
char buf[64];
if (devs_is_number(v)) {
jd_print_double(buf, devs_value_to_double(ctx, args[pos]), precision + 1);
s = buf;
sz = strlen(buf);
} else {
value_t tmp = devs_value_to_string(ctx, v);
// note that tmp is not pinned, it may go away at next allocation, but we only use it
// down below
s = devs_string_get_utf8(ctx, tmp, &sz);
}
while (sz--)
WR(*s++);
continue;
write_c:
WR(c);
}
if (dstlen)
dst[dstlen - 1] = 0; // in case we overflow
return dp;
}