Add xstring module - bounded string builder with three valued comparator
[ccan] / ccan / xstring / xstring.h
1 #ifndef _XSTRING_H
2 #define _XSTRING_H 1
3
4 #include <assert.h>
5 #include <sys/types.h>
6
7 /**
8  * struct xstring - string metadata
9  * @str: pointer to buf
10  * @len: current length of buf contents
11  * @cap: maximum capacity of buf
12  * @truncated: -1 indicates truncation
13  */
14 typedef struct xstring {
15         char *str;
16         size_t len;
17         size_t cap;
18         int truncated;
19 } xstring;
20
21 /**
22  * xstrNew - mallocs and inits
23  * @size: size of buffer to allocate
24  *
25  * mallocs both buffer and struct, calls xstrInit
26  *
27  * Return: ptr to xstring or NULL
28  */
29 xstring *xstrNew(const size_t size);
30
31 /**
32  * xstrInit - initialize an xstring struct
33  * @x: pointer to xstring
34  * @str: buffer to manage
35  * @size: size of str
36  * @keep: if !0, keep existing contents of str;
37  *        otherwise, str[0] = '\0'
38  *
39  * Return: x->truncated
40  */
41 int xstrInit(xstring *x, char *str, const size_t size, int keep);
42
43 /**
44  * xstrClear - clear xstring
45  * @x: pointer to xstring
46  *
47  * This sets x->len and x->truncated to 0 and str[0] to '\0';
48  *
49  * Return: x->truncated (always 0)
50  */
51 #define xstrClear(x) (xstrInit((x), (x)->str, (x)->cap, 0))
52
53 /**
54  * xstrAddChar - add a single character
55  * @x: pointer to xstring
56  * @c: character to append
57  *
58  * Return: x->truncated
59  */
60 int xstrAddChar(xstring *x, const char c);
61
62 /**
63  * xstrAdd - append a string
64  * @x: pointer to xstring
65  * @src: string to append
66  *
67  * Append as much from src as fits - if not all, flag truncation.
68  *
69  * Return: x->truncated
70  */
71 int xstrAdd(xstring *x, const char *src);
72
73 /**
74  * xstrAddSub - append a substring
75  * @x: pointer to xstring
76  * @src: string to append
77  * @len: length of substring
78  *
79  * Append substring and '\0' if len fits, otherwise flag truncation.
80  *
81  * Return: x->truncated
82  */
83 int xstrAddSub(xstring *x, const char *src, size_t len);
84
85 /** xstrCat - append multiple strings
86  * @x: pointer to xstring
87  * @...: one or more strings followed by NULL
88  *
89  * Run xstrAdd for each string.
90  *
91  * Return: x->truncated
92  */
93 int xstrCat(xstring *x, ...);
94
95 /** xstrJoin - append multiple strings joined by sep
96  * @x: pointer to xstring
97  * @sep: separator string
98  * @...: one or more strings followed by NULL
99  *
100  * Run xstrAdd for each string and append sep between each pair.
101  *
102  * Return: x->truncated
103  */
104 int xstrJoin(xstring *x, const char *sep, ...);
105
106 /**
107  * xstrAddSubs - append multiple substrings
108  * @x: pointer to xstring
109  * @...: one or more pairs of string and length followed by NULL
110  *
111  * Run xstrAddSub for each pair of string and length.
112  *
113  * Return: x->truncated
114  */
115 int xstrAddSubs(xstring *x, ...);
116
117 #define transact(x, y)  ({ \
118         size_t last; \
119         int ret; \
120         assert((x)); \
121         last = (x)->len; \
122         if ((ret = (y)) == -1) { \
123                 (x)->len = last; \
124                 *((x)->str + (x)->len) = '\0'; \
125         } \
126         ret; \
127 })
128
129 /**
130  * xstrAddT - append a string as a transaction
131  * @x: pointer to xstring
132  * @src: string to append
133  *
134  * Run xstrAdd. Reterminate at inital length if truncation occurs.
135  *
136  * Return: x->truncated
137  */
138 #define xstrAddT(x, y)        transact(x, xstrAdd((x), y))
139
140 /** xstrCatT - append multiple strings as one transaction
141  * @x: pointer to xstring
142  * @...: one or more strings followed by NULL
143  *
144  * Run xstrCat. Reterminate at inital length if truncation occurs.
145  *
146  * Return: x->truncated
147  */
148 #define xstrCatT(x, y...)     transact(x, xstrCat((x) , ## y))
149
150 /** xstrJoinT - append multiple strings joined by sep as one transaction
151  * @x: pointer to xstring
152  * @sep: separator string
153  * @...: one or more strings followed by NULL
154  *
155  * Run xstrJoin. Reterminate at inital length if truncation occurs.
156  *
157  * Return: x->truncated
158  */
159 #define xstrJoinT(x, y...)    transact(x, xstrJoin((x) , ## y))
160
161 /**
162  * xstrAddSubsT - append multiple substrings as one transaction
163  * @x: pointer to xstring
164  * @...: one or more pairs of string and length followed by NULL
165  *
166  * Run xstrAddSubs. Reterminate at inital length if truncation occurs.
167  *
168  * Return: x->truncated
169  */
170 #define xstrAddSubsT(x, y...) transact(x, xstrAddSubs((x) , ## y))
171
172 /**
173  * xstrAddSubT - same as xstrAddSub
174  */
175 // addsub is already transactional
176 #define xstrAddSubT xstrAddSub
177
178 #define unknown -1
179
180 /**
181  * xstrEq3 - test if two strings are equal
182  * @x: pointer to xstring
183  * @y: pointer to xstring
184  *
185  * Return true (1) if the strings held by x and y match and no truncation has occurred.
186  * Return unknown (-1) if either is flagged as truncated.
187  * Return false (0) otherwise.
188  *
189  * Return: -1, 0, or 1
190  */
191 int xstrEq3(xstring *x, xstring *y);
192
193 /**
194  * xstrEq - test if two strings are equal
195  * @x: pointer to xstring
196  * @y: pointer to xstring
197  *
198  * Same as xstrEq3, but return false (0) for unknown (-1).
199  *
200  * Return: 0 or 1
201  */
202 #define xstrEq(x, y) (xstrEq3((x), (y)) == 1)
203
204 /**
205  * xstrContains3 - test if first string contains second
206  * @x: pointer to xstring
207  * @y: pointer to xstring
208  * @where: -1 (ends), 0 (anywhere), 1 (begins)
209  *
210  * If neither x nor y are truncated, returns true (1) or false (0).
211  * If y is truncated, return unknown (-1).
212  * If x is truncated, return true (1) if known portion of x contains y, unknown (-1) otherwise.
213  *
214  * Return: -1, 0, or 1
215  */
216 int xstrContains3(xstring *x, xstring *y, int where);
217
218 /**
219  * xstrContains3 - test if first string contains second
220  * @x: pointer to xstring
221  * @y: pointer to xstring
222  * @where: -1 (ends), 0 (anywhere), 1 (begins)
223  *
224  * Same as xstrContains3, but return false (0) for unknown (-1).
225  *
226  * Return: 0 or 1
227  */
228 #define xstrContains(x, y, w) (xstrContains3((x), (y), (w)) == 1)
229
230 /**
231  * xstrFree - free malloced memory
232  * @x: pointer to xstring
233  */
234 void xstrFree(xstring *x);
235
236 #endif