diff --git a/doc/releases/migration-guide-4.3.rst b/doc/releases/migration-guide-4.3.rst index 866b21451a46d..6b66025c70475 100644 --- a/doc/releases/migration-guide-4.3.rst +++ b/doc/releases/migration-guide-4.3.rst @@ -26,6 +26,13 @@ Build System Kernel ****** +Base Libraries +************** + +* UTF-8 utils declarations (:c:func:`utf8_trunc`, :c:func:`utf8_lcpy`) have + been moved from ``util.h`` to a separate + :zephyr_file:`include/zephyr/sys/util_utf8.h` file. + Boards ****** diff --git a/include/zephyr/sys/util.h b/include/zephyr/sys/util.h index 13abb2ae6c0bb..c2361d3a9b0d3 100644 --- a/include/zephyr/sys/util.h +++ b/include/zephyr/sys/util.h @@ -29,8 +29,6 @@ #include #include #include -#include - /** @brief Number of bits that make up a type */ #define NUM_BITS(t) (sizeof(t) * BITS_PER_BYTE) @@ -647,63 +645,6 @@ static inline int64_t sign_extend_64(uint64_t value, uint8_t index) return (int64_t)(value << shift) >> shift; } -/** - * @brief Properly truncate a NULL-terminated UTF-8 string - * - * Take a NULL-terminated UTF-8 string and ensure that if the string has been - * truncated (by setting the NULL terminator) earlier by other means, that - * the string ends with a properly formatted UTF-8 character (1-4 bytes). - * - * Example: - * - * @code{.c} - * char test_str[] = "€€€"; - * char trunc_utf8[8]; - * - * printf("Original : %s\n", test_str); // €€€ - * strncpy(trunc_utf8, test_str, sizeof(trunc_utf8)); - * trunc_utf8[sizeof(trunc_utf8) - 1] = '\0'; - * printf("Bad : %s\n", trunc_utf8); // €€� - * utf8_trunc(trunc_utf8); - * printf("Truncated: %s\n", trunc_utf8); // €€ - * @endcode - * - * @param utf8_str NULL-terminated string - * - * @return Pointer to the @p utf8_str - */ -char *utf8_trunc(char *utf8_str); - -/** - * @brief Copies a UTF-8 encoded string from @p src to @p dst - * - * The resulting @p dst will always be NULL terminated if @p n is larger than 0, - * and the @p dst string will always be properly UTF-8 truncated. - * - * @param dst The destination of the UTF-8 string. - * @param src The source string - * @param n The size of the @p dst buffer. Maximum number of characters copied - * is @p n - 1. If 0 nothing will be done, and the @p dst will not be - * NULL terminated. - * - * @return Pointer to the @p dst - */ -char *utf8_lcpy(char *dst, const char *src, size_t n); - -/** - * @brief Counts the characters in a UTF-8 encoded string @p s - * - * Counts the number of UTF-8 characters (code points) in a null-terminated string. - * This function steps through each UTF-8 sequence by checking leading byte patterns. - * It does not fully validate UTF-8 correctness, only counts characters. - * - * @param s The input string - * - * @return Number of UTF-8 characters in @p s on success or (negative) error code - * otherwise. - */ -ssize_t utf8_count_chars(const char *s); - #define __z_log2d(x) (32 - __builtin_clz(x) - 1) #define __z_log2q(x) (64 - __builtin_clzll(x) - 1) #define __z_log2(x) (sizeof(__typeof__(x)) > 4 ? __z_log2q(x) : __z_log2d(x)) diff --git a/include/zephyr/sys/util_utf8.h b/include/zephyr/sys/util_utf8.h new file mode 100644 index 0000000000000..ee9a13a3534f1 --- /dev/null +++ b/include/zephyr/sys/util_utf8.h @@ -0,0 +1,93 @@ +/* + * Copyright The Zephyr Project Contributors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief UTF-8 utilities + * + * Misc UTF-8 utilities. + */ + +#ifndef ZEPHYR_INCLUDE_SYS_UTIL_UFT8_H_ +#define ZEPHYR_INCLUDE_SYS_UTIL_UFT8_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup sys-util + * @{ + */ + +/** + * @brief Properly truncate a NULL-terminated UTF-8 string + * + * Take a NULL-terminated UTF-8 string and ensure that if the string has been + * truncated (by setting the NULL terminator) earlier by other means, that + * the string ends with a properly formatted UTF-8 character (1-4 bytes). + * + * Example: + * + * @code{.c} + * char test_str[] = "€€€"; + * char trunc_utf8[8]; + * + * printf("Original : %s\n", test_str); // €€€ + * strncpy(trunc_utf8, test_str, sizeof(trunc_utf8)); + * trunc_utf8[sizeof(trunc_utf8) - 1] = '\0'; + * printf("Bad : %s\n", trunc_utf8); // €€� + * utf8_trunc(trunc_utf8); + * printf("Truncated: %s\n", trunc_utf8); // €€ + * @endcode + * + * @param utf8_str NULL-terminated string + * + * @return Pointer to the @p utf8_str + */ +char *utf8_trunc(char *utf8_str); + +/** + * @brief Copies a UTF-8 encoded string from @p src to @p dst + * + * The resulting @p dst will always be NULL terminated if @p n is larger than 0, + * and the @p dst string will always be properly UTF-8 truncated. + * + * @param dst The destination of the UTF-8 string. + * @param src The source string + * @param n The size of the @p dst buffer. Maximum number of characters copied + * is @p n - 1. If 0 nothing will be done, and the @p dst will not be + * NULL terminated. + * + * @return Pointer to the @p dst + */ +char *utf8_lcpy(char *dst, const char *src, size_t n); + +/** + * @brief Counts the characters in a UTF-8 encoded string @p s + * + * Counts the number of UTF-8 characters (code points) in a null-terminated string. + * This function steps through each UTF-8 sequence by checking leading byte patterns. + * It does not fully validate UTF-8 correctness, only counts characters. + * + * @param s The input string + * + * @return Number of UTF-8 characters in @p s on success or (negative) error code + * otherwise. + */ +int utf8_count_chars(const char *s); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_SYS_UTIL_UFT8_H_ */ diff --git a/lib/utils/utf8.c b/lib/utils/utf8.c index c1f3ee37fcac7..cbe0eae7100c4 100644 --- a/lib/utils/utf8.c +++ b/lib/utils/utf8.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #define ASCII_CHAR 0x7F #define SEQUENCE_FIRST_MASK 0xC0 @@ -83,9 +83,9 @@ char *utf8_lcpy(char *dst, const char *src, size_t n) return dst; } -ssize_t utf8_count_chars(const char *s) +int utf8_count_chars(const char *s) { - ssize_t count = 0; + int count = 0; const char *p = s; /* getting a pointer to increment */ while (*p != '\0') { diff --git a/subsys/bluetooth/audio/aics.c b/subsys/bluetooth/audio/aics.c index 732a85e7d6955..7c5fc5a5fcd83 100644 --- a/subsys/bluetooth/audio/aics.c +++ b/subsys/bluetooth/audio/aics.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "aics_internal.h" diff --git a/subsys/bluetooth/audio/ccp_call_control_server.c b/subsys/bluetooth/audio/ccp_call_control_server.c index fc14bb178f1a1..053a83ed6bfff 100644 --- a/subsys/bluetooth/audio/ccp_call_control_server.c +++ b/subsys/bluetooth/audio/ccp_call_control_server.c @@ -16,6 +16,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(bt_ccp_call_control_server, CONFIG_BT_CCP_CALL_CONTROL_SERVER_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/has.c b/subsys/bluetooth/audio/has.c index 2cdc8bbe54494..27dc53a4dac89 100644 --- a/subsys/bluetooth/audio/has.c +++ b/subsys/bluetooth/audio/has.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include diff --git a/subsys/bluetooth/audio/has_client.c b/subsys/bluetooth/audio/has_client.c index 78564c851f347..3d48a0ea7e3d2 100644 --- a/subsys/bluetooth/audio/has_client.c +++ b/subsys/bluetooth/audio/has_client.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "has_internal.h" diff --git a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c index 716d2d9bc8dbc..8734805f0bcf0 100644 --- a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "common/bt_shell_private.h" diff --git a/subsys/bluetooth/audio/tbs.c b/subsys/bluetooth/audio/tbs.c index 37bcbf82b22b4..7526c5327e0f2 100644 --- a/subsys/bluetooth/audio/tbs.c +++ b/subsys/bluetooth/audio/tbs.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "audio_internal.h" diff --git a/subsys/bluetooth/audio/tbs_client.c b/subsys/bluetooth/audio/tbs_client.c index f22af7c2e3ee1..7895115c911e0 100644 --- a/subsys/bluetooth/audio/tbs_client.c +++ b/subsys/bluetooth/audio/tbs_client.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/subsys/bluetooth/audio/vocs.c b/subsys/bluetooth/audio/vocs.c index d4d0c29002576..a8a5db18bd1ba 100644 --- a/subsys/bluetooth/audio/vocs.c +++ b/subsys/bluetooth/audio/vocs.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "audio_internal.h" diff --git a/tests/posix/headers/src/types_h.c b/tests/posix/headers/src/types_h.c new file mode 100644 index 0000000000000..09ba5eab85aec --- /dev/null +++ b/tests/posix/headers/src/types_h.c @@ -0,0 +1,12 @@ +/* + * Copyright The Zephyr Project Contributors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* _GNU_SOURCE causes extra headers to be included and can cause dependency + * loops + */ +#define _GNU_SOURCE + +#include diff --git a/tests/unit/util/main.c b/tests/unit/util/main.c index 47d4932d2a733..3d7b45b7afe8e 100644 --- a/tests/unit/util/main.c +++ b/tests/unit/util/main.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include @@ -1008,7 +1008,7 @@ ZTEST(util, test_utf8_lcpy_null_termination) ZTEST(util, test_utf8_count_chars_ASCII) { const char *test_str = "I have 15 char."; - ssize_t count = utf8_count_chars(test_str); + int count = utf8_count_chars(test_str); zassert_equal(count, 15, "Failed to count ASCII"); } @@ -1016,7 +1016,7 @@ ZTEST(util, test_utf8_count_chars_ASCII) ZTEST(util, test_utf8_count_chars_non_ASCII) { const char *test_str = "Hello دنیا!🌍"; - ssize_t count = utf8_count_chars(test_str); + int count = utf8_count_chars(test_str); zassert_equal(count, 12, "Failed to count non-ASCII"); } @@ -1024,8 +1024,8 @@ ZTEST(util, test_utf8_count_chars_non_ASCII) ZTEST(util, test_utf8_count_chars_invalid_utf) { const char test_str[] = { (char)0x80, 0x00 }; - ssize_t count = utf8_count_chars(test_str); - ssize_t expected_result = -EINVAL; + int count = utf8_count_chars(test_str); + int expected_result = -EINVAL; zassert_equal(count, expected_result, "Failed to detect invalid UTF"); }