Added the POSIX standard functions basename and dirname under a new libgen.h header. The implementations modify the input path in-place using cpp::string_view to determine boundaries safely. Added find_last_not_of to cpp::string_view to support trailing slash removal. Implemented: libc/include/libgen.yaml, libgen.h.def: Public API definitions. libc/src/libgen/basename.cpp, dirname.cpp: Generic implementations. libc/test/src/libgen/: Unit and hermetic tests. Registered the new entrypoints for all active Linux targets (x86_64, aarch64, arm, riscv) and added docgen configuration. The tests are skipped when using ASan because death tests do not currently work with them. Assisted-by: Automated tooling, human reviewed.
This commit is contained in:
parent
34b6e1c3b0
commit
dc658f1f11
22 changed files with 460 additions and 0 deletions
|
|
@ -109,6 +109,10 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
libc.src.inttypes.strtoimax
|
||||
libc.src.inttypes.strtoumax
|
||||
|
||||
# libgen.h entrypoints
|
||||
libc.src.libgen.basename
|
||||
libc.src.libgen.dirname
|
||||
|
||||
# stdbit.h entrypoints
|
||||
libc.src.stdbit.stdc_bit_ceil_uc
|
||||
libc.src.stdbit.stdc_bit_ceil_ui
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
libc.src.inttypes.strtoimax
|
||||
libc.src.inttypes.strtoumax
|
||||
|
||||
# libgen.h entrypoints
|
||||
libc.src.libgen.basename
|
||||
libc.src.libgen.dirname
|
||||
|
||||
# stdbit.h entrypoints
|
||||
libc.src.stdbit.stdc_bit_ceil_uc
|
||||
libc.src.stdbit.stdc_bit_ceil_ui
|
||||
|
|
|
|||
|
|
@ -109,6 +109,10 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
libc.src.inttypes.strtoimax
|
||||
libc.src.inttypes.strtoumax
|
||||
|
||||
# libgen.h entrypoints
|
||||
libc.src.libgen.basename
|
||||
libc.src.libgen.dirname
|
||||
|
||||
# stdbit.h entrypoints
|
||||
libc.src.stdbit.stdc_bit_ceil_uc
|
||||
libc.src.stdbit.stdc_bit_ceil_ui
|
||||
|
|
|
|||
|
|
@ -125,6 +125,10 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
libc.src.inttypes.wcstoimax
|
||||
libc.src.inttypes.wcstoumax
|
||||
|
||||
# libgen.h entrypoints
|
||||
libc.src.libgen.basename
|
||||
libc.src.libgen.dirname
|
||||
|
||||
# stdbit.h entrypoints
|
||||
libc.src.stdbit.stdc_bit_ceil_uc
|
||||
libc.src.stdbit.stdc_bit_ceil_ui
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ if (SPHINX_FOUND)
|
|||
float
|
||||
glob
|
||||
inttypes
|
||||
libgen
|
||||
locale
|
||||
nl_types
|
||||
net/if
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ Implementation Status
|
|||
float
|
||||
glob
|
||||
inttypes
|
||||
libgen
|
||||
locale
|
||||
math/index.rst
|
||||
net/if
|
||||
|
|
|
|||
|
|
@ -130,6 +130,14 @@ add_header_macro(
|
|||
.llvm-libc-macros.float_macros
|
||||
)
|
||||
|
||||
add_header_macro(
|
||||
libgen
|
||||
../libc/include/libgen.yaml
|
||||
libgen.h
|
||||
DEPENDS
|
||||
.llvm_libc_common_h
|
||||
)
|
||||
|
||||
add_header_macro(
|
||||
limits
|
||||
../libc/include/limits.yaml
|
||||
|
|
|
|||
20
libc/include/libgen.yaml
Normal file
20
libc/include/libgen.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
header: libgen.h
|
||||
standards:
|
||||
- posix
|
||||
macros: []
|
||||
types: []
|
||||
enums: []
|
||||
objects: []
|
||||
functions:
|
||||
- name: basename
|
||||
standards:
|
||||
- posix
|
||||
return_type: char *
|
||||
arguments:
|
||||
- type: char *
|
||||
- name: dirname
|
||||
standards:
|
||||
- posix
|
||||
return_type: char *
|
||||
arguments:
|
||||
- type: char *
|
||||
|
|
@ -7,6 +7,7 @@ add_subdirectory(dlfcn)
|
|||
add_subdirectory(errno)
|
||||
add_subdirectory(fenv)
|
||||
add_subdirectory(inttypes)
|
||||
add_subdirectory(libgen)
|
||||
add_subdirectory(link)
|
||||
add_subdirectory(math)
|
||||
add_subdirectory(netinet)
|
||||
|
|
|
|||
|
|
@ -205,6 +205,15 @@ public:
|
|||
return npos;
|
||||
}
|
||||
|
||||
LIBC_INLINE constexpr size_t find_last_not_of(const char c,
|
||||
size_t end = npos) const {
|
||||
end = end >= size() ? size() : end + 1;
|
||||
for (; end > 0; --end)
|
||||
if ((*this)[end - 1] != c)
|
||||
return end - 1;
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Finds the first character not equal to c in this view, starting at
|
||||
// position From.
|
||||
LIBC_INLINE constexpr size_t find_first_not_of(const char c,
|
||||
|
|
|
|||
23
libc/src/libgen/CMakeLists.txt
Normal file
23
libc/src/libgen/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
add_entrypoint_object(
|
||||
basename
|
||||
SRCS
|
||||
basename.cpp
|
||||
HDRS
|
||||
basename.h
|
||||
DEPENDS
|
||||
libc.src.__support.CPP.string_view
|
||||
libc.src.__support.common
|
||||
libc.src.__support.macros.config
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
dirname
|
||||
SRCS
|
||||
dirname.cpp
|
||||
HDRS
|
||||
dirname.h
|
||||
DEPENDS
|
||||
libc.src.__support.CPP.string_view
|
||||
libc.src.__support.common
|
||||
libc.src.__support.macros.config
|
||||
)
|
||||
42
libc/src/libgen/basename.cpp
Normal file
42
libc/src/libgen/basename.cpp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Implementation of basename.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/libgen/basename.h"
|
||||
#include "src/__support/CPP/string_view.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/macros/config.h"
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
LLVM_LIBC_FUNCTION(char *, basename, (char *path)) {
|
||||
if (path == nullptr || path[0] == '\0')
|
||||
return const_cast<char *>(".");
|
||||
|
||||
cpp::string_view sv(path);
|
||||
size_t last_non_slash = sv.find_last_not_of('/');
|
||||
|
||||
if (last_non_slash == cpp::string_view::npos)
|
||||
return const_cast<char *>("/");
|
||||
|
||||
size_t last_slash = sv.substr(0, last_non_slash).find_last_of('/');
|
||||
|
||||
size_t start = (last_slash == cpp::string_view::npos) ? 0 : last_slash + 1;
|
||||
size_t end = last_non_slash + 1;
|
||||
|
||||
if (end < sv.size())
|
||||
path[end] = '\0';
|
||||
|
||||
return path + start;
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
30
libc/src/libgen/basename.h
Normal file
30
libc/src/libgen/basename.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Header for basename.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_LIBGEN_BASENAME_H
|
||||
#define LLVM_LIBC_SRC_LIBGEN_BASENAME_H
|
||||
|
||||
#include "src/__support/macros/config.h"
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
/// Return the last component of a pathname.
|
||||
///
|
||||
/// \param path Pointer to the null-terminated pathname string.
|
||||
/// \return Pointer to the last component of path, or "." if path is null or
|
||||
/// empty, or "/" if path is all slashes.
|
||||
char *basename(char *path);
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
|
||||
#endif // LLVM_LIBC_SRC_LIBGEN_BASENAME_H
|
||||
48
libc/src/libgen/dirname.cpp
Normal file
48
libc/src/libgen/dirname.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Implementation of dirname.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/libgen/dirname.h"
|
||||
#include "src/__support/CPP/string_view.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/macros/config.h"
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
LLVM_LIBC_FUNCTION(char *, dirname, (char *path)) {
|
||||
if (path == nullptr || path[0] == '\0')
|
||||
return const_cast<char *>(".");
|
||||
|
||||
cpp::string_view sv(path);
|
||||
size_t last_non_slash = sv.find_last_not_of('/');
|
||||
|
||||
if (last_non_slash == cpp::string_view::npos)
|
||||
return const_cast<char *>("/");
|
||||
|
||||
size_t last_slash = sv.substr(0, last_non_slash).find_last_of('/');
|
||||
|
||||
if (last_slash == cpp::string_view::npos)
|
||||
return const_cast<char *>(".");
|
||||
|
||||
cpp::string_view dir_sv = sv.substr(0, last_slash);
|
||||
size_t dir_last_non_slash = dir_sv.find_last_not_of('/');
|
||||
|
||||
if (dir_last_non_slash == cpp::string_view::npos) {
|
||||
path[1] = '\0';
|
||||
return path;
|
||||
}
|
||||
|
||||
path[dir_last_non_slash + 1] = '\0';
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
30
libc/src/libgen/dirname.h
Normal file
30
libc/src/libgen/dirname.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Header for dirname.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_LIBGEN_DIRNAME_H
|
||||
#define LLVM_LIBC_SRC_LIBGEN_DIRNAME_H
|
||||
|
||||
#include "src/__support/macros/config.h"
|
||||
|
||||
namespace LIBC_NAMESPACE_DECL {
|
||||
|
||||
/// Return the directory component of a pathname.
|
||||
///
|
||||
/// \param path Pointer to the null-terminated pathname string.
|
||||
/// \return Pointer to the directory component of path, or "." if path is null
|
||||
/// or empty, or "/" if path is all slashes.
|
||||
char *dirname(char *path);
|
||||
|
||||
} // namespace LIBC_NAMESPACE_DECL
|
||||
|
||||
#endif // LLVM_LIBC_SRC_LIBGEN_DIRNAME_H
|
||||
|
|
@ -63,6 +63,7 @@ add_subdirectory(complex)
|
|||
add_subdirectory(ctype)
|
||||
add_subdirectory(errno)
|
||||
add_subdirectory(fenv)
|
||||
add_subdirectory(libgen)
|
||||
add_subdirectory(link)
|
||||
add_subdirectory(math)
|
||||
add_subdirectory(netinet)
|
||||
|
|
|
|||
45
libc/test/src/libgen/CMakeLists.txt
Normal file
45
libc/test/src/libgen/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
add_custom_target(libc-libgen-tests)
|
||||
|
||||
add_libc_test(
|
||||
basename_test
|
||||
SUITE
|
||||
libc-libgen-tests
|
||||
SRCS
|
||||
basename_test.cpp
|
||||
DEPENDS
|
||||
libc.src.libgen.basename
|
||||
)
|
||||
|
||||
add_libc_test(
|
||||
dirname_test
|
||||
SUITE
|
||||
libc-libgen-tests
|
||||
SRCS
|
||||
dirname_test.cpp
|
||||
DEPENDS
|
||||
libc.src.libgen.dirname
|
||||
)
|
||||
|
||||
if (NOT LLVM_USE_SANITIZER)
|
||||
add_libc_test(
|
||||
basename_death_test
|
||||
UNIT_TEST_ONLY
|
||||
SUITE
|
||||
libc-libgen-tests
|
||||
SRCS
|
||||
basename_death_test.cpp
|
||||
DEPENDS
|
||||
libc.src.libgen.basename
|
||||
)
|
||||
|
||||
add_libc_test(
|
||||
dirname_death_test
|
||||
UNIT_TEST_ONLY
|
||||
SUITE
|
||||
libc-libgen-tests
|
||||
SRCS
|
||||
dirname_death_test.cpp
|
||||
DEPENDS
|
||||
libc.src.libgen.dirname
|
||||
)
|
||||
endif()
|
||||
22
libc/test/src/libgen/basename_death_test.cpp
Normal file
22
libc/test/src/libgen/basename_death_test.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Death tests for basename.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/libgen/basename.h"
|
||||
#include "test/UnitTest/Test.h"
|
||||
|
||||
#ifdef ENABLE_SUBPROCESS_TESTS
|
||||
TEST(LlvmLibcBasenameTest, ModifyReturnValue) {
|
||||
char *r = LIBC_NAMESPACE::basename(nullptr);
|
||||
ASSERT_DEATH([r]() { r[0] = 'a'; }, WITH_SIGNAL(-1));
|
||||
}
|
||||
#endif
|
||||
62
libc/test/src/libgen/basename_test.cpp
Normal file
62
libc/test/src/libgen/basename_test.cpp
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Unittests for basename.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/libgen/basename.h"
|
||||
#include "test/UnitTest/Test.h"
|
||||
|
||||
TEST(LlvmLibcBasenameTest, NullPointer) {
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::basename(nullptr), ".");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcBasenameTest, EmptyString) {
|
||||
char path[] = "";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::basename(path), ".");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcBasenameTest, RegularPath) {
|
||||
char path[] = "/usr/lib";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::basename(path), "lib");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcBasenameTest, TrailingSlash) {
|
||||
char path[] = "/usr/";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::basename(path), "usr");
|
||||
ASSERT_STREQ(path, "/usr");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcBasenameTest, SingleSlash) {
|
||||
char path[] = "/";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::basename(path), "/");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcBasenameTest, MultipleSlashes) {
|
||||
char path[] = "///";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::basename(path), "/");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcBasenameTest, SimpleName) {
|
||||
char path[] = "a";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::basename(path), "a");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcBasenameTest, SimpleNameTrailingSlash) {
|
||||
char path[] = "a/";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::basename(path), "a");
|
||||
ASSERT_STREQ(path, "a");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcBasenameTest, ComplexPath) {
|
||||
char path[] = "///a///";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::basename(path), "a");
|
||||
ASSERT_STREQ(path, "///a");
|
||||
}
|
||||
22
libc/test/src/libgen/dirname_death_test.cpp
Normal file
22
libc/test/src/libgen/dirname_death_test.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Death tests for dirname.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/libgen/dirname.h"
|
||||
#include "test/UnitTest/Test.h"
|
||||
|
||||
#ifdef ENABLE_SUBPROCESS_TESTS
|
||||
TEST(LlvmLibcDirnameTest, ModifyReturnValue) {
|
||||
char *r = LIBC_NAMESPACE::dirname(nullptr);
|
||||
ASSERT_DEATH([r]() { r[0] = 'a'; }, WITH_SIGNAL(-1));
|
||||
}
|
||||
#endif
|
||||
74
libc/test/src/libgen/dirname_test.cpp
Normal file
74
libc/test/src/libgen/dirname_test.cpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Unittests for dirname.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/libgen/dirname.h"
|
||||
#include "test/UnitTest/Test.h"
|
||||
|
||||
TEST(LlvmLibcDirnameTest, NullPointer) {
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::dirname(nullptr), ".");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcDirnameTest, EmptyString) {
|
||||
char path[] = "";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::dirname(path), ".");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcDirnameTest, RegularPath) {
|
||||
char path[] = "/usr/lib";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::dirname(path), "/usr");
|
||||
ASSERT_STREQ(path, "/usr");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcDirnameTest, TrailingSlash) {
|
||||
char path[] = "/usr/";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::dirname(path), "/");
|
||||
ASSERT_STREQ(path, "/");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcDirnameTest, SingleSlash) {
|
||||
char path[] = "/";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::dirname(path), "/");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcDirnameTest, MultipleSlashes) {
|
||||
char path[] = "///";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::dirname(path), "/");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcDirnameTest, SimpleName) {
|
||||
char path[] = "a";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::dirname(path), ".");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcDirnameTest, SimpleNameTrailingSlash) {
|
||||
char path[] = "a/";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::dirname(path), ".");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcDirnameTest, ComplexPath) {
|
||||
char path[] = "///a///b///";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::dirname(path), "///a");
|
||||
ASSERT_STREQ(path, "///a");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcDirnameTest, SlashA) {
|
||||
char path[] = "/a";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::dirname(path), "/");
|
||||
ASSERT_STREQ(path, "/");
|
||||
}
|
||||
|
||||
TEST(LlvmLibcDirnameTest, MultipleSlashesA) {
|
||||
char path[] = "///a";
|
||||
ASSERT_STREQ(LIBC_NAMESPACE::dirname(path), "/");
|
||||
ASSERT_STREQ(path, "/");
|
||||
}
|
||||
5
libc/utils/docgen/libgen.yaml
Normal file
5
libc/utils/docgen/libgen.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
functions:
|
||||
basename:
|
||||
in-latest-posix: ''
|
||||
dirname:
|
||||
in-latest-posix: ''
|
||||
Loading…
Reference in a new issue