mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-15 10:15:32 +01:00
d54fc63747
application, for unit tests.
270 lines
7.6 KiB
C++
270 lines
7.6 KiB
C++
//
|
|
// wfunction.hpp
|
|
// cpp_tests
|
|
//
|
|
// Created by jief on 15.03.20.
|
|
// Copyright © 2020 Jief_Machak. All rights reserved.
|
|
//
|
|
|
|
/*
|
|
* clang had poisoned identifier like wcslen.
|
|
* It's not possible to define a function with that name, not even a macro... except on the command line.
|
|
* So, for this to work, pass macro definition argument on command line : wcslen=wcslen_fixed wcscmp=__wcscmp_is_disabled__ wcsncmp=wcsncmp_fixed wcsstr=wcsstr_fixed
|
|
*/
|
|
|
|
/*
|
|
* 2021, Mojave.
|
|
* wcslen, wcsncmp seems fixed !
|
|
* wcsstr is NOT.
|
|
* printf with %ls is not.
|
|
* wprintf is not.
|
|
*/
|
|
|
|
#include <wchar.h>
|
|
#include <vector>
|
|
#include <cwchar>
|
|
#include <unistd.h>
|
|
#include <locale.h>
|
|
#include <locale>
|
|
#include <string>
|
|
#include <codecvt>
|
|
//#include "../../../Include/Library/printf_lite.h"
|
|
#include "../../../rEFIt_UEFI/Platform/BootLog.h"
|
|
|
|
#include "xcode_utf_fixed.h"
|
|
|
|
/* few tests for debug purpose */
|
|
extern "C" void xcode_utf_fixed_tests()
|
|
{
|
|
setlocale(LC_ALL, "en_US"); // to allow printf unicode char
|
|
|
|
printf("sizeof(wchar_t)=%zu\n", sizeof(wchar_t));
|
|
printf("sizeof(size_t)=%zu\n", sizeof(size_t));
|
|
printf("sizeof(long)=%zu\n", sizeof(long));
|
|
printf("sizeof(long long)=%zu\n", sizeof(long long));
|
|
printf("sizeof(size_t)=%zu\n", sizeof(size_t));
|
|
#ifndef _MSC_VER
|
|
//printf("%zu\n", (size_t)MAX_UINT64);
|
|
//printf("%zd\n", (size_t)MAX_UINT64);
|
|
#endif
|
|
printf("%lc\n", L'Ľ');
|
|
|
|
#if PRINTF_LITE_REPLACE_STANDARD_FUNCTION == 1
|
|
printf("%ls\n", L"Hello world1");
|
|
char buf[50];
|
|
snprintf(buf, 50, "%ls", L"Hello world2");
|
|
printf("%s\n", buf);
|
|
wprintf(L"%ls\n", L"Hello world൧楔");
|
|
#endif
|
|
|
|
uint64_t uint64 = 1;
|
|
printf("Hello world൧楔 %llu \n", uint64);
|
|
DebugLog(2, "Hello world൧楔 %llu \n", uint64);
|
|
|
|
size_t len1 = wcslen(L"Hell൧楔o world൧楔");
|
|
size_t len1f = wcslen_fixed(L"Hell൧楔o world൧楔");
|
|
printf("len1 = %zu, len1f = %zd\n", len1, len1f);
|
|
|
|
int cmp1 = wcsncmp(L"12楔34", L"12楔35", 4);
|
|
int cmp1f = wcsncmp_fixed(L"12楔34", L"12楔35", 4);
|
|
printf("cmp1 = %d, cmp1f = %d\n", cmp1, cmp1f);
|
|
|
|
{
|
|
const wchar_t* str = L"12ク34";
|
|
const wchar_t* strstr1 = wcsstr(str, L"ク");
|
|
const wchar_t* strstr1f = wcsstr_fixed(str, L"ク");
|
|
printf("strstr1 = %ld, strstr1f = %ld\n", strstr1-str, strstr1f-str);
|
|
}
|
|
|
|
printf("\n\n\n");
|
|
|
|
// char32_t c32 = (int)-1;
|
|
}
|
|
|
|
|
|
#include "xcode_utf_fixed.h"
|
|
|
|
|
|
#if __WCHAR_MAX__ < 0x10000
|
|
|
|
#undef wcslen
|
|
extern "C" size_t wcslen(const wchar_t *);
|
|
#undef wcscmp
|
|
extern "C" int wcscmp(const wchar_t *s1, const wchar_t * s2);
|
|
#undef wcsncmp
|
|
extern "C" int wcsncmp(const wchar_t *, const wchar_t *, size_t);
|
|
#undef wcsstr
|
|
extern "C" wchar_t *wcsstr(const wchar_t *, const wchar_t *);
|
|
|
|
static int is_surrogate(char16_t uc) { return (uc - 0xd800u) < 2048u; }
|
|
static int is_high_surrogate(char16_t uc) { return (uc & 0xfffffc00) == 0xd800; }
|
|
static int is_low_surrogate(char16_t uc) { return (uc & 0xfffffc00) == 0xdc00; }
|
|
|
|
static char32_t surrogate_to_utf32(char16_t high, char16_t low) {
|
|
return char32_t((high << 10) + low - 0x35fdc00); // Safe cast, it fits in 32 bits
|
|
}
|
|
|
|
static void convert_utf16_to_utf32(const char16_t* input, size_t input_size, std::vector<char32_t>* output)
|
|
{
|
|
const char16_t* const end = input + input_size;
|
|
while (input < end && *input) {
|
|
const char16_t uc = *input++;
|
|
if (!is_surrogate(uc)) {
|
|
(*output).push_back(uc);
|
|
} else {
|
|
if (is_high_surrogate(uc) && input < end && is_low_surrogate(*input))
|
|
(*output).push_back(surrogate_to_utf32(uc, *input++));
|
|
else {
|
|
// ERROR
|
|
}
|
|
}
|
|
}
|
|
(*output).push_back(0);
|
|
}
|
|
|
|
std::string to_utf8(const char16_t* s)
|
|
{
|
|
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> conv;
|
|
return conv.to_bytes(s);
|
|
}
|
|
|
|
#else
|
|
|
|
std::string to_utf8(const char32_t* s)
|
|
{
|
|
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
|
|
return conv.to_bytes(s);
|
|
}
|
|
|
|
#endif
|
|
|
|
size_t wcslen_fixed(const wchar_t *s)
|
|
{
|
|
#if __WCHAR_MAX__ >= 0x10000
|
|
return wcslen(s);
|
|
#else
|
|
// wcslen seems not to work if sizeof(wchar_t) == 2
|
|
const wchar_t* p;
|
|
for ( p = s ; *p ; p++ );
|
|
return (size_t)(p-s);
|
|
#endif
|
|
|
|
}
|
|
|
|
int wcsncmp_fixed(const wchar_t *s1, const wchar_t * s2, size_t n)
|
|
{
|
|
#if __WCHAR_MAX__ >= 0x10000
|
|
return wcsncmp(s1, s2, n);
|
|
#else
|
|
// Looks like wcscmp doesn't work with Utf16, even if compiled with -fshort-wchar.
|
|
// So conversion to Utf32 needed first.
|
|
|
|
std::vector<char32_t> s1Utf32;
|
|
std::vector<char32_t> s2Utf32;
|
|
|
|
convert_utf16_to_utf32((const char16_t*)s1, n, &s1Utf32);
|
|
convert_utf16_to_utf32((const char16_t*)s2, n, &s2Utf32);
|
|
|
|
// we don't know the new value of n (x UTF16 chars is not x*2 UTF32 chars), so we can't call wcsncmp
|
|
// but that's ok because we converted only n UTF16 chars in the call of convert_utf16_to_utf32
|
|
int ret = wcscmp((const wchar_t*)s1Utf32.data(), (const wchar_t*)s2Utf32.data());
|
|
return ret;
|
|
#endif
|
|
}
|
|
|
|
#ifdef _LIBCPP_WCHAR_H
|
|
wchar_t* wcsstr_fixed(const wchar_t* haystack, const wchar_t* needle)
|
|
#else
|
|
const wchar_t* wcsstr_fixed(const wchar_t* haystack, const wchar_t* needle)
|
|
#endif
|
|
{
|
|
#if __WCHAR_MAX__ >= 0x10000
|
|
return (wchar_t*)wcsstr(haystack, needle);
|
|
#else
|
|
// Looks like wcscmp doesn't work with Utf16, even if compiled with -fshort-wchar.
|
|
// So conversion to Utf32 needed first.
|
|
|
|
|
|
const wchar_t *a = haystack, *b = needle;
|
|
for (;;)
|
|
if (!*b) return (wchar_t*)(a - wcslen_fixed(needle));
|
|
else if (!*a) return NULL;
|
|
else if (*a++ != *b++) { a = ++haystack; b = needle;}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* macOS 10.15 define vsnprintf as a macro that calls __vsnprintf_chk
|
|
*/
|
|
extern "C" int __vsnprintf_chk (char* buf, size_t len, int check, size_t size, const char* format, va_list va)
|
|
{
|
|
(void)check;
|
|
(void)size;
|
|
return PRINTF_FUNCTION_NAME(PRINTF_CFUNCTION_PREFIX, vsnprint, PRINTF_CFUNCTION_SUFFIX)(buf, len, format, va);
|
|
}
|
|
|
|
#if PRINTF_LITE_REPLACE_STANDARD_FUNCTION == 1
|
|
extern "C" int printf(const char* format, ...)
|
|
{
|
|
int ret;
|
|
#if __WCHAR_MAX__ <= 0xFFFF
|
|
va_list va;
|
|
va_start(va, format);
|
|
char buf[4095];
|
|
ret = PRINTF_FUNCTION_NAME(PRINTF_CFUNCTION_PREFIX, vsnprint, PRINTF_CFUNCTION_SUFFIX)(buf, sizeof(buf)-1, format, va);
|
|
write(1, buf, strlen(buf));
|
|
va_end(va);
|
|
#else
|
|
va_list va;
|
|
va_start(va, format);
|
|
ret = vprintf(format, va);
|
|
va_end(va);
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
#if __WCHAR_MAX__ <= 0xFFFF
|
|
extern "C" int vprintf(const char* format, va_list va)
|
|
{
|
|
int ret;
|
|
char buf[4095];
|
|
ret = PRINTF_FUNCTION_NAME(PRINTF_CFUNCTION_PREFIX, vsnprint, PRINTF_CFUNCTION_SUFFIX)(buf, sizeof(buf)-1, format, va);
|
|
write(1, buf, strlen(buf));
|
|
return ret;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
//extern "C" int snprintf(char * __restrict buf, size_t len, const char * __restrict format, ...)
|
|
//{
|
|
// int ret = PRINTF_FUNCTION_NAME(PRINTF_CFUNCTION_PREFIX, snprint, PRINTF_CFUNCTION_SUFFIX)(buf, sizeof(buf)-1, format);
|
|
// return ret;
|
|
//}
|
|
|
|
int wprintf(const wchar_t* wformat, ...)
|
|
{
|
|
int ret;
|
|
#if __WCHAR_MAX__ <= 0xFFFF
|
|
std::string format = to_utf8((char16_t*)wformat);
|
|
wchar_t wbuf[4095];
|
|
|
|
va_list va;
|
|
va_start(va, wformat);
|
|
ret = PRINTF_FUNCTION_NAME(PRINTF_CFUNCTION_PREFIX, vsnwprint, PRINTF_CFUNCTION_SUFFIX)(wbuf, sizeof(wbuf)-1, format.c_str(), va);
|
|
va_end(va);
|
|
std::string buf = to_utf8((char16_t*)wbuf);
|
|
write(1, buf.c_str(), buf.length());
|
|
#else
|
|
std::string format = to_utf8((char32_t*)wformat);
|
|
wchar_t wbuf[4095];
|
|
va_list va;
|
|
va_start(va, wformat);
|
|
ret = PRINTF_FUNCTION_NAME(PRINTF_CFUNCTION_PREFIX, vsnwprint, PRINTF_CFUNCTION_SUFFIX)(wbuf, sizeof(wbuf)-1, format.c_str(), va);
|
|
va_end(va);
|
|
std::string buf = to_utf8((char32_t*)wbuf);
|
|
write(1, buf.c_str(), buf.length());
|
|
#endif
|
|
return ret;
|
|
}
|