Skip to content

[libc] Implemented wcspbrk #142040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 30, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wchar.wctob
libc.src.wchar.wmemset
libc.src.wchar.wcschr
libc.src.wchar.wcspbrk
libc.src.wchar.wmemcmp

# sys/uio.h entrypoints
Expand Down
7 changes: 7 additions & 0 deletions libc/include/wchar.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ functions:
arguments:
- type: const wchar_t *
- type: wchar_t
- name: wcspbrk
standards:
- stdc
return_type: const wchar_t *
arguments:
- type: const wchar_t *
- type: const wchar_t *
- name: wmemcmp
standards:
- stdc
Expand Down
11 changes: 11 additions & 0 deletions libc/src/wchar/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ add_entrypoint_object(
libc.src.__support.wctype_utils
)

add_entrypoint_object(
wcspbrk
SRCS
wcspbrk.cpp
HDRS
wcspbrk.h
DEPENDS
libc.hdr.wchar_macros
libc.src.__support.wctype_utils
)

add_entrypoint_object(
wmemcmp
SRCS
Expand Down
27 changes: 27 additions & 0 deletions libc/src/wchar/wcspbrk.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===-- Implementation of wcspbrk -----------------------------------------===//
//
// 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/wcspbrk.h"

#include "hdr/types/wchar_t.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(const wchar_t *, wcspbrk,
(const wchar_t *src, const wchar_t *breakset)) {
// currently O(n * m), can be further optimized to O(n + m) with a hash set
for (int src_idx = 0; src[src_idx] != 0; src_idx++)
for (int breakset_idx = 0; breakset[breakset_idx] != 0; breakset_idx++)
if (src[src_idx] == breakset[breakset_idx])
return src + src_idx;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you break the check if src[src_idx] is in breakset out into a helper function this will be easier to read


return nullptr;
}

} // namespace LIBC_NAMESPACE_DECL
21 changes: 21 additions & 0 deletions libc/src/wchar/wcspbrk.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for wcspbrk ---------------------------------===//
//
// 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_WCSPBRK_H
#define LLVM_LIBC_SRC_WCHAR_WCSPBRK_H

#include "hdr/types/wchar_t.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

const wchar_t *wcspbrk(const wchar_t *src, const wchar_t *breakset);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_WCHAR_WCSPBRK_H
10 changes: 10 additions & 0 deletions libc/test/src/wchar/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ add_libc_test(
libc.src.wchar.wcschr
)

add_libc_test(
wcspbrk_test
SUITE
libc_wchar_unittests
SRCS
wcspbrk_test.cpp
DEPENDS
libc.src.wchar.wcspbrk
)

add_libc_test(
wmemcmp_test
SUITE
Expand Down
63 changes: 63 additions & 0 deletions libc/test/src/wchar/wcspbrk_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//===-- Unittests for wcspbrk
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: fix formatting

//----------------------------------------------===//
//
// 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/wchar/wcspbrk.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcWCSPBrkTest, EmptyStringShouldReturnNullptr) {
// The search should not include the null terminator.
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(L"", L""), nullptr);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(L"_", L""), nullptr);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(L"", L"_"), nullptr);
}

TEST(LlvmLibcWCSPBrkTest, ShouldNotFindAnythingAfterNullTerminator) {
const wchar_t src[4] = {'a', 'b', '\0', 'c'};
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"c"), nullptr);
}

TEST(LlvmLibcWCSPBrkTest, ShouldReturnNullptrIfNoCharactersFound) {
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(L"12345", L"abcdef"), nullptr);
}

TEST(LlvmLibcWCSPBrkTest, FindsFirstCharacter) {
const wchar_t *src = L"12345";
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"1"), src);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"-1"), src);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"1_"), src);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"f1_"), src);
}

TEST(LlvmLibcWCSPBrkTest, FindsMiddleCharacter) {
const wchar_t *src = L"12345";
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"3"), src + 2);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"?3"), src + 2);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"3F"), src + 2);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"z3_"), src + 2);
}

TEST(LlvmLibcWCSPBrkTest, FindsLastCharacter) {
const wchar_t *src = L"12345";
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"5"), src + 4);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"r5"), src + 4);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"59"), src + 4);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"n5_"), src + 4);
}

TEST(LlvmLibcWCSPBrkTest, FindsFirstOfRepeated) {
const wchar_t *src = L"A,B,C,D";
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L","), src + 1);
}

TEST(LlvmLibcWCSPBrkTest, FindsFirstInBreakset) {
const wchar_t *src = L"12345";
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"34"), src + 2);
EXPECT_EQ(LIBC_NAMESPACE::wcspbrk(src, L"43"), src + 2);
}
Loading