Coverage Report

Created: 2025-07-11 06:23

/src/libunistring/lib/unistr.h
Line
Count
Source (jump to first uncovered line)
1
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
2
/* Elementary Unicode string functions.
3
   Copyright (C) 2001-2002, 2005-2025 Free Software Foundation, Inc.
4
5
   This file is free software: you can redistribute it and/or modify
6
   it under the terms of the GNU Lesser General Public License as
7
   published by the Free Software Foundation; either version 2.1 of the
8
   License, or (at your option) any later version.
9
10
   This file is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU Lesser General Public License for more details.
14
15
   You should have received a copy of the GNU Lesser General Public License
16
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
17
18
#ifndef _UNISTR_H
19
#define _UNISTR_H
20
21
#include "unitypes.h"
22
23
/* Get common macros for C.  */
24
#include <unistring/cdefs.h>
25
26
/* Get inline if available.  */
27
#include <unistring/inline.h>
28
29
/* Get bool.  */
30
#include <stdbool.h>
31
32
/* Get size_t, ptrdiff_t.  */
33
#include <stddef.h>
34
35
/* Get free().  */
36
#include <stdlib.h>
37
38
#ifdef __cplusplus
39
extern "C" {
40
#endif
41
42
43
/* Conventions:
44
45
   All functions prefixed with u8_ operate on UTF-8 encoded strings.
46
   Their unit is an uint8_t (1 byte).
47
48
   All functions prefixed with u16_ operate on UTF-16 encoded strings.
49
   Their unit is an uint16_t (a 2-byte word).
50
51
   All functions prefixed with u32_ operate on UCS-4 encoded strings.
52
   Their unit is an uint32_t (a 4-byte word).
53
54
   All argument pairs (s, n) denote a Unicode string s[0..n-1] with exactly
55
   n units.
56
57
   All arguments starting with "str" and the arguments of functions starting
58
   with u8_str/u16_str/u32_str denote a NUL terminated string, i.e. a string
59
   which terminates at the first NUL unit.  This termination unit is
60
   considered part of the string for all memory allocation purposes, but
61
   is not considered part of the string for all other logical purposes.
62
63
   Functions returning a string result take a (resultbuf, lengthp) argument
64
   pair.  If resultbuf is not NULL and the result fits into *lengthp units,
65
   it is put in resultbuf, and resultbuf is returned.  Otherwise, a freshly
66
   allocated string is returned.  In both cases, *lengthp is set to the
67
   length (number of units) of the returned string.  In case of error,
68
   NULL is returned and errno is set.  */
69
70
71
/* Elementary string checks.  */
72
73
/* Check whether an UTF-8 string is well-formed.
74
   Return NULL if valid, or a pointer to the first invalid unit otherwise.  */
75
extern const uint8_t *
76
       u8_check (const uint8_t *s, size_t n)
77
       _UC_ATTRIBUTE_PURE;
78
79
/* Check whether an UTF-16 string is well-formed.
80
   Return NULL if valid, or a pointer to the first invalid unit otherwise.  */
81
extern const uint16_t *
82
       u16_check (const uint16_t *s, size_t n)
83
       _UC_ATTRIBUTE_PURE;
84
85
/* Check whether an UCS-4 string is well-formed.
86
   Return NULL if valid, or a pointer to the first invalid unit otherwise.  */
87
extern const uint32_t *
88
       u32_check (const uint32_t *s, size_t n)
89
       _UC_ATTRIBUTE_PURE;
90
91
#ifndef _LIBUNISTRING_NO_CONST_GENERICS
92
/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'.  Programmers
93
   want compiler warnings for 'const' related mistakes.  */
94
# ifdef __cplusplus
95
template <typename T>
96
  T * u8_check_template (T* s, size_t n);
97
template <>
98
  inline uint8_t * u8_check_template (uint8_t *s, size_t n)
99
  { return const_cast<uint8_t *>(u8_check (s, n)); }
100
template <>
101
  inline const uint8_t * u8_check_template (const uint8_t *s, size_t n)
102
  { return u8_check (s, n); }
103
#  undef u8_check
104
#  define u8_check u8_check_template
105
# elif !defined u8_check
106
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
107
       || defined __ICC  || defined __TINYC__ \
108
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
109
#   define u8_check(s,n) \
110
0
      _Generic ((s), \
111
0
                uint8_t *: (uint8_t *) u8_check ((s), (n)), \
112
0
                default  :             u8_check ((s), (n)))
113
#  endif
114
# endif
115
# ifdef __cplusplus
116
template <typename T>
117
  T * u16_check_template (T* s, size_t n);
118
template <>
119
  inline uint16_t * u16_check_template (uint16_t *s, size_t n)
120
  { return const_cast<uint16_t *>(u16_check (s, n)); }
121
template <>
122
  inline const uint16_t * u16_check_template (const uint16_t *s, size_t n)
123
  { return u16_check (s, n); }
124
#  undef u16_check
125
#  define u16_check u16_check_template
126
# elif !defined u16_check
127
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
128
       || defined __ICC  || defined __TINYC__ \
129
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
130
#   define u16_check(s,n) \
131
      _Generic ((s), \
132
                uint16_t *: (uint16_t *) u16_check ((s), (n)), \
133
                default   :              u16_check ((s), (n)))
134
#  endif
135
# endif
136
# ifdef __cplusplus
137
template <typename T>
138
  T * u32_check_template (T* s, size_t n);
139
template <>
140
  inline uint32_t * u32_check_template (uint32_t *s, size_t n)
141
  { return const_cast<uint32_t *>(u32_check (s, n)); }
142
template <>
143
  inline const uint32_t * u32_check_template (const uint32_t *s, size_t n)
144
  { return u32_check (s, n); }
145
#  undef u32_check
146
#  define u32_check u32_check_template
147
# elif !defined u32_check
148
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
149
       || defined __ICC  || defined __TINYC__ \
150
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
151
#   define u32_check(s,n) \
152
      _Generic ((s), \
153
                uint32_t *: (uint32_t *) u32_check ((s), (n)), \
154
                default   :              u32_check ((s), (n)))
155
#  endif
156
# endif
157
#endif
158
159
160
/* Elementary string conversions.  */
161
162
/* Convert an UTF-8 string to an UTF-16 string.  */
163
extern uint16_t *
164
       u8_to_u16 (const uint8_t *s, size_t n, uint16_t *resultbuf,
165
                  size_t *lengthp);
166
167
/* Convert an UTF-8 string to an UCS-4 string.  */
168
extern uint32_t *
169
       u8_to_u32 (const uint8_t *s, size_t n, uint32_t *resultbuf,
170
                  size_t *lengthp);
171
172
/* Convert an UTF-16 string to an UTF-8 string.  */
173
extern uint8_t *
174
       u16_to_u8 (const uint16_t *s, size_t n, uint8_t *resultbuf,
175
                  size_t *lengthp);
176
177
/* Convert an UTF-16 string to an UCS-4 string.  */
178
extern uint32_t *
179
       u16_to_u32 (const uint16_t *s, size_t n, uint32_t *resultbuf,
180
                   size_t *lengthp);
181
182
/* Convert an UCS-4 string to an UTF-8 string.  */
183
extern uint8_t *
184
       u32_to_u8 (const uint32_t *s, size_t n, uint8_t *resultbuf,
185
                  size_t *lengthp);
186
187
/* Convert an UCS-4 string to an UTF-16 string.  */
188
extern uint16_t *
189
       u32_to_u16 (const uint32_t *s, size_t n, uint16_t *resultbuf,
190
                   size_t *lengthp);
191
192
193
/* Elementary string functions.  */
194
195
/* Return the length (number of units) of the first character in S, which is
196
   no longer than N.  Return 0 if it is the NUL character.  Return -1 upon
197
   failure.  */
198
/* Similar to mblen(), except that s must not be NULL.  */
199
extern int
200
       u8_mblen (const uint8_t *s, size_t n)
201
       _UC_ATTRIBUTE_PURE;
202
extern int
203
       u16_mblen (const uint16_t *s, size_t n)
204
       _UC_ATTRIBUTE_PURE;
205
extern int
206
       u32_mblen (const uint32_t *s, size_t n)
207
       _UC_ATTRIBUTE_PURE;
208
209
/* Return the length (number of units) of the first character in S, putting
210
   its 'ucs4_t' representation in *PUC.  Upon failure, *PUC is set to 0xfffd,
211
   and an appropriate number of units is returned.
212
   The number of available units, N, must be > 0.  */
213
/* Similar to mbtowc(), except that puc and s must not be NULL, n must be > 0,
214
   and the NUL character is not treated specially.  */
215
/* The variants with _unsafe suffix are for backward compatibility with
216
   libunistring versions < 0.9.7.  */
217
218
#if 1
219
# if !UNISTRING_HAVE_INLINE
220
extern int
221
       u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n);
222
# else
223
extern int
224
       u8_mbtouc_unsafe_aux (ucs4_t *puc, const uint8_t *s, size_t n);
