blob: 04b7e00dc33fd568fb53d1d82b16b5876d92c8c3 [file] [log] [blame]
Willy Tarreaue11f7272017-05-30 17:49:36 +02001/*
2 * include/common/ist.h
3 * Very simple indirect string manipulation functions.
4 *
5 * Copyright (C) 2014-2017 Willy Tarreau - w@1wt.eu
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#ifndef _COMMON_IST_H
29#define _COMMON_IST_H
30
Christopher Faulet20761452018-06-06 16:33:53 +020031#include <ctype.h>
Willy Tarreaue11f7272017-05-30 17:49:36 +020032#include <string.h>
Willy Tarreaua7280a12018-11-26 19:41:40 +010033#include <unistd.h>
Willy Tarreaue11f7272017-05-30 17:49:36 +020034
35#include <common/config.h>
36
Willy Tarreaud6735d62018-12-07 09:40:01 +010037/* ASCII to lower case conversion table */
38const unsigned char ist_lc[256] __attribute__((__weak__)) = {
39 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
40 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
41 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
42 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
43 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
44 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
45 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
46 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
47 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
48 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
49 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
50 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
51 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
52 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
53 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
54 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
55 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
56 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
57 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
58 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
59 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
60 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
61 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
62 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
63 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
64 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
65 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
66 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
67 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
68 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
69 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
70 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
71};
72
73/* ASCII to upper case conversion table */
74const unsigned char ist_uc[256] __attribute__((__weak__)) = {
75 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
76 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
77 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
78 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
79 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
80 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
81 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
82 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
83 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
84 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
85 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
86 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
87 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
88 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
89 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
90 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
91 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
92 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
93 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
94 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
95 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
96 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
97 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
98 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
99 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
100 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
101 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
102 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
103 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
104 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
105 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
106 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
107};
108
Willy Tarreaue11f7272017-05-30 17:49:36 +0200109/* This string definition will most often be used to represent a read-only
110 * string returned from a function, based on the starting point and its length
111 * in bytes. No storage is provided, only a pointer and a length. The types
112 * here are important as we only want to have 2 native machine words there so
113 * that on modern architectures the compiler is capable of efficiently
114 * returning a register pair without having to allocate stack room from the
115 * caller. This is done with -freg-struct which is often enabled by default.
116 */
117struct ist {
118 char *ptr;
119 size_t len;
120};
121
Willy Tarreau2ba67272017-09-21 15:24:10 +0200122/* makes a constant ist from a constant string, for use in array declarations */
123#define IST(str) { .ptr = str "", .len = (sizeof str "") - 1 }
124
Willy Tarreaue11f7272017-05-30 17:49:36 +0200125/* makes an ist from a regular zero terminated string. Null has length 0.
126 * Constants are detected and replaced with constant initializers. Other values
127 * are measured by hand without strlen() as it's much cheaper and inlinable on
128 * small strings. The construct is complex because we must never call
129 * __builtin_strlen() with an expression otherwise it involves a real
130 * measurement.
131 */
132#if __GNUC__ >= 4
133// gcc >= 4 detects constant propagation of str through __x and resolves the
134// length of constant strings easily.
135#define ist(str) ({ \
136 char *__x = (void *)(str); \
137 (struct ist){ \
138 .ptr = __x, \
139 .len = __builtin_constant_p(str) ? \
140 ((void *)str == (void *)0) ? 0 : \
141 __builtin_strlen(__x) : \
142 ({ \
143 size_t __l = 0; \
144 if (__x) for (__l--; __x[++__l]; ) ; \
145 __l; \
146 }) \
147 }; \
148})
149#else
150// gcc < 4 can't do this, and the side effect is a warning each time a NULL is
151// passed to ist() due to the check on __builtin_strlen(). It doesn't have the
152// ability to know that this code is never called.
153#define ist(str) ({ \
154 char *__x = (void *)(str); \
155 (struct ist){ \
156 .ptr = __x, \
157 .len = __builtin_constant_p(str) ? \
158 ((void *)str == (void *)0) ? 0 : \
159 __builtin_strlen(str) : \
160 ({ \
161 size_t __l = 0; \
162 if (__x) for (__l--; __x[++__l]; ) ; \
163 __l; \
164 }) \
165 }; \
166})
167#endif
168
169/* makes an ist struct from a string and a length */
170static inline struct ist ist2(const void *ptr, size_t len)
171{
172 return (struct ist){ .ptr = (char *)ptr, .len = len };
173}
174
Willy Tarreaue67c4e52017-10-19 06:28:23 +0200175/* This function MODIFIES the string to add a zero AFTER the end, and returns
176 * the start pointer. The purpose is to use it on strings extracted by parsers
177 * from larger strings cut with delimiters that are not important and can be
178 * destroyed. It allows any such string to be used with regular string
179 * functions. It's also convenient to use with printf() to show data extracted
180 * from writable areas. The caller is obviously responsible for ensuring that
181 * the string is valid and that the first byte past the end is writable. If
182 * these conditions cannot be satisfied, use istpad() below instead.
183 */
184static inline char *ist0(struct ist ist)
185{
186 ist.ptr[ist.len] = 0;
187 return ist.ptr;
188}
189
Willy Tarreaue11f7272017-05-30 17:49:36 +0200190/* returns the length of the string */
191static inline size_t istlen(const struct ist ist)
192{
193 return ist.len;
194}
195
196/* skips to next character in the string, always stops at the end */
197static inline struct ist istnext(const struct ist ist)
198{
199 struct ist ret = ist;
200
201 if (ret.len) {
202 ret.len--;
203 ret.ptr++;
204 }
205 return ret;
206}
207
208/* copies the contents from string <ist> to buffer <buf> and adds a trailing
209 * zero. The caller must ensure <buf> is large enough.
210 */
211static inline struct ist istpad(void *buf, const struct ist ist)
212{
213 struct ist ret = { .ptr = buf, .len = ist.len };
214
215 for (ret.len = 0; ret.len < ist.len; ret.len++)
216 ret.ptr[ret.len] = ist.ptr[ret.len];
217
218 ret.ptr[ret.len] = 0;
219 return ret;
220}
221
222/* trims string <ist> to no more than <size> characters. The string is
223 * returned.
224 */
225static inline struct ist isttrim(const struct ist ist, size_t size)
226{
227 struct ist ret = ist;
228
229 if (ret.len > size)
230 ret.len = size;
231 return ret;
232}
233
234/* trims string <ist> to no more than <size>-1 characters and ensures that a
235 * zero is placed after <ist.len> (possibly reduced by one) and before <size>,
236 * unless <size> is already zero. The string is returned. This is mostly aimed
237 * at building printable strings that need to be zero-terminated.
238 */
239static inline struct ist istzero(const struct ist ist, size_t size)
240{
241 struct ist ret = ist;
242
243 if (!size)
244 ret.len = 0;
245 else {
246 if (ret.len > size - 1)
247 ret.len = size - 1;
248 ret.ptr[ret.len] = 0;
249 }
250 return ret;
251}
252
253/* returns the ordinal difference between two strings :
254 * < 0 if ist1 < ist2
255 * = 0 if ist1 == ist2
256 * > 0 if ist1 > ist2
257 */
258static inline int istdiff(const struct ist ist1, const struct ist ist2)
259{
260 struct ist l = ist1;
261 struct ist r = ist2;
262
263 do {
264 if (!l.len--)
265 return -r.len;
266 if (!r.len--)
267 return 1;
268 } while (*l.ptr++ == *r.ptr++);
269
270 return *(unsigned char *)(l.ptr - 1) - *(unsigned char *)(r.ptr - 1);
271}
272
273/* returns non-zero if <ist1> starts like <ist2> (empty strings do match) */
274static inline int istmatch(const struct ist ist1, const struct ist ist2)
275{
276 struct ist l = ist1;
277 struct ist r = ist2;
278
279 if (l.len < r.len)
280 return 0;
281
282 while (r.len--) {
283 if (*l.ptr++ != *r.ptr++)
284 return 0;
285 }
286 return 1;
287}
288
289/* returns non-zero if <ist1> starts like <ist2> on the first <count>
290 * characters (empty strings do match).
291 */
292static inline int istnmatch(const struct ist ist1, const struct ist ist2, size_t count)
293{
294 struct ist l = ist1;
295 struct ist r = ist2;
296
297 if (l.len > count)
298 l.len = count;
299 if (r.len > count)
300 r.len = count;
301 return istmatch(l, r);
302}
303
304/* returns non-zero if <ist1> equals <ist2> (empty strings are equal) */
305static inline int isteq(const struct ist ist1, const struct ist ist2)
306{
307 struct ist l = ist1;
308 struct ist r = ist2;
309
310 if (l.len != r.len)
311 return 0;
312
313 while (l.len--) {
314 if (*l.ptr++ != *r.ptr++)
315 return 0;
316 }
317 return 1;
318}
319
Christopher Faulet20761452018-06-06 16:33:53 +0200320/* returns non-zero if <ist1> equals <ist2>, ignoring the case (empty strings are equal) */
321static inline int isteqi(const struct ist ist1, const struct ist ist2)
322{
323 struct ist l = ist1;
324 struct ist r = ist2;
325
326 if (l.len != r.len)
327 return 0;
328
329 while (l.len--) {
Willy Tarreaud6735d62018-12-07 09:40:01 +0100330 if (*l.ptr != *r.ptr &&
331 ist_lc[(unsigned char)*l.ptr] != ist_lc[(unsigned char)*r.ptr])
Christopher Faulet20761452018-06-06 16:33:53 +0200332 return 0;
Willy Tarreaud6735d62018-12-07 09:40:01 +0100333
Christopher Faulet20761452018-06-06 16:33:53 +0200334 l.ptr++;
335 r.ptr++;
336 }
337 return 1;
338}
339
Willy Tarreaue11f7272017-05-30 17:49:36 +0200340/* returns non-zero if <ist1> equals <ist2> on the first <count> characters
341 * (empty strings are equal).
342 */
343static inline int istneq(const struct ist ist1, const struct ist ist2, size_t count)
344{
345 struct ist l = ist1;
346 struct ist r = ist2;
347
348 if (l.len > count)
349 l.len = count;
350 if (r.len > count)
351 r.len = count;
352 return isteq(l, r);
353}
354
355/* copies <src> over <dst> for a maximum of <count> bytes. Returns the number
356 * of characters copied (src.len), or -1 if it does not fit. In all cases, the
357 * contents are copied prior to reporting an error, so that the destination
358 * at least contains a valid but truncated string.
359 */
360static inline ssize_t istcpy(struct ist *dst, const struct ist src, size_t count)
361{
362 dst->len = 0;
363
364 if (count > src.len)
365 count = src.len;
366
367 while (dst->len < count) {
368 dst->ptr[dst->len] = src.ptr[dst->len];
369 dst->len++;
370 }
371
372 if (dst->len == src.len)
373 return src.len;
374
375 return -1;
376}
377
378/* copies <src> over <dst> for a maximum of <count> bytes. Returns the number
379 * of characters copied, or -1 if it does not fit. A (possibly truncated) valid
380 * copy of <src> is always left into <dst>, and a trailing \0 is appended as
381 * long as <count> is not null, even if that results in reducing the string by
382 * one character.
383 */
384static inline ssize_t istscpy(struct ist *dst, const struct ist src, size_t count)
385{
386 dst->len = 0;
387
388 if (!count)
389 goto fail;
390
391 if (count > src.len)
392 count = src.len + 1;
393
394 while (dst->len < count - 1) {
395 dst->ptr[dst->len] = src.ptr[dst->len];
396 dst->len++;
397 }
398
399 dst->ptr[dst->len] = 0;
400 if (dst->len == src.len)
401 return src.len;
402 fail:
403 return -1;
404}
405
406/* appends <src> after <dst> for a maximum of <count> total bytes in <dst> after
407 * the copy. <dst> is assumed to be <count> or less before the call. The new
408 * string's length is returned, or -1 if a truncation happened. In all cases,
409 * the contents are copied prior to reporting an error, so that the destination
410 * at least contains a valid but truncated string.
411 */
412static inline ssize_t istcat(struct ist *dst, const struct ist src, size_t count)
413{
414 const char *s = src.ptr;
415
416 while (dst->len < count && s != src.ptr + src.len)
417 dst->ptr[dst->len++] = *s++;
418
419 if (s == src.ptr + src.len)
420 return dst->len;
421
422 return -1;
423}
424
425/* appends <src> after <dst> for a maximum of <count> total bytes in <dst> after
426 * the copy. <dst> is assumed to be <count> or less before the call. The new
427 * string's length is returned, or -1 if a truncation happened. In all cases,
428 * the contents are copied prior to reporting an error, so that the destination
429 * at least contains a valid but truncated string.
430 */
431static inline ssize_t istscat(struct ist *dst, const struct ist src, size_t count)
432{
433 const char *s = src.ptr;
434
435 if (!count)
436 goto fail;
437
438 while (dst->len < count - 1 && s != src.ptr + src.len) {
439 dst->ptr[dst->len++] = *s++;
440 }
441
442 dst->ptr[dst->len] = 0;
443 if (s == src.ptr + src.len)
444 return dst->len;
445 fail:
446 return -1;
447}
448
Willy Tarreau3f2d6962018-12-07 08:35:07 +0100449/* copies the entire <src> over <dst>, which must be allocated large enough to
450 * hold the whole contents. No trailing zero is appended, this is mainly used
451 * for protocol processing where the frame length has already been checked. An
452 * ist made of the output and its length are returned. The destination is not
453 * touched if src.len is null.
454 */
455static inline struct ist ist2bin(char *dst, const struct ist src)
456{
457 size_t ofs = 0;
458
459 /* discourage the compiler from trying to optimize for large strings,
460 * but tell it that most of our strings are not empty.
461 */
462 if (__builtin_expect(ofs < src.len, 1)) {
463 do {
464 dst[ofs] = src.ptr[ofs];
465 ofs++;
466 } while (__builtin_expect(ofs < src.len, 0));
467 }
468 return ist2(dst, ofs);
469}
470
471/* copies the entire <src> over <dst>, which must be allocated large enough to
472 * hold the whole contents as well as a trailing zero which is always appended.
473 * This is mainly used for protocol conversions where the frame length has
474 * already been checked. An ist made of the output and its length (not counting
475 * the trailing zero) are returned.
476 */
477static inline struct ist ist2str(char *dst, const struct ist src, size_t count)
478{
479 size_t ofs = 0;
480
481 /* discourage the compiler from trying to optimize for large strings,
482 * but tell it that most of our strings are not empty.
483 */
484 if (__builtin_expect(ofs < src.len, 1)) {
485 do {
486 dst[ofs] = src.ptr[ofs];
487 ofs++;
488 } while (__builtin_expect(ofs < src.len, 0));
489 }
490 dst[ofs] = 0;
491 return ist2(dst, ofs);
492}
493
494/* makes a lower case copy of the entire <src> into <dst>, which must have been
495 * allocated large enough to hold the whole contents. No trailing zero is
496 * appended, this is mainly used for protocol processing where the frame length
497 * has already been checked. An ist made of the output and its length are
498 * returned. The destination is not touched if src.len is null.
499 */
500static inline struct ist ist2bin_lc(char *dst, const struct ist src)
501{
502 size_t ofs = 0;
503
504 /* discourage the compiler from trying to optimize for large strings,
505 * but tell it that most of our strings are not empty.
506 */
507 if (__builtin_expect(ofs < src.len, 1)) {
508 do {
Willy Tarreaud6735d62018-12-07 09:40:01 +0100509 dst[ofs] = ist_lc[(unsigned char)src.ptr[ofs]];
Willy Tarreau3f2d6962018-12-07 08:35:07 +0100510 ofs++;
511 } while (__builtin_expect(ofs < src.len, 0));
512 }
513 return ist2(dst, ofs);
514}
515
516/* makes a lower case copy of the entire <src> into <dst>, which must have been
517 * allocated large enough to hold the whole contents as well as a trailing zero
518 * which is always appended. This is mainly used for protocol conversions where
519 * the frame length has already been checked. An ist made of the output and its
520 * length (not counting the trailing zero) are returned.
521 */
522static inline struct ist ist2str_lc(char *dst, const struct ist src, size_t count)
523{
524 size_t ofs = 0;
525
526 /* discourage the compiler from trying to optimize for large strings,
527 * but tell it that most of our strings are not empty.
528 */
529 if (__builtin_expect(ofs < src.len, 1)) {
530 do {
Willy Tarreaud6735d62018-12-07 09:40:01 +0100531 dst[ofs] = ist_lc[(unsigned char)src.ptr[ofs]];
Willy Tarreau3f2d6962018-12-07 08:35:07 +0100532 ofs++;
533 } while (__builtin_expect(ofs < src.len, 0));
534 }
535 dst[ofs] = 0;
536 return ist2(dst, ofs);
537}
538
539/* makes an upper case copy of the entire <src> into <dst>, which must have
540 * been allocated large enough to hold the whole contents. No trailing zero is
541 * appended, this is mainly used for protocol processing where the frame length
542 * has already been checked. An ist made of the output and its length are
543 * returned. The destination is not touched if src.len is null.
544 */
545static inline struct ist ist2bin_uc(char *dst, const struct ist src)
546{
547 size_t ofs = 0;
548
549 /* discourage the compiler from trying to optimize for large strings,
550 * but tell it that most of our strings are not empty.
551 */
552 if (__builtin_expect(ofs < src.len, 1)) {
553 do {
Willy Tarreaud6735d62018-12-07 09:40:01 +0100554 dst[ofs] = ist_uc[(unsigned char)src.ptr[ofs]];
Willy Tarreau3f2d6962018-12-07 08:35:07 +0100555 ofs++;
556 } while (__builtin_expect(ofs < src.len, 0));
557 }
558 return ist2(dst, ofs);
559}
560
561/* makes an upper case copy of the entire <src> into <dst>, which must have been
562 * allocated large enough to hold the whole contents as well as a trailing zero
563 * which is always appended. This is mainly used for protocol conversions where
564 * the frame length has already been checked. An ist made of the output and its
565 * length (not counting the trailing zero) are returned.
566 */
567static inline struct ist ist2str_uc(char *dst, const struct ist src, size_t count)
568{
569 size_t ofs = 0;
570
571 /* discourage the compiler from trying to optimize for large strings,
572 * but tell it that most of our strings are not empty.
573 */
574 if (__builtin_expect(ofs < src.len, 1)) {
575 do {
Willy Tarreaud6735d62018-12-07 09:40:01 +0100576 dst[ofs] = ist_uc[(unsigned char)src.ptr[ofs]];
Willy Tarreau3f2d6962018-12-07 08:35:07 +0100577 ofs++;
578 } while (__builtin_expect(ofs < src.len, 0));
579 }
580 dst[ofs] = 0;
581 return ist2(dst, ofs);
582}
583
Willy Tarreaue11f7272017-05-30 17:49:36 +0200584/* looks for first occurrence of character <chr> in string <ist>. Returns the
585 * pointer if found, or NULL if not found.
586 */
587static inline char *istchr(const struct ist ist, char chr)
588{
589 char *s = ist.ptr;
590
591 do {
592 if (s >= ist.ptr + ist.len)
593 return NULL;
594 } while (*s++ != chr);
595 return s - 1;
596}
597
598/* looks for first occurrence of character <chr> in string <ist> and returns
599 * the tail of the string starting with this character, or (ist.end,0) if not
600 * found.
601 */
602static inline struct ist istfind(const struct ist ist, char chr)
603{
604 struct ist ret = ist;
605
606 while (ret.len--) {
607 if (*ret.ptr++ == chr)
608 return ist2(ret.ptr - 1, ret.len + 1);
609 }
610 return ist2(ret.ptr, 0);
611}
612
613/* looks for first occurrence of character different from <chr> in string <ist>
614 * and returns the tail of the string starting at this character, or (ist_end,0)
615 * if not found.
616 */
617static inline struct ist istskip(const struct ist ist, char chr)
618{
619 struct ist ret = ist;
620
621 while (ret.len--) {
622 if (*ret.ptr++ != chr)
623 return ist2(ret.ptr - 1, ret.len + 1);
624 }
625 return ist2(ret.ptr, 0);
626}
627
628/* looks for first occurrence of string <pat> in string <ist> and returns the
629 * tail of the string starting at this position, or (NULL,0) if not found. The
630 * empty pattern is found everywhere.
631 */
632static inline struct ist istist(const struct ist ist, const struct ist pat)
633{
634 struct ist ret = ist;
635 size_t pos;
636
637 if (!pat.len)
638 return ret;
639
640 while (1) {
641 loop:
642 ret = istfind(ret, *pat.ptr);
643 if (ret.len < pat.len)
644 break;
645
646 /* ret.len >= 1, pat.len >= 1 and *ret.ptr == *pat.ptr */
647
648 ret = istnext(ret);
649 for (pos = 0; pos < pat.len - 1; ) {
650 ++pos;
651 if (ret.ptr[pos - 1] != pat.ptr[pos])
652 goto loop;
653 }
654 return ist2(ret.ptr - 1, ret.len + 1);
655 }
656 return ist2(NULL, 0);
657}
658
659#endif