locale: Refactor ctype storage and consolidate some files.
* Drop the global definitions from ctype.h, and move them to the internal LocaleData.h: the functions should be used always when building new applications (as they're thread-safe.) * Make __ctype_get_mb_cur_max thread-safe and move it to live alongside the other __ctype...() methods. * Put the __ctype...() methods in two files, clearly indicating versions: ctype_loc_global for the global (non-thread-safe) versions, used for the kernel, and ctype_loc_thread for the libroot versions. * Consolidate more internal functions into LocaleInternal.cpp.
This commit is contained in:
@@ -308,7 +308,7 @@ for platform in [ MultiBootSubDirSetup ] {
|
||||
|
||||
BootMergeObject boot_libroot_$(platform:G=).o :
|
||||
abs.c
|
||||
ctype_loc.cpp
|
||||
ctype_loc_global.cpp
|
||||
ctype_l.cpp
|
||||
ctype.cpp
|
||||
generic_memcpy.c
|
||||
|
||||
@@ -74,7 +74,7 @@ KernelMergeObject kernel_lib_posix.o :
|
||||
utime.c
|
||||
|
||||
# locale
|
||||
ctype_loc.cpp
|
||||
ctype_loc_global.cpp
|
||||
ctype_l.cpp
|
||||
ctype.cpp
|
||||
localeconv.cpp
|
||||
|
||||
@@ -74,7 +74,7 @@ ICUCtypeData::SetTo(const Locale& locale, const char* posixLocaleName)
|
||||
|
||||
ucnv_reset(converter);
|
||||
|
||||
fDataBridge->setMbCurMax(ucnv_getMaxCharSize(converter));
|
||||
*fDataBridge->addrOfMbCurMax = ucnv_getMaxCharSize(converter);
|
||||
|
||||
char buffer[] = { 0, 0 };
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
@@ -150,8 +150,7 @@ ICUCtypeData::SetToPosix()
|
||||
memcpy(fClassInfo, fDataBridge->posixClassInfo, sizeof(fClassInfo));
|
||||
memcpy(fToLowerMap, fDataBridge->posixToLowerMap, sizeof(fToLowerMap));
|
||||
memcpy(fToUpperMap, fDataBridge->posixToUpperMap, sizeof(fToUpperMap));
|
||||
|
||||
fDataBridge->setMbCurMax(1);
|
||||
*fDataBridge->addrOfMbCurMax = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -13,8 +13,9 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
||||
local architecture = $(TARGET_PACKAGING_ARCH) ;
|
||||
|
||||
MergeObject <$(architecture)>posix_locale.o :
|
||||
ctype_l.cpp
|
||||
ctype.cpp
|
||||
ctype_l.cpp
|
||||
ctype_loc_thread.cpp
|
||||
LocaleBackend.cpp
|
||||
LocaleData.cpp
|
||||
LocaleDataBridge.cpp
|
||||
@@ -23,13 +24,12 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
||||
localeconv.cpp
|
||||
nl_langinfo.cpp
|
||||
setlocale.cpp
|
||||
ThreadLocale.cpp
|
||||
wctype_l.cpp
|
||||
wctype.cpp
|
||||
;
|
||||
|
||||
MergeObject <$(architecture)>ctype_loc.o :
|
||||
ctype_loc.cpp
|
||||
MergeObject <$(architecture)>ctype_loc_global.o :
|
||||
ctype_loc_global.cpp
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,12 @@
|
||||
|
||||
|
||||
#include "LocaleBackend.h"
|
||||
#include "LocaleInternal.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ThreadLocale.h>
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
namespace Libroot {
|
||||
|
||||
@@ -329,3 +329,4 @@ const char* gPosixLanginfo[_NL_LANGINFO_LAST] = {
|
||||
const unsigned short* __ctype_b = &BPrivate::Libroot::gPosixClassInfo[128];
|
||||
const int* __ctype_tolower = &BPrivate::Libroot::gPosixToLowerMap[128];
|
||||
const int* __ctype_toupper = &BPrivate::Libroot::gPosixToUpperMap[128];
|
||||
unsigned short int __ctype_mb_cur_max = 1;
|
||||
|
||||
@@ -5,20 +5,17 @@
|
||||
|
||||
|
||||
#include "LocaleBackend.h"
|
||||
#include "LocaleInternal.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <langinfo.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <LocaleData.h>
|
||||
|
||||
|
||||
extern const unsigned short* __ctype_b;
|
||||
extern const int* __ctype_tolower;
|
||||
extern const int* __ctype_toupper;
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
namespace Libroot {
|
||||
|
||||
@@ -37,26 +34,27 @@ LocaleCtypeDataBridge::LocaleCtypeDataBridge(bool isGlobal)
|
||||
addrOfClassInfoTable = &__ctype_b;
|
||||
addrOfToLowerTable = &__ctype_tolower;
|
||||
addrOfToUpperTable = &__ctype_toupper;
|
||||
addrOfMbCurMax = &__ctype_mb_cur_max;
|
||||
} else {
|
||||
addrOfClassInfoTable = &localClassInfoTable;
|
||||
addrOfToLowerTable = &localToLowerTable;
|
||||
addrOfToUpperTable = &localToUpperTable;
|
||||
addrOfMbCurMax = &localMbCurMax;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LocaleCtypeDataBridge::setMbCurMax(unsigned short mbCurMax)
|
||||
{
|
||||
__ctype_mb_cur_max = mbCurMax;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LocaleCtypeDataBridge::ApplyToCurrentThread()
|
||||
{
|
||||
*__ctype_b_loc() = *addrOfClassInfoTable;
|
||||
*__ctype_tolower_loc() = *addrOfToLowerTable;
|
||||
*__ctype_toupper_loc() = *addrOfToUpperTable;
|
||||
if (isGlobal)
|
||||
abort();
|
||||
|
||||
ThreadLocale* threadLocale = GetCurrentThreadLocale();
|
||||
threadLocale->ctype_b = *addrOfClassInfoTable;
|
||||
threadLocale->ctype_tolower = *addrOfToLowerTable;
|
||||
threadLocale->ctype_toupper = *addrOfToUpperTable;
|
||||
threadLocale->mb_cur_max = addrOfMbCurMax;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,8 +74,7 @@ LocaleMonetaryDataBridge::LocaleMonetaryDataBridge()
|
||||
|
||||
LocaleNumericDataBridge::LocaleNumericDataBridge(bool isGlobal)
|
||||
:
|
||||
posixLocaleConv(&gPosixLocaleConv),
|
||||
isGlobal(isGlobal)
|
||||
posixLocaleConv(&gPosixLocaleConv)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -97,8 +94,7 @@ LocaleTimeDataBridge::LocaleTimeDataBridge()
|
||||
TimeConversionDataBridge::TimeConversionDataBridge(bool isGlobal)
|
||||
:
|
||||
localDaylight(daylight),
|
||||
localTimezone(timezone),
|
||||
isGlobal(isGlobal)
|
||||
localTimezone(timezone)
|
||||
{
|
||||
if (isGlobal) {
|
||||
addrOfDaylight = &daylight;
|
||||
@@ -121,8 +117,7 @@ LocaleDataBridge::LocaleDataBridge(bool isGlobal)
|
||||
ctypeDataBridge(isGlobal),
|
||||
numericDataBridge(isGlobal),
|
||||
timeConversionDataBridge(isGlobal),
|
||||
posixLanginfo(gPosixLanginfo),
|
||||
isGlobal(isGlobal)
|
||||
posixLanginfo(gPosixLanginfo)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -131,7 +126,7 @@ void
|
||||
LocaleDataBridge::ApplyToCurrentThread()
|
||||
{
|
||||
ctypeDataBridge.ApplyToCurrentThread();
|
||||
// While timeConverstionDataBridge stores read-write variables,
|
||||
// While timeConversionDataBridge stores read-write variables,
|
||||
// these variables are global (by POSIX definition). Furthermore,
|
||||
// none of the backends seem to access these variables
|
||||
// directly. The values are set in the bridge mostly for
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
/*
|
||||
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de
|
||||
* Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de
|
||||
* Copyright 2022, Trung Nguyen, trungnt282910@gmail.com
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "LocaleInternal.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <tls.h>
|
||||
#include <OS.h>
|
||||
#include <Debug.h>
|
||||
|
||||
#include "LocaleData.h"
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
namespace Libroot {
|
||||
@@ -21,9 +27,8 @@ namespace Libroot {
|
||||
status_t
|
||||
GetLocalesFromEnvironment(int category, const char** locales)
|
||||
{
|
||||
if (category > LC_LAST) {
|
||||
if (category > LC_LAST)
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
const char* locale = getenv("LC_ALL");
|
||||
if (locale != NULL && *locale != '\0')
|
||||
@@ -72,5 +77,33 @@ GetLocalesFromEnvironment(int category, const char** locales)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DestroyThreadLocale(void* ptr)
|
||||
{
|
||||
ThreadLocale* threadLocale = (ThreadLocale*)ptr;
|
||||
delete threadLocale;
|
||||
}
|
||||
|
||||
|
||||
ThreadLocale*
|
||||
GetCurrentThreadLocale()
|
||||
{
|
||||
ThreadLocale* threadLocale = (ThreadLocale*)tls_get(TLS_LOCALE_SLOT);
|
||||
if (threadLocale == NULL) {
|
||||
threadLocale = new ThreadLocale();
|
||||
threadLocale->threadLocaleInfo = NULL;
|
||||
threadLocale->ctype_b = __ctype_b;
|
||||
threadLocale->ctype_tolower = __ctype_tolower;
|
||||
threadLocale->ctype_toupper = __ctype_toupper;
|
||||
threadLocale->mb_cur_max = &__ctype_mb_cur_max;
|
||||
|
||||
on_exit_thread(DestroyThreadLocale, threadLocale);
|
||||
tls_set(TLS_LOCALE_SLOT, threadLocale);
|
||||
}
|
||||
return threadLocale;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Libroot
|
||||
} // namespace BPrivate
|
||||
|
||||
@@ -17,5 +17,19 @@ namespace Libroot {
|
||||
|
||||
status_t GetLocalesFromEnvironment(int category, const char** locales);
|
||||
|
||||
|
||||
// The pointer in the TLS will point to this struct.
|
||||
struct ThreadLocale {
|
||||
struct LocaleBackendData* threadLocaleInfo;
|
||||
|
||||
const unsigned short int* ctype_b;
|
||||
const int* ctype_tolower;
|
||||
const int* ctype_toupper;
|
||||
const unsigned short int* mb_cur_max;
|
||||
};
|
||||
|
||||
ThreadLocale* GetCurrentThreadLocale();
|
||||
|
||||
|
||||
} // namespace Libroot
|
||||
} // namespace BPrivate
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022, Trung Nguyen, trungnt282910@gmail.com
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <tls.h>
|
||||
#include <kernel/OS.h>
|
||||
#include <ThreadLocale.h>
|
||||
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
namespace Libroot {
|
||||
|
||||
|
||||
static void
|
||||
DestroyThreadLocale(void* ptr)
|
||||
{
|
||||
ThreadLocale* threadLocale = (ThreadLocale*)ptr;
|
||||
delete threadLocale;
|
||||
}
|
||||
|
||||
|
||||
ThreadLocale*
|
||||
GetCurrentThreadLocale()
|
||||
{
|
||||
ThreadLocale* threadLocale = (ThreadLocale*)tls_get(TLS_LOCALE_SLOT);
|
||||
if (threadLocale == NULL) {
|
||||
threadLocale = new ThreadLocale();
|
||||
threadLocale->threadLocaleInfo = NULL;
|
||||
threadLocale->ctype_b = __ctype_b;
|
||||
threadLocale->ctype_tolower = __ctype_tolower;
|
||||
threadLocale->ctype_toupper = __ctype_toupper;
|
||||
|
||||
on_exit_thread(DestroyThreadLocale, threadLocale);
|
||||
tls_set(TLS_LOCALE_SLOT, threadLocale);
|
||||
}
|
||||
return threadLocale;
|
||||
}
|
||||
|
||||
|
||||
extern "C" const unsigned short**
|
||||
__ctype_b_loc()
|
||||
{
|
||||
return &GetCurrentThreadLocale()->ctype_b;
|
||||
}
|
||||
|
||||
|
||||
extern "C" const int**
|
||||
__ctype_tolower_loc()
|
||||
{
|
||||
return &GetCurrentThreadLocale()->ctype_tolower;
|
||||
}
|
||||
|
||||
|
||||
extern "C" const int**
|
||||
__ctype_toupper_loc()
|
||||
{
|
||||
return &GetCurrentThreadLocale()->ctype_toupper;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Libroot
|
||||
} // namespace BPrivate
|
||||
@@ -30,16 +30,6 @@ extern "C"
|
||||
{
|
||||
|
||||
|
||||
unsigned short int __ctype_mb_cur_max = 1;
|
||||
|
||||
|
||||
unsigned short
|
||||
__ctype_get_mb_cur_max()
|
||||
{
|
||||
return __ctype_mb_cur_max;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isalnum(int c)
|
||||
{
|
||||
|
||||
+13
-3
@@ -6,28 +6,38 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <LocaleData.h>
|
||||
|
||||
|
||||
// These functions are intended for scenarios where we cannot
|
||||
// link to the whole libroot and access pthread functions;
|
||||
// for example, when we're in the bootloader, kernel or the
|
||||
// runtime_loader.
|
||||
|
||||
extern "C" const unsigned short**
|
||||
|
||||
extern "C" const unsigned short *const *const
|
||||
__ctype_b_loc()
|
||||
{
|
||||
return &__ctype_b;
|
||||
}
|
||||
|
||||
|
||||
extern "C" const int**
|
||||
extern "C" const int *const *const
|
||||
__ctype_tolower_loc()
|
||||
{
|
||||
return &__ctype_tolower;
|
||||
}
|
||||
|
||||
|
||||
extern "C" const int**
|
||||
extern "C" const int *const *const
|
||||
__ctype_toupper_loc()
|
||||
{
|
||||
return &__ctype_toupper;
|
||||
}
|
||||
|
||||
|
||||
extern "C" unsigned short
|
||||
__ctype_get_mb_cur_max()
|
||||
{
|
||||
return __ctype_mb_cur_max;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2022, Trung Nguyen, trungnt282910@gmail.com
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "LocaleInternal.h"
|
||||
|
||||
|
||||
using BPrivate::Libroot::GetCurrentThreadLocale;
|
||||
|
||||
|
||||
extern "C" const unsigned short int *const *const
|
||||
__ctype_b_loc()
|
||||
{
|
||||
return &GetCurrentThreadLocale()->ctype_b;
|
||||
}
|
||||
|
||||
|
||||
extern "C" const int *const *const
|
||||
__ctype_tolower_loc()
|
||||
{
|
||||
return &GetCurrentThreadLocale()->ctype_tolower;
|
||||
}
|
||||
|
||||
|
||||
extern "C" const int *const *const
|
||||
__ctype_toupper_loc()
|
||||
{
|
||||
return &GetCurrentThreadLocale()->ctype_toupper;
|
||||
}
|
||||
|
||||
|
||||
extern "C" unsigned short
|
||||
__ctype_get_mb_cur_max()
|
||||
{
|
||||
return *GetCurrentThreadLocale()->mb_cur_max;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
||||
<src!system!libroot!posix!$(architecture)>fcntl.o
|
||||
|
||||
<src!system!libroot!posix!locale!$(architecture)>ctype.o
|
||||
<src!system!libroot!posix!locale!$(architecture)>ctype_loc.o
|
||||
<src!system!libroot!posix!locale!$(architecture)>ctype_loc_global.o
|
||||
<src!system!libroot!posix!locale!$(architecture)>LocaleData.o
|
||||
|
||||
<src!system!libroot!posix!musl!string!$(architecture)>memchr.o
|
||||
|
||||
Reference in New Issue
Block a user