225
static inline int
226
u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n)
227
20.5M
{
228
20.5M
  uint8_t c = *s;
229
230
20.5M
  if (c < 0x80)
231
11.1M
    {
232
11.1M
      *puc = c;
233
11.1M
      return 1;
234
11.1M
    }
235
9.38M
  else
236
9.38M
    return u8_mbtouc_unsafe_aux (puc, s, n);
237
20.5M
}
Unexecuted instantiation: u8-strconv-from-enc.c:u8_mbtouc_unsafe
Unexecuted instantiation: u32-normalize.c:u8_mbtouc_unsafe
Unexecuted instantiation: u32-cmp.c:u8_mbtouc_unsafe
Unexecuted instantiation: u32-cpy.c:u8_mbtouc_unsafe
Unexecuted instantiation: u32-strlen.c:u8_mbtouc_unsafe
Unexecuted instantiation: u32-to-u8.c:u8_mbtouc_unsafe
Unexecuted instantiation: u8-strlen.c:u8_mbtouc_unsafe
Unexecuted instantiation: u8-to-u32.c:u8_mbtouc_unsafe
Unexecuted instantiation: u8-uctomb-aux.c:u8_mbtouc_unsafe
u8-casemap.c:u8_mbtouc_unsafe
Line
Count
Source
227
10.2M
{
228
10.2M
  uint8_t c = *s;
229
230
10.2M
  if (c < 0x80)
231
5.58M
    {
232
5.58M
      *puc = c;
233
5.58M
      return 1;
234
5.58M
    }
235
4.69M
  else
236
4.69M
    return u8_mbtouc_unsafe_aux (puc, s, n);
237
10.2M
}
Unexecuted instantiation: u8-conv-from-enc.c:u8_mbtouc_unsafe
u8-normalize.c:u8_mbtouc_unsafe
Line
Count
Source
227
10.2M
{
228
10.2M
  uint8_t c = *s;
229
230
10.2M
  if (c < 0x80)
231
5.58M
    {
232
5.58M
      *puc = c;
233
5.58M
      return 1;
234
5.58M
    }
235
4.69M
  else
236
4.69M
    return u8_mbtouc_unsafe_aux (puc, s, n);
237
10.2M
}
Unexecuted instantiation: u8-check.c:u8_mbtouc_unsafe
Unexecuted instantiation: u8-cpy.c:u8_mbtouc_unsafe
Unexecuted instantiation: u8-mblen.c:u8_mbtouc_unsafe
Unexecuted instantiation: u8-mbtouc-unsafe-aux.c:u8_mbtouc_unsafe
Unexecuted instantiation: u8-mbtoucr.c:u8_mbtouc_unsafe
Unexecuted instantiation: striconveh.c:u8_mbtouc_unsafe
Unexecuted instantiation: u8-mbtouc-aux.c:u8_mbtouc_unsafe
Unexecuted instantiation: u8-prev.c:u8_mbtouc_unsafe
238
# endif
239
#endif
240
241
#if 1
242
# if !UNISTRING_HAVE_INLINE
243
extern int
244
       u16_mbtouc_unsafe (ucs4_t *puc, const uint16_t *s, size_t n);
245
# else
246
extern int
247
       u16_mbtouc_unsafe_aux (ucs4_t *puc, const uint16_t *s, size_t n);
248
static inline int
249
u16_mbtouc_unsafe (ucs4_t *puc, const uint16_t *s, size_t n)
250
0
{
251
0
  uint16_t c = *s;
252
0
253
0
  if (c < 0xd800 || c >= 0xe000)
254
0
    {
255
0
      *puc = c;
256
0
      return 1;
257
0
    }
258
0
  else
259
0
    return u16_mbtouc_unsafe_aux (puc, s, n);
260
0
}
Unexecuted instantiation: u8-strconv-from-enc.c:u16_mbtouc_unsafe
Unexecuted instantiation: u32-normalize.c:u16_mbtouc_unsafe
Unexecuted instantiation: u32-cmp.c:u16_mbtouc_unsafe
Unexecuted instantiation: u32-cpy.c:u16_mbtouc_unsafe
Unexecuted instantiation: u32-strlen.c:u16_mbtouc_unsafe
Unexecuted instantiation: u32-to-u8.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-strlen.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-to-u32.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-uctomb-aux.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-casemap.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-conv-from-enc.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-normalize.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-check.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-cpy.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-mblen.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-mbtouc-unsafe-aux.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-mbtoucr.c:u16_mbtouc_unsafe
Unexecuted instantiation: striconveh.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-mbtouc-aux.c:u16_mbtouc_unsafe
Unexecuted instantiation: u8-prev.c:u16_mbtouc_unsafe
261
# endif
262
#endif
263
264
#if 1
265
# if !UNISTRING_HAVE_INLINE
266
extern int
267
       u32_mbtouc_unsafe (ucs4_t *puc, const uint32_t *s, size_t n);
268
# else
269
static inline int
270
u32_mbtouc_unsafe (ucs4_t *puc,
271
                   const uint32_t *s, _GL_ATTRIBUTE_MAYBE_UNUSED size_t n)
272
14.0M
{
273
14.0M
  uint32_t c = *s;
274
275
14.0M
  if (c < 0xd800 || (c >= 0xe000 && c < 0x110000))
276
14.0M
    *puc = c;
277
212
  else
278
    /* invalid multibyte character */
279
212
    *puc = 0xfffd;
280
14.0M
  return 1;
281
14.0M
}
Unexecuted instantiation: u8-strconv-from-enc.c:u32_mbtouc_unsafe
u32-normalize.c:u32_mbtouc_unsafe
Line
Count
Source
272
14.0M
{
273
14.0M
  uint32_t c = *s;
274
275
14.0M
  if (c < 0xd800 || (c >= 0xe000 && c < 0x110000))
276
14.0M
    *puc = c;
277
212
  else
278
    /* invalid multibyte character */
279
212
    *puc = 0xfffd;
280
14.0M
  return 1;
281
14.0M
}
Unexecuted instantiation: u32-cmp.c:u32_mbtouc_unsafe
Unexecuted instantiation: u32-cpy.c:u32_mbtouc_unsafe
Unexecuted instantiation: u32-strlen.c:u32_mbtouc_unsafe
Unexecuted instantiation: u32-to-u8.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-strlen.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-to-u32.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-uctomb-aux.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-casemap.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-conv-from-enc.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-normalize.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-check.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-cpy.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-mblen.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-mbtouc-unsafe-aux.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-mbtoucr.c:u32_mbtouc_unsafe
Unexecuted instantiation: striconveh.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-mbtouc-aux.c:u32_mbtouc_unsafe
Unexecuted instantiation: u8-prev.c:u32_mbtouc_unsafe
282
# endif
283
#endif
284
285
#if 1
286
# if !UNISTRING_HAVE_INLINE
287
extern int
288
       u8_mbtouc (ucs4_t *puc, const uint8_t *s, size_t n);
289
# else
290
extern int
291
       u8_mbtouc_aux (ucs4_t *puc, const uint8_t *s, size_t n);
292
static inline int
293
u8_mbtouc (ucs4_t *puc, const uint8_t *s, size_t n)
294
0
{
295
0
  uint8_t c = *s;
296
297
0
  if (c < 0x80)
298
0
    {
299
0
      *puc = c;
300
0
      return 1;
301
0
    }
302
0
  else
303
0
    return u8_mbtouc_aux (puc, s, n);
304
0
}
Unexecuted instantiation: u8-strconv-from-enc.c:u8_mbtouc
Unexecuted instantiation: u32-normalize.c:u8_mbtouc
Unexecuted instantiation: u32-cmp.c:u8_mbtouc
Unexecuted instantiation: u32-cpy.c:u8_mbtouc
Unexecuted instantiation: u32-strlen.c:u8_mbtouc
Unexecuted instantiation: u32-to-u8.c:u8_mbtouc
Unexecuted instantiation: u8-strlen.c:u8_mbtouc
Unexecuted instantiation: u8-to-u32.c:u8_mbtouc
Unexecuted instantiation: u8-uctomb-aux.c:u8_mbtouc
Unexecuted instantiation: u8-casemap.c:u8_mbtouc
Unexecuted instantiation: u8-conv-from-enc.c:u8_mbtouc
Unexecuted instantiation: u8-normalize.c:u8_mbtouc
Unexecuted instantiation: u8-check.c:u8_mbtouc
Unexecuted instantiation: u8-cpy.c:u8_mbtouc
Unexecuted instantiation: u8-mblen.c:u8_mbtouc
Unexecuted instantiation: u8-mbtouc-unsafe-aux.c:u8_mbtouc
Unexecuted instantiation: u8-mbtoucr.c:u8_mbtouc
Unexecuted instantiation: striconveh.c:u8_mbtouc
Unexecuted instantiation: u8-mbtouc-aux.c:u8_mbtouc
Unexecuted instantiation: u8-prev.c:u8_mbtouc
305
# endif
306
#endif
307
308
#if 1
309
# if !UNISTRING_HAVE_INLINE
310
extern int
311
       u16_mbtouc (ucs4_t *puc, const uint16_t *s, size_t n);
