summaryrefslogtreecommitdiff
path: root/usr/src/lib/libcustr/common/libcustr.h
blob: f8f15db07ba0954b30bc04caee5e69fda38aaef3 (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
189
190
191
192
193
194
195
196
197
198
199
200
201
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright 2019 Joyent, Inc.
 */

#ifndef _LIBCUSTR_H
#define	_LIBCUSTR_H

#include <stdarg.h>
#include <sys/types.h>

/* dynamic string utilities */

#ifdef __cplusplus
extern "C" {
#endif

typedef struct custr custr_t;
typedef struct custr_alloc_ops custr_alloc_ops_t;
typedef struct custr_alloc custr_alloc_t;

/*
 * A custom allocator instance.  To use a custom allocator, the user provides
 * the memory for a given custr_alloc_t and calls custr_alloc_init() with the
 * address of the instance to initialize it.  custr_alloc_init() will invoke
 * the init op (if defined) with any additional arguments.  The user can then
 * save any desired state for the allocator instance in cua_arg.  If a
 * custom allocator instance needs to do any cleanup after it's no longer
 * needed, it should also define the fini op and invoke custr_alloc_fini() to
 * do the cleanup.
 */
#define	CUSTR_VERSION 1
struct custr_alloc {
	uint_t			cua_version;
	const custr_alloc_ops_t	*cua_ops;
	void			*cua_arg;
};

struct custr_alloc_ops {
	/*
	 * Optional allocator constructor.  Returns 0 on success, -1
	 * on failure (and should set errno on failure).
	 */
	int (*custr_ao_init)(custr_alloc_t *, va_list);
	/*
	 * Optional allocator destructor.
	 */
	void (*custr_ao_fini)(custr_alloc_t *);
	/*
	 * Returns at least size_t bytes of allocated memory, or NULL.
	 * It should also set errno on failure.
	 */
	void *(*custr_ao_alloc)(custr_alloc_t *, size_t);
	/*
	 * Free the memory previously allocated with custr_ao_alloc.
	 */
	void (*custr_ao_free)(custr_alloc_t *, void *, size_t);
};

/*
 * Initializes a custr allocator.  custr_alloc_t->cua_version should be set to
 * CUSTR_VERSION prior to calling custr_alloc_init().  Both the custr_ao_alloc
 * and custr_ao_free functions must be defined in custr_alloc_ops_t (the
 * init and fini functions are both optional).  If an init function is
 * provided, it will be called with a va_list parameter initialized to
 * point to any arguments after the custr_alloc_ops_t * argument.
 *
 * If cua_version is not CUSTR_VERSION, or if the custr_ao_alloc or
 * custr_ao_free functions are missing, -1 is returned and errno is set to
 * EINVAL.  If an init function was given and it fails (returns -1 -- see
 * the struct custr_alloc_ops definition aboive), -1 is returned and any
 * value of errno set by the init function is left unchanged.
 *
 * On success, 0 is returned.
 */
int custr_alloc_init(custr_alloc_t *, const custr_alloc_ops_t *, ...);

/*
 * If a fini function was given in the custr_alloc_init() call that initalized
 * the given custr_alloc_t instance, it is called to perform any custom
 * cleanup needed.
 */
void custr_alloc_fini(custr_alloc_t *);

/*
 * Allocate and free a "custr_t" dynamic string object.  Returns 0 on success
 * and -1 otherwise.
 */
int custr_alloc(custr_t **);
int custr_xalloc(custr_t **, custr_alloc_t *);
void custr_free(custr_t *);

/*
 * Allocate a "custr_t" dynamic string object that operates on a fixed external
 * buffer.
 */
int custr_alloc_buf(custr_t **, void *, size_t);

/*
 * Like custr_alloc_buf(), except the given allocator is used to allocate
 * the custr_t * instance (but still uses a fixed external buffer for the
 * string contents).
 */
int custr_xalloc_buf(custr_t **, void *, size_t, custr_alloc_t *);

/*
 * Append a single character, or a NUL-terminated string of characters, to a
 * dynamic string.  Returns 0 on success and -1 otherwise.  The dynamic string
 * will be unmodified if the function returns -1.
 */
int custr_appendc(custr_t *, char);
int custr_append(custr_t *, const char *);

/*
 * Append a format string and arguments as though the contents were being parsed
 * through snprintf. Returns 0 on success and -1 otherwise.  The dynamic string
 * will be unmodified if the function returns -1.
 */
int custr_append_printf(custr_t *, const char *, ...);
int custr_append_vprintf(custr_t *, const char *, va_list);

/*
 * Determine the length in bytes, not including the NUL terminator, of the
 * dynamic string.
 */
size_t custr_len(custr_t *);

/*
 * Clear the contents of a dynamic string.  Does not free the underlying
 * memory.
 */
void custr_reset(custr_t *);

/*
 * custr_remove(cus, idx, len)
 *
 * Remove len bytes from cus, starting at idx.
 *
 * Returns 0 on success or -1 on failure.  On failure, errno will be set to:
 *	EINVAL	Either the idx or len parameter is invalid
 *
 */
int custr_remove(custr_t *, size_t, size_t);

/*
 * custr_rremove(cus, idx, len)
 *
 * Remove len bytes from cus, starting at idx relative to the end of cus.
 * That is, 0 = last byte of cus, 1 = second to last byte of cus, ...).
 * The direction of removal is always towards the end of the string.  I.e.
 * 'custr_rremove(cus, 1, 2)' removes the last two bytes of cus.
 *
 * Returns 0 on success or -1 on failure.  On failure, errno will be set to:
 *	EINVAL	Either the idx or len parameter is invalid
 *
 */
int custr_rremove(custr_t *, size_t, size_t);

/*
 * custr_trunc(cus, idx)
 *
 * Truncate cus starting at idx.
 *
 * Returns 0 on success or -1 on failure.  On failure, errno is set to:
 *	EINVAL	The idx value was invalid.
 */
int custr_trunc(custr_t *, size_t);

/*
 * custr_rtrunc(cus, idx)
 *
 * Truncate cus starting at idx relative to the end of cus (similar to how
 * the idx paramter is treated with custr_rremove()).
 *
 * Returns 0 on success or -1 on failure.  On failure, errno is set to:
 *	EINVAL	The idx value was invalid.
 */
int custr_rtrunc(custr_t *, size_t);

/*
 * Retrieve a const pointer to a NUL-terminated string version of the contents
 * of the dynamic string.  Storage for this string should not be freed, and
 * the pointer will be invalidated by any mutations to the dynamic string.
 */
const char *custr_cstr(custr_t *str);

#ifdef __cplusplus
}
#endif

#endif /* _LIBCUSTR_H */