-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathformat_integers.c
More file actions
155 lines (134 loc) · 3.77 KB
/
Copy pathformat_integers.c
File metadata and controls
155 lines (134 loc) · 3.77 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
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
#include "_printf_internals.h"
/**
* count_digits - calculate how many digits can represent a number in the
* given base.
* @n: the integer.
* @base: the radix of the number.
*
* Return: number of digits in the integer.
*/
unsigned short int count_digits(uintmax_t n, const unsigned short int base)
{
unsigned short int digits = 0;
if (base < 2)
return (0);
/* clang-format off */
do {
/* clang-format on */
n /= base;
++digits;
} while (n);
return (digits);
}
/**
* insert_symbols - insert sign and alt characters if needed.
* @str: pointer to memory block to store the characters.
* @num: the number to be formatted.
* @mods: modifier flags.
*/
static void insert_symbols(char *str, uintmax_t num, const modifiers mods)
{
if (mods.flags.sign || mods.flags.space || mods.int_mod.is_negative)
{
if (mods.int_mod.is_negative)
*(str++) = '-';
else if (mods.flags.sign)
*(str++) = '+';
}
if (num && mods.flags.alternate_form && mods.int_mod.base != BASE10)
{
*(str++) = '0';
if (mods.int_mod.base == BASE02)
*(str++) = 'b';
if (mods.int_mod.base == BASE16)
*(str++) = islower(mods.int_mod.alphabet_case) ? 'x' : 'X';
}
}
/**
* itostr - converts a number to a string representation.
* @str: pointer to memory block to store the string.
* @num: the natural number to convert.
* @mods: modifier flags.
*/
static void itostr(char *const str, uintmax_t num, const integer_mods mods)
{
int d = count_digits(num, mods.base) - 1;
for (; d > -1; --d)
{
if (num % mods.base < 10)
str[d] = num % mods.base + '0';
else
str[d] = ((num % mods.base) - 10) + mods.alphabet_case;
num /= mods.base;
}
}
/**
* init_lengths - initialises various variables.
* @num: the number to be formatted.
* @mods: modifier flags.
* @num_len: total length of the result string.
* @digits: number of non-zero digits in the number.
* @symbols: length of sign + alternate form symbols.
* @zeros: number of 0's to be used as padding.
* @padding: number of blanks/zeros used for padding.
*/
static void init_lengths(
uintmax_t num, const modifiers mods, int *num_len, int *digits,
int *symbols, int *zeros, int *padding)
{
if (mods.flags.sign || mods.flags.space || mods.int_mod.is_negative)
++(*symbols);
if (num && mods.flags.alternate_form && mods.int_mod.base != BASE10)
{
++(*symbols);
if (mods.int_mod.base != BASE08)
++(*symbols);
}
if (num || mods.precision != 0)
*digits = count_digits(num, mods.int_mod.base);
if (mods.precision > *digits)
*zeros = mods.precision - *digits;
*num_len = *symbols + *digits + *zeros;
if (mods.width > *num_len)
*padding = mods.width - *num_len;
}
/**
* format_integers - handles formatting of hexadecimal integers.
* @num: the number to be formatted.
* @buffer: working buffer for `_printf`.
* @mods: modifier flags.
*
* Return: Returns a positive int on success, negative int on failure.
*/
int format_integers(uintmax_t num, char_arr *buffer, const modifiers mods)
{
char *wip_str = NULL;
int bytes_written = 0;
int num_len = 0, digits = 0, symbols = 0, zeros = 0, padding = 0;
init_lengths(num, mods, &num_len, &digits, &symbols, &zeros, &padding);
wip_str = malloc(padding + num_len + 1);
if (!wip_str)
{
buffer_flush(buffer);
return (-1);
}
_memset(wip_str, ' ', padding + num_len);
wip_str[padding + num_len] = '\0';
if (!mods.flags.left_adjust)
{
if (mods.flags.zero_padding && mods.precision < 0)
zeros += padding;
else
wip_str += padding;
}
insert_symbols(wip_str, num, mods);
_memset(wip_str + symbols, '0', zeros);
if (digits)
itostr(wip_str + symbols + zeros, num, mods.int_mod);
if (!mods.flags.left_adjust &&
!(mods.flags.zero_padding && mods.precision < 0))
wip_str -= padding;
bytes_written = buffer_puts(buffer, wip_str);
free(wip_str);
return (bytes_written);
}