312
# else
313
extern int
314
       u16_mbtouc_aux (ucs4_t *puc, const uint16_t *s, size_t n);
315
static inline int
316
u16_mbtouc (ucs4_t *puc, const uint16_t *s, size_t n)
317
0
{
318
0
  uint16_t c = *s;
319
0
320
0
  if (c < 0xd800 || c >= 0xe000)
321
0
    {
322
0
      *puc = c;
323
0
      return 1;
324
0
    }
325
0
  else
326
0
    return u16_mbtouc_aux (puc, s, n);
327
0
}
Unexecuted instantiation: u8-strconv-from-enc.c:u16_mbtouc
Unexecuted instantiation: u32-normalize.c:u16_mbtouc
Unexecuted instantiation: u32-cmp.c:u16_mbtouc
Unexecuted instantiation: u32-cpy.c:u16_mbtouc
Unexecuted instantiation: u32-strlen.c:u16_mbtouc
Unexecuted instantiation: u32-to-u8.c:u16_mbtouc
Unexecuted instantiation: u8-strlen.c:u16_mbtouc
Unexecuted instantiation: u8-to-u32.c:u16_mbtouc
Unexecuted instantiation: u8-uctomb-aux.c:u16_mbtouc
Unexecuted instantiation: u8-casemap.c:u16_mbtouc
Unexecuted instantiation: u8-conv-from-enc.c:u16_mbtouc
Unexecuted instantiation: u8-normalize.c:u16_mbtouc
Unexecuted instantiation: u8-check.c:u16_mbtouc
Unexecuted instantiation: u8-cpy.c:u16_mbtouc
Unexecuted instantiation: u8-mblen.c:u16_mbtouc
Unexecuted instantiation: u8-mbtouc-unsafe-aux.c:u16_mbtouc
Unexecuted instantiation: u8-mbtoucr.c:u16_mbtouc
Unexecuted instantiation: striconveh.c:u16_mbtouc
Unexecuted instantiation: u8-mbtouc-aux.c:u16_mbtouc
Unexecuted instantiation: u8-prev.c:u16_mbtouc
328
# endif
329
#endif
330
331
#if 1
332
# if !UNISTRING_HAVE_INLINE
333
extern int
334
       u32_mbtouc (ucs4_t *puc, const uint32_t *s, size_t n);
335
# else
336
static inline int
337
u32_mbtouc (ucs4_t *puc, const uint32_t *s,
338
            _GL_ATTRIBUTE_MAYBE_UNUSED size_t n)
339
0
{
340
0
  uint32_t c = *s;
341
0
342
0
  if (c < 0xd800 || (c >= 0xe000 && c < 0x110000))
343
0
    *puc = c;
344
0
  else
345
0
    /* invalid multibyte character */
346
0
    *puc = 0xfffd;
347
0
  return 1;
348
0
}
Unexecuted instantiation: u8-strconv-from-enc.c:u32_mbtouc
Unexecuted instantiation: u32-normalize.c:u32_mbtouc
Unexecuted instantiation: u32-cmp.c:u32_mbtouc
Unexecuted instantiation: u32-cpy.c:u32_mbtouc
Unexecuted instantiation: u32-strlen.c:u32_mbtouc
Unexecuted instantiation: u32-to-u8.c:u32_mbtouc
Unexecuted instantiation: u8-strlen.c:u32_mbtouc
Unexecuted instantiation: u8-to-u32.c:u32_mbtouc
Unexecuted instantiation: u8-uctomb-aux.c:u32_mbtouc
Unexecuted instantiation: u8-casemap.c:u32_mbtouc
Unexecuted instantiation: u8-conv-from-enc.c:u32_mbtouc
Unexecuted instantiation: u8-normalize.c:u32_mbtouc
Unexecuted instantiation: u8-check.c:u32_mbtouc
Unexecuted instantiation: u8-cpy.c:u32_mbtouc
Unexecuted instantiation: u8-mblen.c:u32_mbtouc
Unexecuted instantiation: u8-mbtouc-unsafe-aux.c:u32_mbtouc
Unexecuted instantiation: u8-mbtoucr.c:u32_mbtouc
Unexecuted instantiation: striconveh.c:u32_mbtouc
Unexecuted instantiation: u8-mbtouc-aux.c:u32_mbtouc
Unexecuted instantiation: u8-prev.c:u32_mbtouc
349
# endif
350
#endif
351
352
/* Return the length (number of units) of the first character in S, putting
353
   its 'ucs4_t' representation in *PUC.  Upon failure, *PUC is set to 0xfffd,
354
   and -1 is returned for an invalid sequence of units, -2 is returned for an
355
   incomplete sequence of units.
356
   The number of available units, N, must be > 0.  */
357
/* Similar to u*_mbtouc(), except that the return value gives more details
358
   about the failure, similar to mbrtowc().  */
359
360
#if 1
361
extern int
362
       u8_mbtoucr (ucs4_t *puc, const uint8_t *s, size_t n);
363
#endif
364
365
#if 1
366
extern int
367
       u16_mbtoucr (ucs4_t *puc, const uint16_t *s, size_t n);
368
#endif
369
370
#if 1
371
extern int
372
       u32_mbtoucr (ucs4_t *puc, const uint32_t *s, size_t n);
373
#endif
374
375
/* Put the multibyte character represented by UC in S, returning its
376
   length.  Return -1 upon failure, -2 if the number of available units, N,
377
   is too small.  The latter case cannot occur if N >= 6/2/1, respectively.  */
378
/* Similar to wctomb(), except that s must not be NULL, and the argument n
379
   must be specified.  */
380
381
#if 1
382
/* Auxiliary function, also used by u8_chr, u8_strchr, u8_strrchr.  */
383
extern int
384
       u8_uctomb_aux (uint8_t *s, ucs4_t uc, ptrdiff_t n);
385
# if !UNISTRING_HAVE_INLINE
386
extern int
387
       u8_uctomb (uint8_t *s, ucs4_t uc, ptrdiff_t n);
388
# else
389
static inline int
390
u8_uctomb (uint8_t *s, ucs4_t uc, ptrdiff_t n)
391
33.1M
{
392
33.1M
  if (uc < 0x80 && n > 0)
393
17.0M
    {
394
17.0M
      s[0] = uc;
395
17.0M
      return 1;
396
17.0M
    }
397
16.1M
  else
398
16.1M
    return u8_uctomb_aux (s, uc, n);
399
33.1M
}
Unexecuted instantiation: u8-strconv-from-enc.c:u8_uctomb
Unexecuted instantiation: u32-normalize.c:u8_uctomb
Unexecuted instantiation: u32-cmp.c:u8_uctomb
Unexecuted instantiation: u32-cpy.c:u8_uctomb
Unexecuted instantiation: u32-strlen.c:u8_uctomb
u32-to-u8.c:u8_uctomb
Line
Count
Source
391
12.2M
{
392
12.2M
  if (uc < 0x80 && n > 0)
393
5.42M
    {
394
5.42M
      s[0] = uc;
395
5.42M
      return 1;
396
5.42M
    }
397
6.79M
  else
398
6.79M
    return u8_uctomb_aux (s, uc, n);
399
12.2M
}
Unexecuted instantiation: u8-strlen.c:u8_uctomb
Unexecuted instantiation: u8-to-u32.c:u8_uctomb
Unexecuted instantiation: u8-uctomb-aux.c:u8_uctomb
u8-casemap.c:u8_uctomb
Line
Count
Source
391
10.2M
{
392
10.2M
  if (uc < 0x80 && n > 0)
393
5.58M
    {
394
5.58M
      s[0] = uc;
395
5.58M
      return 1;
396
5.58M
    }
397
4.69M
  else
398
4.69M
    return u8_uctomb_aux (s, uc, n);
399
10.2M
}
Unexecuted instantiation: u8-conv-from-enc.c:u8_uctomb
u8-normalize.c:u8_uctomb
Line
Count
Source
391
10.6M
{
392
10.6M
  if (uc < 0x80 && n > 0)
393
6.00M
    {
394
6.00M
      s[0] = uc;
395
6.00M
      return 1;
396
6.00M
    }
397
4.63M
  else
398
4.63M
    return u8_uctomb_aux (s, uc, n);
399
10.6M
}
Unexecuted instantiation: u8-check.c:u8_uctomb
Unexecuted instantiation: u8-cpy.c:u8_uctomb
Unexecuted instantiation: u8-mblen.c:u8_uctomb
Unexecuted instantiation: u8-mbtouc-unsafe-aux.c:u8_uctomb
Unexecuted instantiation: u8-mbtoucr.c:u8_uctomb
Unexecuted instantiation: striconveh.c:u8_uctomb
Unexecuted instantiation: u8-mbtouc-aux.c:u8_uctomb
Unexecuted instantiation: u8-prev.c:u8_uctomb
400
# endif
401
#endif
402
403
#if 1
404
/* Auxiliary function, also used by u16_chr, u16_strchr, u16_strrchr.  */
405
extern int
406
       u16_uctomb_aux (uint16_t *s, ucs4_t uc, ptrdiff_t n);
