summaryrefslogtreecommitdiff
path: root/src/util.h
blob: c0973218effb6e4a053c06e39b4e6f1c79c4bcfb (plain)
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
#pragma once

#include <err.h>

static inline bool
is_hex(const char *str)
{
   return (strlen(str) > 2 && str[0] == '0' && str[1] == 'x');
}

static inline unsigned long long int
hexdecstrtoull(const char *str, char **endptr)
{
   return strtoull(str, endptr, (is_hex(str) ? 16 : 10));
}

struct region {
   size_t start, end, offset;
};

static inline bool
region_parse(struct region *region, const char *line)
{
   *region = (struct region){0};
   if (sscanf(line, "%zx-%zx %*s %zx", &region->start, &region->end, &region->offset) < 3 || region->start > region->end) {
      warnx("failed to parse mapping:\n%s", line);
      return false;
   }
   region->end = (region->end > 0 ? region->end - 1 : 0);
   return true;
}

static inline size_t
for_each_token_in_str(const char *str, const char token, void (*cb)(const char *line, void *data), void *data)
{
   size_t ate = 0;
   for (char *line = (char*)str, *nl; (nl = strchr(line, token)); line = nl + 1) {
      *nl = 0;
      cb(line, data);
      *nl = token;
      ate += nl + 1 - line;
   }
   return ate;
}

static inline void
for_each_token_in_file(FILE *f, const char token, void (*cb)(const char *line, void *data), void *data)
{
   char *buffer = NULL;
   const size_t step = 1024;
   size_t allocated = 0, written = 0, read = 0;
   do {
      if (written + read >= allocated && !(buffer = realloc(buffer, (allocated += step) + 1)))
         err(EXIT_FAILURE"realloc");

      buffer[(written += read)] = 0;
      const size_t ate = for_each_token_in_str(buffer, token, cb, data);
      memmove(buffer, buffer + ate, (written = written - ate));
   } while ((read = fread(buffer + written, 1, allocated - written, f)));

   if (written > 0)
      cb(buffer, data);

   free(buffer);
}