Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
34 changes: 34 additions & 0 deletions libc/src/wchar/wcspbrk.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===-- 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 {

bool contains_char(const wchar_t *str, wchar_t target) {
for (; *str != 0; str++)
Copy link
Contributor

Choose a reason for hiding this comment

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

since this is a wide char null byte this should be L'\0' instead of 0.

if (*str == target)
return true;

return false;
}

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++)
if (contains_char(breakset, src[src_idx]))
return src + src_idx;

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
62 changes: 62 additions & 0 deletions libc/test/src/wchar/wcspbrk_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//===-- Unittests 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
//
//===----------------------------------------------------------------------===//

#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