407
# if !UNISTRING_HAVE_INLINE
408
extern int
409
       u16_uctomb (uint16_t *s, ucs4_t uc, ptrdiff_t n);
410
# else
411
static inline int
412
u16_uctomb (uint16_t *s, ucs4_t uc, ptrdiff_t n)
413
0
{
414
0
  if (uc < 0xd800 && n > 0)
415
0
    {
416
0
      s[0] = uc;
417
0
      return 1;
418
0
    }
419
0
  else
420
0
    return u16_uctomb_aux (s, uc, n);
421
0
}
Unexecuted instantiation: u8-strconv-from-enc.c:u16_uctomb
Unexecuted instantiation: u32-normalize.c:u16_uctomb
Unexecuted instantiation: u32-cmp.c:u16_uctomb
Unexecuted instantiation: u32-cpy.c:u16_uctomb
Unexecuted instantiation: u32-strlen.c:u16_uctomb
Unexecuted instantiation: u32-to-u8.c:u16_uctomb
Unexecuted instantiation: u8-strlen.c:u16_uctomb
Unexecuted instantiation: u8-to-u32.c:u16_uctomb
Unexecuted instantiation: u8-uctomb-aux.c:u16_uctomb
Unexecuted instantiation: u8-casemap.c:u16_uctomb
Unexecuted instantiation: u8-conv-from-enc.c:u16_uctomb
Unexecuted instantiation: u8-normalize.c:u16_uctomb
Unexecuted instantiation: u8-check.c:u16_uctomb
Unexecuted instantiation: u8-cpy.c:u16_uctomb
Unexecuted instantiation: u8-mblen.c:u16_uctomb
Unexecuted instantiation: u8-mbtouc-unsafe-aux.c:u16_uctomb
Unexecuted instantiation: u8-mbtoucr.c:u16_uctomb
Unexecuted instantiation: striconveh.c:u16_uctomb
Unexecuted instantiation: u8-mbtouc-aux.c:u16_uctomb
Unexecuted instantiation: u8-prev.c:u16_uctomb
422
# endif
423
#endif
424
425
#if 1
426
# if !UNISTRING_HAVE_INLINE
427
extern int
428
       u32_uctomb (uint32_t *s, ucs4_t uc, ptrdiff_t n);
429
# else
430
static inline int
431
u32_uctomb (uint32_t *s, ucs4_t uc, ptrdiff_t n)
432
14.0M
{
433
14.0M
  if (uc < 0xd800 || (uc >= 0xe000 && uc < 0x110000))
434
14.0M
    {
435
14.0M
      if (n > 0)
436
14.0M
        {
437
14.0M
          *s = uc;
438
14.0M
          return 1;
439
14.0M
        }
440
0
      else
441
0
        return -2;
442
14.0M
    }
443
0
  else
444
0
    return -1;
445
14.0M
}
Unexecuted instantiation: u8-strconv-from-enc.c:u32_uctomb
u32-normalize.c:u32_uctomb
Line
Count
Source
432
14.0M
{
433
14.0M
  if (uc < 0xd800 || (uc >= 0xe000 && uc < 0x110000))
434
14.0M
    {
435
14.0M
      if (n > 0)
436
14.0M
        {
437
14.0M
          *s = uc;
438
14.0M
          return 1;
439
14.0M
        }
440
0
      else
441
0
        return -2;
442
14.0M
    }
443
0
  else
444
0
    return -1;
445
14.0M
}
Unexecuted instantiation: u32-cmp.c:u32_uctomb
Unexecuted instantiation: u32-cpy.c:u32_uctomb
Unexecuted instantiation: u32-strlen.c:u32_uctomb
Unexecuted instantiation: u32-to-u8.c:u32_uctomb
Unexecuted instantiation: u8-strlen.c:u32_uctomb
Unexecuted instantiation: u8-to-u32.c:u32_uctomb
Unexecuted instantiation: u8-uctomb-aux.c:u32_uctomb
Unexecuted instantiation: u8-casemap.c:u32_uctomb
Unexecuted instantiation: u8-conv-from-enc.c:u32_uctomb
Unexecuted instantiation: u8-normalize.c:u32_uctomb
Unexecuted instantiation: u8-check.c:u32_uctomb
Unexecuted instantiation: u8-cpy.c:u32_uctomb
Unexecuted instantiation: u8-mblen.c:u32_uctomb
Unexecuted instantiation: u8-mbtouc-unsafe-aux.c:u32_uctomb
Unexecuted instantiation: u8-mbtoucr.c:u32_uctomb
Unexecuted instantiation: striconveh.c:u32_uctomb
Unexecuted instantiation: u8-mbtouc-aux.c:u32_uctomb
Unexecuted instantiation: u8-prev.c:u32_uctomb
446
# endif
447
#endif
448
449
/* Copy N units from SRC to DEST.  */
450
/* Similar to memcpy().  */
451
extern uint8_t *
452
       u8_cpy (uint8_t *_UC_RESTRICT dest, const uint8_t *src, size_t n);
453
extern uint16_t *
454
       u16_cpy (uint16_t *_UC_RESTRICT dest, const uint16_t *src, size_t n);
455
extern uint32_t *
456
       u32_cpy (uint32_t *_UC_RESTRICT dest, const uint32_t *src, size_t n);
457
458
/* Copy N units from SRC to DEST, returning pointer after last written unit.  */
459
/* Similar to mempcpy().  */
460
extern uint8_t *
461
       u8_pcpy (uint8_t *_UC_RESTRICT dest, const uint8_t *src, size_t n);
462
extern uint16_t *
463
       u16_pcpy (uint16_t *_UC_RESTRICT dest, const uint16_t *src, size_t n);
464
extern uint32_t *
465
       u32_pcpy (uint32_t *_UC_RESTRICT dest, const uint32_t *src, size_t n);
466
467
/* Copy N units from SRC to DEST, guaranteeing correct behavior for
468
   overlapping memory areas.  */
469
/* Similar to memmove().  */
470
extern uint8_t *
471
       u8_move (uint8_t *dest, const uint8_t *src, size_t n);
472
extern uint16_t *
473
       u16_move (uint16_t *dest, const uint16_t *src, size_t n);
474
extern uint32_t *
475
       u32_move (uint32_t *dest, const uint32_t *src, size_t n);
476
477
/* Set the first N characters of S to UC.  UC should be a character that
478
   occupies only 1 unit.  */
479
/* Similar to memset().  */
480
extern uint8_t *
481
       u8_set (uint8_t *s, ucs4_t uc, size_t n);
482
extern uint16_t *
483
       u16_set (uint16_t *s, ucs4_t uc, size_t n);
484
extern uint32_t *
485
       u32_set (uint32_t *s, ucs4_t uc, size_t n);
486
487
/* Compare S1 and S2, each of length N.  */
488
/* Similar to memcmp().  */
489
extern int
490
       u8_cmp (const uint8_t *s1, const uint8_t *s2, size_t n)
491
       _UC_ATTRIBUTE_PURE;
492
extern int
493
       u16_cmp (const uint16_t *s1, const uint16_t *s2, size_t n)
494
       _UC_ATTRIBUTE_PURE;
495
extern int
496
       u32_cmp (const uint32_t *s1, const uint32_t *s2, size_t n)
497
       _UC_ATTRIBUTE_PURE;
498
499
/* Compare S1 and S2.  */
500
/* Similar to the gnulib function memcmp2().  */
501
extern int
502
       u8_cmp2 (const uint8_t *s1, size_t n1, const uint8_t *s2, size_t n2)
503
       _UC_ATTRIBUTE_PURE;
504
extern int
505
       u16_cmp2 (const uint16_t *s1, size_t n1, const uint16_t *s2, size_t n2)
506
       _UC_ATTRIBUTE_PURE;
507
extern int
508
       u32_cmp2 (const uint32_t *s1, size_t n1, const uint32_t *s2, size_t n2)
509
       _UC_ATTRIBUTE_PURE;
510
511
/* Search the string at S for UC.  */
512
/* Similar to memchr().  */
513
extern uint8_t *
514
       u8_chr (const uint8_t *s, size_t n, ucs4_t uc)
515
       _UC_ATTRIBUTE_PURE;
516
extern uint16_t *
517
       u16_chr (const uint16_t *s, size_t n, ucs4_t uc)
518
       _UC_ATTRIBUTE_PURE;
519
extern uint32_t *
520
       u32_chr (const uint32_t *s, size_t n, ucs4_t uc)
521
       _UC_ATTRIBUTE_PURE;
522
#ifndef _LIBUNISTRING_NO_CONST_GENERICS
523
/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'.  Programmers
524
   want compiler warnings for 'const' related mistakes.  */
525
# ifdef __cplusplus
526
template <typename T>
527
  T * u8_chr_template (T* str, size_t n, ucs4_t uc);
528
template <>
529
  inline uint8_t * u8_chr_template (uint8_t *str, size_t n, ucs4_t uc)
530
  { return u8_chr (str, n, uc); }
531
template <>
532
  inline const uint8_t * u8_chr_template (const uint8_t *str, size_t n, ucs4_t uc)
