aboutsummaryrefslogtreecommitdiff
path: root/lib.c
blob: 0c3f4f9a043cbd63fd1ce3035c91a95b227845e1 (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
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
/* lib.c
 * Created: 2023-09-02
 * Author: Aryadev Chavali
 * Description: General functions used throughout
 */

#include <string.h>

#include "./lib.h"

buffer_t *buffer_init_str(const char *name, const char *str, size_t str_size)
{
  buffer_t *buf = malloc(sizeof(*buf) + str_size + 1);
  buf->name     = name;
  buf->size     = str_size;
  buf->capacity = str_size;
  if (str)
  {
    memcpy(buf->data, str, str_size);
    buf->data[str_size] = '\0';
  }
  return buf;
}

bool buffer_ensure(buffer_t **buffer, u64 expected)
{
  if (!buffer)
    return false;
  else if (!*buffer)
  {
    *buffer = buffer_init_str(NULL, NULL, expected);
  }
  else if (buffer[0]->capacity <= expected)
  {
    buffer[0]->capacity = MAX(buffer[0]->capacity * 2, expected);
    *buffer = realloc(*buffer, sizeof(**buffer) + buffer[0]->capacity);
  }
  return true;
}

bool buffer_ensure_relative(buffer_t **buffer, u64 expected)
{
  return buffer_ensure(buffer,
                       buffer && *buffer ? buffer[0]->size + expected : 0);
}

bool buffer_append(buffer_t **buffer, u8 datum)
{
  bool ret = buffer_ensure_relative(buffer, 1);
  if (ret)
    buffer[0]->data[buffer[0]->size++] = datum;
  return ret;
}

bool buffer_append_bytes(buffer_t **buffer, u8 *data, u64 size)
{
  bool ret = buffer_ensure_relative(buffer, size);
  if (ret)
  {
    memcpy(buffer[0]->data + buffer[0]->size, data, size);
    buffer[0]->size += size;
  }
  return ret;
}

void print_error(const char *handle, size_t row, size_t column,
                 const char *reason)
{
  fprintf(stderr, "%s:%lu:%lu:%s\n", handle, row, column, reason);
}

char *fread_all(FILE *fp)
{
  const size_t CHUNK_SIZE = 1024, MULT = 2;
  struct
  {
    char *data;
    size_t used, available;
  } buffer = {calloc(CHUNK_SIZE, sizeof(*buffer.data)), 0, CHUNK_SIZE};

  if (!buffer.data)
  {
    print_error(
        "[internal]", 0, 0,
        "ERROR: Out of Memory (could not allocate buffer in fread_all)");
    return NULL;
  }

  size_t acc = 0, bytes_read = 0;
  while ((bytes_read = fread(buffer.data + acc, sizeof(*buffer.data),
                             CHUNK_SIZE, fp)) != 0)
  {
    buffer.used += bytes_read;
    acc += bytes_read;
    if (buffer.used + CHUNK_SIZE >= buffer.available)
    {
      buffer.available = MAX(buffer.available * MULT, buffer.used + CHUNK_SIZE);
      buffer.data      = realloc(buffer.data, buffer.available);
    }
  }
  buffer.data              = realloc(buffer.data, buffer.used + 1);
  buffer.data[buffer.used] = '\0';
  return buffer.data;
}

bool usable_character(char c)
{
  return c == '>' || c == '<' || c == '+' || c == '-' || c == '-' || c == '.' ||
         c == ',' || c == '[' || c == ']';
}