diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index e8f59c9d5cd73..5e8278e586286 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -1264,6 +1264,7 @@ if(LLVM_LIBC_FULL_BUILD) # wchar.h entrypoints libc.src.wchar.mblen libc.src.wchar.mbrlen + libc.src.wchar.mbsinit libc.src.wchar.mbrtowc libc.src.wchar.mbtowc libc.src.wchar.wcrtomb diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml index 0285f1924a2fa..6e1f595cdb7d6 100644 --- a/libc/include/wchar.yaml +++ b/libc/include/wchar.yaml @@ -53,6 +53,12 @@ functions: - type: wchar_t *__restrict - type: const char *__restrict - type: size_t + - name: mbsinit + standards: + - stdc + return_type: int + arguments: + - type: mbstate_t * - name: mblen standards: - stdc diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt index 43f44a941d451..49f4a1b58764c 100644 --- a/libc/src/wchar/CMakeLists.txt +++ b/libc/src/wchar/CMakeLists.txt @@ -136,6 +136,21 @@ add_entrypoint_object( libc.src.__support.libc_errno ) +add_entrypoint_object( + mbsinit + SRCS + mbsinit.cpp + HDRS + mbsinit.h + DEPENDS + libc.hdr.types.wchar_t + libc.hdr.types.mbstate_t + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.wchar.character_converter + libc.src.__support.wchar.mbstate +) + add_entrypoint_object( mbrtowc SRCS diff --git a/libc/src/wchar/mbsinit.cpp b/libc/src/wchar/mbsinit.cpp new file mode 100644 index 0000000000000..23ba542ceefa3 --- /dev/null +++ b/libc/src/wchar/mbsinit.cpp @@ -0,0 +1,26 @@ +//===-- Implementation of mbsinit -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/wchar/mbsinit.h" + +#include "hdr/types/mbstate_t.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/__support/wchar/character_converter.h" +#include "src/__support/wchar/mbstate.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, mbsinit, (mbstate_t * ps)) { + if (ps == nullptr) + return true; + internal::CharacterConverter cr(reinterpret_cast(ps)); + return cr.isValidState() && cr.isEmpty(); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/wchar/mbsinit.h b/libc/src/wchar/mbsinit.h new file mode 100644 index 0000000000000..fa6be0f596fd0 --- /dev/null +++ b/libc/src/wchar/mbsinit.h @@ -0,0 +1,22 @@ +//===-- Implementation header for mbsinit ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_WCHAR_MBSINIT_H +#define LLVM_LIBC_SRC_WCHAR_MBSINIT_H + +#include "hdr/types/mbstate_t.h" +#include "hdr/types/size_t.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +int mbsinit(mbstate_t *ps); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_WCHAR_MBSINIT_H diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt index f420ecc465a53..fad89dc2131ed 100644 --- a/libc/test/src/wchar/CMakeLists.txt +++ b/libc/test/src/wchar/CMakeLists.txt @@ -99,7 +99,22 @@ add_libc_test( libc.src.string.memset libc.src.wchar.mbrlen libc.hdr.types.mbstate_t + libc.hdr.types.wchar_t libc.test.UnitTest.ErrnoCheckingTest +) + +add_libc_test( + mbsinit_test + SUITE + libc_wchar_unittests + SRCS + mbsinit_test.cpp + DEPENDS + libc.src.string.memset + libc.src.wchar.mbsinit + libc.src.wchar.mbrtowc + libc.hdr.types.mbstate_t + libc.hdr.types.wchar_t ) add_libc_test( diff --git a/libc/test/src/wchar/mbsinit_test.cpp b/libc/test/src/wchar/mbsinit_test.cpp new file mode 100644 index 0000000000000..ecb48aa921608 --- /dev/null +++ b/libc/test/src/wchar/mbsinit_test.cpp @@ -0,0 +1,33 @@ +//===-- Unittests for mbsinit ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "hdr/types/wchar_t.h" +#include "src/string/memset.h" +#include "src/wchar/mbrtowc.h" +#include "src/wchar/mbsinit.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcMBSInitTest, EmptyState) { + mbstate_t ps; + LIBC_NAMESPACE::memset(&ps, 0, sizeof(mbstate_t)); + ASSERT_NE(LIBC_NAMESPACE::mbsinit(&ps), 0); + ASSERT_NE(LIBC_NAMESPACE::mbsinit(nullptr), 0); +} + +TEST(LlvmLibcMBSInitTest, ConversionTest) { + const char *src = "\xf0\x9f\xa4\xa3"; // 4 byte emoji + wchar_t dest[2]; + mbstate_t ps; + LIBC_NAMESPACE::memset(&ps, 0, sizeof(mbstate_t)); + + ASSERT_NE(LIBC_NAMESPACE::mbsinit(&ps), 0); + LIBC_NAMESPACE::mbrtowc(dest, src, 2, &ps); // partial conversion + ASSERT_EQ(LIBC_NAMESPACE::mbsinit(&ps), 0); + LIBC_NAMESPACE::mbrtowc(dest, src + 2, 2, &ps); // complete conversion + ASSERT_NE(LIBC_NAMESPACE::mbsinit(&ps), 0); // state should be reset now +}