Rizin
unix-like reverse engineering framework and cli tools
util.c File Reference

Miscellaneous utility functions. More...

#include "private.h"
#include <stdarg.h>

Go to the source code of this file.

Enumerations

enum  { UNKNOWN , WORKS , BROKEN }
 Thousand separator support in uint64_to_str() and uint64_to_nicestr() More...
 

Functions

void * xrealloc (void *ptr, size_t size)
 Safe realloc() that never returns NULL. More...
 
char * xstrdup (const char *src)
 Safe strdup() that never returns NULL. More...
 
uint64_t str_to_uint64 (const char *name, const char *value, uint64_t min, uint64_t max)
 Fancy version of strtoull() More...
 
uint64_t round_up_to_mib (uint64_t n)
 Round an integer up to the next full MiB and convert to MiB. More...
 
static void check_thousand_sep (uint32_t slot)
 
const char * uint64_to_str (uint64_t value, uint32_t slot)
 Convert uint64_t to a string. More...
 
const char * uint64_to_nicestr (uint64_t value, enum nicestr_unit unit_min, enum nicestr_unit unit_max, bool always_also_bytes, uint32_t slot)
 Convert uint64_t to a nice human readable string. More...
 
void my_snprintf (char **pos, size_t *left, const char *fmt,...)
 
bool is_empty_filename (const char *filename)
 Check if filename is empty and print an error message. More...
 
bool is_tty_stdin (void)
 Test if stdin is a terminal. More...
 
bool is_tty_stdout (void)
 Test if stdout is a terminal. More...
 

Variables

static char bufs [4][128]
 Buffers for uint64_to_str() and uint64_to_nicestr() More...
 
static enum { ... }  thousand = UNKNOWN
 Thousand separator support in uint64_to_str() and uint64_to_nicestr() More...
 

Detailed Description

Miscellaneous utility functions.

Definition in file util.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Thousand separator support in uint64_to_str() and uint64_to_nicestr()

Enumerator
UNKNOWN 
WORKS 
BROKEN 

Definition at line 21 of file util.c.

static enum @663 thousand
Thousand separator support in uint64_to_str() and uint64_to_nicestr()
@ UNKNOWN
Definition: util.c:21
@ WORKS
Definition: util.c:21
@ BROKEN
Definition: util.c:21

Function Documentation

◆ check_thousand_sep()

static void check_thousand_sep ( uint32_t  slot)
static

Check if thousands separator is supported. Run-time checking is easiest because it seems to be sometimes lacking even on a POSIXish system. Note that trying to use thousands separators when snprintf() doesn't support them results in undefined behavior. This just has happened to work well enough in practice.

DJGPP 2.05 added support for thousands separators but it's broken at least under WinXP with Finnish locale that uses a non-breaking space as the thousands separator. Workaround by disabling thousands separators for DJGPP builds.

Definition at line 156 of file util.c.

157 {
158  if (thousand == UNKNOWN) {
159  bufs[slot][0] = '\0';
160 #ifndef __DJGPP__
161  snprintf(bufs[slot], sizeof(bufs[slot]), "%'u", 1U);
162 #endif
163  thousand = bufs[slot][0] == '1' ? WORKS : BROKEN;
164  }
165 
166  return;
167 }
snprintf
Definition: kernel.h:364
static char bufs[4][128]
Buffers for uint64_to_str() and uint64_to_nicestr()
Definition: util.c:18

References BROKEN, bufs, snprintf, thousand, UNKNOWN, and WORKS.

Referenced by uint64_to_nicestr(), and uint64_to_str().

◆ is_empty_filename()

bool is_empty_filename ( const char *  filename)

Check if filename is empty and print an error message.

Definition at line 264 of file util.c.

265 {
266  if (filename[0] == '\0') {
267  message_error(_("Empty filename, skipping"));
268  return true;
269  }
270 
271  return false;
272 }
const char * filename
Definition: ioapi.h:137
void message_error(const char *fmt,...)
Definition: message.c:764
#define _(String)
Definition: opintl.h:53

References _, and message_error().

Referenced by io_open_src().

◆ is_tty_stdin()

bool is_tty_stdin ( void  )

Test if stdin is a terminal.

If stdin is a terminal, an error message is printed and exit status set to EXIT_ERROR.

Definition at line 276 of file util.c.

