Branch data Line data Source code
1 : : #include "rational.h"
2 : : #include <stdio.h>
3 : :
4 : : /**
5 : : * @brief Convert bytes
6 : : *
7 : : */
8 : : static inline Byte tobyte(const size_t) __attribute__((always_inline));
9 : : static inline Byte tobyte(const size_t bytes)
10 : : {
11 : : /// Number of bytes in a kibibyte
12 : : /// 1024
13 : 1186 : const size_t bytes_in_kibibyte = 1024ULL;
14 : :
15 : : /// Number of bytes in a mebibyte
16 : : /// 1024*1024
17 : 1186 : const size_t bytes_in_mebibyte = bytes_in_kibibyte * 1024ULL;
18 : :
19 : : /// Number of bytes in a gibibyte
20 : : /// 1024*1024*1024
21 : 1186 : const size_t bytes_in_gibibyte = bytes_in_mebibyte * 1024ULL;
22 : :
23 : : /// Number of bytes in a tebibyte
24 : : /// 1024*1024*1024*1024
25 : 1186 : const size_t bytes_in_tebibyte = bytes_in_gibibyte * 1024ULL;
26 : :
27 : : /// Number of bytes in a pebibyte
28 : : /// 1024*1024*1024*1024*1024
29 : 1186 : const size_t bytes_in_pebibyte = bytes_in_tebibyte * 1024ULL;
30 : :
31 : : /// Number of bytes in an exbibyte
32 : : /// 1024*1024*1024*1024*1024*1024
33 : 1186 : const size_t bytes_in_exbibyte = bytes_in_pebibyte * 1024ULL;
34 : :
35 : : /*
36 : : *
37 : : * Fill out the corresponding values of the structure
38 : : *
39 : : */
40 : :
41 : : // Initializing of the structure that will be returned
42 : : // from the function
43 : 1186 : Byte byte = {0};
44 : :
45 : 1186 : byte.exbibytes = bytes/bytes_in_exbibyte;
46 : :
47 : 1186 : const size_t exbibytes = byte.exbibytes*bytes_in_exbibyte;
48 : 1186 : byte.pebibytes = (bytes - exbibytes)/bytes_in_pebibyte;
49 : :
50 : 1186 : const size_t pebibytes = byte.pebibytes*bytes_in_pebibyte;
51 : 1186 : byte.tebibytes = (bytes - exbibytes - pebibytes)/bytes_in_tebibyte;
52 : :
53 : 1186 : const size_t tebibytes = byte.tebibytes*bytes_in_tebibyte;
54 : 1186 : byte.gibibytes = (bytes - exbibytes - pebibytes - tebibytes)/bytes_in_gibibyte;
55 : :
56 : 1186 : const size_t gibibytes = byte.gibibytes*bytes_in_gibibyte;
57 : 1186 : byte.mebibytes = (bytes - exbibytes - pebibytes - tebibytes - gibibytes)/bytes_in_mebibyte;
58 : :
59 : 1186 : const size_t mebibytes = byte.mebibytes*bytes_in_mebibyte;
60 : 1186 : byte.kibibytes = (bytes - exbibytes - pebibytes - tebibytes - gibibytes - mebibytes)/bytes_in_kibibyte;
61 : :
62 : 1186 : const size_t kibibytes = byte.kibibytes*bytes_in_kibibyte;
63 : 1186 : byte.bytes = (bytes - exbibytes - pebibytes - tebibytes - gibibytes - mebibytes - kibibytes);
64 : :
65 : 1186 : return(byte);
66 : : }
67 : :
68 : : /**
69 : : * @brief Append one non-zero unit to the resulting size string.
70 : : *
71 : : * @param result Output string being built.
72 : : * @param result_size Size of the output buffer.
73 : : * @param used_len Current used length of the output buffer.
74 : : * @param bytes Unit value to append when it is non-zero.
75 : : * @param suffix Unit suffix (B, KiB, MiB, GiB, TiB, PiB, EiB).
76 : : */
77 : 5812 : static void catbyte_r(
78 : : char *const result,
79 : : const size_t result_size,
80 : : size_t *const used_len,
81 : : const size_t bytes,
82 : : const char *const suffix)
83 : : {
84 [ + + + + ]: 5812 : if(bytes == 0ULL || *used_len >= result_size)
85 : : {
86 : 3896 : return;
87 : : }
88 : :
89 : 1916 : const int written = snprintf(result + *used_len,result_size - *used_len,"%zu%s ",bytes,suffix);
90 : :
91 [ + + ]: 1916 : if(written < 0)
92 : : {
93 : 1 : return;
94 : : }
95 : :
96 : 1915 : const size_t write_size = (size_t)written;
97 : :
98 [ + + ]: 1915 : if(write_size >= result_size - *used_len)
99 : : {
100 : : /*
101 : : * snprintf() has already written the largest prefix that fits.
102 : : * Mark the buffer as full so later units do not try to append text
103 : : */
104 : 5 : *used_len = result_size;
105 : 5 : result[result_size - 1ULL] = '\0';
106 : :
107 : : /*
108 : : * If the visible prefix ends right after a unit separator, hide that
109 : : * separator so callers get a clean partial value
110 : : */
111 [ + + + + ]: 5 : if(result_size > 1ULL && result[result_size - 2ULL] == ' ')
112 : : {
113 : 1 : result[result_size - 2ULL] = '\0';
114 : : }
115 : : } else {
116 : 1910 : *used_len += write_size;
117 : : }
118 : : }
119 : :
120 : : /**
121 : : * @brief Convert bytes to a human-readable size string in caller-provided buffer.
122 : : *
123 : : * @details Convert number of bytes to human-readable string:
124 : : * B - Byte
125 : : * KiB - Kibibyte
126 : : * MiB - Mebibyte
127 : : * GiB - Gibibyte
128 : : * TiB - Tebibyte
129 : : * PiB - Pebibyte
130 : : * EiB - Exbibyte
131 : : *
132 : : * @param bytes Number of bytes to format.
133 : : * @param format Output style:
134 : : * - FULL_VIEW: show all non-zero units.
135 : : * - MAJOR_VIEW: show only the highest non-zero unit.
136 : : * @param buffer Destination buffer.
137 : : * @param buffer_size Destination buffer size in bytes.
138 : : * @return @p buffer on success, NULL when @p buffer is NULL or @p buffer_size is zero.
139 : : */
140 : 1238 : char *bkbmbgbtbpbeb_r(
141 : : const size_t bytes,
142 : : const ByteFormat format,
143 : : char *buffer,
144 : : const size_t buffer_size)
145 : : {
146 [ + + + + ]: 1238 : if(buffer == NULL || buffer_size == 0ULL)
147 : : {
148 : 2 : return(NULL);
149 : : }
150 : :
151 : 1236 : buffer[0] = '\0';
152 : 1236 : size_t used_len = 0ULL;
153 : :
154 : : // If the number passed is 0 Bytes
155 [ + + ]: 1236 : if(bytes == 0ULL)
156 : : {
157 : 50 : (void)snprintf(buffer,buffer_size,"0B");
158 : 50 : return(buffer);
159 : : }
160 : :
161 : : Byte byte = tobyte(bytes);
162 : :
163 [ + + ]: 1186 : if(format == MAJOR_VIEW)
164 : : {
165 [ + + ]: 415 : if(byte.exbibytes > 0ULL)
166 : : {
167 : 1 : catbyte_r(buffer,buffer_size,&used_len,byte.exbibytes,"EiB");
168 [ + + ]: 414 : } else if(byte.pebibytes > 0ULL){
169 : 1 : catbyte_r(buffer,buffer_size,&used_len,byte.pebibytes,"PiB");
170 [ + + ]: 413 : } else if(byte.tebibytes > 0ULL){
171 : 1 : catbyte_r(buffer,buffer_size,&used_len,byte.tebibytes,"TiB");
172 [ + + ]: 412 : } else if(byte.gibibytes > 0ULL){
173 : 2 : catbyte_r(buffer,buffer_size,&used_len,byte.gibibytes,"GiB");
174 [ + + ]: 410 : } else if(byte.mebibytes > 0ULL){
175 : 112 : catbyte_r(buffer,buffer_size,&used_len,byte.mebibytes,"MiB");
176 [ + + ]: 298 : } else if(byte.kibibytes > 0ULL){
177 : 110 : catbyte_r(buffer,buffer_size,&used_len,byte.kibibytes,"KiB");
178 : : } else {
179 : 188 : catbyte_r(buffer,buffer_size,&used_len,byte.bytes,"B");
180 : : }
181 : :
182 : : } else {
183 : 771 : catbyte_r(buffer,buffer_size,&used_len,byte.exbibytes,"EiB");
184 : 771 : catbyte_r(buffer,buffer_size,&used_len,byte.pebibytes,"PiB");
185 : 771 : catbyte_r(buffer,buffer_size,&used_len,byte.tebibytes,"TiB");
186 : 771 : catbyte_r(buffer,buffer_size,&used_len,byte.gibibytes,"GiB");
187 : 771 : catbyte_r(buffer,buffer_size,&used_len,byte.mebibytes,"MiB");
188 : 771 : catbyte_r(buffer,buffer_size,&used_len,byte.kibibytes,"KiB");
189 : 771 : catbyte_r(buffer,buffer_size,&used_len,byte.bytes,"B");
190 : : }
191 : :
192 [ + + + + ]: 1186 : if(used_len > 0ULL && buffer[used_len - 1ULL] == ' ')
193 : : {
194 : 1180 : buffer[used_len - 1ULL] = '\0';
195 : : }
196 : :
197 : 1186 : return(buffer);
198 : : }
199 : :
200 : : /**
201 : : * @brief Convert bytes to a human-readable size string.
202 : : *
203 : : * @param bytes Number of bytes to format.
204 : : * @param format Output style:
205 : : * - FULL_VIEW: show all non-zero units.
206 : : * - MAJOR_VIEW: show only the highest non-zero unit.
207 : : * @return Pointer to a static buffer with formatted text.
208 : : */
209 : 958 : char *bkbmbgbtbpbeb(
210 : : const size_t bytes,
211 : : const ByteFormat format)
212 : : {
213 : : // Zero out a static memory area with a string array
214 : : static char result[MAX_CHARACTERS] = {0};
215 : :
216 : 958 : (void)bkbmbgbtbpbeb_r(bytes,format,result,sizeof(result));
217 : :
218 : 958 : return(result);
219 : : }
220 : : #if 0
221 : : /// Test
222 : : /// 4617322122555958282 = ((1024*1024*1024*1024*1024*1024)*4)+((1024*1024*1024*1024*1024)*5)+((1024*1024*1024*1024)*6)+((1024*1024*1024)*7)+((1024*1024)*8)+((1024)*9)+10
223 : : /// Should be 4EiB 5PiB 6TiB 7GiB 8MiB 9KiB 10B
224 : : int main(void)
225 : : {
226 : : const size_t bytes = 4617322122555958282ULL;
227 : : printf("%s\n",bkbmbgbtbpbeb(bytes,FULL_VIEW));
228 : : return 0;
229 : : }
230 : : #endif
|