From ffb95bace4ccbb3294683d8fe8eb2f3e1ed88587 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Wed, 22 Jun 2022 16:07:50 +0200 Subject: [PATCH] LibC: Implement `wcsftime` using a makeshift solution --- Userland/Libraries/LibC/wchar.cpp | 42 +++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/Userland/Libraries/LibC/wchar.cpp b/Userland/Libraries/LibC/wchar.cpp index c2b74fae60..c712199629 100644 --- a/Userland/Libraries/LibC/wchar.cpp +++ b/Userland/Libraries/LibC/wchar.cpp @@ -1,14 +1,17 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2022, Tim Schumacher * * SPDX-License-Identifier: BSD-2-Clause */ #include #include +#include #include #include #include +#include #include static unsigned int mbstate_expected_bytes(mbstate_t* state) @@ -687,13 +690,38 @@ size_t wcsspn(wchar_t const* wcs, wchar_t const* accept) } // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wcsftime.html -size_t wcsftime(wchar_t* __restrict wcs, size_t maxsize, wchar_t const* __restrict format, const struct tm* __restrict timeptr) +size_t wcsftime(wchar_t* destination, size_t maxsize, wchar_t const* format, const struct tm* tm) { - (void)wcs; - (void)maxsize; - (void)format; - (void)timeptr; - dbgln("FIXME: Implement wcsftime()"); - TODO(); + // FIXME: Add actual wide char support for this. + char* ascii_format = static_cast(malloc(wcslen(format) + 1)); + char* ascii_destination = static_cast(malloc(maxsize)); + + VERIFY(ascii_format && ascii_destination); + + // These are copied by value because we will change the pointers without rolling them back. + ScopeGuard free_ascii = [ascii_format, ascii_destination] { + free(ascii_format); + free(ascii_destination); + }; + + char* ascii_format_copy = ascii_format; + do { + VERIFY(*format <= 0x7f); + *ascii_format_copy++ = static_cast(*format); + } while (*format++ != L'\0'); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + size_t ret = strftime(ascii_destination, maxsize, ascii_format, tm); +#pragma GCC diagnostic pop + + if (ret == 0) + return 0; + + do { + *destination++ = *ascii_destination; + } while (*ascii_destination++ != '\0'); + + return ret; } }