-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfmt_no.c
164 lines (152 loc) · 4.44 KB
/
fmt_no.c
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/** Convert long integer to strings with highlighting
* (c) Kurt Garloff <kurt@garloff.de>, 2013
* License: GNU GPL v2 or v3
*/
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "fmt_no.h"
#include <string.h>
#ifdef TEST
#define BOLD "\x1b[0;32m"
//#define BOLD "\x1b[0;1m"
#define NORM "\x1b[0;0m"
#endif
//typedef long long off_t;
static int mypow(int base, int pwr)
{
int i;
float pw = 1;
for (i = 0; i < pwr; ++i)
pw *= base;
return pw;
}
static char fmtbufs[8][64];
/** Format integers: pre digits before the ., post digits after.
* The integer is divided by scale prior to being returned as string.
* The string has groups of <group> digits that are highlighted with bold
* and norm strings. If boldinvis is set, the number will be prefixed
* with bold if the foremost group should be bold ...
* Limitations:
* - We can't return more than 8 strings in parallel, before
* we start overwriting buffers.
* - The string can't be longer than 64 chars, which should be
* enough though to print all possible 64bit ints.
*/
char* fmt_int_b(unsigned char pre, unsigned char post, unsigned int scale,
loff_t no, const char* bold, const char* norm,
const char boldinvis, const unsigned char base,
const unsigned char group)
{
static int fbno = -1;
const int blen = bold? strlen(bold): 0;
const int nlen = norm? strlen(norm): 0;
int idx = sizeof(fmtbufs[0])-1;
char pos;
loff_t my_no;
char* fmtbuf = fmtbufs[++fbno%8];
char isneg = no < 0;
const unsigned char twogroup = group? 2*group: 127;
if (!scale)
scale = 1;
fmtbuf[idx] = 0;
no = (isneg? -no: no);
if (post) {
/* Avoid 64bit overflow */
my_no = (no * mypow(base, post) + scale/2) / scale;
if (my_no < 0)
my_no = 0;
while (post--) {
unsigned char digit = my_no - base*(my_no/base);
fmtbuf[--idx] = digit >= 10? 'a'-10+digit: '0' + digit;
my_no /= base;
}
fmtbuf[--idx] = '.';
my_no = no / scale;
} else
my_no = (no + scale/2) / scale;
for (pos = 0; (pos < pre-isneg || !pre) && (my_no || !pos); ++pos) {
unsigned char digit = my_no - base*(my_no/base);
if (bold && pos && !(pos % twogroup)) {
/* insert bold */
memcpy(fmtbuf+idx-blen, bold, blen);
idx -= blen;
if (!boldinvis && --pre <= pos+isneg) {
pos++; break;
}
} else if (norm && !((pos+group) % twogroup)) {
/* insert norm */
memcpy(fmtbuf+idx-nlen, norm, nlen);
idx -= nlen;
if (!boldinvis && --pre <= pos+isneg) {
pos++; break;
}
}
fmtbuf[--idx] = digit >= 10? 'a'-10+digit: '0' + digit;
my_no /= base;
}
/* overflow */
if (my_no) {
if (post)
fmtbuf[sizeof(fmtbufs[0])-2] = '+';
else if (!isneg)
++idx;
}
/* Do we need a leading bold? */
if (bold && boldinvis && group && ((pos-1) % twogroup >= group)) {
memcpy(fmtbuf+idx-blen, bold, blen);
idx -= blen;
}
if (isneg) {
if (my_no && !post)
fmtbuf[--idx] = '<';
else
fmtbuf[--idx] = '-';
} else if (my_no && !post)
fmtbuf[--idx] = '>';
/* Fill */
if (pos+isneg < pre) {
memset(fmtbuf+idx+pos+isneg-pre, ' ', pre-pos-isneg);
idx -= pre-pos-isneg;
}
return fmtbuf+idx;
}
#ifdef TEST
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int i; loff_t l;
for (i = 1; i < argc; ++i) {
l = atoll(argv[i]);
printf("%16.2f:\n%s\n_%s\n__%s\n___%s\n",
(double)l/1024.0,
fmt_int(13, 1, 1024, l, BOLD, NORM, 1),
fmt_int(12, 1, 1024, l, BOLD, NORM, 1),
fmt_int(11, 1, 1024, l, BOLD, NORM, 1),
fmt_int(10, 1, 1024, l, BOLD, NORM, 1));
printf("____%s\n_____%s\n______%s\n_______%s\n________%s\n_________%s\n%s\n",
fmt_int( 9, 2, 1024, l, BOLD, NORM, 1),
fmt_int( 8, 2, 1024, l, BOLD, NORM, 1),
fmt_int( 7, 2, 1024, l, BOLD, NORM, 1),
fmt_int( 6, 2, 1024, l, BOLD, NORM, 1),
fmt_int( 5, 2, 1024, l, ",", ",", 0),
fmt_int( 4, 2, 1024, l, ",", ",", 0),
fmt_int(13, 2, 1024, l, ",", ",", 0));
printf("____%s\n_____%s\n______%s\n_______%s\n________%s\n_________%s\n%s\n",
fmt_int( 9, 0, 1024, l, BOLD, NORM, 1),
fmt_int( 8, 0, 1024, l, BOLD, NORM, 1),
fmt_int( 7, 0, 1024, l, BOLD, NORM, 1),
fmt_int( 6, 0, 1024, l, BOLD, NORM, 1),
fmt_int( 5, 0, 1024, l, ",", ",", 0),
fmt_int( 4, 0, 1024, l, ",", ",", 0),
fmt_int(13, 0, 1024, l, ",", ",", 0));
printf("\n%s\n", fmt_int(0, 1, 1024, l, BOLD, NORM, 1));
printf("%s\n", fmt_int_b(0, 1, 1024, l, BOLD, NORM, 1, 10, 0));
printf("0x%s\n\n", fmt_int_b(0, 1, 1024, l, BOLD, NORM, 1, 16, 4));
}
return 0;
}
#endif