533
  { return u8_chr (str, n, uc); }
534
#  undef u8_chr
535
#  define u8_chr u8_chr_template
536
# elif !defined u8_chr
537
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
538
       || defined __ICC  || defined __TINYC__ \
539
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
540
#   define u8_chr(s,n,u) \
541
      _Generic ((s), \
542
                uint8_t const *: (uint8_t const *) u8_chr ((s), (n), (u)), \
543
                default        :                   u8_chr ((s), (n), (u)))
544
#  endif
545
# endif
546
# ifdef __cplusplus
547
template <typename T>
548
  T * u16_chr_template (T* str, size_t n, ucs4_t uc);
549
template <>
550
  inline uint16_t * u16_chr_template (uint16_t *str, size_t n, ucs4_t uc)
551
  { return u16_chr (str, n, uc); }
552
template <>
553
  inline const uint16_t * u16_chr_template (const uint16_t *str, size_t n, ucs4_t uc)
554
  { return u16_chr (str, n, uc); }
555
#  undef u16_chr
556
#  define u16_chr u16_chr_template
557
# elif !defined u16_chr
558
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
559
       || defined __ICC  || defined __TINYC__ \
560
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
561
#   define u16_chr(s,n,u) \
562
      _Generic ((s), \
563
                uint16_t const *: (uint16_t const *) u16_chr ((s), (n), (u)), \
564
                default         :                    u16_chr ((s), (n), (u)))
565
#  endif
566
# endif
567
# ifdef __cplusplus
568
template <typename T>
569
  T * u32_chr_template (T* str, size_t n, ucs4_t uc);
570
template <>
571
  inline uint32_t * u32_chr_template (uint32_t *str, size_t n, ucs4_t uc)
572
  { return u32_chr (str, n, uc); }
573
template <>
574
  inline const uint32_t * u32_chr_template (const uint32_t *str, size_t n, ucs4_t uc)
575
  { return u32_chr (str, n, uc); }
576
#  undef u32_chr
577
#  define u32_chr u32_chr_template
578
# elif !defined u32_chr
579
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
580
       || defined __ICC  || defined __TINYC__ \
581
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
582
#   define u32_chr(s,n,u) \
583
      _Generic ((s), \
584
                uint32_t const *: (uint32_t const *) u32_chr ((s), (n), (u)), \
585
                default         :                    u32_chr ((s), (n), (u)))
586
#  endif
587
# endif
588
#endif
589
590
/* Count the number of Unicode characters in the N units from S.  */
591
/* Similar to mbsnlen().  */
592
extern size_t
593
       u8_mbsnlen (const uint8_t *s, size_t n)
594
       _UC_ATTRIBUTE_PURE;
595
extern size_t
596
       u16_mbsnlen (const uint16_t *s, size_t n)
597
       _UC_ATTRIBUTE_PURE;
598
extern size_t
599
       u32_mbsnlen (const uint32_t *s, size_t n)
600
       _UC_ATTRIBUTE_PURE;
601
602
/* Elementary string functions with memory allocation.  */
603
604
/* Make a freshly allocated copy of S, of length N.  */
605
extern uint8_t *
606
       u8_cpy_alloc (const uint8_t *s, size_t n);
607
extern uint16_t *
608
       u16_cpy_alloc (const uint16_t *s, size_t n);
609
extern uint32_t *
610
       u32_cpy_alloc (const uint32_t *s, size_t n);
611
612
/* Elementary string functions on NUL terminated strings.  */
613
614
/* Return the length (number of units) of the first character in S.
615
   Return 0 if it is the NUL character.  Return -1 upon failure.  */
616
extern int
617
       u8_strmblen (const uint8_t *s)
618
       _UC_ATTRIBUTE_PURE;
619
extern int
620
       u16_strmblen (const uint16_t *s)
621
       _UC_ATTRIBUTE_PURE;
622
extern int
623
       u32_strmblen (const uint32_t *s)
624
       _UC_ATTRIBUTE_PURE;
625
626
/* Return the length (number of units) of the first character in S, putting
627
   its 'ucs4_t' representation in *PUC.  Return 0 if it is the NUL
628
   character.  Return -1 upon failure.  */
629
extern int
630
       u8_strmbtouc (ucs4_t *puc, const uint8_t *s);
631
extern int
632
       u16_strmbtouc (ucs4_t *puc, const uint16_t *s);
633
extern int
634
       u32_strmbtouc (ucs4_t *puc, const uint32_t *s);
635
636
/* Forward iteration step.  Advances the pointer past the next character,
637
   or returns NULL if the end of the string has been reached.  Puts the
638
   character's 'ucs4_t' representation in *PUC.  */
639
extern const uint8_t *
640
       u8_next (ucs4_t *puc, const uint8_t *s);
641
extern const uint16_t *
642
       u16_next (ucs4_t *puc, const uint16_t *s);
643
extern const uint32_t *
644
       u32_next (ucs4_t *puc, const uint32_t *s);
645
#ifndef _LIBUNISTRING_NO_CONST_GENERICS
646
/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'.  Programmers
647
   want compiler warnings for 'const' related mistakes.  */
648
# ifdef __cplusplus
649
template <typename T>
650
  T * u8_next_template (ucs4_t *puc, T* s);
651
template <>
652
  inline uint8_t * u8_next_template (ucs4_t *puc, uint8_t *s)
653
  { return const_cast<uint8_t *>(u8_next (puc, s)); }
654
template <>
655
  inline const uint8_t * u8_next_template (ucs4_t *puc, const uint8_t *s)
656
  { return u8_next (puc, s); }
657
#  undef u8_next
658
#  define u8_next u8_next_template
659
# elif !defined u8_next
660
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
661
       || defined __ICC  || defined __TINYC__ \
662
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
663
#   define u8_next(p,s) \
664
      _Generic ((s), \
665
                uint8_t *: (uint8_t *) u8_next ((p), (s)), \
666
                default  :             u8_next ((p), (s)))
667
#  endif
668
# endif
669
# ifdef __cplusplus
670
template <typename T>
671
  T * u16_next_template (ucs4_t *puc, T* s);
672
template <>
673
  inline uint16_t * u16_next_template (ucs4_t *puc, uint16_t *s)
674
  { return const_cast<uint16_t *>(u16_next (puc, s)); }
675
template <>
676
  inline const uint16_t * u16_next_template (ucs4_t *puc, const uint16_t *s)
677
  { return u16_next (puc, s); }
678
#  undef u16_next
679
#  define u16_next u16_next_template
680
# elif !defined u16_next
681
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
682
       || defined __ICC  || defined __TINYC__ \
683
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
684
#   define u16_next(p,s) \
685
      _Generic ((s), \
686
                uint16_t *: (uint16_t *) u16_next ((p), (s)), \
687
                default   :              u16_next ((p), (s)))
688
#  endif
689
# endif
690
# ifdef __cplusplus
691
template <typename T>
692
  T * u32_next_template (ucs4_t *puc, T* s);
693
template <>
694
  inline uint32_t * u32_next_template (ucs4_t *puc, uint32_t *s)
695
  { return const_cast<uint32_t *>(u32_next (puc, s)); }
696
template <>
697
  inline const uint32_t * u32_next_template (ucs4_t *puc, const uint32_t *s)
698
  { return u32_next (puc, s); }
699
#  undef u32_next
700
#  define u32_next u32_next_template
701
# elif !defined u32_next
702
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
703
       || defined __ICC  || defined __TINYC__ \
704
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
705
#   define u32_next(p,s) \
706
      _Generic ((s), \
707
                uint32_t *: (uint32_t *) u32_next ((p), (s)), \
708
                default   :              u32_next ((p), (s)))
709
#  endif
710
# endif
711
#endif
712
713
/* Backward iteration step.  Advances the pointer to point to the previous
714
   character, or returns NULL if the beginning of the string had been reached.
715
   Puts the character's 'ucs4_t' representation in *PUC.  */
716
extern const uint8_t *
717
       u8_prev (ucs4_t *puc, const uint8_t *s, const uint8_t *start);
718
extern const uint16_t *
719
       u16_prev (ucs4_t *puc, const uint16_t *s, const uint16_t *start);
720
extern const uint32_t *
721
       u32_prev (ucs4_t *puc, const uint32_t *s, const uint32_t *start);
722
#ifndef _LIBUNISTRING_NO_CONST_GENERICS
723
/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'.  Programmers
724
   want compiler warnings for 'const' related mistakes.  */
725
# ifdef __cplusplus
726
template <typename T>
727
  T * u8_prev_template (ucs4_t *puc, T* s, const uint8_t *start);
728
template <>
729
  inline uint8_t * u8_prev_template (ucs4_t *puc, uint8_t *s, const uint8_t *start)
730
  { return const_cast<uint8_t *>(u8_prev (puc, s, start)); }
731
template <>
732
  inline const uint8_t * u8_prev_template (ucs4_t *puc, const uint8_t *s, const uint8_t *start)
733
  { return u8_prev (puc, s, start); }
