Skip to content

Commit 667843c

Browse files
committed
[libc] Add strtok implementation.
Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D85615
1 parent bebe6a6 commit 667843c

File tree

8 files changed

+160
-2
lines changed

8 files changed

+160
-2
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ set(TARGET_LIBC_ENTRYPOINTS
3434
libc.src.string.strrchr
3535
libc.src.string.strspn
3636
libc.src.string.strstr
37+
libc.src.string.strtok
3738
)
3839

3940
set(TARGET_LIBM_ENTRYPOINTS

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ set(TARGET_LIBC_ENTRYPOINTS
5252
libc.src.string.strrchr
5353
libc.src.string.strspn
5454
libc.src.string.strstr
55+
libc.src.string.strtok
5556

5657
# sys/mman.h entrypoints
5758
libc.src.sys.mman.mmap

libc/src/string/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ add_entrypoint_object(
132132
.string_utils
133133
)
134134

135+
add_entrypoint_object(
136+
strtok
137+
SRCS
138+
strtok.cpp
139+
HDRS
140+
strtok.h
141+
DEPENDS
142+
libc.utils.CPP.standalone_cpp
143+
)
144+
135145
# Helper to define a function with multiple implementations
136146
# - Computes flags to satisfy required/rejected features and arch,
137147
# - Declares an entry point,

libc/src/string/string_utils.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
#ifndef LIBC_SRC_STRING_STRING_UTILS_H
1010
#define LIBC_SRC_STRING_STRING_UTILS_H
1111

12-
#include "src/string/memory_utils/utils.h"
13-
1412
#include "utils/CPP/Bitset.h"
1513
#include <stddef.h> // size_t
1614

libc/src/string/strtok.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===-- Implementation of strtok ------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/string/strtok.h"
10+
11+
#include "src/__support/common.h"
12+
#include "utils/CPP/Bitset.h"
13+
14+
namespace __llvm_libc {
15+
16+
static char *strtok_str = nullptr;
17+
18+
char *LLVM_LIBC_ENTRYPOINT(strtok)(char *src, const char *delimiter_string) {
19+
cpp::Bitset<256> delimiter_set;
20+
for (; *delimiter_string; ++delimiter_string)
21+
delimiter_set.set(*delimiter_string);
22+
23+
src = src ? src : strtok_str;
24+
for (; *src && delimiter_set.test(*src); ++src)
25+
;
26+
if (!*src) {
27+
strtok_str = src;
28+
return nullptr;
29+
}
30+
char *token = src;
31+
for (; *src && !delimiter_set.test(*src); ++src)
32+
;
33+
34+
strtok_str = src;
35+
if (*strtok_str) {
36+
*strtok_str = '\0';
37+
++strtok_str;
38+
}
39+
return token;
40+
}
41+
42+
} // namespace __llvm_libc

libc/src/string/strtok.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===-- Implementation header for strtok ------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_STRING_STRTOK_H
10+
#define LLVM_LIBC_SRC_STRING_STRTOK_H
11+
12+
namespace __llvm_libc {
13+
14+
char *strtok(char *src, const char *delimiter_string);
15+
16+
} // namespace __llvm_libc
17+
18+
#endif // LLVM_LIBC_SRC_STRING_STRTOK_H

libc/test/src/string/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ add_libc_unittest(
132132
libc.src.string.strpbrk
133133
)
134134

135+
add_libc_unittest(
136+
strtok_test
137+
SUITE
138+
libc_string_unittests
139+
SRCS
140+
strtok_test.cpp
141+
DEPENDS
142+
libc.src.string.strtok
143+
)
144+
135145
# Tests all implementations that can run on the host.
136146
function(add_libc_multi_impl_test name)
137147
get_property(fq_implementations GLOBAL PROPERTY ${name}_implementations)

libc/test/src/string/strtok_test.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//===-- Unittests for strtok ---------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/string/strtok.h"
10+
#include "utils/UnitTest/Test.h"
11+
12+
TEST(StrTokTest, NoTokenFound) {
13+
char empty[] = "";
14+
ASSERT_STREQ(__llvm_libc::strtok(empty, ""), nullptr);
15+
ASSERT_STREQ(__llvm_libc::strtok(empty, "_"), nullptr);
16+
17+
char single[] = "_";
18+
ASSERT_STREQ(__llvm_libc::strtok(single, ""), "_");
19+
20+
char multiple[] = "1,2";
21+
ASSERT_STREQ(__llvm_libc::strtok(multiple, ":"), "1,2");
22+
}
23+
24+
TEST(StrTokTest, DelimiterAsFirstCharacterShouldBeIgnored) {
25+
char src[] = ".123";
26+
ASSERT_STREQ(__llvm_libc::strtok(src, "."), "123");
27+
}
28+
29+
TEST(StrTokTest, DelimiterIsMiddleCharacter) {
30+
char src[] = "12,34";
31+
ASSERT_STREQ(__llvm_libc::strtok(src, ","), "12");
32+
}
33+
34+
TEST(StrTokTest, DelimiterAsLastCharacterShouldBeIgnored) {
35+
char src[] = "1234:";
36+
ASSERT_STREQ(__llvm_libc::strtok(src, ":"), "1234");
37+
}
38+
39+
TEST(StrTokTest, MultipleDelimiters) {
40+
char src[] = "12,.34";
41+
ASSERT_STREQ(__llvm_libc::strtok(src, "."), "12,");
42+
ASSERT_STREQ(__llvm_libc::strtok(src, ".,"), "12");
43+
ASSERT_STREQ(__llvm_libc::strtok(src, ",."), "12");
44+
ASSERT_STREQ(__llvm_libc::strtok(src, ":,."), "12");
45+
}
46+
47+
TEST(StrTokTest, ShouldNotGoPastNullTerminator) {
48+
char src[] = {'1', '2', '\0', ',', '3'};
49+
ASSERT_STREQ(__llvm_libc::strtok(src, ","), "12");
50+
}
51+
52+
TEST(StrTokTest, SubsequentCallsShouldFindFollowingDelimiters) {
53+
char src[] = "12,34.56";
54+
char *token = __llvm_libc::strtok(src, ",.");
55+
ASSERT_STREQ(token, "12");
56+
token = __llvm_libc::strtok(nullptr, ",.");
57+
ASSERT_STREQ(token, "34");
58+
token = __llvm_libc::strtok(nullptr, ",.");
59+
ASSERT_STREQ(token, "56");
60+
token = __llvm_libc::strtok(nullptr, "_:,_");
61+
ASSERT_STREQ(token, nullptr);
62+
// Subsequent calls after hitting the end of the string should also return
63+
// nullptr.
64+
token = __llvm_libc::strtok(nullptr, "_:,_");
65+
ASSERT_STREQ(token, nullptr);
66+
}
67+
68+
TEST(StrTokTest, DelimitersShouldNotBeIncludedInToken) {
69+
char src[] = "__ab__:_cd__:__ef__:__";
70+
char *token = __llvm_libc::strtok(src, "_:");
71+
ASSERT_STREQ(token, "ab");
72+
token = __llvm_libc::strtok(nullptr, ":_");
73+
ASSERT_STREQ(token, "cd");
74+
token = __llvm_libc::strtok(nullptr, "_:,");
75+
ASSERT_STREQ(token, "ef");
76+
token = __llvm_libc::strtok(nullptr, "_:,_");
77+
ASSERT_STREQ(token, nullptr);
78+
}

0 commit comments

Comments
 (0)