277 {
278  const bool ret = isatty(STDIN_FILENO);
279 
280  if (ret)
281  message_error(_("Compressed data cannot be read from "
282  "a terminal"));
283 
284  return ret;
285 }
#define STDIN_FILENO
Definition: private.h:37

References _, message_error(), and STDIN_FILENO.

Referenced by main().

◆ is_tty_stdout()

bool is_tty_stdout ( void  )

Test if stdout is a terminal.

If stdout is a terminal, an error message is printed and exit status set to EXIT_ERROR.

Definition at line 289 of file util.c.

290 {
291  const bool ret = isatty(STDOUT_FILENO);
292 
293  if (ret)
294  message_error(_("Compressed data cannot be written to "
295  "a terminal"));
296 
297  return ret;
298 }
#define STDOUT_FILENO
Definition: private.h:41

References _, message_error(), and STDOUT_FILENO.

Referenced by main().

◆ my_snprintf()

void my_snprintf ( char **  pos,
size_t left,
const char *  fmt,
  ... 
)

Definition at line 239 of file util.c.

240 {
241  va_list ap;
242  va_start(ap, fmt);
243  const int len = vsnprintf(*pos, *left, fmt, ap);
244  va_end(ap);
245 
246  // If an error occurred, we want the caller to think that the whole
247  // buffer was used. This way no more data will be written to the
248  // buffer. We don't need better error handling here, although it
249  // is possible that the result looks garbage on the terminal if
250  // e.g. an UTF-8 character gets split. That shouldn't (easily)
251  // happen though, because the buffers used have some extra room.
252  if (len < 0 || (size_t)(len) >= *left) {
253  *left = 0;
254  } else {
255  *pos += len;
256  *left -= (size_t)(len);
257  }
258 
259  return;
260 }
size_t len
Definition: 6502dis.c:15
vsnprintf
Definition: kernel.h:366
int size_t
Definition: sftypes.h:40
int pos
Definition: main.c:11

References len, pos, and vsnprintf.

Referenced by get_check_names(), message_filters_to_str(), progress_sizes(), and uint64_to_nicestr().

◆ round_up_to_mib()

uint64_t round_up_to_mib ( uint64_t  n)

Round an integer up to the next full MiB and convert to MiB.

This is used when printing memory usage and limit.

Definition at line 139 of file util.c.

140 {
141  return (n >> 20) + ((n & ((UINT32_C(1) << 20) - 1)) != 0);
142 }
int n
Definition: mipsasm.c:19
#define UINT32_C(val)

References n, and UINT32_C.

Referenced by coder_init(), memlimit_show(), message_mem_needed(), print_info_adv(), and print_totals_adv().

◆ str_to_uint64()

uint64_t str_to_uint64 ( const char *  name,
const char *  value,
uint64_t  min,
uint64_t  max 
)

Fancy version of strtoull()

Parameters
nameName of the option to show in case of an error
valueString containing the number to be parsed; may contain suffixes "k", "M", "G", "Ki", "Mi", or "Gi"
minMinimum valid value
maxMaximum valid value
Returns
Parsed value that is in the range [min, max]. Does not return if an error occurs.

Definition at line 58 of file util.c.

