Skip to content

Commit 2897413

Browse files
committed
Add new examples showcasing Ext_Array and Ext_HashMap/Ext_Entry macros
1 parent cf90ef6 commit 2897413

3 files changed

Lines changed: 189 additions & 1 deletion

File tree

Makefile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ LDFLAGS ?=
66
all: examples
77

88
.PHONY: examples
9-
examples: examples/01_dynamic_array examples/02_hashmap examples/03_arena examples/03_arena.wasm examples/04_cat examples/05_ls
9+
examples: examples/01_dynamic_array \
10+
examples/01_inline_dynamic_array \
11+
examples/02_hashmap \
12+
examples/02_inline_hashmap \
13+
examples/03_arena \
14+
examples/03_arena.wasm \
15+
examples/04_cat \
16+
examples/05_ls
1017

1118
examples/%: examples/%.c extlib.h
1219
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@

examples/01_inline_dynamic_array.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Example: Inline Dynamic arrays
3+
* Same example as `01_dynamic_array`, but uses macros to define the array struct layout in-line.
4+
*/
5+
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
9+
#define EXTLIB_IMPL
10+
#include "../extlib.h"
11+
12+
static int qsort_cmp(const void *a, const void *b) {
13+
return ss_cmp(ss_trim(*(StringSlice *)a), ss_trim(*(StringSlice *)b));
14+
}
15+
16+
int main(void) {
17+
Array(StringSlice) lines = {0};
18+
StringBuffer file = {0};
19+
20+
int res;
21+
while((res = read_line(stdin, &file)) > 0);
22+
if(res < 0) return 1;
23+
24+
StringSlice ss = sb_to_ss(file);
25+
while(ss.size) {
26+
StringSlice line = ss_split_once(&ss, '\n');
27+
if(ss_trim(line).size == 0) continue;
28+
ext_array_push(&lines, line);
29+
}
30+
31+
qsort(lines.items, lines.size, sizeof(*lines.items), qsort_cmp);
32+
array_foreach(StringSlice, line, &lines) {
33+
printf(SS_Fmt "\n", SS_Arg(*line));
34+
}
35+
36+
array_free(&lines);
37+
sb_free(&file);
38+
return 0;
39+
}

examples/02_inline_hashmap.c

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/**
2+
* Example: Inline hashmap
3+
* Same example as `02_hashmap`, but uses macros to define the hashmap struct layout in-line.
4+
*/
5+
6+
#include <stddef.h>
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
#include <string.h>
10+
11+
#define EXTLIB_IMPL
12+
#include "../extlib.h"
13+
14+
#define HIST_DEF 80
15+
16+
#define shift(argc, argv) ((argc)--, *(argv)++)
17+
18+
const char *symbols = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
19+
20+
typedef Entry(StringSlice, size_t) WordFreq;
21+
22+
static bool reverse;
23+
24+
static int qsort_cmp(const void *a, const void *b) {
25+
const WordFreq *e1 = a, *e2 = b;
26+
if(e1->value < e2->value) return reverse ? -1 : 1;
27+
if(e1->value > e2->value) return reverse ? 1 : -1;
28+
return 0;
29+
}
30+
31+
static void usage(const char *prog) {
32+
fprintf(stderr, "USAGE: %s [OPTIONS] [path]\n", prog);
33+
fprintf(stderr, "OPTIONS\n");
34+
fprintf(stderr,
35+
" -h <number> print word frequency as a histogram. <number> is the maximum column "
36+
"width, and must be > 0\n");
37+
fprintf(stderr, " -r print the statistics in reverse order (ascending)\n");
38+
}
39+
40+
int main(int argc, char **argv) {
41+
char *prog = shift(argc, argv);
42+
int hist = 0;
43+
44+
int npos = 0;
45+
for(int i = 0; i < argc; i++) {
46+
char *arg = argv[i];
47+
if(strcmp("--", arg) == 0) {
48+
for(int j = i + 1; j < argc; j++) argv[npos++] = argv[j];
49+
break;
50+
}
51+
52+
size_t arglen = strlen(arg);
53+
if(arglen <= 1 || *arg != '-') {
54+
argv[npos++] = arg;
55+
continue;
56+
}
57+
58+
char opt = arg[1];
59+
switch(opt) {
60+
case 'h':
61+
hist = HIST_DEF;
62+
if(i + 1 >= argc) break; // last argument
63+
64+
char *endptr;
65+
long ncols = strtol(argv[i + 1], &endptr, 10);
66+
if(*endptr != '\0') break; // next argument is not an integer; stick with default cols
67+
i++;
68+
69+
if(ncols <= 0) {
70+
fprintf(stderr, "'-h' must be > 0\n");
71+
usage(prog);
72+
return 1;
73+
}
74+
75+
hist = (int)ncols;
76+
break;
77+
case 'r':
78+
reverse = true;
79+
break;
80+
default:
81+
fprintf(stderr, "Unknown option '%c'\n", opt);
82+
usage(prog);
83+
return 1;
84+
}
85+
}
86+
argc = npos;
87+
88+
StringBuffer file = {0};
89+
if(argc > 0) {
90+
if(!read_file(argv[0], &file)) {
91+
usage(prog);
92+
return 1;
93+
}
94+
} else {
95+
int res;
96+
while((res = read_line(stdin, &file)) > 0);
97+
if(res < 0) return 1;
98+
}
99+
sb_replace(&file, 0, symbols, ' ');
100+
101+
HashMap(StringSlice, size_t) words_freq = {0};
102+
StringSlice file_slice = sb_to_ss(file);
103+
while(file_slice.size) {
104+
StringSlice word = ss_split_once_ws(&file_slice);
105+
if(word.size == 0) continue;
106+
hmap_get_default_ss(&words_freq, word, 0)->value++;
107+
}
108+
109+
size_t max_freq = 0;
110+
size_t max_word_len = 0;
111+
Array(WordFreq) sorted_freqs = {0};
112+
113+
hmap_foreach(WordFreq, e, &words_freq) {
114+
if(e->value > max_freq) max_freq = e->value;
115+
if(e->key.size > max_word_len) max_word_len = e->key.size;
116+
array_push(&sorted_freqs, *e);
117+
}
118+
119+
qsort(sorted_freqs.items, sorted_freqs.size, sizeof(*sorted_freqs.items), qsort_cmp);
120+
121+
if(hist) {
122+
array_foreach(WordFreq, e, &sorted_freqs) {
123+
int ncols = hist * e->value / max_freq;
124+
if(!ncols) ncols = 1;
125+
for(int i = 0; i < ncols; i++) {
126+
printf("#");
127+
}
128+
printf("%*.*s %*zu", (int)(hist - ncols + e->key.size + 1), SS_Arg(e->key),
129+
(int)(max_word_len - e->key.size + 1), e->value);
130+
printf("\n");
131+
}
132+
} else {
133+
array_foreach(WordFreq, e, &sorted_freqs) {
134+
printf("%zu " SS_Fmt "\n", e->value, SS_Arg(e->key));
135+
}
136+
}
137+
138+
sb_free(&file);
139+
array_free(&sorted_freqs);
140+
hmap_free(&words_freq);
141+
return 0;
142+
}

0 commit comments

Comments
 (0)