1500cf85bSJason King /*
2500cf85bSJason King  * This file and its contents are supplied under the terms of the
3500cf85bSJason King  * Common Development and Distribution License ("CDDL"), version 1.0.
4500cf85bSJason King  * You may only use this file in accordance with the terms of version
5500cf85bSJason King  * 1.0 of the CDDL.
6500cf85bSJason King  *
7500cf85bSJason King  * A full copy of the text of the CDDL should have accompanied this
8500cf85bSJason King  * source.  A copy of the CDDL is also available via the Internet at
9500cf85bSJason King  * http://www.illumos.org/license/CDDL.
10500cf85bSJason King  */
11500cf85bSJason King 
12500cf85bSJason King /*
13*356ce177SJason King  * Copyright 2019 Joyent, Inc.
14500cf85bSJason King  */
15500cf85bSJason King 
16500cf85bSJason King #ifndef _LIBCUSTR_H
17500cf85bSJason King #define	_LIBCUSTR_H
18500cf85bSJason King 
19500cf85bSJason King #include <stdarg.h>
20500cf85bSJason King #include <sys/types.h>
21500cf85bSJason King 
22500cf85bSJason King /* dynamic string utilities */
23500cf85bSJason King 
24500cf85bSJason King #ifdef __cplusplus
25500cf85bSJason King extern "C" {
26500cf85bSJason King #endif
27500cf85bSJason King 
28500cf85bSJason King typedef struct custr custr_t;
29773dbec3SJason King typedef struct custr_alloc_ops custr_alloc_ops_t;
30773dbec3SJason King typedef struct custr_alloc custr_alloc_t;
31773dbec3SJason King 
32773dbec3SJason King /*
33773dbec3SJason King  * A custom allocator instance.  To use a custom allocator, the user provides
34773dbec3SJason King  * the memory for a given custr_alloc_t and calls custr_alloc_init() with the
35773dbec3SJason King  * address of the instance to initialize it.  custr_alloc_init() will invoke
36773dbec3SJason King  * the init op (if defined) with any additional arguments.  The user can then
37773dbec3SJason King  * save any desired state for the allocator instance in cua_arg.  If a
38773dbec3SJason King  * custom allocator instance needs to do any cleanup after it's no longer
39773dbec3SJason King  * needed, it should also define the fini op and invoke custr_alloc_fini() to
40773dbec3SJason King  * do the cleanup.
41773dbec3SJason King  */
42773dbec3SJason King #define	CUSTR_VERSION 1
43773dbec3SJason King struct custr_alloc {
44773dbec3SJason King 	uint_t			cua_version;
45773dbec3SJason King 	const custr_alloc_ops_t	*cua_ops;
46773dbec3SJason King 	void			*cua_arg;
47773dbec3SJason King };
48773dbec3SJason King 
49773dbec3SJason King struct custr_alloc_ops {
50773dbec3SJason King 	/*
51773dbec3SJason King 	 * Optional allocator constructor.  Returns 0 on success, -1
52773dbec3SJason King 	 * on failure (and should set errno on failure).
53773dbec3SJason King 	 */
54773dbec3SJason King 	int (*custr_ao_init)(custr_alloc_t *, va_list);
55773dbec3SJason King 	/*
56773dbec3SJason King 	 * Optional allocator destructor.
57773dbec3SJason King 	 */
58773dbec3SJason King 	void (*custr_ao_fini)(custr_alloc_t *);
59773dbec3SJason King 	/*
60773dbec3SJason King 	 * Returns at least size_t bytes of allocated memory, or NULL.
61773dbec3SJason King 	 * It should also set errno on failure.
62773dbec3SJason King 	 */
63773dbec3SJason King 	void *(*custr_ao_alloc)(custr_alloc_t *, size_t);
64773dbec3SJason King 	/*
65773dbec3SJason King 	 * Free the memory previously allocated with custr_ao_alloc.
66773dbec3SJason King 	 */
67773dbec3SJason King 	void (*custr_ao_free)(custr_alloc_t *, void *, size_t);
68773dbec3SJason King };
69773dbec3SJason King 
70773dbec3SJason King /*
71773dbec3SJason King  * Initializes a custr allocator.  custr_alloc_t->cua_version should be set to
72773dbec3SJason King  * CUSTR_VERSION prior to calling custr_alloc_init().  Both the custr_ao_alloc
73773dbec3SJason King  * and custr_ao_free functions must be defined in custr_alloc_ops_t (the
74773dbec3SJason King  * init and fini functions are both optional).  If an init function is
75773dbec3SJason King  * provided, it will be called with a va_list parameter initialized to
76773dbec3SJason King  * point to any arguments after the custr_alloc_ops_t * argument.
77773dbec3SJason King  *
78773dbec3SJason King  * If cua_version is not CUSTR_VERSION, or if the custr_ao_alloc or
79773dbec3SJason King  * custr_ao_free functions are missing, -1 is returned and errno is set to
80773dbec3SJason King  * EINVAL.  If an init function was given and it fails (returns -1 -- see
81773dbec3SJason King  * the struct custr_alloc_ops definition aboive), -1 is returned and any
82773dbec3SJason King  * value of errno set by the init function is left unchanged.
83773dbec3SJason King  *
84773dbec3SJason King  * On success, 0 is returned.
85773dbec3SJason King  */
86773dbec3SJason King int custr_alloc_init(custr_alloc_t *, const custr_alloc_ops_t *, ...);
87773dbec3SJason King 
88773dbec3SJason King /*
89773dbec3SJason King  * If a fini function was given in the custr_alloc_init() call that initalized
90773dbec3SJason King  * the given custr_alloc_t instance, it is called to perform any custom
91773dbec3SJason King  * cleanup needed.
92773dbec3SJason King  */
93773dbec3SJason King void custr_alloc_fini(custr_alloc_t *);
94500cf85bSJason King 
95500cf85bSJason King /*
96500cf85bSJason King  * Allocate and free a "custr_t" dynamic string object.  Returns 0 on success
97500cf85bSJason King  * and -1 otherwise.
98500cf85bSJason King  */
99500cf85bSJason King int custr_alloc(custr_t **);
100773dbec3SJason King int custr_xalloc(custr_t **, custr_alloc_t *);
101500cf85bSJason King void custr_free(custr_t *);
102500cf85bSJason King 
103500cf85bSJason King /*
104500cf85bSJason King  * Allocate a "custr_t" dynamic string object that operates on a fixed external
105500cf85bSJason King  * buffer.
106500cf85bSJason King  */
107500cf85bSJason King int custr_alloc_buf(custr_t **, void *, size_t);
108500cf85bSJason King 
109773dbec3SJason King /*
110773dbec3SJason King  * Like custr_alloc_buf(), except the given allocator is used to allocate
111773dbec3SJason King  * the custr_t * instance (but still uses a fixed external buffer for the
112773dbec3SJason King  * string contents).
113773dbec3SJason King  */
114773dbec3SJason King int custr_xalloc_buf(custr_t **, void *, size_t, custr_alloc_t *);
115773dbec3SJason King 
116500cf85bSJason King /*
117500cf85bSJason King  * Append a single character, or a NUL-terminated string of characters, to a
118500cf85bSJason King  * dynamic string.  Returns 0 on success and -1 otherwise.  The dynamic string
119500cf85bSJason King  * will be unmodified if the function returns -1.
120500cf85bSJason King  */
121500cf85bSJason King int custr_appendc(custr_t *, char);
122500cf85bSJason King int custr_append(custr_t *, const char *);
123500cf85bSJason King 
124500cf85bSJason King /*
125500cf85bSJason King  * Append a format string and arguments as though the contents were being parsed
126500cf85bSJason King  * through snprintf. Returns 0 on success and -1 otherwise.  The dynamic string
127500cf85bSJason King  * will be unmodified if the function returns -1.
128500cf85bSJason King  */
129500cf85bSJason King int custr_append_printf(custr_t *, const char *, ...);
130500cf85bSJason King int custr_append_vprintf(custr_t *, const char *, va_list);
131500cf85bSJason King 
132500cf85bSJason King /*
133500cf85bSJason King  * Determine the length in bytes, not including the NUL terminator, of the
134500cf85bSJason King  * dynamic string.
135500cf85bSJason King  */
136500cf85bSJason King size_t custr_len(custr_t *);
137500cf85bSJason King 
138500cf85bSJason King /*
139500cf85bSJason King  * Clear the contents of a dynamic string.  Does not free the underlying
140500cf85bSJason King  * memory.
141500cf85bSJason King  */
142500cf85bSJason King void custr_reset(custr_t *);
143500cf85bSJason King 
144*356ce177SJason King /*
145*356ce177SJason King  * custr_remove(cus, idx, len)
146*356ce177SJason King  *
147*356ce177SJason King  * Remove len bytes from cus, starting at idx.
148*356ce177SJason King  *
149*356ce177SJason King  * Returns 0 on success or -1 on failure.  On failure, errno will be set to:
150*356ce177SJason King  *	EINVAL	Either the idx or len parameter is invalid
151*356ce177SJason King  *
152*356ce177SJason King  */
153*356ce177SJason King int custr_remove(custr_t *, size_t, size_t);
154*356ce177SJason King 
155*356ce177SJason King /*
156*356ce177SJason King  * custr_rremove(cus, idx, len)
157*356ce177SJason King  *
158*356ce177SJason King  * Remove len bytes from cus, starting at idx relative to the end of cus.
159*356ce177SJason King  * That is, 0 = last byte of cus, 1 = second to last byte of cus, ...).
160*356ce177SJason King  * The direction of removal is always towards the end of the string.  I.e.
161*356ce177SJason King  * 'custr_rremove(cus, 1, 2)' removes the last two bytes of cus.
162*356ce177SJason King  *
163*356ce177SJason King  * Returns 0 on success or -1 on failure.  On failure, errno will be set to:
164*356ce177SJason King  *	EINVAL	Either the idx or len parameter is invalid
165*356ce177SJason King  *
166*356ce177SJason King  */
167*356ce177SJason King int custr_rremove(custr_t *, size_t, size_t);
168*356ce177SJason King 
169*356ce177SJason King /*
170*356ce177SJason King  * custr_trunc(cus, idx)
171*356ce177SJason King  *
172*356ce177SJason King  * Truncate cus starting at idx.
173*356ce177SJason King  *
174*356ce177SJason King  * Returns 0 on success or -1 on failure.  On failure, errno is set to:
175*356ce177SJason King  *	EINVAL	The idx value was invalid.
176*356ce177SJason King  */
177*356ce177SJason King int custr_trunc(custr_t *, size_t);
178*356ce177SJason King 
179*356ce177SJason King /*
180*356ce177SJason King  * custr_rtrunc(cus, idx)
181*356ce177SJason King  *
182*356ce177SJason King  * Truncate cus starting at idx relative to the end of cus (similar to how
183*356ce177SJason King  * the idx paramter is treated with custr_rremove()).
184*356ce177SJason King  *
185*356ce177SJason King  * Returns 0 on success or -1 on failure.  On failure, errno is set to:
186*356ce177SJason King  *	EINVAL	The idx value was invalid.
187*356ce177SJason King  */
188*356ce177SJason King int custr_rtrunc(custr_t *, size_t);
189*356ce177SJason King 
190500cf85bSJason King /*
191500cf85bSJason King  * Retrieve a const pointer to a NUL-terminated string version of the contents
192500cf85bSJason King  * of the dynamic string.  Storage for this string should not be freed, and
193500cf85bSJason King  * the pointer will be invalidated by any mutations to the dynamic string.
194500cf85bSJason King  */
195500cf85bSJason King const char *custr_cstr(custr_t *str);
196500cf85bSJason King 
197500cf85bSJason King #ifdef __cplusplus
198500cf85bSJason King }
199500cf85bSJason King #endif
200500cf85bSJason King 
201500cf85bSJason King #endif /* _LIBCUSTR_H */