summaryrefslogtreecommitdiffstats
path: root/include/flat.h
blob: 17a1cc40ea95fba426ad76d62d6c300cfa80d0a6 (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
111
112
113
114
115
116
117
118
119
120
// flat.h - Directory traversal utility functions

#ifndef FLAT_H

#include <stdint.h>
#include <sys/stat.h>

char *flat_path(int, ...);
int64_t flat_directory_entry_count(char const *);
char **flat_directory_entries(char const *);

#define MKDIR(x) (mkdir(x, 0777))

#endif // FLAT_H

#ifdef FLAT_IMPLEMENTATION

#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#include <dirent.h>

char *flat_path(int s_n, ...) {
  va_list list;
  size_t c_n = 0;

  if (s_n < 1)
    return NULL;

  // First, measure the total length required.
  va_start(list, s_n);
  for (int i = 0; i < s_n; i++) {
    const char *s = va_arg(list, char *);
    c_n += strlen(s);
  }

  va_end(list);

  // Allocate return buffer.
  char *r = malloc(c_n + 1);
  if (r == NULL)
    return NULL;

  // Concatenate all the strings into the return buffer.
  char *d = r;
  va_start(list, s_n);

  for (int i = 0; i < s_n; i++) {
    const char *s = va_arg(list, char *);

    // This loop is a strcpy.
    while ((*d++ = *s++))
      ;
    d--;
  }

  va_end(list);
  return r;
}

int64_t flat_directory_entry_count(char const *path) {
  DIR *dir;
  struct dirent *ent;

  if (!(dir = opendir(path))) {
    return 0;
  }
  int64_t n = 0;

  while ((ent = readdir(dir))) {
    if (!strcmp(ent->d_name, "."))
      continue;

    if (!strcmp(ent->d_name, ".."))
      continue;

    n++;
  }

  closedir(dir);

  return n;
}

char **flat_directory_entries(char const *path) {
  int64_t n = flat_directory_entry_count(path);
  char **entries = calloc(n + 1, sizeof(char **));

  DIR *dir;
  struct dirent *ent;

  int64_t i = 0;
  int64_t entry_n = 0;

  if (!(dir = opendir(path))) {
    return NULL;
  }
  while (i < n) {
    ent = readdir(dir);

    if (!strcmp(ent->d_name, "."))
      continue;

    if (!strcmp(ent->d_name, ".."))
      continue;

    entry_n = strlen(ent->d_name);
    entries[i] = malloc(entry_n + 1);
    strcpy(entries[i], ent->d_name);

    i++;
  }

  closedir(dir);

  return entries;
}

#endif // FLAT_IMPELEMTATION