mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-25 17:25:08 +02:00
AK: Make Utf16String::number(Integral) fast like String::number()
Move the fast String::number() implementation to a shareable place so both string types can make use of it.
This commit is contained in:
committed by
Andreas Kling
parent
feafaf09fc
commit
1c04b6da3b
Notes:
github-actions[bot]
2025-10-05 09:26:20 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/1c04b6da3bd Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6396
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2022, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2018-2025, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <AK/MemMem.h>
|
||||
#include <AK/Stream.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringNumber.h>
|
||||
#include <AK/Utf16View.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <stdlib.h>
|
||||
@@ -563,42 +564,7 @@ String String::roman_number_from(size_t value, Case target_case)
|
||||
template<Integral T>
|
||||
String String::number(T value)
|
||||
{
|
||||
// Maximum number of base-10 digits for T + sign
|
||||
constexpr size_t max_digits = sizeof(T) * 3 + 2;
|
||||
char buffer[max_digits];
|
||||
char* ptr = buffer + max_digits;
|
||||
bool is_negative = false;
|
||||
|
||||
using UnsignedT = MakeUnsigned<T>;
|
||||
|
||||
UnsignedT unsigned_value;
|
||||
if constexpr (IsSigned<T>) {
|
||||
if (value < 0) {
|
||||
is_negative = true;
|
||||
// Handle signed min correctly
|
||||
unsigned_value = static_cast<UnsignedT>(0) - static_cast<UnsignedT>(value);
|
||||
} else {
|
||||
unsigned_value = static_cast<UnsignedT>(value);
|
||||
}
|
||||
} else {
|
||||
unsigned_value = value;
|
||||
}
|
||||
|
||||
if (unsigned_value == 0) {
|
||||
*--ptr = '0';
|
||||
} else {
|
||||
while (unsigned_value != 0) {
|
||||
*--ptr = '0' + (unsigned_value % 10);
|
||||
unsigned_value /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_negative) {
|
||||
*--ptr = '-';
|
||||
}
|
||||
|
||||
size_t size = buffer + max_digits - ptr;
|
||||
return from_utf8_without_validation(ReadonlyBytes { ptr, size });
|
||||
return create_string_from_number<String, T>(value);
|
||||
}
|
||||
|
||||
template String String::number(char);
|
||||
|
||||
52
AK/StringNumber.h
Normal file
52
AK/StringNumber.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace AK {
|
||||
|
||||
template<class StringType, Integral T>
|
||||
StringType create_string_from_number(T value)
|
||||
{
|
||||
// Maximum number of base-10 digits for T + sign
|
||||
constexpr size_t max_digits = sizeof(T) * 3 + 2;
|
||||
char buffer[max_digits];
|
||||
char* ptr = buffer + max_digits;
|
||||
bool is_negative = false;
|
||||
|
||||
using UnsignedT = MakeUnsigned<T>;
|
||||
|
||||
UnsignedT unsigned_value;
|
||||
if constexpr (IsSigned<T>) {
|
||||
if (value < 0) {
|
||||
is_negative = true;
|
||||
// Handle signed min correctly
|
||||
unsigned_value = static_cast<UnsignedT>(0) - static_cast<UnsignedT>(value);
|
||||
} else {
|
||||
unsigned_value = static_cast<UnsignedT>(value);
|
||||
}
|
||||
} else {
|
||||
unsigned_value = value;
|
||||
}
|
||||
|
||||
if (unsigned_value == 0) {
|
||||
*--ptr = '0';
|
||||
} else {
|
||||
while (unsigned_value != 0) {
|
||||
*--ptr = '0' + (unsigned_value % 10);
|
||||
unsigned_value /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_negative) {
|
||||
*--ptr = '-';
|
||||
}
|
||||
|
||||
size_t size = buffer + max_digits - ptr;
|
||||
return StringType::from_utf8_without_validation(ReadonlyBytes { ptr, size });
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <AK/Stream.h>
|
||||
#include <AK/StringNumber.h>
|
||||
#include <AK/Utf16String.h>
|
||||
#include <AK/Utf32View.h>
|
||||
|
||||
@@ -166,4 +167,22 @@ ErrorOr<void> Formatter<Utf16String>::format(FormatBuilder& builder, Utf16String
|
||||
return builder.put_string(utf16_string.ascii_view());
|
||||
}
|
||||
|
||||
template<Integral T>
|
||||
Utf16String Utf16String::number(T value)
|
||||
{
|
||||
return create_string_from_number<Utf16String, T>(value);
|
||||
}
|
||||
|
||||
template Utf16String Utf16String::number(char);
|
||||
template Utf16String Utf16String::number(signed char);
|
||||
template Utf16String Utf16String::number(unsigned char);
|
||||
template Utf16String Utf16String::number(signed short);
|
||||
template Utf16String Utf16String::number(unsigned short);
|
||||
template Utf16String Utf16String::number(int);
|
||||
template Utf16String Utf16String::number(unsigned int);
|
||||
template Utf16String Utf16String::number(long);
|
||||
template Utf16String Utf16String::number(unsigned long);
|
||||
template Utf16String Utf16String::number(long long);
|
||||
template Utf16String Utf16String::number(unsigned long long);
|
||||
|
||||
}
|
||||
|
||||
@@ -96,8 +96,11 @@ public:
|
||||
return builder.to_utf16_string();
|
||||
}
|
||||
|
||||
template<Arithmetic T>
|
||||
ALWAYS_INLINE static Utf16String number(T value)
|
||||
template<Integral T>
|
||||
[[nodiscard]] static Utf16String number(T);
|
||||
|
||||
template<FloatingPoint T>
|
||||
[[nodiscard]] static Utf16String number(T value)
|
||||
{
|
||||
return formatted("{}", value);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user