1 /**************************************************************************/
2 /* */
3 /* OCaml */
4 /* */
5 /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
6 /* */
7 /* Copyright 2002 Institut National de Recherche en Informatique et */
8 /* en Automatique. */
9 /* */
10 /* All rights reserved. This file is distributed under the terms of */
11 /* the GNU Lesser General Public License version 2.1, with the */
12 /* special exception on linking described in the file LICENSE. */
13 /* */
14 /**************************************************************************/
15
16 /* printf-like formatting of 64-bit integers, in case the C library
17 printf() function does not support them. */
18
19 #ifndef CAML_INT64_FORMAT_H
20 #define CAML_INT64_FORMAT_H
21
22 #ifdef CAML_INTERNALS
23
I64_format(char * buffer,char * fmt,int64_t x)24 static void I64_format(char * buffer, char * fmt, int64_t x)
25 {
26 static char conv_lower[] = "0123456789abcdef";
27 static char conv_upper[] = "0123456789ABCDEF";
28 char rawbuffer[24];
29 char justify, signstyle, filler, alternate, signedconv;
30 int base, width, sign, i, rawlen;
31 char * cvtbl;
32 char * p, * r;
33 int64_t wbase, digit;
34
35 /* Parsing of format */
36 justify = '+';
37 signstyle = '-';
38 filler = ' ';
39 alternate = 0;
40 base = 0;
41 signedconv = 0;
42 width = 0;
43 cvtbl = conv_lower;
44 for (p = fmt; *p != 0; p++) {
45 switch (*p) {
46 case '-':
47 justify = '-'; break;
48 case '+': case ' ':
49 signstyle = *p; break;
50 case '0':
51 filler = '0'; break;
52 case '#':
53 alternate = 1; break;
54 case '1': case '2': case '3': case '4': case '5':
55 case '6': case '7': case '8': case '9':
56 width = atoi(p);
57 while (p[1] >= '0' && p[1] <= '9') p++;
58 break;
59 case 'd': case 'i':
60 signedconv = 1; /* fallthrough */
61 case 'u':
62 base = 10; break;
63 case 'x':
64 base = 16; break;
65 case 'X':
66 base = 16; cvtbl = conv_upper; break;
67 case 'o':
68 base = 8; break;
69 }
70 }
71 if (base == 0) { buffer[0] = 0; return; }
72 /* Do the conversion */
73 sign = 1;
74 if (signedconv && I64_is_negative(x)) { sign = -1; x = I64_neg(x); }
75 r = rawbuffer + sizeof(rawbuffer);
76 wbase = I64_of_int32(base);
77 do {
78 I64_udivmod(x, wbase, &x, &digit);
79 *--r = cvtbl[I64_to_int32(digit)];
80 } while (! I64_is_zero(x));
81 rawlen = rawbuffer + sizeof(rawbuffer) - r;
82 /* Adjust rawlen to reflect additional chars (sign, etc) */
83 if (signedconv && (sign < 0 || signstyle != '-')) rawlen++;
84 if (alternate) {
85 if (base == 8) rawlen += 1;
86 if (base == 16) rawlen += 2;
87 }
88 /* Do the formatting */
89 p = buffer;
90 if (justify == '+' && filler == ' ') {
91 for (i = rawlen; i < width; i++) *p++ = ' ';
92 }
93 if (signedconv) {
94 if (sign < 0) *p++ = '-';
95 else if (signstyle != '-') *p++ = signstyle;
96 }
97 if (alternate && base == 8) *p++ = '0';
98 if (alternate && base == 16) { *p++ = '0'; *p++ = 'x'; }
99 if (justify == '+' && filler == '0') {
100 for (i = rawlen; i < width; i++) *p++ = '0';
101 }
102 while (r < rawbuffer + sizeof(rawbuffer)) *p++ = *r++;
103 if (justify == '-') {
104 for (i = rawlen; i < width; i++) *p++ = ' ';
105 }
106 *p = 0;
107 }
108
109 #endif /* CAML_INTERNALS */
110
111 #endif /* CAML_INT64_FORMAT_H */
112