Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: src/xz/util.c

Issue 7109015: Update XZ Utils to 5.0.3 (in deps) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/xz/
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/xz/util.h ('k') | src/xz/xz.1 » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /////////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////////
2 // 2 //
3 /// \file util.c 3 /// \file util.c
4 /// \brief Miscellaneous utility functions 4 /// \brief Miscellaneous utility functions
5 // 5 //
6 // Author: Lasse Collin 6 // Author: Lasse Collin
7 // 7 //
8 // This file has been put into the public domain. 8 // This file has been put into the public domain.
9 // You can do whatever you want with this file. 9 // You can do whatever you want with this file.
10 // 10 //
11 /////////////////////////////////////////////////////////////////////////////// 11 ///////////////////////////////////////////////////////////////////////////////
12 12
13 #include "private.h" 13 #include "private.h"
14 #include <stdarg.h> 14 #include <stdarg.h>
15 15
16 16
17 /// Buffers for uint64_to_str() and uint64_to_nicestr()
18 static char bufs[4][128];
19
20 /// Thousand separator support in uint64_to_str() and uint64_to_nicestr()
21 static enum { UNKNOWN, WORKS, BROKEN } thousand = UNKNOWN;
22
23
17 extern void * 24 extern void *
18 xrealloc(void *ptr, size_t size) 25 xrealloc(void *ptr, size_t size)
19 { 26 {
20 assert(size > 0); 27 assert(size > 0);
21 28
22 ptr = realloc(ptr, size); 29 ptr = realloc(ptr, size);
23 if (ptr == NULL) 30 if (ptr == NULL)
24 message_fatal("%s", strerror(errno)); 31 message_fatal("%s", strerror(errno));
25 32
26 return ptr; 33 return ptr;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 } 125 }
119 126
120 127
121 extern uint64_t 128 extern uint64_t
122 round_up_to_mib(uint64_t n) 129 round_up_to_mib(uint64_t n)
123 { 130 {
124 return (n >> 20) + ((n & ((UINT32_C(1) << 20) - 1)) != 0); 131 return (n >> 20) + ((n & ((UINT32_C(1) << 20) - 1)) != 0);
125 } 132 }
126 133
127 134
135 /// Check if thousand separator is supported. Run-time checking is easiest,
136 /// because it seems to be sometimes lacking even on POSIXish system.
137 static void
138 check_thousand_sep(uint32_t slot)
139 {
140 if (thousand == UNKNOWN) {
141 bufs[slot][0] = '\0';
142 snprintf(bufs[slot], sizeof(bufs[slot]), "%'u", 1U);
143 thousand = bufs[slot][0] == '1' ? WORKS : BROKEN;
144 }
145
146 return;
147 }
148
149
128 extern const char * 150 extern const char *
129 uint64_to_str(uint64_t value, uint32_t slot) 151 uint64_to_str(uint64_t value, uint32_t slot)
130 { 152 {
131 // 2^64 with thousand separators is 26 bytes plus trailing '\0'.
132 static char bufs[4][32];
133
134 assert(slot < ARRAY_SIZE(bufs)); 153 assert(slot < ARRAY_SIZE(bufs));
135 154
136 » static enum { UNKNOWN, WORKS, BROKEN } thousand = UNKNOWN; 155 » check_thousand_sep(slot);
137 » if (thousand == UNKNOWN) {
138 » » bufs[slot][0] = '\0';
139 » » snprintf(bufs[slot], sizeof(bufs[slot]), "%'" PRIu64,
140 » » » » UINT64_C(1));
141 » » thousand = bufs[slot][0] == '1' ? WORKS : BROKEN;
142 » }
143 156
144 if (thousand == WORKS) 157 if (thousand == WORKS)
145 snprintf(bufs[slot], sizeof(bufs[slot]), "%'" PRIu64, value); 158 snprintf(bufs[slot], sizeof(bufs[slot]), "%'" PRIu64, value);
146 else 159 else
147 snprintf(bufs[slot], sizeof(bufs[slot]), "%" PRIu64, value); 160 snprintf(bufs[slot], sizeof(bufs[slot]), "%" PRIu64, value);
148 161
149 return bufs[slot]; 162 return bufs[slot];
150 } 163 }
151 164
152 165
153 extern const char * 166 extern const char *
154 uint64_to_nicestr(uint64_t value, enum nicestr_unit unit_min, 167 uint64_to_nicestr(uint64_t value, enum nicestr_unit unit_min,
155 enum nicestr_unit unit_max, bool always_also_bytes, 168 enum nicestr_unit unit_max, bool always_also_bytes,
156 uint32_t slot) 169 uint32_t slot)
157 { 170 {
158 assert(unit_min <= unit_max); 171 assert(unit_min <= unit_max);
159 assert(unit_max <= NICESTR_TIB); 172 assert(unit_max <= NICESTR_TIB);
173 assert(slot < ARRAY_SIZE(bufs));
174
175 check_thousand_sep(slot);
160 176
161 enum nicestr_unit unit = NICESTR_B; 177 enum nicestr_unit unit = NICESTR_B;
162 » const char *str; 178 » char *pos = bufs[slot];
179 » size_t left = sizeof(bufs[slot]);
163 180
164 if ((unit_min == NICESTR_B && value < 10000) 181 if ((unit_min == NICESTR_B && value < 10000)
165 || unit_max == NICESTR_B) { 182 || unit_max == NICESTR_B) {
166 // The value is shown as bytes. 183 // The value is shown as bytes.
167 » » str = uint64_to_str(value, slot); 184 » » if (thousand == WORKS)
185 » » » my_snprintf(&pos, &left, "%'u", (unsigned int)value);
186 » » else
187 » » » my_snprintf(&pos, &left, "%u", (unsigned int)value);
168 } else { 188 } else {
169 // Scale the value to a nicer unit. Unless unit_min and 189 // Scale the value to a nicer unit. Unless unit_min and
170 // unit_max limit us, we will show at most five significant 190 // unit_max limit us, we will show at most five significant
171 // digits with one decimal place. 191 // digits with one decimal place.
172 double d = (double)(value); 192 double d = (double)(value);
173 do { 193 do {
174 d /= 1024.0; 194 d /= 1024.0;
175 ++unit; 195 ++unit;
176 } while (unit < unit_min || (d > 9999.9 && unit < unit_max)); 196 } while (unit < unit_min || (d > 9999.9 && unit < unit_max));
177 197
178 » » str = double_to_str(d); 198 » » if (thousand == WORKS)
199 » » » my_snprintf(&pos, &left, "%'.1f", d);
200 » » else
201 » » » my_snprintf(&pos, &left, "%.1f", d);
179 } 202 }
180 203
181 static const char suffix[5][4] = { "B", "KiB", "MiB", "GiB", "TiB" }; 204 static const char suffix[5][4] = { "B", "KiB", "MiB", "GiB", "TiB" };
205 my_snprintf(&pos, &left, " %s", suffix[unit]);
182 206
183 » // Minimum buffer size: 207 » if (always_also_bytes && value >= 10000) {
184 » // 26 2^64 with thousand separators 208 » » if (thousand == WORKS)
185 » // 4 " KiB" 209 » » » snprintf(pos, left, " (%'" PRIu64 " B)", value);
186 » // 2 " (" 210 » » else
187 » // 26 2^64 with thousand separators 211 » » » snprintf(pos, left, " (%" PRIu64 " B)", value);
188 » // 3 " B)" 212 » }
189 » // 1 '\0'
190 » // 62 Total
191 » static char buf[4][64];
192 » char *pos = buf[slot];
193 » size_t left = sizeof(buf[slot]);
194 » my_snprintf(&pos, &left, "%s %s", str, suffix[unit]);
195 213
196 » if (always_also_bytes && value >= 10000) 214 » return bufs[slot];
197 » » snprintf(pos, left, " (%s B)", uint64_to_str(value, slot));
198
199 » return buf[slot];
200 } 215 }
201 216
202 217
203 extern const char *
204 double_to_str(double value)
205 {
206 static char buf[64];
207
208 static enum { UNKNOWN, WORKS, BROKEN } thousand = UNKNOWN;
209 if (thousand == UNKNOWN) {
210 buf[0] = '\0';
211 snprintf(buf, sizeof(buf), "%'.1f", 2.0);
212 thousand = buf[0] == '2' ? WORKS : BROKEN;
213 }
214
215 if (thousand == WORKS)
216 snprintf(buf, sizeof(buf), "%'.1f", value);
217 else
218 snprintf(buf, sizeof(buf), "%.1f", value);
219
220 return buf;
221 }
222
223
224 extern void 218 extern void
225 my_snprintf(char **pos, size_t *left, const char *fmt, ...) 219 my_snprintf(char **pos, size_t *left, const char *fmt, ...)
226 { 220 {
227 va_list ap; 221 va_list ap;
228 va_start(ap, fmt); 222 va_start(ap, fmt);
229 const int len = vsnprintf(*pos, *left, fmt, ap); 223 const int len = vsnprintf(*pos, *left, fmt, ap);
230 va_end(ap); 224 va_end(ap);
231 225
232 // If an error occurred, we want the caller to think that the whole 226 // If an error occurred, we want the caller to think that the whole
233 // buffer was used. This way no more data will be written to the 227 // buffer was used. This way no more data will be written to the
234 » // buffer. We don't need better error handling here. 228 » // buffer. We don't need better error handling here, although it
229 » // is possible that the result looks garbage on the terminal if
230 » // e.g. an UTF-8 character gets split. That shouldn't (easily)
231 » // happen though, because the buffers used have some extra room.
235 if (len < 0 || (size_t)(len) >= *left) { 232 if (len < 0 || (size_t)(len) >= *left) {
236 *left = 0; 233 *left = 0;
237 } else { 234 } else {
238 *pos += len; 235 *pos += len;
239 *left -= len; 236 *left -= len;
240 } 237 }
241 238
242 return; 239 return;
243 } 240 }
244 241
245 242
246 /*
247 /// \brief Simple quoting to get rid of ASCII control characters
248 ///
249 /// This is not so cool and locale-dependent, but should be good enough
250 /// At least we don't print any control characters on the terminal.
251 ///
252 extern char *
253 str_quote(const char *str)
254 {
255 size_t dest_len = 0;
256 bool has_ctrl = false;
257
258 while (str[dest_len] != '\0')
259 if (*(unsigned char *)(str + dest_len++) < 0x20)
260 has_ctrl = true;
261
262 char *dest = malloc(dest_len + 1);
263 if (dest != NULL) {
264 if (has_ctrl) {
265 for (size_t i = 0; i < dest_len; ++i)
266 if (*(unsigned char *)(str + i) < 0x20)
267 dest[i] = '?';
268 else
269 dest[i] = str[i];
270
271 dest[dest_len] = '\0';
272
273 } else {
274 // Usually there are no control characters,
275 // so we can optimize.
276 memcpy(dest, str, dest_len + 1);
277 }
278 }
279
280 return dest;
281 }
282 */
283
284
285 extern bool 243 extern bool
286 is_empty_filename(const char *filename) 244 is_empty_filename(const char *filename)
287 { 245 {
288 if (filename[0] == '\0') { 246 if (filename[0] == '\0') {
289 message_error(_("Empty filename, skipping")); 247 message_error(_("Empty filename, skipping"));
290 return true; 248 return true;
291 } 249 }
292 250
293 return false; 251 return false;
294 } 252 }
(...skipping 16 matching lines...) Expand all
311 is_tty_stdout(void) 269 is_tty_stdout(void)
312 { 270 {
313 const bool ret = isatty(STDOUT_FILENO); 271 const bool ret = isatty(STDOUT_FILENO);
314 272
315 if (ret) 273 if (ret)
316 message_error(_("Compressed data cannot be written to " 274 message_error(_("Compressed data cannot be written to "
317 "a terminal")); 275 "a terminal"));
318 276
319 return ret; 277 return ret;
320 } 278 }
OLDNEW
« no previous file with comments | « src/xz/util.h ('k') | src/xz/xz.1 » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698