59 {
60  uint64_t result = 0;
61 
62  // Skip blanks.
63  while (*value == ' ' || *value == '\t')
64  ++value;
65 
66  // Accept special value "max". Supporting "min" doesn't seem useful.
67  if (strcmp(value, "max") == 0)
68  return max;
69 
70  if (*value < '0' || *value > '9')
71  message_fatal(_("%s: Value is not a non-negative "
72  "decimal integer"), value);
73 
74  do {
75  // Don't overflow.
76  if (result > UINT64_MAX / 10)
77  goto error;
78 
79  result *= 10;
80 
81  // Another overflow check
82  const uint32_t add = (uint32_t)(*value - '0');
83  if (UINT64_MAX - add < result)
84  goto error;
85 
86  result += add;
87  ++value;
88  } while (*value >= '0' && *value <= '9');
89 
90  if (*value != '\0') {
91  // Look for suffix. Originally this supported both base-2
92  // and base-10, but since there seems to be little need
93  // for base-10 in this program, treat everything as base-2
94  // and also be more relaxed about the case of the first
95  // letter of the suffix.
96  uint64_t multiplier = 0;
97  if (*value == 'k' || *value == 'K')
98  multiplier = UINT64_C(1) << 10;
99  else if (*value == 'm' || *value == 'M')
100  multiplier = UINT64_C(1) << 20;
101  else if (*value == 'g' || *value == 'G')
102  multiplier = UINT64_C(1) << 30;
103 
104  ++value;
105 
106  // Allow also e.g. Ki, KiB, and KB.
107  if (*value != '\0' && strcmp(value, "i") != 0
108  && strcmp(value, "iB") != 0
109  && strcmp(value, "B") != 0)
110  multiplier = 0;
111 
112  if (multiplier == 0) {
113  message(V_ERROR, _("%s: Invalid multiplier suffix"),
114  value - 1);
115  message_fatal(_("Valid suffixes are `KiB' (2^10), "
116  "`MiB' (2^20), and `GiB' (2^30)."));
117  }
118 
119  // Don't overflow here either.
120  if (result > UINT64_MAX / multiplier)
121  goto error;
122 
123  result *= multiplier;
124  }
125 
126  if (result < min || result > max)
127  goto error;
128 
129  return result;
130 
131 error:
132  message_fatal(_("Value of the option `%s' must be in the range "
133  "[%" PRIu64 ", %" PRIu64 "]"),
134  name, min, max);
135 }
static int value
Definition: cmd_api.c:93
int max
Definition: enough.c:225
#define PRIu64
Definition: macros.h:18
void message_fatal(const char *fmt,...)
Definition: message.c:777
@ V_ERROR
Only error messages.
Definition: message.h:16
#define min(a, b)
Definition: qsort.h:83
unsigned int uint32_t
Definition: sftypes.h:29
unsigned long uint64_t
Definition: sftypes.h:28
#define UINT64_MAX
#define UINT64_C(val)
Definition: z80asm.h:102
char * message
Definition: main.c:12
void error(const char *msg)
Definition: untgz.c:593
static int add(char *argv[])
Definition: ziptool.c:84

References _, add(), error(), max, message, message_fatal(), min, PRIu64, UINT64_C, UINT64_MAX, V_ERROR, and value.

Referenced by parse_block_list(), parse_memlimit(), parse_options(), and parse_real().

◆ uint64_to_nicestr()

const char* uint64_to_nicestr ( uint64_t  value,
enum nicestr_unit  unit_min,
enum nicestr_unit  unit_max,
bool  always_also_bytes,
uint32_t  slot 
)

Convert uint64_t to a nice human readable string.

This is like uint64_to_str() but uses B, KiB, MiB, GiB, or TiB suffix and optionally includes the exact size in parenthesis.

Parameters
valueValue to be printed
unit_minSmallest unit to use. This and unit_max are used e.g. when showing the progress indicator to force the unit to MiB.
unit_maxBiggest unit to use. assert(unit_min <= unit_max).
always_also_bytesShow also the exact byte value in parenthesis if the nicely formatted string uses bigger unit than bytes.
slotWhich static buffer to use to hold the string. This is shared with uint64_to_str().
Returns
Pointer to statically allocated buffer containing the string.
Note
This uses double_to_str() internally so the static buffer in double_to_str() will be overwritten.

Definition at line 187 of file util.c.

190 {
191  assert(unit_min <= unit_max);
192  assert(unit_max <= NICESTR_TIB);
193  assert(slot < ARRAY_SIZE(bufs));
194 
195  check_thousand_sep(slot);
196 
197  enum nicestr_unit unit = NICESTR_B;
198  char *pos = bufs[slot];
199  size_t left = sizeof(bufs[slot]);
200 
201  if ((unit_min == NICESTR_B && value < 10000)
202  || unit_max == NICESTR_B) {
203  // The value is shown as bytes.
204  if (thousand == WORKS)
205  my_snprintf(&pos, &left, "%'u", (unsigned int)value);
206  else
207  my_snprintf(&pos, &left, "%u", (unsigned int)value);
208  } else {
209  // Scale the value to a nicer unit. Unless unit_min and
210  // unit_max limit us, we will show at most five significant
211  // digits with one decimal place.
212  double d = (double)(value);
213  do {
214  d /= 1024.0;
215  ++unit;
216  } while (unit < unit_min || (d > 9999.9 && unit < unit_max));
217 
218  if (thousand == WORKS)
219  my_snprintf(&pos, &left, "%'.1f", d);
220  else
221  my_snprintf(&pos, &left, "%.1f", d);
222  }
223 
224  static const char suffix[5][4] = { "B", "KiB", "MiB", "GiB", "TiB" };
225  my_snprintf(&pos, &left, " %s", suffix[unit]);
226 
227  if (always_also_bytes && value >= 10000) {
228  if (thousand == WORKS)
229  snprintf(pos, left, " (%'" PRIu64 " B)", value);
230  else
231  snprintf(pos, left, " (%" PRIu64 " B)", value);
232  }
233 
234  return bufs[slot];
235 }
#define ARRAY_SIZE(a)
unsigned char suffix[65536]
Definition: gun.c:164
assert(limit<=UINT32_MAX/2)
#define d(i)
Definition: sha256.c:44
void my_snprintf(char **pos, size_t *left, const char *fmt,...)
Definition: util.c:239
static void check_thousand_sep(uint32_t slot)
Definition: util.c:156
nicestr_unit
Definition: util.h:64
@ NICESTR_B
Definition: util.h:65
@ NICESTR_TIB
Definition: util.h:69

