summaryrefslogtreecommitdiff
path: root/dynstr.h
blob: d0ac24747356f51394a0371986a2d46f5937f968 (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
/*
 * 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.
 */

#ifndef DYNSTR_H
#define DYNSTR_H

#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stddef.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 zero or more existing ones. The
 * argument list has zero or more pointers to dynamic strings, and
 * then a NULL pointer. */
Dynstr *dynstr_cat(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 dynamic
 * string is not long enough, or the offset is past the end of the string,
 * the copy is truncated. Return number of bytes copied. */
size_t dynstr_memcpy(void *mem, Dynstr *dynstr, size_t offset, size_t size);

/* Search for first or last byte with a given value in a string, 
 * within a given range. Return offset of matching byte, or 
 * DYNSTR_NOT_FOUND if not found. Offset is from beginning of string,
 * not beginning of range. */
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, 
 * within a given range. Return offset of match, or 
 * DYNSTR_NOT_FOUND if not found. Offset is from beginning of string,
 * not beginning of range. */
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, either FILE or a Unix file
 * handle. 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);
size_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 number of bytes read, just like for fread(3).
 * A value less than the requested may indicate an error or end-of-file.
 * Use ferror(3) and feof(3) to determine which. If it was an error, errno
 * has been set by fread(3). */
Dynstr *dynstr_read(int file, size_t size);
Dynstr *dynstr_fread(FILE *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