734
#  undef u8_prev
735
#  define u8_prev u8_prev_template
736
# elif !defined u8_prev
737
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
738
       || defined __ICC  || defined __TINYC__ \
739
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
740
#   define u8_prev(p,s,start) \
741
0
      _Generic ((s), \
742
0
                uint8_t *: (uint8_t *) u8_prev ((p), (s), (start)), \
743
0
                default  :             u8_prev ((p), (s), (start)))
744
#  endif
745
# endif
746
# ifdef __cplusplus
747
template <typename T>
748
  T * u16_prev_template (ucs4_t *puc, T* s, const uint16_t *start);
749
template <>
750
  inline uint16_t * u16_prev_template (ucs4_t *puc, uint16_t *s, const uint16_t *start)
751
  { return const_cast<uint16_t *>(u16_prev (puc, s, start)); }
752
template <>
753
  inline const uint16_t * u16_prev_template (ucs4_t *puc, const uint16_t *s, const uint16_t *start)
754
  { return u16_prev (puc, s, start); }
755
#  undef u16_prev
756
#  define u16_prev u16_prev_template
757
# elif !defined u16_prev
758
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
759
       || defined __ICC  || defined __TINYC__ \
760
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
761
#   define u16_prev(p,s,start) \
762
      _Generic ((s), \
763
                uint16_t *: (uint16_t *) u16_prev ((p), (s), (start)), \
764
                default   :              u16_prev ((p), (s), (start)))
765
#  endif
766
# endif
767
# ifdef __cplusplus
768
template <typename T>
769
  T * u32_prev_template (ucs4_t *puc, T* s, const uint32_t *start);
770
template <>
771
  inline uint32_t * u32_prev_template (ucs4_t *puc, uint32_t *s, const uint32_t *start)
772
  { return const_cast<uint32_t *>(u32_prev (puc, s, start)); }
773
template <>
774
  inline const uint32_t * u32_prev_template (ucs4_t *puc, const uint32_t *s, const uint32_t *start)
775
  { return u32_prev (puc, s, start); }
776
#  undef u32_prev
777
#  define u32_prev u32_prev_template
778
# elif !defined u32_prev
779
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
780
       || defined __ICC  || defined __TINYC__ \
781
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
782
#   define u32_prev(p,s,start) \
783
      _Generic ((s), \
784
                uint32_t *: (uint32_t *) u32_prev ((p), (s), (start)), \
785
                default   :              u32_prev ((p), (s), (start)))
786
#  endif
787
# endif
788
#endif
789
790
/* Return the number of units in S.  */
791
/* Similar to strlen(), wcslen().  */
792
extern size_t
793
       u8_strlen (const uint8_t *s)
794
       _UC_ATTRIBUTE_PURE;
795
extern size_t
796
       u16_strlen (const uint16_t *s)
797
       _UC_ATTRIBUTE_PURE;
798
extern size_t
799
       u32_strlen (const uint32_t *s)
800
       _UC_ATTRIBUTE_PURE;
801
802
/* Return the number of units in S, but at most MAXLEN.  */
803
/* Similar to strnlen(), wcsnlen().  */
804
extern size_t
805
       u8_strnlen (const uint8_t *s, size_t maxlen)
806
       _UC_ATTRIBUTE_PURE;
807
extern size_t
808
       u16_strnlen (const uint16_t *s, size_t maxlen)
809
       _UC_ATTRIBUTE_PURE;
810
extern size_t
811
       u32_strnlen (const uint32_t *s, size_t maxlen)
812
       _UC_ATTRIBUTE_PURE;
813
814
/* Copy SRC to DEST.  */
815
/* Similar to strcpy(), wcscpy().  */
816
extern uint8_t *
817
       u8_strcpy (uint8_t *_UC_RESTRICT dest, const uint8_t *src);
818
extern uint16_t *
819
       u16_strcpy (uint16_t *_UC_RESTRICT dest, const uint16_t *src);
820
extern uint32_t *
821
       u32_strcpy (uint32_t *_UC_RESTRICT dest, const uint32_t *src);
822
823
/* Copy SRC to DEST, returning the address of the terminating NUL in DEST.  */
824
/* Similar to stpcpy().  */
825
extern uint8_t *
826
       u8_stpcpy (uint8_t *_UC_RESTRICT dest, const uint8_t *src);
827
extern uint16_t *
828
       u16_stpcpy (uint16_t *_UC_RESTRICT dest, const uint16_t *src);
829
extern uint32_t *
830
       u32_stpcpy (uint32_t *_UC_RESTRICT dest, const uint32_t *src);
831
832
/* Copy no more than N units of SRC to DEST.  */
833
/* Similar to strncpy(), wcsncpy().  */
834
extern uint8_t *
835
       u8_strncpy (uint8_t *_UC_RESTRICT dest, const uint8_t *src, size_t n);
836
extern uint16_t *
837
       u16_strncpy (uint16_t *_UC_RESTRICT dest, const uint16_t *src, size_t n);
838
extern uint32_t *
839
       u32_strncpy (uint32_t *_UC_RESTRICT dest, const uint32_t *src, size_t n);
840
841
/* Copy no more than N units of SRC to DEST.  Return a pointer past the last
842
   non-NUL unit written into DEST.  */
843
/* Similar to stpncpy().  */
844
extern uint8_t *
845
       u8_stpncpy (uint8_t *_UC_RESTRICT dest, const uint8_t *src, size_t n);
846
extern uint16_t *
847
       u16_stpncpy (uint16_t *_UC_RESTRICT dest, const uint16_t *src, size_t n);
848
extern uint32_t *
849
       u32_stpncpy (uint32_t *_UC_RESTRICT dest, const uint32_t *src, size_t n);
850
851
/* Append SRC onto DEST.  */
852
/* Similar to strcat(), wcscat().  */
853
extern uint8_t *
854
       u8_strcat (uint8_t *_UC_RESTRICT dest, const uint8_t *src);
855
extern uint16_t *
856
       u16_strcat (uint16_t *_UC_RESTRICT dest, const uint16_t *src);
857
extern uint32_t *
858
       u32_strcat (uint32_t *_UC_RESTRICT dest, const uint32_t *src);
859
860
/* Append no more than N units of SRC onto DEST.  */
861
/* Similar to strncat(), wcsncat().  */
862
extern uint8_t *
863
       u8_strncat (uint8_t *_UC_RESTRICT dest, const uint8_t *src, size_t n);
864
extern uint16_t *
865
       u16_strncat (uint16_t *_UC_RESTRICT dest, const uint16_t *src, size_t n);
866
extern uint32_t *
867
       u32_strncat (uint32_t *_UC_RESTRICT dest, const uint32_t *src, size_t n);
868
869
/* Compare S1 and S2.  */
870
/* Similar to strcmp(), wcscmp().  */
871
#ifdef __sun
872
/* Avoid a collision with the u8_strcmp() function in Solaris 11 libc.  */
873
extern int
874
       u8_strcmp_gnu (const uint8_t *s1, const uint8_t *s2)
875
       _UC_ATTRIBUTE_PURE;
876
# define u8_strcmp u8_strcmp_gnu
877
#else
878
extern int
879
       u8_strcmp (const uint8_t *s1, const uint8_t *s2)
880
       _UC_ATTRIBUTE_PURE;
881
#endif
882
extern int
883
       u16_strcmp (const uint16_t *s1, const uint16_t *s2)
884
       _UC_ATTRIBUTE_PURE;
885
extern int
886
       u32_strcmp (const uint32_t *s1, const uint32_t *s2)
887
       _UC_ATTRIBUTE_PURE;
888
889
/* Compare S1 and S2 using the collation rules of the current locale.
890
   Return -1 if S1 < S2, 0 if S1 = S2, 1 if S1 > S2.
891
   Upon failure, set errno and return any value.  */
892
/* Similar to strcoll(), wcscoll().  */
893
extern int
894
       u8_strcoll (const uint8_t *s1, const uint8_t *s2);
895
extern int
896
       u16_strcoll (const uint16_t *s1, const uint16_t *s2);
897
extern int
898
       u32_strcoll (const uint32_t *s1, const uint32_t *s2);
899
900
/* Compare no more than N units of S1 and S2.  */
901
/* Similar to strncmp(), wcsncmp().  */
902
extern int
903
       u8_strncmp (const uint8_t *s1, const uint8_t *s2, size_t n)
904
       _UC_ATTRIBUTE_PURE;
905
extern int
906
       u16_strncmp (const uint16_t *s1, const uint16_t *s2, size_t n)
907
       _UC_ATTRIBUTE_PURE;
908
extern int
909
       u32_strncmp (const uint32_t *s1, const uint32_t *s2, size_t n)
910
       _UC_ATTRIBUTE_PURE;
911
912
/* Duplicate S, returning an identical malloc'd string.  */
913
/* Similar to strdup(), wcsdup().  */
914
extern uint8_t *
915
       u8_strdup (const uint8_t *s)
916
       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
917
extern uint16_t *
918
       u16_strdup (const uint16_t *s)
919
       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
920
extern uint32_t *
921
       u32_strdup (const uint32_t *s)
922
       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
