extern const uint32_t *
u32_grapheme_next (const uint32_t *s, const uint32_t *end)
_UC_ATTRIBUTE_PURE;
+#ifndef _LIBUNISTRING_NO_CONST_GENERICS
+/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'. Programmers
+ want compiler warnings for 'const' related mistakes. */
+# ifdef __cplusplus
+template <typename T>
+ T * u8_grapheme_next_template (T* s, const uint8_t *end);
+template <>
+ inline uint8_t * u8_grapheme_next_template (uint8_t *s, const uint8_t *end)
+ { return const_cast<uint8_t *>(u8_grapheme_next (s, end)); }
+template <>
+ inline const uint8_t * u8_grapheme_next_template (const uint8_t *s, const uint8_t *end)
+ { return u8_grapheme_next (s, end); }
+# define u8_grapheme_next u8_grapheme_next_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u8_grapheme_next(s,end) (typeof ((s) + 0)) u8_grapheme_next ((s), (end))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u8_grapheme_next(s,end) \
+ _Generic ((s), \
+ uint8_t *: (uint8_t *) u8_grapheme_next ((s), (end)), \
+ default : u8_grapheme_next ((s), (end)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u16_grapheme_next_template (T* s, const uint16_t *end);
+template <>
+ inline uint16_t * u16_grapheme_next_template (uint16_t *s, const uint16_t *end)
+ { return const_cast<uint16_t *>(u16_grapheme_next (s, end)); }
+template <>
+ inline const uint16_t * u16_grapheme_next_template (const uint16_t *s, const uint16_t *end)
+ { return u16_grapheme_next (s, end); }
+# define u16_grapheme_next u16_grapheme_next_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u16_grapheme_next(s,end) (typeof ((s) + 0)) u16_grapheme_next ((s), (end))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u16_grapheme_next(s,end) \
+ _Generic ((s), \
+ uint16_t *: (uint16_t *) u16_grapheme_next ((s), (end)), \
+ default : u16_grapheme_next ((s), (end)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u32_grapheme_next_template (T* s, const uint32_t *end);
+template <>
+ inline uint32_t * u32_grapheme_next_template (uint32_t *s, const uint32_t *end)
+ { return const_cast<uint32_t *>(u32_grapheme_next (s, end)); }
+template <>
+ inline const uint32_t * u32_grapheme_next_template (const uint32_t *s, const uint32_t *end)
+ { return u32_grapheme_next (s, end); }
+# define u32_grapheme_next u32_grapheme_next_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u32_grapheme_next(s,end) (typeof ((s) + 0)) u32_grapheme_next ((s), (end))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u32_grapheme_next(s,end) \
+ _Generic ((s), \
+ uint32_t *: (uint32_t *) u32_grapheme_next ((s), (end)), \
+ default : u32_grapheme_next ((s), (end)))
+# endif
+# endif
+#endif
/* Returns the start of the previous grapheme cluster before S, or NULL if the
start of the string has been reached.
extern const uint32_t *
u32_grapheme_prev (const uint32_t *s, const uint32_t *start)
_UC_ATTRIBUTE_PURE;
+#ifndef _LIBUNISTRING_NO_CONST_GENERICS
+/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'. Programmers
+ want compiler warnings for 'const' related mistakes. */
+# ifdef __cplusplus
+template <typename T>
+ T * u8_grapheme_prev_template (T* s, const uint8_t *start);
+template <>
+ inline uint8_t * u8_grapheme_prev_template (uint8_t *s, const uint8_t *start)
+ { return const_cast<uint8_t *>(u8_grapheme_prev (s, start)); }
+template <>
+ inline const uint8_t * u8_grapheme_prev_template (const uint8_t *s, const uint8_t *start)
+ { return u8_grapheme_prev (s, start); }
+# define u8_grapheme_prev u8_grapheme_prev_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u8_grapheme_prev(s,start) (typeof ((s) + 0)) u8_grapheme_prev ((s), (start))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u8_grapheme_prev(s,start) \
+ _Generic ((s), \
+ uint8_t *: (uint8_t *) u8_grapheme_prev ((s), (start)), \
+ default : u8_grapheme_prev ((s), (start)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u16_grapheme_prev_template (T* s, const uint16_t *start);
+template <>
+ inline uint16_t * u16_grapheme_prev_template (uint16_t *s, const uint16_t *start)
+ { return const_cast<uint16_t *>(u16_grapheme_prev (s, start)); }
+template <>
+ inline const uint16_t * u16_grapheme_prev_template (const uint16_t *s, const uint16_t *start)
+ { return u16_grapheme_prev (s, start); }
+# define u16_grapheme_prev u16_grapheme_prev_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u16_grapheme_prev(s,start) (typeof ((s) + 0)) u16_grapheme_prev ((s), (start))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u16_grapheme_prev(s,start) \
+ _Generic ((s), \
+ uint16_t *: (uint16_t *) u16_grapheme_prev ((s), (start)), \
+ default : u16_grapheme_prev ((s), (start)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u32_grapheme_prev_template (T* s, const uint32_t *start);
+template <>
+ inline uint32_t * u32_grapheme_prev_template (uint32_t *s, const uint32_t *start)
+ { return const_cast<uint32_t *>(u32_grapheme_prev (s, start)); }
+template <>
+ inline const uint32_t * u32_grapheme_prev_template (const uint32_t *s, const uint32_t *start)
+ { return u32_grapheme_prev (s, start); }
+# define u32_grapheme_prev u32_grapheme_prev_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u32_grapheme_prev(s,start) (typeof ((s) + 0)) u32_grapheme_prev ((s), (start))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u32_grapheme_prev(s,start) \
+ _Generic ((s), \
+ uint32_t *: (uint32_t *) u32_grapheme_prev ((s), (start)), \
+ default : u32_grapheme_prev ((s), (start)))
+# endif
+# endif
+#endif
/* Determine the grapheme cluster boundaries in S, and store the result at
p[0..n-1]. p[i] = 1 means that a new grapheme cluster begins at s[i]. p[i]
u32_check (const uint32_t *s, size_t n)
_UC_ATTRIBUTE_PURE;
+#ifndef _LIBUNISTRING_NO_CONST_GENERICS
+/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'. Programmers
+ want compiler warnings for 'const' related mistakes. */
+# ifdef __cplusplus
+template <typename T>
+ T * u8_check_template (T* s, size_t n);
+template <>
+ inline uint8_t * u8_check_template (uint8_t *s, size_t n)
+ { return const_cast<uint8_t *>(u8_check (s, n)); }
+template <>
+ inline const uint8_t * u8_check_template (const uint8_t *s, size_t n)
+ { return u8_check (s, n); }
+# define u8_check u8_check_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u8_check(s,n) (typeof ((s) + 0)) u8_check ((s), (n))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u8_check(s,n) \
+ _Generic ((s), \
+ uint8_t *: (uint8_t *) u8_check ((s), (n)), \
+ default : u8_check ((s), (n)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u16_check_template (T* s, size_t n);
+template <>
+ inline uint16_t * u16_check_template (uint16_t *s, size_t n)
+ { return const_cast<uint16_t *>(u16_check (s, n)); }
+template <>
+ inline const uint16_t * u16_check_template (const uint16_t *s, size_t n)
+ { return u16_check (s, n); }
+# define u16_check u16_check_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u16_check(s,n) (typeof ((s) + 0)) u16_check ((s), (n))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u16_check(s,n) \
+ _Generic ((s), \
+ uint16_t *: (uint16_t *) u16_check ((s), (n)), \
+ default : u16_check ((s), (n)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u32_check_template (T* s, size_t n);
+template <>
+ inline uint32_t * u32_check_template (uint32_t *s, size_t n)
+ { return const_cast<uint32_t *>(u32_check (s, n)); }
+template <>
+ inline const uint32_t * u32_check_template (const uint32_t *s, size_t n)
+ { return u32_check (s, n); }
+# define u32_check u32_check_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u32_check(s,n) (typeof ((s) + 0)) u32_check ((s), (n))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u32_check(s,n) \
+ _Generic ((s), \
+ uint32_t *: (uint32_t *) u32_check ((s), (n)), \
+ default : u32_check ((s), (n)))
+# endif
+# endif
+#endif
+
/* Elementary string conversions. */
extern uint32_t *
u32_chr (const uint32_t *s, size_t n, ucs4_t uc)
_UC_ATTRIBUTE_PURE;
+#ifndef _LIBUNISTRING_NO_CONST_GENERICS
+/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'. Programmers
+ want compiler warnings for 'const' related mistakes. */
+# ifdef __cplusplus
+template <typename T>
+ T * u8_chr_template (T* str, size_t n, ucs4_t uc);
+template <>
+ inline uint8_t * u8_chr_template (uint8_t *str, size_t n, ucs4_t uc)
+ { return u8_chr (str, n, uc); }
+template <>
+ inline const uint8_t * u8_chr_template (const uint8_t *str, size_t n, ucs4_t uc)
+ { return u8_chr (str, n, uc); }
+# define u8_chr u8_chr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u8_chr(s,n,u) (typeof ((s) + 0)) u8_chr ((s), (n), (u))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u8_chr(s,n,u) \
+ _Generic ((s), \
+ uint8_t const *: (uint8_t const *) u8_chr ((s), (n), (u)), \
+ default : u8_chr ((s), (n), (u)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u16_chr_template (T* str, size_t n, ucs4_t uc);
+template <>
+ inline uint16_t * u16_chr_template (uint16_t *str, size_t n, ucs4_t uc)
+ { return u16_chr (str, n, uc); }
+template <>
+ inline const uint16_t * u16_chr_template (const uint16_t *str, size_t n, ucs4_t uc)
+ { return u16_chr (str, n, uc); }
+# define u16_chr u16_chr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u16_chr(s,n,u) (typeof ((s) + 0)) u16_chr ((s), (n), (u))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u16_chr(s,n,u) \
+ _Generic ((s), \
+ uint16_t const *: (uint16_t const *) u16_chr ((s), (n), (u)), \
+ default : u16_chr ((s), (n), (u)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u32_chr_template (T* str, size_t n, ucs4_t uc);
+template <>
+ inline uint32_t * u32_chr_template (uint32_t *str, size_t n, ucs4_t uc)
+ { return u32_chr (str, n, uc); }
+template <>
+ inline const uint32_t * u32_chr_template (const uint32_t *str, size_t n, ucs4_t uc)
+ { return u32_chr (str, n, uc); }
+# define u32_chr u32_chr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u32_chr(s,n,u) (typeof ((s) + 0)) u32_chr ((s), (n), (u))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u32_chr(s,n,u) \
+ _Generic ((s), \
+ uint32_t const *: (uint32_t const *) u32_chr ((s), (n), (u)), \
+ default : u32_chr ((s), (n), (u)))
+# endif
+# endif
+#endif
/* Count the number of Unicode characters in the N units from S. */
/* Similar to mbsnlen(). */
u16_next (ucs4_t *puc, const uint16_t *s);
extern const uint32_t *
u32_next (ucs4_t *puc, const uint32_t *s);
+#ifndef _LIBUNISTRING_NO_CONST_GENERICS
+/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'. Programmers
+ want compiler warnings for 'const' related mistakes. */
+# ifdef __cplusplus
+template <typename T>
+ T * u8_next_template (ucs4_t *puc, T* s);
+template <>
+ inline uint8_t * u8_next_template (ucs4_t *puc, uint8_t *s)
+ { return const_cast<uint8_t *>(u8_next (puc, s)); }
+template <>
+ inline const uint8_t * u8_next_template (ucs4_t *puc, const uint8_t *s)
+ { return u8_next (puc, s); }
+# define u8_next u8_next_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u8_next(p,s) (typeof ((s) + 0)) u8_next ((p), (s))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u8_next(p,s) \
+ _Generic ((s), \
+ uint8_t *: (uint8_t *) u8_next ((p), (s)), \
+ default : u8_next ((p), (s)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u16_next_template (ucs4_t *puc, T* s);
+template <>
+ inline uint16_t * u16_next_template (ucs4_t *puc, uint16_t *s)
+ { return const_cast<uint16_t *>(u16_next (puc, s)); }
+template <>
+ inline const uint16_t * u16_next_template (ucs4_t *puc, const uint16_t *s)
+ { return u16_next (puc, s); }
+# define u16_next u16_next_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u16_next(p,s) (typeof ((s) + 0)) u16_next ((p), (s))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u16_next(p,s) \
+ _Generic ((s), \
+ uint16_t *: (uint16_t *) u16_next ((p), (s)), \
+ default : u16_next ((p), (s)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u32_next_template (ucs4_t *puc, T* s);
+template <>
+ inline uint32_t * u32_next_template (ucs4_t *puc, uint32_t *s)
+ { return const_cast<uint32_t *>(u32_next (puc, s)); }
+template <>
+ inline const uint32_t * u32_next_template (ucs4_t *puc, const uint32_t *s)
+ { return u32_next (puc, s); }
+# define u32_next u32_next_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u32_next(p,s) (typeof ((s) + 0)) u32_next ((p), (s))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u32_next(p,s) \
+ _Generic ((s), \
+ uint32_t *: (uint32_t *) u32_next ((p), (s)), \
+ default : u32_next ((p), (s)))
+# endif
+# endif
+#endif
/* Backward iteration step. Advances the pointer to point to the previous
character, or returns NULL if the beginning of the string had been reached.
u16_prev (ucs4_t *puc, const uint16_t *s, const uint16_t *start);
extern const uint32_t *
u32_prev (ucs4_t *puc, const uint32_t *s, const uint32_t *start);
+#ifndef _LIBUNISTRING_NO_CONST_GENERICS
+/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'. Programmers
+ want compiler warnings for 'const' related mistakes. */
+# ifdef __cplusplus
+template <typename T>
+ T * u8_prev_template (ucs4_t *puc, T* s, const uint8_t *start);
+template <>
+ inline uint8_t * u8_prev_template (ucs4_t *puc, uint8_t *s, const uint8_t *start)
+ { return const_cast<uint8_t *>(u8_prev (puc, s, start)); }
+template <>
+ inline const uint8_t * u8_prev_template (ucs4_t *puc, const uint8_t *s, const uint8_t *start)
+ { return u8_prev (puc, s, start); }
+# define u8_prev u8_prev_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u8_prev(p,s,start) (typeof ((s) + 0)) u8_prev ((p), (s), (start))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u8_prev(p,s,start) \
+ _Generic ((s), \
+ uint8_t *: (uint8_t *) u8_prev ((p), (s), (start)), \
+ default : u8_prev ((p), (s), (start)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u16_prev_template (ucs4_t *puc, T* s, const uint16_t *start);
+template <>
+ inline uint16_t * u16_prev_template (ucs4_t *puc, uint16_t *s, const uint16_t *start)
+ { return const_cast<uint16_t *>(u16_prev (puc, s, start)); }
+template <>
+ inline const uint16_t * u16_prev_template (ucs4_t *puc, const uint16_t *s, const uint16_t *start)
+ { return u16_prev (puc, s, start); }
+# define u16_prev u16_prev_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u16_prev(p,s,start) (typeof ((s) + 0)) u16_prev ((p), (s), (start))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u16_prev(p,s,start) \
+ _Generic ((s), \
+ uint16_t *: (uint16_t *) u16_prev ((p), (s), (start)), \
+ default : u16_prev ((p), (s), (start)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u32_prev_template (ucs4_t *puc, T* s, const uint32_t *start);
+template <>
+ inline uint32_t * u32_prev_template (ucs4_t *puc, uint32_t *s, const uint32_t *start)
+ { return const_cast<uint32_t *>(u32_prev (puc, s, start)); }
+template <>
+ inline const uint32_t * u32_prev_template (ucs4_t *puc, const uint32_t *s, const uint32_t *start)
+ { return u32_prev (puc, s, start); }
+# define u32_prev u32_prev_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u32_prev(p,s,start) (typeof ((s) + 0)) u32_prev ((p), (s), (start))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u32_prev(p,s,start) \
+ _Generic ((s), \
+ uint32_t *: (uint32_t *) u32_prev ((p), (s), (start)), \
+ default : u32_prev ((p), (s), (start)))
+# endif
+# endif
+#endif
/* Return the number of units in S. */
/* Similar to strlen(), wcslen(). */
extern uint32_t *
u32_strchr (const uint32_t *str, ucs4_t uc)
_UC_ATTRIBUTE_PURE;
+#ifndef _LIBUNISTRING_NO_CONST_GENERICS
+/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'. Programmers
+ want compiler warnings for 'const' related mistakes. */
+# ifdef __cplusplus
+template <typename T>
+ T * u8_strchr_template (T* str, ucs4_t uc);
+template <>
+ inline uint8_t * u8_strchr_template (uint8_t *str, ucs4_t uc)
+ { return u8_strchr (str, uc); }
+template <>
+ inline const uint8_t * u8_strchr_template (const uint8_t *str, ucs4_t uc)
+ { return u8_strchr (str, uc); }
+# define u8_strchr u8_strchr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u8_strchr(s,u) (typeof ((s) + 0)) u8_strchr ((s), (u))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u8_strchr(s,u) \
+ _Generic ((s), \
+ uint8_t const *: (uint8_t const *) u8_strchr ((s), (u)), \
+ default : u8_strchr ((s), (u)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u16_strchr_template (T* str, ucs4_t uc);
+template <>
+ inline uint16_t * u16_strchr_template (uint16_t *str, ucs4_t uc)
+ { return u16_strchr (str, uc); }
+template <>
+ inline const uint16_t * u16_strchr_template (const uint16_t *str, ucs4_t uc)
+ { return u16_strchr (str, uc); }
+# define u16_strchr u16_strchr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u16_strchr(s,u) (typeof ((s) + 0)) u16_strchr ((s), (u))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u16_strchr(s,u) \
+ _Generic ((s), \
+ uint16_t const *: (uint16_t const *) u16_strchr ((s), (u)), \
+ default : u16_strchr ((s), (u)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u32_strchr_template (T* str, ucs4_t uc);
+template <>
+ inline uint32_t * u32_strchr_template (uint32_t *str, ucs4_t uc)
+ { return u32_strchr (str, uc); }
+template <>
+ inline const uint32_t * u32_strchr_template (const uint32_t *str, ucs4_t uc)
+ { return u32_strchr (str, uc); }
+# define u32_strchr u32_strchr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u32_strchr(s,u) (typeof ((s) + 0)) u32_strchr ((s), (u))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u32_strchr(s,u) \
+ _Generic ((s), \
+ uint32_t const *: (uint32_t const *) u32_strchr ((s), (u)), \
+ default : u32_strchr ((s), (u)))
+# endif
+# endif
+#endif
/* Find the last occurrence of UC in STR. */
/* Similar to strrchr(), wcsrchr(). */
extern uint32_t *
u32_strrchr (const uint32_t *str, ucs4_t uc)
_UC_ATTRIBUTE_PURE;
+#ifndef _LIBUNISTRING_NO_CONST_GENERICS
+/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'. Programmers
+ want compiler warnings for 'const' related mistakes. */
+# ifdef __cplusplus
+template <typename T>
+ T * u8_strrchr_template (T* str, ucs4_t uc);
+template <>
+ inline uint8_t * u8_strrchr_template (uint8_t *str, ucs4_t uc)
+ { return u8_strrchr (str, uc); }
+template <>
+ inline const uint8_t * u8_strrchr_template (const uint8_t *str, ucs4_t uc)
+ { return u8_strrchr (str, uc); }
+# define u8_strrchr u8_strrchr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u8_strrchr(s,u) (typeof ((s) + 0)) u8_strrchr ((s), (u))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u8_strrchr(s,u) \
+ _Generic ((s), \
+ uint8_t const *: (uint8_t const *) u8_strrchr ((s), (u)), \
+ default : u8_strrchr ((s), (u)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u16_strrchr_template (T* str, ucs4_t uc);
+template <>
+ inline uint16_t * u16_strrchr_template (uint16_t *str, ucs4_t uc)
+ { return u16_strrchr (str, uc); }
+template <>
+ inline const uint16_t * u16_strrchr_template (const uint16_t *str, ucs4_t uc)
+ { return u16_strrchr (str, uc); }
+# define u16_strrchr u16_strrchr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u16_strrchr(s,u) (typeof ((s) + 0)) u16_strrchr ((s), (u))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u16_strrchr(s,u) \
+ _Generic ((s), \
+ uint16_t const *: (uint16_t const *) u16_strrchr ((s), (u)), \
+ default : u16_strrchr ((s), (u)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u32_strrchr_template (T* str, ucs4_t uc);
+template <>
+ inline uint32_t * u32_strrchr_template (uint32_t *str, ucs4_t uc)
+ { return u32_strrchr (str, uc); }
+template <>
+ inline const uint32_t * u32_strrchr_template (const uint32_t *str, ucs4_t uc)
+ { return u32_strrchr (str, uc); }
+# define u32_strrchr u32_strrchr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u32_strrchr(s,u) (typeof ((s) + 0)) u32_strrchr ((s), (u))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u32_strrchr(s,u) \
+ _Generic ((s), \
+ uint32_t const *: (uint32_t const *) u32_strrchr ((s), (u)), \
+ default : u32_strrchr ((s), (u)))
+# endif
+# endif
+#endif
/* Return the length of the initial segment of STR which consists entirely
of Unicode characters not in REJECT. */
extern uint32_t *
u32_strpbrk (const uint32_t *str, const uint32_t *accept)
_UC_ATTRIBUTE_PURE;
+#ifndef _LIBUNISTRING_NO_CONST_GENERICS
+/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'. Programmers
+ want compiler warnings for 'const' related mistakes. */
+# ifdef __cplusplus
+template <typename T>
+ T * u8_strpbrk_template (T* str, const uint8_t *accept);
+template <>
+ inline uint8_t * u8_strpbrk_template (uint8_t *str, const uint8_t *accept)
+ { return u8_strpbrk (str, accept); }
+template <>
+ inline const uint8_t * u8_strpbrk_template (const uint8_t *str, const uint8_t *accept)
+ { return u8_strpbrk (str, accept); }
+# define u8_strpbrk u8_strpbrk_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u8_strpbrk(s,a) (typeof ((s) + 0)) u8_strpbrk ((s), (a))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u8_strpbrk(s,a) \
+ _Generic ((s), \
+ uint8_t const *: (uint8_t const *) u8_strpbrk ((s), (a)), \
+ default : u8_strpbrk ((s), (a)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u16_strpbrk_template (T* str, const uint16_t *accept);
+template <>
+ inline uint16_t * u16_strpbrk_template (uint16_t *str, const uint16_t *accept)
+ { return u16_strpbrk (str, accept); }
+template <>
+ inline const uint16_t * u16_strpbrk_template (const uint16_t *str, const uint16_t *accept)
+ { return u16_strpbrk (str, accept); }
+# define u16_strpbrk u16_strpbrk_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u16_strpbrk(s,a) (typeof ((s) + 0)) u16_strpbrk ((s), (a))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u16_strpbrk(s,a) \
+ _Generic ((s), \
+ uint16_t const *: (uint16_t const *) u16_strpbrk ((s), (a)), \
+ default : u16_strpbrk ((s), (a)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u32_strpbrk_template (T* str, const uint32_t *accept);
+template <>
+ inline uint32_t * u32_strpbrk_template (uint32_t *str, const uint32_t *accept)
+ { return u32_strpbrk (str, accept); }
+template <>
+ inline const uint32_t * u32_strpbrk_template (const uint32_t *str, const uint32_t *accept)
+ { return u32_strpbrk (str, accept); }
+# define u32_strpbrk u32_strpbrk_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u32_strpbrk(s,a) (typeof ((s) + 0)) u32_strpbrk ((s), (a))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u32_strpbrk(s,a) \
+ _Generic ((s), \
+ uint32_t const *: (uint32_t const *) u32_strpbrk ((s), (a)), \
+ default : u32_strpbrk ((s), (a)))
+# endif
+# endif
+#endif
/* Find the first occurrence of NEEDLE in HAYSTACK. */
/* Similar to strstr(), wcsstr(). */
extern uint32_t *
u32_strstr (const uint32_t *haystack, const uint32_t *needle)
_UC_ATTRIBUTE_PURE;
+#ifndef _LIBUNISTRING_NO_CONST_GENERICS
+/* Don't silently convert a 'const uintN_t *' to a 'uintN_t *'. Programmers
+ want compiler warnings for 'const' related mistakes. */
+# ifdef __cplusplus
+template <typename T>
+ T * u8_strstr_template (T* haystack, const uint8_t *needle);
+template <>
+ inline uint8_t * u8_strstr_template (uint8_t *haystack, const uint8_t *needle)
+ { return u8_strstr (haystack, needle); }
+template <>
+ inline const uint8_t * u8_strstr_template (const uint8_t *haystack, const uint8_t *needle)
+ { return u8_strstr (haystack, needle); }
+# define u8_strstr u8_strstr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u8_strstr(h,n) (typeof ((h) + 0)) u8_strstr ((h), (n))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u8_strstr(h,n) \
+ _Generic ((h), \
+ uint8_t const *: (uint8_t const *) u8_strstr ((h), (n)), \
+ default : u8_strstr ((h), (n)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u16_strstr_template (T* haystack, const uint16_t *needle);
+template <>
+ inline uint16_t * u16_strstr_template (uint16_t *haystack, const uint16_t *needle)
+ { return u16_strstr (haystack, needle); }
+template <>
+ inline const uint16_t * u16_strstr_template (const uint16_t *haystack, const uint16_t *needle)
+ { return u16_strstr (haystack, needle); }
+# define u16_strstr u16_strstr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u16_strstr(h,n) (typeof ((h) + 0)) u16_strstr ((h), (n))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u16_strstr(h,n) \
+ _Generic ((h), \
+ uint16_t const *: (uint16_t const *) u16_strstr ((h), (n)), \
+ default : u16_strstr ((h), (n)))
+# endif
+# endif
+# ifdef __cplusplus
+template <typename T>
+ T * u32_strstr_template (T* haystack, const uint32_t *needle);
+template <>
+ inline uint32_t * u32_strstr_template (uint32_t *haystack, const uint32_t *needle)
+ { return u32_strstr (haystack, needle); }
+template <>
+ inline const uint32_t * u32_strstr_template (const uint32_t *haystack, const uint32_t *needle)
+ { return u32_strstr (haystack, needle); }
+# define u32_strstr u32_strstr_template
+# else
+# if __STDC_VERSION__ >= 202311
+# define u32_strstr(h,n) (typeof ((h) + 0)) u32_strstr ((h), (n))
+# elif ((__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) || (__clang_major__ >= 3) \
+ || defined __ICC || defined __TINYC__)
+# define u32_strstr(h,n) \
+ _Generic ((h), \
+ uint32_t const *: (uint32_t const *) u32_strstr ((h), (n)), \
+ default : u32_strstr ((h), (n)))
+# endif
+# endif
+#endif
/* Test whether STR starts with PREFIX. */
extern bool