libs/posix: Implemented new locale functions
Implemented the missing POSIX functions in <locale.h>: newlocale, duplocale, uselocale, and freelocale, and also provided missing type definitions for <locale.h>. Implemented missing POSIX locale-based function variants. Modified LocaleBackend so that it could support thread-local locales. Some glibc-like locale-related variables supporting ctype and printf family of functions have also been updated to reflect the thread-local variables present in the latest glibc sources. As there have been some modifications to global symbols in libroot, libroot_stubs.c has been regenerated. Bug: #17168 Change-Id: Ibf296c58c47d42d1d1dfb2ce64042442f2679431 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5351 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
86fa1c21e1
commit
d338200e2b
@@ -8,11 +8,11 @@
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
#include <wctype.h>
|
||||
|
||||
|
||||
struct lconv;
|
||||
struct lc_time_t;
|
||||
struct locale_data; // glibc
|
||||
|
||||
@@ -22,29 +22,38 @@ namespace Libroot {
|
||||
|
||||
|
||||
struct LocaleCtypeDataBridge {
|
||||
const unsigned short** addrOfClassInfoTable;
|
||||
const int** addrOfToLowerTable;
|
||||
const int** addrOfToUpperTable;
|
||||
private:
|
||||
const unsigned short* localClassInfoTable;
|
||||
const int* localToLowerTable;
|
||||
const int* localToUpperTable;
|
||||
|
||||
const unsigned short* posixClassInfo;
|
||||
const int* posixToLowerMap;
|
||||
const int* posixToUpperMap;
|
||||
public:
|
||||
const unsigned short** addrOfClassInfoTable;
|
||||
const int** addrOfToLowerTable;
|
||||
const int** addrOfToUpperTable;
|
||||
|
||||
LocaleCtypeDataBridge();
|
||||
const unsigned short* const posixClassInfo;
|
||||
const int* const posixToLowerMap;
|
||||
const int* const posixToUpperMap;
|
||||
|
||||
bool isGlobal;
|
||||
|
||||
LocaleCtypeDataBridge(bool isGlobal);
|
||||
|
||||
void setMbCurMax(unsigned short mbCurMax);
|
||||
void ApplyToCurrentThread();
|
||||
};
|
||||
|
||||
|
||||
struct LocaleMessagesDataBridge {
|
||||
const char** posixLanginfo;
|
||||
const char** const posixLanginfo;
|
||||
|
||||
LocaleMessagesDataBridge();
|
||||
};
|
||||
|
||||
|
||||
struct LocaleMonetaryDataBridge {
|
||||
const struct lconv* posixLocaleConv;
|
||||
const struct lconv* const posixLocaleConv;
|
||||
|
||||
LocaleMonetaryDataBridge();
|
||||
};
|
||||
@@ -71,29 +80,42 @@ private:
|
||||
values[6];
|
||||
};
|
||||
locale_data* originalGlibcLocale;
|
||||
GlibcNumericLocale glibcNumericLocaleData;
|
||||
|
||||
public:
|
||||
const struct lconv* posixLocaleConv;
|
||||
GlibcNumericLocale glibcNumericLocale;
|
||||
const struct lconv* const posixLocaleConv;
|
||||
GlibcNumericLocale* glibcNumericLocale;
|
||||
bool isGlobal;
|
||||
|
||||
LocaleNumericDataBridge();
|
||||
LocaleNumericDataBridge(bool isGlobal);
|
||||
~LocaleNumericDataBridge();
|
||||
|
||||
void ApplyToCurrentThread();
|
||||
};
|
||||
|
||||
|
||||
struct LocaleTimeDataBridge {
|
||||
const struct lc_time_t* posixLCTimeInfo;
|
||||
const struct lc_time_t* const posixLCTimeInfo;
|
||||
|
||||
LocaleTimeDataBridge();
|
||||
};
|
||||
|
||||
|
||||
struct TimeConversionDataBridge {
|
||||
private:
|
||||
int localDaylight;
|
||||
long localTimezone;
|
||||
char* localTZName[2];
|
||||
char localTZName0[64];
|
||||
char localTZName1[64];
|
||||
|
||||
public:
|
||||
int* addrOfDaylight;
|
||||
long* addrOfTimezone;
|
||||
char** addrOfTZName;
|
||||
bool isGlobal;
|
||||
|
||||
TimeConversionDataBridge();
|
||||
TimeConversionDataBridge(bool isGlobal);
|
||||
};
|
||||
|
||||
|
||||
@@ -104,9 +126,12 @@ struct LocaleDataBridge {
|
||||
LocaleNumericDataBridge numericDataBridge;
|
||||
LocaleTimeDataBridge timeDataBridge;
|
||||
TimeConversionDataBridge timeConversionDataBridge;
|
||||
const char** posixLanginfo;
|
||||
const char** const posixLanginfo;
|
||||
bool isGlobal;
|
||||
|
||||
LocaleDataBridge();
|
||||
LocaleDataBridge(bool isGlobal);
|
||||
|
||||
void ApplyToCurrentThread();
|
||||
};
|
||||
|
||||
|
||||
@@ -162,12 +187,25 @@ public:
|
||||
virtual void Initialize(LocaleDataBridge* dataBridge) = 0;
|
||||
|
||||
static status_t LoadBackend();
|
||||
static LocaleBackend* CreateBackend();
|
||||
static void DestroyBackend(LocaleBackend* instance);
|
||||
};
|
||||
|
||||
|
||||
extern LocaleBackend* gLocaleBackend;
|
||||
// The real struct behind locale_t
|
||||
struct LocaleBackendData {
|
||||
int magic;
|
||||
LocaleBackend* backend;
|
||||
LocaleDataBridge* databridge;
|
||||
};
|
||||
|
||||
|
||||
LocaleBackendData* GetCurrentLocaleInfo();
|
||||
void SetCurrentLocaleInfo(LocaleBackendData* newLocale);
|
||||
LocaleBackend* GetCurrentLocaleBackend();
|
||||
extern LocaleBackend* gGlobalLocaleBackend;
|
||||
extern LocaleDataBridge gGlobalLocaleDataBridge;
|
||||
|
||||
} // namespace Libroot
|
||||
} // namespace BPrivate
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 {
|
||||
|
||||
|
||||
// This struct is taken from glibc's __locale_struct
|
||||
// from xlocale.h.
|
||||
// It will also be used by glibc so it should have the same
|
||||
// layout.
|
||||
struct GlibcLocaleStruct {
|
||||
void *__locales[7]; /* 7 = __LC_LAST. */
|
||||
|
||||
const unsigned short int *__ctype_b;
|
||||
const int *__ctype_tolower;
|
||||
const int *__ctype_toupper;
|
||||
};
|
||||
|
||||
|
||||
// Taken from glibc's bits/locale.h
|
||||
// glibc uses different codes from our the native locale.h.
|
||||
// This should be the values used for the indexes
|
||||
// in GlibcLocaleStruct.
|
||||
enum {
|
||||
GLIBC_LC_CTYPE = 0,
|
||||
GLIBC_LC_NUMERIC = 1,
|
||||
GLIBC_LC_TIME = 2,
|
||||
GLIBC_LC_COLLATE = 3,
|
||||
GLIBC_LC_MONETARY = 4,
|
||||
GLIBC_LC_MESSAGES = 5,
|
||||
GLIBC_LC_ALL = 6,
|
||||
};
|
||||
|
||||
|
||||
// The pointer in the TLS will point to this struct.
|
||||
struct ThreadLocale {
|
||||
GlibcLocaleStruct glibcLocaleStruct;
|
||||
LocaleBackendData* threadLocaleInfo;
|
||||
};
|
||||
|
||||
|
||||
ThreadLocale* GetCurrentThreadLocale();
|
||||
|
||||
|
||||
} // namespace Libroot
|
||||
} // namespace BPrivate
|
||||
|
||||
|
||||
#endif // _THREAD_LOCALE_H
|
||||
@@ -29,6 +29,7 @@
|
||||
#define _TIMELOCAL_H_
|
||||
|
||||
|
||||
#include <locale.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
|
||||
@@ -54,6 +55,7 @@ struct lc_time_t {
|
||||
|
||||
__BEGIN_DECLS
|
||||
const struct lc_time_t* __get_current_time_locale(void);
|
||||
const struct lc_time_t* __get_time_locale(locale_t);
|
||||
__END_DECLS
|
||||
|
||||
|
||||
|
||||
@@ -33,11 +33,15 @@ extern wchar_t *__wcpcpy(wchar_t *dest, const wchar_t *src);
|
||||
extern wchar_t *__wcpncpy(wchar_t *dest, const wchar_t *src, size_t srcLength);
|
||||
extern size_t __wcrtomb(char *dest, wchar_t wc, mbstate_t *mbState);
|
||||
extern int __wcscasecmp(const wchar_t *wcs1, const wchar_t *wcs2);
|
||||
extern int __wcscasecmp_l(const wchar_t *wcs1, const wchar_t *wcs2,
|
||||
locale_t locale);
|
||||
extern wchar_t *__wcscat(wchar_t *dest, const wchar_t *src);
|
||||
extern wchar_t *__wcschr(const wchar_t *wcs, wchar_t wc);
|
||||
extern wchar_t *__wcschrnul(const wchar_t *wcs, wchar_t wc);
|
||||
extern int __wcscmp(const wchar_t *wcs1, const wchar_t *wcs2);
|
||||
extern int __wcscoll(const wchar_t *wcs1, const wchar_t *wcs2);
|
||||
extern int __wcscoll_l(const wchar_t *wcs1, const wchar_t *wcs2,
|
||||
locale_t locale);
|
||||
extern wchar_t *__wcscpy(wchar_t *dest, const wchar_t *src);
|
||||
extern size_t __wcscspn(const wchar_t *wcs, const wchar_t *reject);
|
||||
extern wchar_t *__wcsdup(const wchar_t *wcs);
|
||||
@@ -48,6 +52,8 @@ extern size_t __wcslcpy(wchar_t *dest, const wchar_t *src, size_t maxLength);
|
||||
extern size_t __wcslen(const wchar_t *wcs);
|
||||
extern int __wcsncasecmp(const wchar_t *wcs1, const wchar_t *wcs2,
|
||||
size_t maxLength);
|
||||
extern int __wcsncasecmp_l(const wchar_t *wcs1, const wchar_t *wcs2,
|
||||
size_t maxLength, locale_t locale);
|
||||
extern wchar_t *__wcsncat(wchar_t *dest, const wchar_t *src, size_t srcLength);
|
||||
extern int __wcsncmp(const wchar_t *wcs1, const wchar_t *wcs2,
|
||||
size_t length);
|
||||
@@ -76,6 +82,8 @@ extern int __wctomb(char *string, wchar_t wc);
|
||||
extern wchar_t *__wcswcs(const wchar_t *haystack, const wchar_t *needle);
|
||||
extern int __wcswidth(const wchar_t *wcs, size_t length);
|
||||
extern size_t __wcsxfrm(wchar_t *dest, const wchar_t *src, size_t destLength);
|
||||
extern size_t __wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t destLength,
|
||||
locale_t locale);
|
||||
extern int __wctob(wint_t wc);
|
||||
extern int __wcwidth(wchar_t wc);
|
||||
extern wchar_t *__wmemchr(const wchar_t *wcs, wchar_t wc, size_t n);
|
||||
|
||||
Reference in New Issue
Block a user