923
924
/* Find the first occurrence of UC in STR.  */
925
/* Similar to strchr(), wcschr().  */
926
extern uint8_t *
927
       u8_strchr (const uint8_t *str, ucs4_t uc)
928
       _UC_ATTRIBUTE_PURE;
929
extern uint16_t *
930
       u16_strchr (const uint16_t *str, ucs4_t uc)
931
       _UC_ATTRIBUTE_PURE;
932
extern uint32_t *
933
       u32_strchr (const uint32_t *str, ucs4_t uc)
934
       _UC_ATTRIBUTE_PURE;
935
#ifndef _LIBUNISTRING_NO_CONST_GENERICS
936
/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'.  Programmers
937
   want compiler warnings for 'const' related mistakes.  */
938
# ifdef __cplusplus
939
template <typename T>
940
  T * u8_strchr_template (T* str, ucs4_t uc);
941
template <>
942
  inline uint8_t * u8_strchr_template (uint8_t *str, ucs4_t uc)
943
  { return u8_strchr (str, uc); }
944
template <>
945
  inline const uint8_t * u8_strchr_template (const uint8_t *str, ucs4_t uc)
946
  { return u8_strchr (str, uc); }
947
#  undef u8_strchr
948
#  define u8_strchr u8_strchr_template
949
# elif !defined u8_strchr
950
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
951
       || defined __ICC  || defined __TINYC__ \
952
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
953
#   define u8_strchr(s,u) \
954
      _Generic ((s), \
955
                uint8_t const *: (uint8_t const *) u8_strchr ((s), (u)), \
956
                default        :                   u8_strchr ((s), (u)))
957
#  endif
958
# endif
959
# ifdef __cplusplus
960
template <typename T>
961
  T * u16_strchr_template (T* str, ucs4_t uc);
962
template <>
963
  inline uint16_t * u16_strchr_template (uint16_t *str, ucs4_t uc)
964
  { return u16_strchr (str, uc); }
965
template <>
966
  inline const uint16_t * u16_strchr_template (const uint16_t *str, ucs4_t uc)
967
  { return u16_strchr (str, uc); }
968
#  undef u16_strchr
969
#  define u16_strchr u16_strchr_template
970
# elif !defined u16_strchr
971
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
972
       || defined __ICC  || defined __TINYC__ \
973
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
974
#   define u16_strchr(s,u) \
975
      _Generic ((s), \
976
                uint16_t const *: (uint16_t const *) u16_strchr ((s), (u)), \
977
                default         :                    u16_strchr ((s), (u)))
978
#  endif
979
# endif
980
# ifdef __cplusplus
981
template <typename T>
982
  T * u32_strchr_template (T* str, ucs4_t uc);
983
template <>
984
  inline uint32_t * u32_strchr_template (uint32_t *str, ucs4_t uc)
985
  { return u32_strchr (str, uc); }
986
template <>
987
  inline const uint32_t * u32_strchr_template (const uint32_t *str, ucs4_t uc)
988
  { return u32_strchr (str, uc); }
989
#  undef u32_strchr
990
#  define u32_strchr u32_strchr_template
991
# elif !defined u32_strchr
992
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
993
       || defined __ICC  || defined __TINYC__ \
994
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
995
#   define u32_strchr(s,u) \
996
      _Generic ((s), \
997
                uint32_t const *: (uint32_t const *) u32_strchr ((s), (u)), \
998
                default         :                    u32_strchr ((s), (u)))
999
#  endif
1000
# endif
1001
#endif
1002
1003
/* Find the last occurrence of UC in STR.  */
1004
/* Similar to strrchr(), wcsrchr().  */
1005
extern uint8_t *
1006
       u8_strrchr (const uint8_t *str, ucs4_t uc)
1007
       _UC_ATTRIBUTE_PURE;
1008
extern uint16_t *
1009
       u16_strrchr (const uint16_t *str, ucs4_t uc)
1010
       _UC_ATTRIBUTE_PURE;
1011
extern uint32_t *
1012
       u32_strrchr (const uint32_t *str, ucs4_t uc)
1013
       _UC_ATTRIBUTE_PURE;
1014
#ifndef _LIBUNISTRING_NO_CONST_GENERICS
1015
/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'.  Programmers
1016
   want compiler warnings for 'const' related mistakes.  */
1017
# ifdef __cplusplus
1018
template <typename T>
1019
  T * u8_strrchr_template (T* str, ucs4_t uc);
1020
template <>
1021
  inline uint8_t * u8_strrchr_template (uint8_t *str, ucs4_t uc)
1022
  { return u8_strrchr (str, uc); }
1023
template <>
1024
  inline const uint8_t * u8_strrchr_template (const uint8_t *str, ucs4_t uc)
1025
  { return u8_strrchr (str, uc); }
1026
#  undef u8_strrchr
1027
#  define u8_strrchr u8_strrchr_template
1028
# elif !defined u8_strrchr
1029
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
1030
       || defined __ICC  || defined __TINYC__ \
1031
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
1032
#   define u8_strrchr(s,u) \
1033
      _Generic ((s), \
1034
                uint8_t const *: (uint8_t const *) u8_strrchr ((s), (u)), \
1035
                default        :                   u8_strrchr ((s), (u)))
1036
#  endif
1037
# endif
1038
# ifdef __cplusplus
1039
template <typename T>
1040
  T * u16_strrchr_template (T* str, ucs4_t uc);
1041
template <>
1042
  inline uint16_t * u16_strrchr_template (uint16_t *str, ucs4_t uc)
1043
  { return u16_strrchr (str, uc); }
1044
template <>
1045
  inline const uint16_t * u16_strrchr_template (const uint16_t *str, ucs4_t uc)
1046
  { return u16_strrchr (str, uc); }
1047
#  undef u16_strrchr
1048
#  define u16_strrchr u16_strrchr_template
1049
# elif !defined u16_strrchr
1050
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
1051
       || defined __ICC  || defined __TINYC__ \
1052
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
1053
#   define u16_strrchr(s,u) \
1054
      _Generic ((s), \
1055
                uint16_t const *: (uint16_t const *) u16_strrchr ((s), (u)), \
1056
                default         :                    u16_strrchr ((s), (u)))
1057
#  endif
1058
# endif
1059
# ifdef __cplusplus
1060
template <typename T>
1061
  T * u32_strrchr_template (T* str, ucs4_t uc);
1062
template <>
1063
  inline uint32_t * u32_strrchr_template (uint32_t *str, ucs4_t uc)
1064
  { return u32_strrchr (str, uc); }
1065
template <>
1066
  inline const uint32_t * u32_strrchr_template (const uint32_t *str, ucs4_t uc)
1067
  { return u32_strrchr (str, uc); }
1068
#  undef u32_strrchr
1069
#  define u32_strrchr u32_strrchr_template
1070
# elif !defined u32_strrchr
1071
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
1072
       || defined __ICC  || defined __TINYC__ \
1073
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
1074
#   define u32_strrchr(s,u) \
1075
      _Generic ((s), \
1076
                uint32_t const *: (uint32_t const *) u32_strrchr ((s), (u)), \
1077
                default         :                    u32_strrchr ((s), (u)))
1078
#  endif
1079
# endif
1080
#endif
1081
1082
/* Return the length of the initial segment of STR which consists entirely
1083
   of Unicode characters not in REJECT.  */
1084
/* Similar to strcspn(), wcscspn().  */
1085
extern size_t
1086
       u8_strcspn (const uint8_t *str, const uint8_t *reject)
1087
       _UC_ATTRIBUTE_PURE;
1088
extern size_t
1089
       u16_strcspn (const uint16_t *str, const uint16_t *reject)
1090
       _UC_ATTRIBUTE_PURE;
1091
extern size_t
1092
       u32_strcspn (const uint32_t *str, const uint32_t *reject)
1093
       _UC_ATTRIBUTE_PURE;
1094
1095
/* Return the length of the initial segment of STR which consists entirely
1096
   of Unicode characters in ACCEPT.  */
1097
/* Similar to strspn(), wcsspn().  */
1098
extern size_t
1099
       u8_strspn (const uint8_t *str, const uint8_t *accept)
1100
       _UC_ATTRIBUTE_PURE;
1101
extern size_t
1102
       u16_strspn (const uint16_t *str, const uint16_t *accept)
1103
       _UC_ATTRIBUTE_PURE;
1104
extern size_t
1105
       u32_strspn (const uint32_t *str, const uint32_t *accept)
1106
       _UC_ATTRIBUTE_PURE;
1107
1108
/* Find the first occurrence in STR of any character in ACCEPT.  */
1109
/* Similar to strpbrk(), wcspbrk().  */
1110
extern uint8_t *
1111
       u8_strpbrk (const uint8_t *str, const uint8_t *accept)
1112
       _UC_ATTRIBUTE_PURE;
1113
extern uint16_t *
1114
       u16_strpbrk (const uint16_t *str, const uint16_t *accept)
1115
       _UC_ATTRIBUTE_PURE;
1116
extern uint32_t *
1117
       u32_strpbrk (const uint32_t *str, const uint32_t *accept)
