[libc-commits] [libc] [libc][wctype] Upstream custom slice implementation from PtrHash-cc prototype to LLVM libc (PR #174779)
Muhammad Bassiouni via libc-commits
libc-commits at lists.llvm.org
Fri Jan 9 10:00:33 PST 2026
https://github.com/bassiounix updated https://github.com/llvm/llvm-project/pull/174779
>From 81dbf6bb866481eb72f37070075934b31c40d583 Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Wed, 7 Jan 2026 16:42:29 +0200
Subject: [PATCH 1/8] [libc][wctype] Upstream custom slice implementation from
PtrHash-cc prototype to LLVM libc
---
.../wctype/conversion/utils/CMakeLists.txt | 11 ++
.../__support/wctype/conversion/utils/slice.h | 113 ++++++++++++++++++
2 files changed, 124 insertions(+)
create mode 100644 libc/src/__support/wctype/conversion/utils/CMakeLists.txt
create mode 100644 libc/src/__support/wctype/conversion/utils/slice.h
diff --git a/libc/src/__support/wctype/conversion/utils/CMakeLists.txt b/libc/src/__support/wctype/conversion/utils/CMakeLists.txt
new file mode 100644
index 0000000000000..edd6270f47126
--- /dev/null
+++ b/libc/src/__support/wctype/conversion/utils/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_header_library(
+ slice
+ HDRS
+ slice.h
+ DEPENDS
+ libc.hdr.types.size_t
+ libc.src.__support.CPP.algorithm
+ libc.src.__support.CPP.expected
+ libc.src.__support.CPP.span
+ libc.src.__support.libc_assert
+)
diff --git a/libc/src/__support/wctype/conversion/utils/slice.h b/libc/src/__support/wctype/conversion/utils/slice.h
new file mode 100644
index 0000000000000..f630ad21d73c2
--- /dev/null
+++ b/libc/src/__support/wctype/conversion/utils/slice.h
@@ -0,0 +1,113 @@
+//===-- Internal utils for wctype conversion code - slice -------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// Similar to cpp::span with additional functionality
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_WCTYPE_CONVERSION_UTILS_SLICE_H
+#define LLVM_LIBC_SRC___SUPPORT_WCTYPE_CONVERSION_UTILS_SLICE_H
+
+#include "hdr/types/size_t.h"
+#include "src/__support/CPP/algorithm.h"
+#include "src/__support/CPP/expected.h"
+#include "src/__support/CPP/span.h"
+#include "src/__support/libc_assert.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace internal_wctype_conversion_utils {
+
+enum class Ordering {
+ /// An ordering where a compared value is less than another.
+ Less = -1,
+ /// An ordering where a compared value is equal to another.
+ Equal = 0,
+ /// An ordering where a compared value is greater than another.
+ Greater = 1,
+};
+
+template <typename T> struct Slice : public cpp::span<T> {
+ LIBC_INLINE constexpr Slice() : cpp::span<T>() {}
+
+ LIBC_INLINE constexpr Slice(T *ptr, size_t len) : cpp::span<T>(ptr, len) {}
+ LIBC_INLINE constexpr Slice(T const *ptr, size_t len)
+ : cpp::span<T>(ptr, len) {}
+
+ template <typename U, size_t N>
+ LIBC_INLINE constexpr Slice<U>(cpp::array<U, N> &arr) : cpp::span<T>(arr) {}
+
+ LIBC_INLINE constexpr Slice(const Slice<T> &) = default;
+ LIBC_INLINE constexpr Slice(Slice<T> &&) = default;
+
+ LIBC_INLINE constexpr Slice(const cpp::span<T> &s) : cpp::span<T>(s) {}
+ LIBC_INLINE constexpr Slice(cpp::span<T> &&s) : cpp::span<T>(s) {}
+
+ LIBC_INLINE constexpr Slice &operator=(const Slice<T> &n) = default;
+ LIBC_INLINE constexpr Slice &operator=(Slice<T> &&n) = default;
+
+ LIBC_INLINE constexpr Slice &operator=(const cpp::span<T> &n) {
+ this->operator=(n);
+ return *this;
+ }
+ LIBC_INLINE constexpr Slice &operator=(cpp::span<T> &&n) {
+ this->operator=(n);
+ return *this;
+ }
+
+ template <typename Fn>
+ LIBC_INLINE constexpr cpp::expected<size_t, size_t>
+ binary_search_by(Fn func) const {
+ auto size = this->size();
+ if (size == 0) {
+ return cpp::unexpected<size_t>(0);
+ }
+
+ auto base = 0;
+
+ while (size > 1) {
+ auto half = size / 2;
+ auto mid = base + half;
+ auto cmp = func(this->operator[](mid));
+ base = (cmp == Ordering::Greater) ? base : mid;
+ size -= half;
+ }
+
+ auto cmp = func(this->operator[](base));
+ if (cmp == Ordering::Equal) {
+ LIBC_ASSERT(base < this->size());
+ return base;
+ } else {
+ auto result = base + static_cast<size_t>(cmp == Ordering::Less);
+ LIBC_ASSERT(result <= this->size());
+ return cpp::unexpected(result);
+ }
+ }
+
+ LIBC_INLINE constexpr Slice<T> range(size_t start, size_t end) const {
+ return Slice<T>(this->data() + start, end - start);
+ }
+
+ LIBC_INLINE constexpr bool contains(T elm) const {
+ for (auto it : *this) {
+ if (elm == it) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ LIBC_INLINE constexpr void copy_from_slice(Slice<T> other) const {
+ for (size_t i = 0; i < cpp::min(this->size(), other.size()); i++) {
+ this->data()[i] = other.data()[i];
+ }
+ }
+};
+
+} // namespace internal_wctype_conversion_utils
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_WCTYPE_CONVERSION_UTILS_SLICE_H
>From 957172402986bebf946b589cae5be20eae3a10ea Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Wed, 7 Jan 2026 20:22:03 +0200
Subject: [PATCH 2/8] fix nesting
---
libc/src/__support/wctype/conversion/utils/slice.h | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/libc/src/__support/wctype/conversion/utils/slice.h b/libc/src/__support/wctype/conversion/utils/slice.h
index f630ad21d73c2..69f8e58fc568e 100644
--- a/libc/src/__support/wctype/conversion/utils/slice.h
+++ b/libc/src/__support/wctype/conversion/utils/slice.h
@@ -18,7 +18,9 @@
namespace LIBC_NAMESPACE_DECL {
-namespace internal_wctype_conversion_utils {
+namespace wctype_internal {
+
+namespace conversion_utils {
enum class Ordering {
/// An ordering where a compared value is less than another.
@@ -106,7 +108,10 @@ template <typename T> struct Slice : public cpp::span<T> {
}
};
-} // namespace internal_wctype_conversion_utils
+
+} // namespace conversion_utils
+
+} // namespace wctype_internal
} // namespace LIBC_NAMESPACE_DECL
>From a306d1f2b22665df3db58f9103b719761907ba14 Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Wed, 7 Jan 2026 20:28:12 +0200
Subject: [PATCH 3/8] format
---
libc/src/__support/wctype/conversion/utils/slice.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/libc/src/__support/wctype/conversion/utils/slice.h b/libc/src/__support/wctype/conversion/utils/slice.h
index 69f8e58fc568e..fa5831f053529 100644
--- a/libc/src/__support/wctype/conversion/utils/slice.h
+++ b/libc/src/__support/wctype/conversion/utils/slice.h
@@ -108,7 +108,6 @@ template <typename T> struct Slice : public cpp::span<T> {
}
};
-
} // namespace conversion_utils
} // namespace wctype_internal
>From 394b3fa5d4cb29e8989a06522997b8214b6c707a Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Fri, 9 Jan 2026 18:16:47 +0200
Subject: [PATCH 4/8] call explicit operator
---
libc/src/__support/wctype/conversion/utils/slice.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/src/__support/wctype/conversion/utils/slice.h b/libc/src/__support/wctype/conversion/utils/slice.h
index fa5831f053529..4b90c2504db15 100644
--- a/libc/src/__support/wctype/conversion/utils/slice.h
+++ b/libc/src/__support/wctype/conversion/utils/slice.h
@@ -51,11 +51,11 @@ template <typename T> struct Slice : public cpp::span<T> {
LIBC_INLINE constexpr Slice &operator=(Slice<T> &&n) = default;
LIBC_INLINE constexpr Slice &operator=(const cpp::span<T> &n) {
- this->operator=(n);
+ cpp::span<T>::operator=(n);
return *this;
}
LIBC_INLINE constexpr Slice &operator=(cpp::span<T> &&n) {
- this->operator=(n);
+ cpp::span<T>::operator=(n);
return *this;
}
>From 42b6d9dba0c4f0878061e012d3e591b81f69735f Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Fri, 9 Jan 2026 18:19:45 +0200
Subject: [PATCH 5/8] Add bounds checking asserts
---
libc/src/__support/wctype/conversion/utils/slice.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/src/__support/wctype/conversion/utils/slice.h b/libc/src/__support/wctype/conversion/utils/slice.h
index 4b90c2504db15..d7fd7bd8dcc7d 100644
--- a/libc/src/__support/wctype/conversion/utils/slice.h
+++ b/libc/src/__support/wctype/conversion/utils/slice.h
@@ -89,6 +89,7 @@ template <typename T> struct Slice : public cpp::span<T> {
}
LIBC_INLINE constexpr Slice<T> range(size_t start, size_t end) const {
+ LIBC_ASSERT(start <= end && end <= this->size());
return Slice<T>(this->data() + start, end - start);
}
>From 9de4f4d7b48f19648f12dc60a46af3bc8413068e Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Fri, 9 Jan 2026 19:20:38 +0200
Subject: [PATCH 6/8] add docs comment
---
.../src/__support/wctype/conversion/utils/slice.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/libc/src/__support/wctype/conversion/utils/slice.h b/libc/src/__support/wctype/conversion/utils/slice.h
index d7fd7bd8dcc7d..90a5268342d06 100644
--- a/libc/src/__support/wctype/conversion/utils/slice.h
+++ b/libc/src/__support/wctype/conversion/utils/slice.h
@@ -59,6 +59,21 @@ template <typename T> struct Slice : public cpp::span<T> {
return *this;
}
+ // Binary searches this slice with a comparator function.
+ //
+ // The comparator function should return an order code that indicates whether
+ // its argument is `Less`, `Equal` or `Greater` the desired target.
+ // If the slice is not sorted or if the comparator function does not
+ // implement an order consistent with the sort order of the underlying
+ // slice, the returned result is unspecified and meaningless.
+ //
+ // If the value is found then `cpp::expected<size_t>` is returned,
+ // containing the index of the matching element. If there are multiple
+ // matches, then any one of the matches could be returned. The index is chosen
+ // deterministically.
+ // If the value is not found then `cpp::unexpected<size_t>` is returned,
+ // containing the index where a matching element could be inserted while
+ // maintaining sorted order.
template <typename Fn>
LIBC_INLINE constexpr cpp::expected<size_t, size_t>
binary_search_by(Fn func) const {
>From cd09aabdb2565f7ed7f07cccb108a5e7fbb23295 Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Fri, 9 Jan 2026 20:00:56 +0200
Subject: [PATCH 7/8] make type size_t
---
libc/src/__support/wctype/conversion/utils/slice.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/__support/wctype/conversion/utils/slice.h b/libc/src/__support/wctype/conversion/utils/slice.h
index 90a5268342d06..4aa6fb919e761 100644
--- a/libc/src/__support/wctype/conversion/utils/slice.h
+++ b/libc/src/__support/wctype/conversion/utils/slice.h
@@ -82,7 +82,7 @@ template <typename T> struct Slice : public cpp::span<T> {
return cpp::unexpected<size_t>(0);
}
- auto base = 0;
+ size_t base = 0;
while (size > 1) {
auto half = size / 2;
>From 84e97b7648506a08fddf27711e9db3cc1a841b1c Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Fri, 9 Jan 2026 20:01:16 +0200
Subject: [PATCH 8/8] rename method to `slice_form_range`
---
libc/src/__support/wctype/conversion/utils/slice.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libc/src/__support/wctype/conversion/utils/slice.h b/libc/src/__support/wctype/conversion/utils/slice.h
index 4aa6fb919e761..7eaa2da2d5c5c 100644
--- a/libc/src/__support/wctype/conversion/utils/slice.h
+++ b/libc/src/__support/wctype/conversion/utils/slice.h
@@ -103,7 +103,8 @@ template <typename T> struct Slice : public cpp::span<T> {
}
}
- LIBC_INLINE constexpr Slice<T> range(size_t start, size_t end) const {
+ LIBC_INLINE constexpr Slice<T> slice_form_range(size_t start,
+ size_t end) const {
LIBC_ASSERT(start <= end && end <= this->size());
return Slice<T>(this->data() + start, end - start);
}
More information about the libc-commits
mailing list