summaryrefslogtreecommitdiff
path: root/lib/dynstr.h
blob: a4c23c5cf2e61a13dabbeaabf934567eb48c1d23 (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
 * dynstr.h - dynamic C string library
 *
 * This is a library for managing dynamic C strings of bytes (not
 * multibyte characters).
 *
 * Each dynamic string is immutable: once created, it cannot be modified.
 * To achieve changes, create new strings. This allows an implementation
 * of the API to make use of copy-on-write techniques to save memory,
 * and avoid unnecessary copying.
 *
 * Dynamic allocation can fail. By default, the routines in this library
 * return NULL for failures. The caller may use the 
 * dynstr_set_malloc_error_handler function to set a function that gets
 * called before NULL is returned. This function can, for example, abort
 * the program (see dynstr_malloc_error_abort), or use longjmp to jump
 * some error handling routine.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef DYNSTR_H
#define DYNSTR_H

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


/* Version number of the shared library. */
#define DYNSTR_VERSION_MAJOR 0
#define DYNSTR_VERSION_MINOR 0
#define DYNSTR_VERSION_PATCH 0


/* Magic value returned by functions that search for things within
 * dynamic strings, to indicate 'not found'. */
#define DYNSTR_NOT_FOUND (~(size_t)0)


/* The abstract type for dynamic strings. The type is opaque: the caller
 * may only operate on it using the functions declared in this header. */
typedef struct Dynstr Dynstr;


/* Initialize or re-initialize the library. This sets all global variables
 * used internally to their defaults. This is mainly useful for unit
 * tests. */
void dynstr_init(void);

/* Set the memory allocator to use, instead of malloc. This is mainly
 * useful for unit tests. */
void dynstr_set_malloc(void *(*allocator)(size_t));

/* Get the memory allocator being used. This is mainly useful for unit 
 * tests. */
void *(*dynstr_get_malloc(void))(size_t);

/* Type of callback functions for handling malloc failures. */
typedef void dynstr_error_handler(int error, size_t size, void *oldptr);

/* Get and set malloc error handler. */
dynstr_error_handler *dynstr_get_malloc_error_handler(void);
void dynstr_set_malloc_error_handler(dynstr_error_handler *handler);

/* Malloc error handler that aborts the program (using abort, not exit). */
void dynstr_malloc_error_abort(int error, size_t size, void *oldptr);

/* Malloc error handler that does nothing. This is the default handler.
 * It causes NULL to be returned. */
void dynstr_malloc_error_indicate(int error, size_t size, void *oldptr);


/* Create a new, empty string. */
Dynstr *dynstr_new_empty(void);

/* Create a new string, copy contents from a NUL-terminated C string. */
Dynstr *dynstr_new_from_cstring(const char *cstring);

/* Create a new string, copy contents from an arbitrary memory area. */
Dynstr *dynstr_new_from_memory(const void *mem, size_t size);

/* Create a new string, use contents from a constant C string. The caller
 * MUST make sure the contents of the C string do not change while the
 * dynamic string exists, since the dynamic string will not copy the
 * contents, but use it directly. */
Dynstr *dynstr_new_from_constant_cstring(const char *cstring);

/* Create a new string, use contents from an arbitrary memory area. The caller
 * MUST make sure the contents of the memory area do not change while the
 * dynamic string exists, since the dynamic string will not copy the
 * contents, but use it directly. */
Dynstr *dynstr_new_from_constant_memory(const void *mem, size_t size);

/* Free a dynamic string. */
void dynstr_free(Dynstr *dynstr);

/* Return length of dynamic string, in bytes. */
size_t dynstr_len(Dynstr *dynstr);

/* Is the dynamic string empty? In other words, is its length 0? */
bool dynstr_is_empty(Dynstr *dynstr);

/* Create a new string, copying its contents from an existing one. */
Dynstr *dynstr_substr(Dynstr *dynstr, size_t offset, size_t size);

/* Create a new string by catenating two existing ones. Return NULL on
 * failure. */
Dynstr *dynstr_cat(Dynstr *dynstr1, Dynstr *dynstr2);

/* Create a new string by catenating zero or more existing ones. The
 * argument list has zero or more pointers to dynamic strings, and
 * then a NULL pointer. */
Dynstr *dynstr_cat_many(Dynstr *dynstr, ...);

/* Return value of byte at a given offset. The value is non-negative. If
 * the offset is past the end of the string, -1 is returned. */
int dynstr_byte_at(Dynstr *dynstr, size_t offset);

/* Copy contents of a dynamic string into a memory area. If the offset or 
 * size extends past the end of the string, only as much as actually exists 
 * in the string is actually copied. The rest of the output memory area will 
 * be filled with garbage. Return number of bytes actually copied, which may 
 * be less than requested, and may be zero. */
size_t dynstr_memcpy(void *mem, Dynstr *dynstr, size_t offset, size_t size);

/* Create a dynamically allocated C string copy of the dynamic string.
 * This is like strdup. If the dynamic string contains NUL bytes, then
 * that is the caller's problem. Return pointer to the C string. The
 * caller is responsible for freeing it. Return NULL on error. */
char *dynstr_strdup(Dynstr *dynstr);

/* Search for first or last byte with a given value in a string, 
 * starting at a given offset and until the end of the string. Return offset 
 * of matching byte, or DYNSTR_NOT_FOUND if not found. Offset is from 
 * beginning of string. */
size_t dynstr_first_byte(Dynstr *dynstr, size_t offset, int byte);
size_t dynstr_last_byte(Dynstr *dynstr, size_t offset, int byte);

/* Search for first or last occurrence of a substring in a string, 
 * starting at a given offset and until the end of the string. Return 
 * offset of match, or DYNSTR_NOT_FOUND if not found. Offset is from 
 * beginning of string. */
size_t dynstr_first_string(Dynstr *dynstr, size_t offset, Dynstr *pattern);
size_t dynstr_last_string(Dynstr *dynstr, size_t offset, Dynstr *pattern);

/* Compare two strings, return 0 if they are equal, negative if the
 * first comes before the second, and positive if second comes first.
 * Comparisons are done byte-by-byte using unsigned values. */
int dynstr_cmp(Dynstr *dynstr1, Dynstr *dynstr2);

/* Write a dynamic string into an open file (using stdio). Return value is 
 * number of bytes written, just like for fwrite(3).
 * If an error occurs, the size is less than the length of the string,
 * and errno has been set by fwrite(3). */
size_t dynstr_fwrite(FILE *file, Dynstr *dynstr);

/* Write a dynamic string into an open Unix file handle. Return value is 
 * number of bytes written, or -1. */
ssize_t dynstr_write(int file, Dynstr *dynstr);

/* Read a number of bytes from an open file, either FILE or a Unix file
 * handle. Return value is the string that was read. The string is empty
 * to indicate EOF, or NULL for error. */
Dynstr *dynstr_fread(FILE *file, size_t size);
Dynstr *dynstr_read(int file, size_t size);

/* Read a line from an open file, either a FILE or a Unix file handle.
 * The line ends with the first newline byte, or at the end of the file.
 * If there was an error, NULL is returned, and errno is set, and the
 * partially read line is discarded. */
Dynstr *dynstr_freadline(FILE *file);
Dynstr *dynstr_readline(int file);

#endif