|
|
vtv.h - vtv-tools - virtual terminal video tools |
|
|
 |
git clone git://bitreich.org/vtv-tools git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/vtv-tools (git://bitreich.org) |
|
|
 |
Log |
|
|
 |
Files |
|
|
 |
Refs |
|
|
 |
Tags |
|
|
 |
README |
|
|
 |
LICENSE |
|
|
|
--- |
|
|
|
vtv.h (2139B) |
|
|
|
--- |
|
|
|
1 // Single-header library for reading VTV files. |
|
|
|
2 // |
|
|
|
3 // VTV is an almost trivial format, but there are still a few things |
|
|
|
4 // that are convenient to write once and for all (e.g. error |
|
|
|
5 // handling). |
|
|
|
6 // |
|
|
|
7 // Copyright 2023 Troels Henriksen <athas@sigkill.dk> |
|
|
|
8 // |
|
|
|
9 // See LICENSE file for licensing information. |
|
|
|
10 |
|
|
|
11 #pragma once |
|
|
|
12 |
|
|
|
13 struct vtv { |
|
|
|
14 int num_lines; |
|
|
|
15 char** lines; |
|
|
|
16 }; |
|
|
|
17 |
|
|
|
18 void vtv_free(struct vtv* vtv) { |
|
|
|
19 for (int i = 0; i < vtv->num_lines; i++) { |
|
|
|
20 free(vtv->lines[i]); |
|
|
|
21 } |
|
|
|
22 free(vtv->lines); |
|
|
|
23 free(vtv); |
|
|
|
24 } |
|
|
|
25 |
|
|
|
26 // Returns nonzero on error. |
|
|
|
27 int vtv_read_lines(FILE* f, char*** lines_out, int *num_lines_out) { |
|
|
|
28 size_t n, num_lines = 0, capacity = 10; |
|
|
|
29 char** lines = calloc(capacity, sizeof(char*)); |
|
|
|
30 ssize_t len; |
|
|
|
31 |
|
|
|
32 while ((len = getline(&lines[num_lines], &n, f)) > 0) { |
|
|
|
33 lines[num_lines][len-1] = 0; // Strip newline. |
|
|
|
34 if (++num_lines == capacity) { |
|
|
|
35 capacity *= 2; |
|
|
|
36 lines = reallocarray(lines, capacity, sizeof(char*)); |
|
|
|
37 for (unsigned int i = num_lines; i < capacity; i++) { |
|
|
|
38 lines[i] = NULL; |
|
|
|
39 } |
|
|
|
40 } |
|
|
|
41 } |
|
|
|
42 |
|
|
|
43 *lines_out = lines; |
|
|
|
44 *num_lines_out = num_lines; |
|
|
|
45 return 0; |
|
|
|
46 } |
|
|
|
47 |
|
|
|
48 // Show the given frame on the provided file. If there are not enough |
|
|
|
49 // lines, show the provided line instead of the missing ones. |
|
|
|
50 void vtv_show_frame(struct vtv* vtv, |
|
|
|
51 FILE* f, |
|
|
|
52 int frame, |
|
|
|
53 int lines_per_frame, |
|
|
|
54 const char *missing_line) { |
|
|
|
55 for (int i = 0; i < lines_per_frame; i++) { |
|
|
|
56 int j = frame*lines_per_frame + i; |
|
|
|
57 if (j < vtv->num_lines) { |
|
|
|
58 fputs(vtv->lines[j], f); |
|
|
|
59 fputc('\n', f); |
|
|
|
60 } else { |
|
|
|
61 fputs(missing_line, f); |
|
|
|
62 fputc('\n', f); |
|
|
|
63 } |
|
|
|
64 } |
|
|
|
65 } |
|
|
|
66 |
|
|
|
67 // Returns NULL on error. |
|
|
|
68 struct vtv* vtv_read(FILE *f) { |
|
|
|
69 struct vtv* vtv = malloc(sizeof(struct vtv)); |
|
|
|
70 if (vtv_read_lines(f, &vtv->lines, &vtv->num_lines) == 0) { |
|
|
|
71 return vtv; |
|
|
|
72 } else { |
|
|
|
73 free(vtv); |
|
|
|
74 return NULL; |
|
|
|
75 } |
|
|
|
76 } |
|
|
|
77 |
|
|
|
78 // Returns NULL on error. |
|
|
|
79 struct vtv* vtv_read_from_file(const char *fname) { |
|
|
|
80 FILE *f = fopen(fname, "r"); |
|
|
|
81 if (f == NULL) { |
|
|
|
82 return NULL; |
|
|
|
83 } else { |
|
|
|
84 struct vtv* vtv = vtv_read(f); |
|
|
|
85 fclose(f); |
|
|
|
86 return vtv; |
|
|
|
87 } |
|
|
|
88 } |
|