References ARRAY_SIZE, assert(), bufs, check_thousand_sep(), d, my_snprintf(), NICESTR_B, NICESTR_TIB, pos, PRIu64, snprintf, suffix, thousand, value, and WORKS.

Referenced by print_adv_helper(), print_info_basic(), print_totals_basic(), and progress_sizes().

◆ uint64_to_str()

const char* uint64_to_str ( uint64_t  value,
uint32_t  slot 
)

Convert uint64_t to a string.

Convert the given value to a string with locale-specific thousand separators, if supported by the snprintf() implementation. The string is stored into an internal static buffer indicated by the slot argument. A pointer to the selected buffer is returned.

This function exists, because non-POSIX systems don't support thousand separator in format strings. Solving the problem in a simple way doesn't work, because it breaks gettext (specifically, the xgettext tool).

Definition at line 171 of file util.c.

172 {
173  assert(slot < ARRAY_SIZE(bufs));
174 
175  check_thousand_sep(slot);
176 
177  if (thousand == WORKS)
178  snprintf(bufs[slot], sizeof(bufs[slot]), "%'" PRIu64, value);
179  else
180  snprintf(bufs[slot], sizeof(bufs[slot]), "%" PRIu64, value);
181 
182  return bufs[slot];
183 }

References ARRAY_SIZE, assert(), bufs, check_thousand_sep(), PRIu64, snprintf, thousand, value, and WORKS.

Referenced by coder_init(), memlimit_show(), message_mem_needed(), print_adv_helper(), print_info_adv(), print_info_basic(), print_totals_adv(), and print_totals_basic().

◆ xrealloc()

void* xrealloc ( void *  ptr,
size_t  size 
)

Safe realloc() that never returns NULL.

Definition at line 25 of file util.c.

26 {
27  assert(size > 0);
28 
29  // Save ptr so that we can free it if realloc fails.
30  // The point is that message_fatal ends up calling stdio functions
31  // which in some libc implementations might allocate memory from
32  // the heap. Freeing ptr improves the chances that there's free
33  // memory for stdio functions if they need it.
34  void *p = ptr;
35  ptr = realloc(ptr, size);
36 
37  if (ptr == NULL) {
38  const int saved_errno = errno;
39  free(p);
40  message_fatal("%s", strerror(saved_errno));
41  }
42 
43  return ptr;
44 }
#define NULL
Definition: cris-opc.c:27
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
void * p
Definition: libc.cpp:67
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144

References assert(), free(), message_fatal(), NULL, p, and realloc().

Referenced by read_name().

◆ xstrdup()

char* xstrdup ( const char *  src)

Safe strdup() that never returns NULL.

Definition at line 48 of file util.c.

49 {
50  assert(src != NULL);
51  const size_t size = strlen(src) + 1;
52  char *dest = xmalloc(size);
53  return memcpy(dest, src, size);
54 }
lzma_index * src
Definition: index.h:567
#define xmalloc
Definition: disas-asm.h:43
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
char * dest
Definition: lz4.h:697

References assert(), dest, memcpy(), NULL, src, and xmalloc.

Referenced by parse_environment(), parse_options(), and suffix_set().

Variable Documentation

◆ bufs

◆ 

enum { ... } thousand

Thousand separator support in uint64_to_str() and uint64_to_nicestr()

Referenced by check_thousand_sep(), uint64_to_nicestr(), and uint64_to_str().