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:
+3
-11
@@ -61,15 +61,9 @@ enum {
|
|||||||
_ISgraph = 0x8000 /* graphical */
|
_ISgraph = 0x8000 /* graphical */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Characteristics */
|
extern const unsigned short int *const *const __ctype_b_loc();
|
||||||
extern const unsigned short int *__ctype_b;
|
extern const int *const *const __ctype_tolower_loc();
|
||||||
/* Case conversions */
|
extern const int *const *const __ctype_toupper_loc();
|
||||||
extern const int *__ctype_tolower;
|
|
||||||
extern const int *__ctype_toupper;
|
|
||||||
|
|
||||||
extern const unsigned short int **__ctype_b_loc();
|
|
||||||
extern const int **__ctype_tolower_loc();
|
|
||||||
extern const int **__ctype_toupper_loc();
|
|
||||||
|
|
||||||
#define __isctype(c, type) \
|
#define __isctype(c, type) \
|
||||||
((*__ctype_b_loc())[(int)(c)] & (unsigned short int)type)
|
((*__ctype_b_loc())[(int)(c)] & (unsigned short int)type)
|
||||||
@@ -96,8 +90,6 @@ extern const int **__ctype_toupper_loc();
|
|||||||
#define isupper(c) __isctype((c), _ISupper)
|
#define isupper(c) __isctype((c), _ISupper)
|
||||||
#define isxdigit(c) __isctype((c), _ISxdigit)
|
#define isxdigit(c) __isctype((c), _ISxdigit)
|
||||||
|
|
||||||
extern unsigned short int __ctype_mb_cur_max;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,11 +25,13 @@ private:
|
|||||||
const unsigned short* localClassInfoTable;
|
const unsigned short* localClassInfoTable;
|
||||||
const int* localToLowerTable;
|
const int* localToLowerTable;
|
||||||
const int* localToUpperTable;
|
const int* localToUpperTable;
|
||||||
|
unsigned short localMbCurMax;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const unsigned short** addrOfClassInfoTable;
|
const unsigned short** addrOfClassInfoTable;
|
||||||
const int** addrOfToLowerTable;
|
const int** addrOfToLowerTable;
|
||||||
const int** addrOfToUpperTable;
|
const int** addrOfToUpperTable;
|
||||||
|
unsigned short* addrOfMbCurMax;
|
||||||
|
|
||||||
const unsigned short* const posixClassInfo;
|
const unsigned short* const posixClassInfo;
|
||||||
const int* const posixToLowerMap;
|
const int* const posixToLowerMap;
|
||||||
@@ -39,7 +41,6 @@ public:
|
|||||||
|
|
||||||
LocaleCtypeDataBridge(bool isGlobal);
|
LocaleCtypeDataBridge(bool isGlobal);
|
||||||
|
|
||||||
void setMbCurMax(unsigned short mbCurMax);
|
|
||||||
void ApplyToCurrentThread();
|
void ApplyToCurrentThread();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,7 +62,6 @@ struct LocaleMonetaryDataBridge {
|
|||||||
struct LocaleNumericDataBridge {
|
struct LocaleNumericDataBridge {
|
||||||
public:
|
public:
|
||||||
const struct lconv* const posixLocaleConv;
|
const struct lconv* const posixLocaleConv;
|
||||||
bool isGlobal;
|
|
||||||
|
|
||||||
LocaleNumericDataBridge(bool isGlobal);
|
LocaleNumericDataBridge(bool isGlobal);
|
||||||
~LocaleNumericDataBridge();
|
~LocaleNumericDataBridge();
|
||||||
@@ -89,7 +89,6 @@ public:
|
|||||||
int* addrOfDaylight;
|
int* addrOfDaylight;
|
||||||
long* addrOfTimezone;
|
long* addrOfTimezone;
|
||||||
char** addrOfTZName;
|
char** addrOfTZName;
|
||||||
bool isGlobal;
|
|
||||||
|
|
||||||
TimeConversionDataBridge(bool isGlobal);
|
TimeConversionDataBridge(bool isGlobal);
|
||||||
};
|
};
|
||||||
@@ -103,7 +102,6 @@ struct LocaleDataBridge {
|
|||||||
LocaleTimeDataBridge timeDataBridge;
|
LocaleTimeDataBridge timeDataBridge;
|
||||||
TimeConversionDataBridge timeConversionDataBridge;
|
TimeConversionDataBridge timeConversionDataBridge;
|
||||||
const char** const posixLanginfo;
|
const char** const posixLanginfo;
|
||||||
bool isGlobal;
|
|
||||||
|
|
||||||
LocaleDataBridge(bool isGlobal);
|
LocaleDataBridge(bool isGlobal);
|
||||||
|
|
||||||
@@ -182,6 +180,7 @@ LocaleBackend* GetCurrentLocaleBackend();
|
|||||||
extern LocaleBackend* gGlobalLocaleBackend;
|
extern LocaleBackend* gGlobalLocaleBackend;
|
||||||
extern LocaleDataBridge gGlobalLocaleDataBridge;
|
extern LocaleDataBridge gGlobalLocaleDataBridge;
|
||||||
|
|
||||||
|
|
||||||
} // namespace Libroot
|
} // namespace Libroot
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,15 @@
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
// Global storage (exported for BeOS and older Haiku compatibility)
|
||||||
|
extern const unsigned short int *__ctype_b;
|
||||||
|
extern const int *__ctype_tolower;
|
||||||
|
extern const int *__ctype_toupper;
|
||||||
|
extern unsigned short int __ctype_mb_cur_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
namespace Libroot {
|
namespace Libroot {
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022, Trung Nguyen, [email protected]
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _THREAD_LOCALE_H
|
|
||||||
#define _THREAD_LOCALE_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "LocaleBackend.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
namespace Libroot {
|
|
||||||
|
|
||||||
|
|
||||||
// The pointer in the TLS will point to this struct.
|
|
||||||
struct ThreadLocale {
|
|
||||||
LocaleBackendData* threadLocaleInfo;
|
|
||||||
|
|
||||||
const unsigned short int* ctype_b;
|
|
||||||
const int* ctype_tolower;
|
|
||||||
const int* ctype_toupper;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
ThreadLocale* GetCurrentThreadLocale();
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Libroot
|
|
||||||
} // namespace BPrivate
|
|
||||||
|
|
||||||
|
|
||||||
#endif // _THREAD_LOCALE_H
|
|
||||||
@@ -308,7 +308,7 @@ for platform in [ MultiBootSubDirSetup ] {
|
|||||||
|
|
||||||
BootMergeObject boot_libroot_$(platform:G=).o :
|
BootMergeObject boot_libroot_$(platform:G=).o :
|
||||||
abs.c
|
abs.c
|
||||||
ctype_loc.cpp
|
ctype_loc_global.cpp
|
||||||
ctype_l.cpp
|
ctype_l.cpp
|
||||||
ctype.cpp
|
ctype.cpp
|
||||||
generic_memcpy.c
|
generic_memcpy.c
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ KernelMergeObject kernel_lib_posix.o :
|
|||||||
utime.c
|
utime.c
|
||||||
|
|
||||||
# locale
|
# locale
|
||||||
ctype_loc.cpp
|
ctype_loc_global.cpp
|
||||||
ctype_l.cpp
|
ctype_l.cpp
|
||||||
ctype.cpp
|
ctype.cpp
|
||||||
localeconv.cpp
|
localeconv.cpp
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ ICUCtypeData::SetTo(const Locale& locale, const char* posixLocaleName)
|
|||||||
|
|
||||||
ucnv_reset(converter);
|
ucnv_reset(converter);
|
||||||
|
|
||||||
fDataBridge->setMbCurMax(ucnv_getMaxCharSize(converter));
|
*fDataBridge->addrOfMbCurMax = ucnv_getMaxCharSize(converter);
|
||||||
|
|
||||||
char buffer[] = { 0, 0 };
|
char buffer[] = { 0, 0 };
|
||||||
for (int i = 0; i < 256; ++i) {
|
for (int i = 0; i < 256; ++i) {
|
||||||
@@ -150,8 +150,7 @@ ICUCtypeData::SetToPosix()
|
|||||||
memcpy(fClassInfo, fDataBridge->posixClassInfo, sizeof(fClassInfo));
|
memcpy(fClassInfo, fDataBridge->posixClassInfo, sizeof(fClassInfo));
|
||||||
memcpy(fToLowerMap, fDataBridge->posixToLowerMap, sizeof(fToLowerMap));
|
memcpy(fToLowerMap, fDataBridge->posixToLowerMap, sizeof(fToLowerMap));
|
||||||
memcpy(fToUpperMap, fDataBridge->posixToUpperMap, sizeof(fToUpperMap));
|
memcpy(fToUpperMap, fDataBridge->posixToUpperMap, sizeof(fToUpperMap));
|
||||||
|
*fDataBridge->addrOfMbCurMax = 1;
|
||||||
fDataBridge->setMbCurMax(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
|||||||
local architecture = $(TARGET_PACKAGING_ARCH) ;
|
local architecture = $(TARGET_PACKAGING_ARCH) ;
|
||||||
|
|
||||||
MergeObject <$(architecture)>posix_locale.o :
|
MergeObject <$(architecture)>posix_locale.o :
|
||||||
ctype_l.cpp
|
|
||||||
ctype.cpp
|
ctype.cpp
|
||||||
|
ctype_l.cpp
|
||||||
|
ctype_loc_thread.cpp
|
||||||
LocaleBackend.cpp
|
LocaleBackend.cpp
|
||||||
LocaleData.cpp
|
LocaleData.cpp
|
||||||
LocaleDataBridge.cpp
|
LocaleDataBridge.cpp
|
||||||
@@ -23,13 +24,12 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
|||||||
localeconv.cpp
|
localeconv.cpp
|
||||||
nl_langinfo.cpp
|
nl_langinfo.cpp
|
||||||
setlocale.cpp
|
setlocale.cpp
|
||||||
ThreadLocale.cpp
|
|
||||||
wctype_l.cpp
|
wctype_l.cpp
|
||||||
wctype.cpp
|
wctype.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
MergeObject <$(architecture)>ctype_loc.o :
|
MergeObject <$(architecture)>ctype_loc_global.o :
|
||||||
ctype_loc.cpp
|
ctype_loc_global.cpp
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,12 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "LocaleBackend.h"
|
#include "LocaleBackend.h"
|
||||||
|
#include "LocaleInternal.h"
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <ThreadLocale.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
namespace Libroot {
|
namespace Libroot {
|
||||||
|
|||||||
@@ -329,3 +329,4 @@ const char* gPosixLanginfo[_NL_LANGINFO_LAST] = {
|
|||||||
const unsigned short* __ctype_b = &BPrivate::Libroot::gPosixClassInfo[128];
|
const unsigned short* __ctype_b = &BPrivate::Libroot::gPosixClassInfo[128];
|
||||||
const int* __ctype_tolower = &BPrivate::Libroot::gPosixToLowerMap[128];
|
const int* __ctype_tolower = &BPrivate::Libroot::gPosixToLowerMap[128];
|
||||||
const int* __ctype_toupper = &BPrivate::Libroot::gPosixToUpperMap[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 "LocaleBackend.h"
|
||||||
|
#include "LocaleInternal.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <langinfo.h>
|
#include <langinfo.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include <LocaleData.h>
|
#include <LocaleData.h>
|
||||||
|
|
||||||
|
|
||||||
extern const unsigned short* __ctype_b;
|
|
||||||
extern const int* __ctype_tolower;
|
|
||||||
extern const int* __ctype_toupper;
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
namespace Libroot {
|
namespace Libroot {
|
||||||
|
|
||||||
@@ -37,26 +34,27 @@ LocaleCtypeDataBridge::LocaleCtypeDataBridge(bool isGlobal)
|
|||||||
addrOfClassInfoTable = &__ctype_b;
|
addrOfClassInfoTable = &__ctype_b;
|
||||||
addrOfToLowerTable = &__ctype_tolower;
|
addrOfToLowerTable = &__ctype_tolower;
|
||||||
addrOfToUpperTable = &__ctype_toupper;
|
addrOfToUpperTable = &__ctype_toupper;
|
||||||
|
addrOfMbCurMax = &__ctype_mb_cur_max;
|
||||||
} else {
|
} else {
|
||||||
addrOfClassInfoTable = &localClassInfoTable;
|
addrOfClassInfoTable = &localClassInfoTable;
|
||||||
addrOfToLowerTable = &localToLowerTable;
|
addrOfToLowerTable = &localToLowerTable;
|
||||||
addrOfToUpperTable = &localToUpperTable;
|
addrOfToUpperTable = &localToUpperTable;
|
||||||
|
addrOfMbCurMax = &localMbCurMax;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LocaleCtypeDataBridge::setMbCurMax(unsigned short mbCurMax)
|
|
||||||
{
|
|
||||||
__ctype_mb_cur_max = mbCurMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
LocaleCtypeDataBridge::ApplyToCurrentThread()
|
LocaleCtypeDataBridge::ApplyToCurrentThread()
|
||||||
{
|
{
|
||||||
*__ctype_b_loc() = *addrOfClassInfoTable;
|
if (isGlobal)
|
||||||
*__ctype_tolower_loc() = *addrOfToLowerTable;
|
abort();
|
||||||
*__ctype_toupper_loc() = *addrOfToUpperTable;
|
|
||||||
|
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)
|
LocaleNumericDataBridge::LocaleNumericDataBridge(bool isGlobal)
|
||||||
:
|
:
|
||||||
posixLocaleConv(&gPosixLocaleConv),
|
posixLocaleConv(&gPosixLocaleConv)
|
||||||
isGlobal(isGlobal)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,8 +94,7 @@ LocaleTimeDataBridge::LocaleTimeDataBridge()
|
|||||||
TimeConversionDataBridge::TimeConversionDataBridge(bool isGlobal)
|
TimeConversionDataBridge::TimeConversionDataBridge(bool isGlobal)
|
||||||
:
|
:
|
||||||
localDaylight(daylight),
|
localDaylight(daylight),
|
||||||
localTimezone(timezone),
|
localTimezone(timezone)
|
||||||
isGlobal(isGlobal)
|
|
||||||
{
|
{
|
||||||
if (isGlobal) {
|
if (isGlobal) {
|
||||||
addrOfDaylight = &daylight;
|
addrOfDaylight = &daylight;
|
||||||
@@ -121,8 +117,7 @@ LocaleDataBridge::LocaleDataBridge(bool isGlobal)
|
|||||||
ctypeDataBridge(isGlobal),
|
ctypeDataBridge(isGlobal),
|
||||||
numericDataBridge(isGlobal),
|
numericDataBridge(isGlobal),
|
||||||
timeConversionDataBridge(isGlobal),
|
timeConversionDataBridge(isGlobal),
|
||||||
posixLanginfo(gPosixLanginfo),
|
posixLanginfo(gPosixLanginfo)
|
||||||
isGlobal(isGlobal)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +126,7 @@ void
|
|||||||
LocaleDataBridge::ApplyToCurrentThread()
|
LocaleDataBridge::ApplyToCurrentThread()
|
||||||
{
|
{
|
||||||
ctypeDataBridge.ApplyToCurrentThread();
|
ctypeDataBridge.ApplyToCurrentThread();
|
||||||
// While timeConverstionDataBridge stores read-write variables,
|
// While timeConversionDataBridge stores read-write variables,
|
||||||
// these variables are global (by POSIX definition). Furthermore,
|
// these variables are global (by POSIX definition). Furthermore,
|
||||||
// none of the backends seem to access these variables
|
// none of the backends seem to access these variables
|
||||||
// directly. The values are set in the bridge mostly for
|
// directly. The values are set in the bridge mostly for
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2004-2007, Axel Dörfler, [email protected]
|
* Copyright 2004-2007, Axel Dörfler, [email protected]
|
||||||
* Copyright 2010, Oliver Tappe, [email protected]
|
* Copyright 2010, Oliver Tappe, [email protected]
|
||||||
|
* Copyright 2022, Trung Nguyen, [email protected]
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "LocaleInternal.h"
|
#include "LocaleInternal.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
|
||||||
|
#include <tls.h>
|
||||||
|
#include <OS.h>
|
||||||
#include <Debug.h>
|
#include <Debug.h>
|
||||||
|
|
||||||
|
#include "LocaleData.h"
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
namespace Libroot {
|
namespace Libroot {
|
||||||
@@ -21,9 +27,8 @@ namespace Libroot {
|
|||||||
status_t
|
status_t
|
||||||
GetLocalesFromEnvironment(int category, const char** locales)
|
GetLocalesFromEnvironment(int category, const char** locales)
|
||||||
{
|
{
|
||||||
if (category > LC_LAST) {
|
if (category > LC_LAST)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
|
||||||
|
|
||||||
const char* locale = getenv("LC_ALL");
|
const char* locale = getenv("LC_ALL");
|
||||||
if (locale != NULL && *locale != '\0')
|
if (locale != NULL && *locale != '\0')
|
||||||
@@ -72,5 +77,33 @@ GetLocalesFromEnvironment(int category, const char** locales)
|
|||||||
return B_OK;
|
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 Libroot
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
@@ -17,5 +17,19 @@ namespace Libroot {
|
|||||||
|
|
||||||
status_t GetLocalesFromEnvironment(int category, const char** locales);
|
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 Libroot
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022, Trung Nguyen, [email protected]
|
|
||||||
* 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
|
int
|
||||||
isalnum(int c)
|
isalnum(int c)
|
||||||
{
|
{
|
||||||
|
|||||||
+13
-3
@@ -6,28 +6,38 @@
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <LocaleData.h>
|
||||||
|
|
||||||
|
|
||||||
// These functions are intended for scenarios where we cannot
|
// These functions are intended for scenarios where we cannot
|
||||||
// link to the whole libroot and access pthread functions;
|
// link to the whole libroot and access pthread functions;
|
||||||
// for example, when we're in the bootloader, kernel or the
|
// for example, when we're in the bootloader, kernel or the
|
||||||
// runtime_loader.
|
// runtime_loader.
|
||||||
|
|
||||||
extern "C" const unsigned short**
|
|
||||||
|
extern "C" const unsigned short *const *const
|
||||||
__ctype_b_loc()
|
__ctype_b_loc()
|
||||||
{
|
{
|
||||||
return &__ctype_b;
|
return &__ctype_b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" const int**
|
extern "C" const int *const *const
|
||||||
__ctype_tolower_loc()
|
__ctype_tolower_loc()
|
||||||
{
|
{
|
||||||
return &__ctype_tolower;
|
return &__ctype_tolower;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" const int**
|
extern "C" const int *const *const
|
||||||
__ctype_toupper_loc()
|
__ctype_toupper_loc()
|
||||||
{
|
{
|
||||||
return &__ctype_toupper;
|
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, [email protected]
|
||||||
|
* 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!$(architecture)>fcntl.o
|
||||||
|
|
||||||
<src!system!libroot!posix!locale!$(architecture)>ctype.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!locale!$(architecture)>LocaleData.o
|
||||||
|
|
||||||
<src!system!libroot!posix!musl!string!$(architecture)>memchr.o
|
<src!system!libroot!posix!musl!string!$(architecture)>memchr.o
|
||||||
|
|||||||
Reference in New Issue
Block a user