libroot: Make glibc use the native Haiku locale structs.
It accesses values through macros, so just write functions that fetch the appropriate value from Haiku's structures. Note that the values for multibyte digit characters are hardcoded. As far as I can tell, we never set or updated these in glibc's locale structures, so it always just used the default, so this should not be a behavioral change from before.
This commit is contained in:
@@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
|
|
||||||
struct lc_time_t;
|
struct lc_time_t;
|
||||||
struct locale_data; // glibc
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
@@ -60,37 +59,12 @@ struct LocaleMonetaryDataBridge {
|
|||||||
|
|
||||||
|
|
||||||
struct LocaleNumericDataBridge {
|
struct LocaleNumericDataBridge {
|
||||||
private:
|
|
||||||
// struct used by glibc to store numeric locale data
|
|
||||||
struct GlibcNumericLocale {
|
|
||||||
const char* name;
|
|
||||||
const char* filedata;
|
|
||||||
off_t filesize;
|
|
||||||
int mmaped;
|
|
||||||
unsigned int usage_count;
|
|
||||||
int use_translit;
|
|
||||||
const char *options;
|
|
||||||
unsigned int nstrings;
|
|
||||||
union locale_data_value
|
|
||||||
{
|
|
||||||
const uint32_t* wstr;
|
|
||||||
const char* string;
|
|
||||||
unsigned int word;
|
|
||||||
}
|
|
||||||
values[6];
|
|
||||||
};
|
|
||||||
locale_data* originalGlibcLocale;
|
|
||||||
GlibcNumericLocale glibcNumericLocaleData;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const struct lconv* const posixLocaleConv;
|
const struct lconv* const posixLocaleConv;
|
||||||
GlibcNumericLocale* glibcNumericLocale;
|
|
||||||
bool isGlobal;
|
bool isGlobal;
|
||||||
|
|
||||||
LocaleNumericDataBridge(bool isGlobal);
|
LocaleNumericDataBridge(bool isGlobal);
|
||||||
~LocaleNumericDataBridge();
|
~LocaleNumericDataBridge();
|
||||||
|
|
||||||
void ApplyToCurrentThread();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef _THREAD_LOCALE_H
|
#ifndef _THREAD_LOCALE_H
|
||||||
#define _THREAD_LOCALE_H
|
#define _THREAD_LOCALE_H
|
||||||
|
|
||||||
@@ -15,38 +14,13 @@ namespace BPrivate {
|
|||||||
namespace Libroot {
|
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.
|
// The pointer in the TLS will point to this struct.
|
||||||
struct ThreadLocale {
|
struct ThreadLocale {
|
||||||
GlibcLocaleStruct glibcLocaleStruct;
|
LocaleBackendData* threadLocaleInfo;
|
||||||
LocaleBackendData* threadLocaleInfo;
|
|
||||||
|
const unsigned short int* ctype_b;
|
||||||
|
const int* ctype_tolower;
|
||||||
|
const int* ctype_toupper;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,11 +37,9 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
|||||||
posix_stdio.o
|
posix_stdio.o
|
||||||
posix_musl.o
|
posix_musl.o
|
||||||
posix_gnu_arch_$(TARGET_ARCH).o
|
posix_gnu_arch_$(TARGET_ARCH).o
|
||||||
posix_gnu_ctype.o
|
|
||||||
posix_gnu_ext.o
|
posix_gnu_ext.o
|
||||||
posix_gnu_iconv.o
|
posix_gnu_iconv.o
|
||||||
posix_gnu_libio.o
|
posix_gnu_libio.o
|
||||||
posix_gnu_locale.o
|
|
||||||
posix_gnu_regex.o
|
posix_gnu_regex.o
|
||||||
posix_gnu_stdio.o
|
posix_gnu_stdio.o
|
||||||
posix_gnu_stdlib.o
|
posix_gnu_stdlib.o
|
||||||
|
|||||||
@@ -34,9 +34,6 @@ ICUNumericData::ICUNumericData(pthread_key_t tlsKey, struct lconv& localeConv)
|
|||||||
void
|
void
|
||||||
ICUNumericData::Initialize(LocaleNumericDataBridge* dataBridge)
|
ICUNumericData::Initialize(LocaleNumericDataBridge* dataBridge)
|
||||||
{
|
{
|
||||||
dataBridge->glibcNumericLocale->values[0].string = fDecimalPoint;
|
|
||||||
dataBridge->glibcNumericLocale->values[1].string = fThousandsSep;
|
|
||||||
dataBridge->glibcNumericLocale->values[2].string = fGrouping;
|
|
||||||
fDataBridge = dataBridge;
|
fDataBridge = dataBridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,14 +59,10 @@ ICUNumericData::SetTo(const Locale& locale, const char* posixLocaleName)
|
|||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
result = _SetLocaleconvEntry(formatSymbols, fDecimalPoint,
|
result = _SetLocaleconvEntry(formatSymbols, fDecimalPoint,
|
||||||
DecimalFormatSymbols::kDecimalSeparatorSymbol);
|
DecimalFormatSymbols::kDecimalSeparatorSymbol);
|
||||||
fDataBridge->glibcNumericLocale->values[3].word
|
|
||||||
= (unsigned int)fDecimalPoint[0];
|
|
||||||
}
|
}
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
result = _SetLocaleconvEntry(formatSymbols, fThousandsSep,
|
result = _SetLocaleconvEntry(formatSymbols, fThousandsSep,
|
||||||
DecimalFormatSymbols::kGroupingSeparatorSymbol);
|
DecimalFormatSymbols::kGroupingSeparatorSymbol);
|
||||||
fDataBridge->glibcNumericLocale->values[4].word
|
|
||||||
= (unsigned int)fThousandsSep[0];
|
|
||||||
}
|
}
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
int32 groupingSize = numberFormat->getGroupingSize();
|
int32 groupingSize = numberFormat->getGroupingSize();
|
||||||
@@ -104,10 +97,6 @@ ICUNumericData::SetToPosix()
|
|||||||
strcpy(fDecimalPoint, fDataBridge->posixLocaleConv->decimal_point);
|
strcpy(fDecimalPoint, fDataBridge->posixLocaleConv->decimal_point);
|
||||||
strcpy(fThousandsSep, fDataBridge->posixLocaleConv->thousands_sep);
|
strcpy(fThousandsSep, fDataBridge->posixLocaleConv->thousands_sep);
|
||||||
strcpy(fGrouping, fDataBridge->posixLocaleConv->grouping);
|
strcpy(fGrouping, fDataBridge->posixLocaleConv->grouping);
|
||||||
fDataBridge->glibcNumericLocale->values[3].word
|
|
||||||
= (unsigned int)fDecimalPoint[0];
|
|
||||||
fDataBridge->glibcNumericLocale->values[4].word
|
|
||||||
= (unsigned int)fThousandsSep[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -5,11 +5,9 @@ for arch in $(TARGET_ARCHS) {
|
|||||||
HaikuSubInclude arch $(arch) ;
|
HaikuSubInclude arch $(arch) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src system libroot posix glibc ctype ;
|
|
||||||
SubInclude HAIKU_TOP src system libroot posix glibc extensions ;
|
SubInclude HAIKU_TOP src system libroot posix glibc extensions ;
|
||||||
SubInclude HAIKU_TOP src system libroot posix glibc iconv ;
|
SubInclude HAIKU_TOP src system libroot posix glibc iconv ;
|
||||||
SubInclude HAIKU_TOP src system libroot posix glibc libio ;
|
SubInclude HAIKU_TOP src system libroot posix glibc libio ;
|
||||||
SubInclude HAIKU_TOP src system libroot posix glibc locale ;
|
|
||||||
SubInclude HAIKU_TOP src system libroot posix glibc regex ;
|
SubInclude HAIKU_TOP src system libroot posix glibc regex ;
|
||||||
SubInclude HAIKU_TOP src system libroot posix glibc stdio-common ;
|
SubInclude HAIKU_TOP src system libroot posix glibc stdio-common ;
|
||||||
SubInclude HAIKU_TOP src system libroot posix glibc stdlib ;
|
SubInclude HAIKU_TOP src system libroot posix glibc stdlib ;
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
#include <locale/langinfo.h>
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#ifndef _LOCALE_H
|
|
||||||
#include <locale/locale.h>
|
|
||||||
|
|
||||||
/* Locale object for C locale. */
|
|
||||||
extern struct __locale_struct _nl_C_locobj;
|
|
||||||
|
|
||||||
/* Now define the internal interfaces. */
|
|
||||||
extern struct lconv *__localeconv (void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1 +1 @@
|
|||||||
#include <locale/xlocale.h>
|
/* Nothing here. */
|
||||||
|
|||||||
@@ -1,157 +0,0 @@
|
|||||||
/* Copyright (C) 1991,92,1995-1999,2000,2001 Free Software Foundation, Inc.
|
|
||||||
This file is part of the GNU C Library.
|
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with the GNU C Library; if not, write to the Free
|
|
||||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
02111-1307 USA. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ISO C99 Standard: 7.11 Localization <locale.h>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _LOCALE_H
|
|
||||||
#define _LOCALE_H 1
|
|
||||||
|
|
||||||
#include <features.h>
|
|
||||||
|
|
||||||
#define __need_NULL
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <bits/locale.h>
|
|
||||||
|
|
||||||
__BEGIN_DECLS
|
|
||||||
|
|
||||||
/* These are the possibilities for the first argument to setlocale.
|
|
||||||
The code assumes that the lowest LC_* symbol has the value zero. */
|
|
||||||
#define LC_CTYPE __LC_CTYPE
|
|
||||||
#define LC_NUMERIC __LC_NUMERIC
|
|
||||||
#define LC_TIME __LC_TIME
|
|
||||||
#define LC_COLLATE __LC_COLLATE
|
|
||||||
#define LC_MONETARY __LC_MONETARY
|
|
||||||
#define LC_MESSAGES __LC_MESSAGES
|
|
||||||
#define LC_ALL __LC_ALL
|
|
||||||
|
|
||||||
|
|
||||||
/* Structure giving information about numeric and monetary notation. */
|
|
||||||
struct lconv
|
|
||||||
{
|
|
||||||
/* Numeric (non-monetary) information. */
|
|
||||||
|
|
||||||
char *decimal_point; /* Decimal point character. */
|
|
||||||
char *thousands_sep; /* Thousands separator. */
|
|
||||||
/* Each element is the number of digits in each group;
|
|
||||||
elements with higher indices are farther left.
|
|
||||||
An element with value CHAR_MAX means that no further grouping is done.
|
|
||||||
An element with value 0 means that the previous element is used
|
|
||||||
for all groups farther left. */
|
|
||||||
char *grouping;
|
|
||||||
|
|
||||||
/* Monetary information. */
|
|
||||||
|
|
||||||
/* First three chars are a currency symbol from ISO 4217.
|
|
||||||
Fourth char is the separator. Fifth char is '\0'. */
|
|
||||||
char *int_curr_symbol;
|
|
||||||
char *currency_symbol; /* Local currency symbol. */
|
|
||||||
char *mon_decimal_point; /* Decimal point character. */
|
|
||||||
char *mon_thousands_sep; /* Thousands separator. */
|
|
||||||
char *mon_grouping; /* Like `grouping' element (above). */
|
|
||||||
char *positive_sign; /* Sign for positive values. */
|
|
||||||
char *negative_sign; /* Sign for negative values. */
|
|
||||||
char int_frac_digits; /* Int'l fractional digits. */
|
|
||||||
char frac_digits; /* Local fractional digits. */
|
|
||||||
/* 1 if currency_symbol precedes a positive value, 0 if succeeds. */
|
|
||||||
char p_cs_precedes;
|
|
||||||
/* 1 iff a space separates currency_symbol from a positive value. */
|
|
||||||
char p_sep_by_space;
|
|
||||||
/* 1 if currency_symbol precedes a negative value, 0 if succeeds. */
|
|
||||||
char n_cs_precedes;
|
|
||||||
/* 1 iff a space separates currency_symbol from a negative value. */
|
|
||||||
char n_sep_by_space;
|
|
||||||
/* Positive and negative sign positions:
|
|
||||||
0 Parentheses surround the quantity and currency_symbol.
|
|
||||||
1 The sign string precedes the quantity and currency_symbol.
|
|
||||||
2 The sign string follows the quantity and currency_symbol.
|
|
||||||
3 The sign string immediately precedes the currency_symbol.
|
|
||||||
4 The sign string immediately follows the currency_symbol. */
|
|
||||||
char p_sign_posn;
|
|
||||||
char n_sign_posn;
|
|
||||||
#ifdef __USE_ISOC99
|
|
||||||
/* 1 if int_curr_symbol precedes a positive value, 0 if succeeds. */
|
|
||||||
char int_p_cs_precedes;
|
|
||||||
/* 1 iff a space separates int_curr_symbol from a positive value. */
|
|
||||||
char int_p_sep_by_space;
|
|
||||||
/* 1 if int_curr_symbol precedes a negative value, 0 if succeeds. */
|
|
||||||
char int_n_cs_precedes;
|
|
||||||
/* 1 iff a space separates int_curr_symbol from a negative value. */
|
|
||||||
char int_n_sep_by_space;
|
|
||||||
/* Positive and negative sign positions:
|
|
||||||
0 Parentheses surround the quantity and int_curr_symbol.
|
|
||||||
1 The sign string precedes the quantity and int_curr_symbol.
|
|
||||||
2 The sign string follows the quantity and int_curr_symbol.
|
|
||||||
3 The sign string immediately precedes the int_curr_symbol.
|
|
||||||
4 The sign string immediately follows the int_curr_symbol. */
|
|
||||||
char int_p_sign_posn;
|
|
||||||
char int_n_sign_posn;
|
|
||||||
#else
|
|
||||||
char __int_p_cs_precedes;
|
|
||||||
char __int_p_sep_by_space;
|
|
||||||
char __int_n_cs_precedes;
|
|
||||||
char __int_n_sep_by_space;
|
|
||||||
char __int_p_sign_posn;
|
|
||||||
char __int_n_sign_posn;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Set and/or return the current locale. */
|
|
||||||
extern char *setlocale (int __category, __const char *__locale) __THROW;
|
|
||||||
|
|
||||||
/* Return the numeric/monetary information for the current locale. */
|
|
||||||
extern struct lconv *localeconv (void) __THROW;
|
|
||||||
|
|
||||||
#ifdef __USE_GNU
|
|
||||||
/* The concept of one static locale per category is not very well
|
|
||||||
thought out. Many applications will need to process its data using
|
|
||||||
information from several different locales. Another application is
|
|
||||||
the implementation of the internationalization handling in the
|
|
||||||
upcoming ISO C++ standard library. To support this another set of
|
|
||||||
the functions using locale data exist which have an additional
|
|
||||||
argument.
|
|
||||||
|
|
||||||
Attention: all these functions are *not* standardized in any form.
|
|
||||||
This is a proof-of-concept implementation. */
|
|
||||||
|
|
||||||
/* Get locale datatype definition. */
|
|
||||||
# include <xlocale.h>
|
|
||||||
|
|
||||||
/* Return a reference to a data structure representing a set of locale
|
|
||||||
datasets. Unlike for the CATEGORY parameter for `setlocale' the
|
|
||||||
CATEGORY_MASK parameter here uses a single bit for each category.
|
|
||||||
I.e., 1 << LC_CTYPE means to load data for this category. If
|
|
||||||
BASE is non-null the appropriate category information in the BASE
|
|
||||||
record is replaced. */
|
|
||||||
extern __locale_t __newlocale (int __category_mask, __const char *__locale,
|
|
||||||
__locale_t __base) __THROW;
|
|
||||||
|
|
||||||
/* Return a duplicate of the set of locale in DATASET. All usage
|
|
||||||
counters are increased if necessary. */
|
|
||||||
extern __locale_t __duplocale (__locale_t __dataset) __THROW;
|
|
||||||
|
|
||||||
/* Free the data associated with a locale dataset previously returned
|
|
||||||
by a call to `setlocale_r'. */
|
|
||||||
extern void __freelocale (__locale_t __dataset) __THROW;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__END_DECLS
|
|
||||||
|
|
||||||
#endif /* locale.h */
|
|
||||||
@@ -1,109 +1,149 @@
|
|||||||
/* Declarations for internal libc locale interfaces
|
/*
|
||||||
Copyright (C) 1995, 96, 97, 98, 99,2000,2001 Free Software Foundation, Inc.
|
* Copyright 2025, Haiku, Inc. All Rights Reserved.
|
||||||
This file is part of the GNU C Library.
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with the GNU C Library; if not, write to the Free
|
|
||||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
02111-1307 USA. */
|
|
||||||
|
|
||||||
#ifndef _LOCALEINFO_H
|
#ifndef _LOCALEINFO_H
|
||||||
#define _LOCALEINFO_H 1
|
#define _LOCALEINFO_H
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <langinfo.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
// __locale_struct
|
#include <stdlib.h>
|
||||||
#include <xlocale.h>
|
|
||||||
// LC_* values
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
/* This has to be changed whenever a new locale is defined. */
|
|
||||||
#define __LC_LAST 7
|
|
||||||
|
|
||||||
/* We use a special value for the usage counter in `locale_data' to
|
enum {
|
||||||
signal that this data must never be removed anymore. */
|
LC_CTYPE__NL_CTYPE_OUTDIGITS_MB_LEN = 0,
|
||||||
#define MAX_USAGE_COUNT (UINT_MAX - 1)
|
LC_CTYPE__NL_CTYPE_OUTDIGIT0_MB,
|
||||||
#define UNDELETABLE UINT_MAX
|
LC_CTYPE__NL_CTYPE_OUTDIGIT1_MB,
|
||||||
|
LC_CTYPE__NL_CTYPE_OUTDIGIT2_MB,
|
||||||
|
LC_CTYPE__NL_CTYPE_OUTDIGIT3_MB,
|
||||||
|
LC_CTYPE__NL_CTYPE_OUTDIGIT4_MB,
|
||||||
|
LC_CTYPE__NL_CTYPE_OUTDIGIT5_MB,
|
||||||
|
LC_CTYPE__NL_CTYPE_OUTDIGIT6_MB,
|
||||||
|
LC_CTYPE__NL_CTYPE_OUTDIGIT7_MB,
|
||||||
|
LC_CTYPE__NL_CTYPE_OUTDIGIT8_MB,
|
||||||
|
LC_CTYPE__NL_CTYPE_OUTDIGIT9_MB,
|
||||||
|
LC_CTYPE__NL_CTYPE_MB_CUR_MAX,
|
||||||
|
|
||||||
/* Structure describing locale data in core for a category. */
|
#define LC_CTYPE__NL_CTYPE_INDIGITS_MB_LEN LC_CTYPE__NL_CTYPE_OUTDIGITS_MB_LEN
|
||||||
struct locale_data
|
#define LC_CTYPE__NL_CTYPE_INDIGITS0_MB LC_CTYPE__NL_CTYPE_OUTDIGIT0_MB
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
const char *filedata; /* Region mapping the file data. */
|
|
||||||
off_t filesize; /* Size of the file (and the region). */
|
|
||||||
int mmaped; /* If nonzero the data is mmaped. */
|
|
||||||
|
|
||||||
unsigned int usage_count; /* Counter for users. */
|
#define LC_CTYPE__NL_CTYPE_OUTDIGITS_WC_LEN LC_CTYPE__NL_CTYPE_OUTDIGITS_MB_LEN
|
||||||
|
#define LC_CTYPE__NL_CTYPE_OUTDIGIT0_WC LC_CTYPE__NL_CTYPE_OUTDIGIT0_MB
|
||||||
|
#define LC_CTYPE__NL_CTYPE_INDIGITS_WC_LEN LC_CTYPE__NL_CTYPE_INDIGITS_MB_LEN
|
||||||
|
#define LC_CTYPE__NL_CTYPE_INDIGITS0_WC LC_CTYPE__NL_CTYPE_INDIGITS0_MB
|
||||||
|
|
||||||
int use_translit; /* Nonzero if the mb*towv*() and wc*tomb()
|
LC_MONETARY_MON_DECIMAL_POINT,
|
||||||
functions should use transliteration. */
|
LC_MONETARY_MON_THOUSANDS_SEP,
|
||||||
const char *options; /* Extra options from the locale name,
|
LC_MONETARY_MON_GROUPING,
|
||||||
not used in the path to the locale data. */
|
|
||||||
|
|
||||||
unsigned int nstrings; /* Number of strings below. */
|
#define LC_MONETARY__NL_MONETARY_DECIMAL_POINT_WC LC_MONETARY_MON_DECIMAL_POINT
|
||||||
union locale_data_value
|
#define LC_MONETARY__NL_MONETARY_THOUSANDS_SEP_WC LC_MONETARY_MON_THOUSANDS_SEP
|
||||||
{
|
|
||||||
const uint32_t *wstr;
|
LC_NUMERIC_DECIMAL_POINT,
|
||||||
const char *string;
|
LC_NUMERIC_THOUSANDS_SEP,
|
||||||
unsigned int word;
|
LC_NUMERIC_GROUPING,
|
||||||
}
|
|
||||||
values __flexarr; /* Items, usually pointers into `filedata'. */
|
#define LC_NUMERIC__NL_NUMERIC_DECIMAL_POINT_WC LC_NUMERIC_DECIMAL_POINT
|
||||||
|
#define LC_NUMERIC__NL_NUMERIC_THOUSANDS_SEP_WC LC_NUMERIC_THOUSANDS_SEP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline const char*
|
||||||
|
_nl_current(int value)
|
||||||
|
{
|
||||||
|
struct lconv* lconv = localeconv();
|
||||||
|
switch (value) {
|
||||||
|
// TODO: Not correct for non-ASCII/UTF-8 multibyte locales!
|
||||||
|
// (perhaps via alloca+wcrtomb? or do we need new localeinfo?)
|
||||||
|
#define DIGIT(D) case LC_CTYPE__NL_CTYPE_OUTDIGIT##D##_MB: return #D
|
||||||
|
DIGIT(0);
|
||||||
|
DIGIT(1);
|
||||||
|
DIGIT(2);
|
||||||
|
DIGIT(3);
|
||||||
|
DIGIT(4);
|
||||||
|
DIGIT(5);
|
||||||
|
DIGIT(6);
|
||||||
|
DIGIT(7);
|
||||||
|
DIGIT(8);
|
||||||
|
DIGIT(9);
|
||||||
|
#undef DIGIT
|
||||||
|
|
||||||
/* Name of the standard locales. */
|
case LC_MONETARY_MON_DECIMAL_POINT:
|
||||||
extern const char _nl_C_name[];
|
return lconv->mon_decimal_point;
|
||||||
extern const char _nl_POSIX_name[];
|
case LC_MONETARY_MON_THOUSANDS_SEP:
|
||||||
|
return lconv->mon_thousands_sep;
|
||||||
|
case LC_MONETARY_MON_GROUPING:
|
||||||
|
return lconv->mon_grouping;
|
||||||
|
|
||||||
/* The standard codeset. */
|
case LC_NUMERIC_DECIMAL_POINT:
|
||||||
extern const char _nl_C_codeset[];
|
return lconv->decimal_point;
|
||||||
|
case LC_NUMERIC_THOUSANDS_SEP:
|
||||||
|
return lconv->thousands_sep;
|
||||||
|
case LC_NUMERIC_GROUPING:
|
||||||
|
return lconv->grouping;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is the internal locale_t object that holds the global locale
|
static inline const wchar_t
|
||||||
controlled by calls to setlocale. A thread's TSD locale pointer
|
_nl_current_word(int value)
|
||||||
points to this when `uselocale (LC_GLOBAL_LOCALE)' is in effect. */
|
{
|
||||||
extern struct __locale_struct _nl_global_locale;
|
struct lconv* lconv = NULL;
|
||||||
|
mbstate_t temp;
|
||||||
|
const char* str = NULL;
|
||||||
|
wchar_t out = 0;
|
||||||
|
|
||||||
extern struct __locale_struct* _nl_current_locale();
|
switch (value) {
|
||||||
#define _NL_CURRENT_LOCALE (_nl_current_locale())
|
case LC_CTYPE__NL_CTYPE_OUTDIGITS_WC_LEN:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* We always use UTF-32 in wchar_t. */
|
||||||
|
#define DIGIT(D) case LC_CTYPE__NL_CTYPE_OUTDIGIT##D##_MB: return 0x0030 + D
|
||||||
|
DIGIT(0);
|
||||||
|
DIGIT(1);
|
||||||
|
DIGIT(2);
|
||||||
|
DIGIT(3);
|
||||||
|
DIGIT(4);
|
||||||
|
DIGIT(5);
|
||||||
|
DIGIT(6);
|
||||||
|
DIGIT(7);
|
||||||
|
DIGIT(8);
|
||||||
|
DIGIT(9);
|
||||||
|
#undef DIGIT
|
||||||
|
|
||||||
|
case LC_CTYPE__NL_CTYPE_MB_CUR_MAX:
|
||||||
|
return __ctype_get_mb_cur_max();
|
||||||
|
|
||||||
|
case LC_MONETARY_MON_DECIMAL_POINT:
|
||||||
|
lconv = localeconv();
|
||||||
|
str = lconv->mon_decimal_point;
|
||||||
|
break;
|
||||||
|
case LC_MONETARY_MON_THOUSANDS_SEP:
|
||||||
|
lconv = localeconv();
|
||||||
|
str = lconv->mon_thousands_sep;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LC_NUMERIC_DECIMAL_POINT:
|
||||||
|
lconv = localeconv();
|
||||||
|
str = lconv->decimal_point;
|
||||||
|
break;
|
||||||
|
case LC_NUMERIC_THOUSANDS_SEP:
|
||||||
|
lconv = localeconv();
|
||||||
|
str = lconv->thousands_sep;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (str == NULL)
|
||||||
|
return out;
|
||||||
|
|
||||||
|
mbrtowc(&out, str, 1, &temp);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return a pointer to the current `struct __locale_data' for CATEGORY. */
|
|
||||||
#define _NL_CURRENT_DATA(category) \
|
|
||||||
(_NL_CURRENT_LOCALE->__locales[category])
|
|
||||||
|
|
||||||
/* Extract the current CATEGORY locale's string for ITEM. */
|
|
||||||
#define _NL_CURRENT(category, item) \
|
#define _NL_CURRENT(category, item) \
|
||||||
(_NL_CURRENT_DATA (category)->values[_NL_ITEM_INDEX (item)].string)
|
_nl_current(category##_##item)
|
||||||
|
|
||||||
/* Extract the current CATEGORY locale's string for ITEM. */
|
|
||||||
#define _NL_CURRENT_WSTR(category, item) \
|
|
||||||
((wchar_t *) _NL_CURRENT_DATA (category)->values[_NL_ITEM_INDEX (item)].wstr)
|
|
||||||
|
|
||||||
/* Extract the current CATEGORY locale's word for ITEM. */
|
|
||||||
#define _NL_CURRENT_WORD(category, item) \
|
#define _NL_CURRENT_WORD(category, item) \
|
||||||
((uint32_t) _NL_CURRENT_DATA (category)->values[_NL_ITEM_INDEX (item)].word)
|
_nl_current_word(category##_##item)
|
||||||
|
|
||||||
/* This is used in lc-CATEGORY.c to define _nl_current_CATEGORY. */
|
|
||||||
#define _NL_CURRENT_DEFINE(category) \
|
|
||||||
/* No per-category variable here. */
|
|
||||||
|
|
||||||
/* Postload processing. */
|
|
||||||
extern void _nl_postload_ctype (void);
|
|
||||||
extern void _nl_postload_time (void);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* localeinfo.h */
|
#endif /* _LOCALEINFO_H */
|
||||||
|
|||||||
@@ -27,14 +27,6 @@ namespace BPrivate {
|
|||||||
namespace Libroot {
|
namespace Libroot {
|
||||||
|
|
||||||
|
|
||||||
extern "C" GlibcLocaleStruct* _nl_current_locale();
|
|
||||||
extern "C" GlibcLocaleStruct _nl_global_locale;
|
|
||||||
#define _NL_CURRENT_DATA(category) \
|
|
||||||
((locale_data*&)(_nl_current_locale()->__locales[category]))
|
|
||||||
#define _NL_GLOBAL_DATA(category) \
|
|
||||||
((locale_data*&)(_nl_global_locale.__locales[category]))
|
|
||||||
|
|
||||||
|
|
||||||
LocaleCtypeDataBridge::LocaleCtypeDataBridge(bool isGlobal)
|
LocaleCtypeDataBridge::LocaleCtypeDataBridge(bool isGlobal)
|
||||||
:
|
:
|
||||||
localClassInfoTable(__ctype_b),
|
localClassInfoTable(__ctype_b),
|
||||||
@@ -89,34 +81,13 @@ LocaleMonetaryDataBridge::LocaleMonetaryDataBridge()
|
|||||||
LocaleNumericDataBridge::LocaleNumericDataBridge(bool isGlobal)
|
LocaleNumericDataBridge::LocaleNumericDataBridge(bool isGlobal)
|
||||||
:
|
:
|
||||||
posixLocaleConv(&gPosixLocaleConv),
|
posixLocaleConv(&gPosixLocaleConv),
|
||||||
glibcNumericLocale(&glibcNumericLocaleData),
|
|
||||||
isGlobal(isGlobal)
|
isGlobal(isGlobal)
|
||||||
{
|
{
|
||||||
|
|
||||||
memcpy(glibcNumericLocale, _NL_GLOBAL_DATA(GLIBC_LC_NUMERIC),
|
|
||||||
sizeof(GlibcNumericLocale));
|
|
||||||
|
|
||||||
if (isGlobal) {
|
|
||||||
originalGlibcLocale = _NL_GLOBAL_DATA(GLIBC_LC_NUMERIC);
|
|
||||||
_NL_GLOBAL_DATA(GLIBC_LC_NUMERIC) = (locale_data*)glibcNumericLocale;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LocaleNumericDataBridge::~LocaleNumericDataBridge()
|
LocaleNumericDataBridge::~LocaleNumericDataBridge()
|
||||||
{
|
{
|
||||||
if (isGlobal) {
|
|
||||||
_NL_GLOBAL_DATA(GLIBC_LC_NUMERIC) = originalGlibcLocale;
|
|
||||||
} else if (_NL_CURRENT_DATA(GLIBC_LC_NUMERIC) == (locale_data*)glibcNumericLocale) {
|
|
||||||
_NL_CURRENT_DATA(GLIBC_LC_NUMERIC) = _NL_GLOBAL_DATA(GLIBC_LC_NUMERIC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
LocaleNumericDataBridge::ApplyToCurrentThread()
|
|
||||||
{
|
|
||||||
_NL_CURRENT_DATA(GLIBC_LC_NUMERIC) = (locale_data*)glibcNumericLocale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -164,7 +135,6 @@ void
|
|||||||
LocaleDataBridge::ApplyToCurrentThread()
|
LocaleDataBridge::ApplyToCurrentThread()
|
||||||
{
|
{
|
||||||
ctypeDataBridge.ApplyToCurrentThread();
|
ctypeDataBridge.ApplyToCurrentThread();
|
||||||
numericDataBridge.ApplyToCurrentThread();
|
|
||||||
// While timeConverstionDataBridge stores read-write variables,
|
// While timeConverstionDataBridge 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
|
||||||
|
|||||||
@@ -11,15 +11,13 @@
|
|||||||
#include <ThreadLocale.h>
|
#include <ThreadLocale.h>
|
||||||
|
|
||||||
|
|
||||||
// From glibc's localeinfo.h
|
|
||||||
extern BPrivate::Libroot::GlibcLocaleStruct _nl_global_locale;
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
namespace Libroot {
|
namespace Libroot {
|
||||||
|
|
||||||
|
|
||||||
static void DestroyThreadLocale(void* ptr)
|
static void
|
||||||
|
DestroyThreadLocale(void* ptr)
|
||||||
{
|
{
|
||||||
ThreadLocale* threadLocale = (ThreadLocale*)ptr;
|
ThreadLocale* threadLocale = (ThreadLocale*)ptr;
|
||||||
delete threadLocale;
|
delete threadLocale;
|
||||||
@@ -32,8 +30,11 @@ GetCurrentThreadLocale()
|
|||||||
ThreadLocale* threadLocale = (ThreadLocale*)tls_get(TLS_LOCALE_SLOT);
|
ThreadLocale* threadLocale = (ThreadLocale*)tls_get(TLS_LOCALE_SLOT);
|
||||||
if (threadLocale == NULL) {
|
if (threadLocale == NULL) {
|
||||||
threadLocale = new ThreadLocale();
|
threadLocale = new ThreadLocale();
|
||||||
threadLocale->glibcLocaleStruct = _nl_global_locale;
|
|
||||||
threadLocale->threadLocaleInfo = NULL;
|
threadLocale->threadLocaleInfo = NULL;
|
||||||
|
threadLocale->ctype_b = __ctype_b;
|
||||||
|
threadLocale->ctype_tolower = __ctype_tolower;
|
||||||
|
threadLocale->ctype_toupper = __ctype_toupper;
|
||||||
|
|
||||||
on_exit_thread(DestroyThreadLocale, threadLocale);
|
on_exit_thread(DestroyThreadLocale, threadLocale);
|
||||||
tls_set(TLS_LOCALE_SLOT, threadLocale);
|
tls_set(TLS_LOCALE_SLOT, threadLocale);
|
||||||
}
|
}
|
||||||
@@ -41,32 +42,24 @@ GetCurrentThreadLocale()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Exported so that glibc could also use.
|
|
||||||
extern "C" GlibcLocaleStruct*
|
|
||||||
_nl_current_locale()
|
|
||||||
{
|
|
||||||
return &GetCurrentThreadLocale()->glibcLocaleStruct;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" const unsigned short**
|
extern "C" const unsigned short**
|
||||||
__ctype_b_loc()
|
__ctype_b_loc()
|
||||||
{
|
{
|
||||||
return &GetCurrentThreadLocale()->glibcLocaleStruct.__ctype_b;
|
return &GetCurrentThreadLocale()->ctype_b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" const int**
|
extern "C" const int**
|
||||||
__ctype_tolower_loc()
|
__ctype_tolower_loc()
|
||||||
{
|
{
|
||||||
return &GetCurrentThreadLocale()->glibcLocaleStruct.__ctype_tolower;
|
return &GetCurrentThreadLocale()->ctype_tolower;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" const int**
|
extern "C" const int**
|
||||||
__ctype_toupper_loc()
|
__ctype_toupper_loc()
|
||||||
{
|
{
|
||||||
return &GetCurrentThreadLocale()->glibcLocaleStruct.__ctype_toupper;
|
return &GetCurrentThreadLocale()->ctype_toupper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user