about summary refs log tree commit diff
path: root/util.h
blob: c54bfabefb9b04245cf6ed3989e35957741e7176 (plain) (blame)
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
121
122
123
124
125
126
127
128
129
130
131
/*
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef NANO_EXPORTER_UTIL_H_
#define NANO_EXPORTER_UTIL_H_ 1

#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>

// character buffers

/** Opaque type for an internally maintained character (byte) buffer. */
typedef struct bbuf bbuf;

/** Allocates a new buffer with \p initial_size, growing up to \p max_size. */
bbuf *bbuf_alloc(size_t initial_size, size_t max_size);
/** Frees all the storage associated with \p buf. */
void bbuf_free(bbuf *buf);
/** Clears the contents of the buffer, resetting it to the empty string. */
void bbuf_reset(bbuf *buf);
/** Returns the current length of the buffer contents. */
size_t bbuf_len(bbuf *buf);
/** Appends \p len bytes from address \p src to the buffer \p buf. */
void bbuf_put(bbuf *buf, const void *src, size_t len);
/** Appends the null-terminated string at \p src to the buffer \p buf. */
void bbuf_puts(bbuf *buf, const char *src);
/** Appends a single byte \p c to \p buf. */
void bbuf_putc(bbuf *buf, int c);
/** Appends a formatted string to \p buf. */
void bbuf_putf(bbuf *buf, const char *fmt, ...);
/**
 * Returns the contents of \p buf, writing the length to \p len.
 *
 * There may not be a terminating '\0' byte after the contents. And even if there is, the returned
 * length will not include it.
 */
char *bbuf_get(struct bbuf *buf, size_t *len);
/** Compares the contents of \p buf to the string in \p other, in shortlex order. */
int bbuf_cmp(bbuf *buf, const char *other);

// string lists

/** Type for a singly linked list of strings. */
struct slist {
  struct slist *next;
  char data[];
};

/** Splits \p str into a list of strings, using \p delim as the delimiter. */
struct slist *slist_split(const char *str, const char *delim);
/**
 * Appends \p str to a string list.
 *
 * The address of the new element is written to the location pointed by \p prev, which should be
 * either the `next` pointer of the last element of an existing list, or (for an empty list) the
 * future pointer to a list head. The return value will point at the `next` pointer of the newly
 * allocated element, so code like the following can be used to iteratively construct a list:
 *
 *     struct slist *list = 0;
 *     struct slist **prev = &list;
 *     while (...) {
 *       // do something to get a string 'str'
 *       prev = slist_append(prev, str);
 *     }
 */
struct slist **slist_append(struct slist **prev, const char *str);
/** Prepends \p str to a string list, returning the new head node. */
struct slist *slist_prepend(struct slist *list, const char *str);
/** Returns `true` if \p list contains as element the string \p key. */
bool slist_contains(const struct slist *list, const char *key);
/**
 * Returns `true` if any element of \p list matches \p key.
 *
 * The strings must match exactly, with the exception that if the list elements ends in the '*'
 * character, any \p key string that starts with the prefix before the '*' will count as matching.
 */
bool slist_matches(const struct slist *list, const char *key);

// miscellaneous utilities

/** Calls `malloc(size)` and aborts if memory allocation failed. */
void *must_malloc(size_t size);

/** Calls `realloc(ptr, size)` and aborts if memory allocation failed. */
void *must_realloc(void *ptr, size_t size);

/** Calls `strdup(src)` and aborts if memory allocation failed. */
char *must_strdup(const char *src);

/**
 * Reads a full line from \p stream into buffer \p s of size \p size.
 *
 * This function is otherwise identical to standard `fgets`, except that if a full line did not fit
 * in the input buffer, characters are discarded from the stream up to and including the next
 * newline character. If the file ends before a newline is encountered, a null pointer is
 * required. This way this function always reads complete lines, which are just truncated if they
 * don't fit in the buffer.
 */
char *fgets_line(char *s, int size, FILE *stream);

/**
 * Fully writes the contents of \p buf (\p len bytes) into file descriptor \p fd.
 *
 * If not all bytes could be written, this function just tries again. It returns 0 on success, or -1
 * if any of the `write` calls failed with an error.
 */
int write_all(int fd, const void *buf, size_t len);

ssize_t read_file_at(int dirfd, char *pathname, char *buf, size_t bufsiz);

#ifndef PATH
/** Macro for constructing absolute paths in release, relative paths in tests. */
#define PATH(p) p
#endif // PATH

#endif // NANO_EXPORTER_UTIL_H_