mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
AK: Allow printing wide characters using %ls modifier
This commit is contained in:
parent
824cf570d3
commit
704e1d13f4
Notes:
sideshowbarker
2024-07-17 16:30:18 +09:00
Author: https://github.com/safarp Commit: https://github.com/SerenityOS/serenity/commit/704e1d13f4 Pull-request: https://github.com/SerenityOS/serenity/pull/13151 Reviewed-by: https://github.com/alimpfard ✅
4 changed files with 84 additions and 2 deletions
|
@ -11,6 +11,7 @@
|
|||
#include <AK/Types.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#ifdef __serenity__
|
||||
extern "C" size_t strlen(const char*);
|
||||
|
@ -277,8 +278,8 @@ ALWAYS_INLINE int print_octal_number(PutChFunc putch, CharType*& bufptr, u64 num
|
|||
return field_width;
|
||||
}
|
||||
|
||||
template<typename PutChFunc, typename CharType>
|
||||
ALWAYS_INLINE int print_string(PutChFunc putch, CharType*& bufptr, const char* str, size_t len, bool left_pad, size_t field_width, bool dot, size_t precision, bool has_fraction)
|
||||
template<typename PutChFunc, typename T, typename CharType>
|
||||
ALWAYS_INLINE int print_string(PutChFunc putch, CharType*& bufptr, T str, size_t len, bool left_pad, size_t field_width, bool dot, size_t precision, bool has_fraction)
|
||||
{
|
||||
if (has_fraction)
|
||||
len = min(len, precision);
|
||||
|
@ -339,6 +340,17 @@ struct PrintfImpl {
|
|||
|
||||
ALWAYS_INLINE int format_s(const ModifierState& state, ArgumentListRefT ap) const
|
||||
{
|
||||
// FIXME: Narrow characters should be converted to wide characters on the fly and vice versa.
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/wprintf.html
|
||||
#ifndef KERNEL
|
||||
if (state.long_qualifiers) {
|
||||
const wchar_t* sp = NextArgument<const wchar_t*>()(ap);
|
||||
if (!sp)
|
||||
sp = L"(null)";
|
||||
return print_string(m_putch, m_bufptr, sp, wcslen(sp), state.left_pad, state.field_width, state.dot, state.precision, state.has_precision);
|
||||
}
|
||||
#endif
|
||||
const char* sp = NextArgument<const char*>()(ap);
|
||||
if (!sp)
|
||||
sp = "(null)";
|
||||
|
|
|
@ -48,6 +48,7 @@ set(AK_TEST_SOURCES
|
|||
TestNonnullRefPtr.cpp
|
||||
TestNumberFormat.cpp
|
||||
TestOptional.cpp
|
||||
TestPrint.cpp
|
||||
TestQueue.cpp
|
||||
TestQuickSort.cpp
|
||||
TestRedBlackTree.cpp
|
||||
|
|
58
Tests/AK/TestPrint.cpp
Normal file
58
Tests/AK/TestPrint.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2022, the SerenityOS developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibTest/TestCase.h>
|
||||
#include <wchar.h>
|
||||
|
||||
TEST_CASE(swprint_no_format)
|
||||
{
|
||||
wchar_t buffer[256];
|
||||
size_t len = swprintf(buffer, 64, L"Well, hello friends!");
|
||||
|
||||
VERIFY(wcscmp(buffer, L"Well, hello friends!") == 0);
|
||||
VERIFY(wcscmp(buffer, L"Well, hello friends") != 0);
|
||||
VERIFY(wcslen(buffer) == len);
|
||||
}
|
||||
|
||||
TEST_CASE(swprint_single_wchar_argument)
|
||||
{
|
||||
wchar_t buffer[256];
|
||||
size_t len = swprintf(buffer, 64, L"Well, %ls friends!", L"hello");
|
||||
|
||||
VERIFY(wcscmp(buffer, L"Well, hello friends!") == 0);
|
||||
VERIFY(wcscmp(buffer, L"Well, hello friends") != 0);
|
||||
VERIFY(wcslen(buffer) == len);
|
||||
}
|
||||
|
||||
TEST_CASE(swprint_single_char_argument)
|
||||
{
|
||||
wchar_t buffer[256];
|
||||
size_t len = swprintf(buffer, 64, L"Well, %s friends!", "hello");
|
||||
|
||||
VERIFY(wcscmp(buffer, L"Well, hello friends!") == 0);
|
||||
VERIFY(wcscmp(buffer, L"Well, hello friends") != 0);
|
||||
VERIFY(wcslen(buffer) == len);
|
||||
}
|
||||
|
||||
TEST_CASE(swprint_single_narrow_char_argument)
|
||||
{
|
||||
wchar_t buffer[256];
|
||||
size_t len = swprintf(buffer, 64, L"Well, %hs friends!", "hello");
|
||||
|
||||
VERIFY(wcscmp(buffer, L"Well, hello friends!") == 0);
|
||||
VERIFY(wcscmp(buffer, L"Well, hello friends") != 0);
|
||||
VERIFY(wcslen(buffer) == len);
|
||||
}
|
||||
|
||||
TEST_CASE(swprint_mixed_arguments)
|
||||
{
|
||||
wchar_t buffer[256];
|
||||
size_t len = swprintf(buffer, 64, L"Well, %ls friends! %hs is less then %s.", L"hello", "10", "20");
|
||||
|
||||
VERIFY(wcscmp(buffer, L"Well, hello friends! 10 is less then 20.") == 0);
|
||||
VERIFY(wcscmp(buffer, L"Well, hello friends! 10 is less then 2.") != 0);
|
||||
VERIFY(wcslen(buffer) == len);
|
||||
}
|
|
@ -118,6 +118,17 @@ struct ArgvNextArgument<const char*, V> {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename V>
|
||||
struct ArgvNextArgument<const wchar_t*, V> {
|
||||
ALWAYS_INLINE const wchar_t* operator()(V arg) const
|
||||
{
|
||||
if (arg.argc == 0)
|
||||
return L"";
|
||||
|
||||
return L"";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename V>
|
||||
struct ArgvNextArgument<int, V> {
|
||||
ALWAYS_INLINE int operator()(V arg) const
|
||||
|
|
Loading…
Reference in a new issue