1118
       _UC_ATTRIBUTE_PURE;
1119
#ifndef _LIBUNISTRING_NO_CONST_GENERICS
1120
/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'.  Programmers
1121
   want compiler warnings for 'const' related mistakes.  */
1122
# ifdef __cplusplus
1123
template <typename T>
1124
  T * u8_strpbrk_template (T* str, const uint8_t *accept);
1125
template <>
1126
  inline uint8_t * u8_strpbrk_template (uint8_t *str, const uint8_t *accept)
1127
  { return u8_strpbrk (str, accept); }
1128
template <>
1129
  inline const uint8_t * u8_strpbrk_template (const uint8_t *str, const uint8_t *accept)
1130
  { return u8_strpbrk (str, accept); }
1131
#  undef u8_strpbrk
1132
#  define u8_strpbrk u8_strpbrk_template
1133
# elif !defined u8_strpbrk
1134
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
1135
       || defined __ICC  || defined __TINYC__ \
1136
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
1137
#   define u8_strpbrk(s,a) \
1138
      _Generic ((s), \
1139
                uint8_t const *: (uint8_t const *) u8_strpbrk ((s), (a)), \
1140
                default        :                   u8_strpbrk ((s), (a)))
1141
#  endif
1142
# endif
1143
# ifdef __cplusplus
1144
template <typename T>
1145
  T * u16_strpbrk_template (T* str, const uint16_t *accept);
1146
template <>
1147
  inline uint16_t * u16_strpbrk_template (uint16_t *str, const uint16_t *accept)
1148
  { return u16_strpbrk (str, accept); }
1149
template <>
1150
  inline const uint16_t * u16_strpbrk_template (const uint16_t *str, const uint16_t *accept)
1151
  { return u16_strpbrk (str, accept); }
1152
#  undef u16_strpbrk
1153
#  define u16_strpbrk u16_strpbrk_template
1154
# elif !defined u16_strpbrk
1155
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
1156
       || defined __ICC  || defined __TINYC__ \
1157
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
1158
#   define u16_strpbrk(s,a) \
1159
      _Generic ((s), \
1160
                uint16_t const *: (uint16_t const *) u16_strpbrk ((s), (a)), \
1161
                default         :                    u16_strpbrk ((s), (a)))
1162
#  endif
1163
# endif
1164
# ifdef __cplusplus
1165
template <typename T>
1166
  T * u32_strpbrk_template (T* str, const uint32_t *accept);
1167
template <>
1168
  inline uint32_t * u32_strpbrk_template (uint32_t *str, const uint32_t *accept)
1169
  { return u32_strpbrk (str, accept); }
1170
template <>
1171
  inline const uint32_t * u32_strpbrk_template (const uint32_t *str, const uint32_t *accept)
1172
  { return u32_strpbrk (str, accept); }
1173
#  undef u32_strpbrk
1174
#  define u32_strpbrk u32_strpbrk_template
1175
# elif !defined u32_strpbrk
1176
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
1177
       || defined __ICC  || defined __TINYC__ \
1178
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
1179
#   define u32_strpbrk(s,a) \
1180
      _Generic ((s), \
1181
                uint32_t const *: (uint32_t const *) u32_strpbrk ((s), (a)), \
1182
                default         :                    u32_strpbrk ((s), (a)))
1183
#  endif
1184
# endif
1185
#endif
1186
1187
/* Find the first occurrence of NEEDLE in HAYSTACK.  */
1188
/* Similar to strstr(), wcsstr().  */
1189
extern uint8_t *
1190
       u8_strstr (const uint8_t *haystack, const uint8_t *needle)
1191
       _UC_ATTRIBUTE_PURE;
1192
extern uint16_t *
1193
       u16_strstr (const uint16_t *haystack, const uint16_t *needle)
1194
       _UC_ATTRIBUTE_PURE;
1195
extern uint32_t *
1196
       u32_strstr (const uint32_t *haystack, const uint32_t *needle)
1197
       _UC_ATTRIBUTE_PURE;
1198
#ifndef _LIBUNISTRING_NO_CONST_GENERICS
1199
/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'.  Programmers
1200
   want compiler warnings for 'const' related mistakes.  */
1201
# ifdef __cplusplus
1202
template <typename T>
1203
  T * u8_strstr_template (T* haystack, const uint8_t *needle);
1204
template <>
1205
  inline uint8_t * u8_strstr_template (uint8_t *haystack, const uint8_t *needle)
1206
  { return u8_strstr (haystack, needle); }
1207
template <>
1208
  inline const uint8_t * u8_strstr_template (const uint8_t *haystack, const uint8_t *needle)
1209
  { return u8_strstr (haystack, needle); }
1210
#  undef u8_strstr
1211
#  define u8_strstr u8_strstr_template
1212
# elif !defined u8_strstr
1213
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
1214
       || defined __ICC  || defined __TINYC__ \
1215
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
1216
#   define u8_strstr(h,n) \
1217
      _Generic ((h), \
1218
                uint8_t const *: (uint8_t const *) u8_strstr ((h), (n)), \
1219
                default        :                   u8_strstr ((h), (n)))
1220
#  endif
1221
# endif
1222
# ifdef __cplusplus
1223
template <typename T>
1224
  T * u16_strstr_template (T* haystack, const uint16_t *needle);
1225
template <>
1226
  inline uint16_t * u16_strstr_template (uint16_t *haystack, const uint16_t *needle)
1227
  { return u16_strstr (haystack, needle); }
1228
template <>
1229
  inline const uint16_t * u16_strstr_template (const uint16_t *haystack, const uint16_t *needle)
1230
  { return u16_strstr (haystack, needle); }
1231
#  undef u16_strstr
1232
#  define u16_strstr u16_strstr_template
1233
# elif !defined u16_strstr
1234
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
1235
       || defined __ICC  || defined __TINYC__ \
1236
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
1237
#   define u16_strstr(h,n) \
1238
      _Generic ((h), \
1239
                uint16_t const *: (uint16_t const *) u16_strstr ((h), (n)), \
1240
                default         :                    u16_strstr ((h), (n)))
1241
#  endif
1242
# endif
1243
# ifdef __cplusplus
1244
template <typename T>
1245
  T * u32_strstr_template (T* haystack, const uint32_t *needle);
1246
template <>
1247
  inline uint32_t * u32_strstr_template (uint32_t *haystack, const uint32_t *needle)
1248
  { return u32_strstr (haystack, needle); }
1249
template <>
1250
  inline const uint32_t * u32_strstr_template (const uint32_t *haystack, const uint32_t *needle)
1251
  { return u32_strstr (haystack, needle); }
1252
#  undef u32_strstr
1253
#  define u32_strstr u32_strstr_template
1254
# elif !defined u32_strstr
1255
#  if ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
1256
       || defined __ICC  || defined __TINYC__ \
1257
       || (__STDC_VERSION__ >= 201112L && !(defined __GNUC__ || defined __clang__)))
1258
#   define u32_strstr(h,n) \
1259
      _Generic ((h), \
1260
                uint32_t const *: (uint32_t const *) u32_strstr ((h), (n)), \
1261
                default         :                    u32_strstr ((h), (n)))
1262
#  endif
1263
# endif
1264
#endif
1265
1266
/* Test whether STR starts with PREFIX.  */
1267
extern bool
1268
       u8_startswith (const uint8_t *str, const uint8_t *prefix)
1269
       _UC_ATTRIBUTE_PURE;
1270
extern bool
1271
       u16_startswith (const uint16_t *str, const uint16_t *prefix)
1272
       _UC_ATTRIBUTE_PURE;
1273
extern bool
1274
       u32_startswith (const uint32_t *str, const uint32_t *prefix)
1275
       _UC_ATTRIBUTE_PURE;
1276
1277
/* Test whether STR ends with SUFFIX.  */
1278
extern bool
1279
       u8_endswith (const uint8_t *str, const uint8_t *suffix)
1280
       _UC_ATTRIBUTE_PURE;
1281
extern bool
1282
       u16_endswith (const uint16_t *str, const uint16_t *suffix)
1283
       _UC_ATTRIBUTE_PURE;
1284
extern bool
1285
       u32_endswith (const uint32_t *str, const uint32_t *suffix)
1286
       _UC_ATTRIBUTE_PURE;
1287
1288
/* Divide STR into tokens separated by characters in DELIM.
1289
   This interface is actually more similar to wcstok than to strtok.  */
1290
/* Similar to strtok_r(), wcstok().  */
1291
extern uint8_t *
1292
       u8_strtok (uint8_t *_UC_RESTRICT str, const uint8_t *delim,
1293
                  uint8_t **ptr);
1294
extern uint16_t *
1295
       u16_strtok (uint16_t *_UC_RESTRICT str, const uint16_t *delim,
1296
                   uint16_t **ptr);
1297
extern uint32_t *
1298
       u32_strtok (uint32_t *_UC_RESTRICT str, const uint32_t *delim,
1299
                   uint32_t **ptr);
1300
1301
1302
#ifdef __cplusplus
1303
}
1304
#endif
1305
1306
#endif /* _UNISTR_H */