1/* 2 * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "LocaleBackend.h" 8 9#include <ctype.h> 10#include <langinfo.h> 11#include <string.h> 12#include <time.h> 13 14#include <PosixCtype.h> 15#include <PosixLanginfo.h> 16#include <PosixLCTimeInfo.h> 17#include <PosixLocaleConv.h> 18#include <ThreadLocale.h> 19 20 21extern const unsigned short* __ctype_b; 22extern const int* __ctype_tolower; 23extern const int* __ctype_toupper; 24 25 26namespace BPrivate { 27namespace Libroot { 28 29 30extern "C" GlibcLocaleStruct* _nl_current_locale(); 31extern "C" GlibcLocaleStruct _nl_global_locale; 32#define _NL_CURRENT_DATA(category) \ 33 ((locale_data*&)(_nl_current_locale()->__locales[category])) 34#define _NL_GLOBAL_DATA(category) \ 35 ((locale_data*&)(_nl_global_locale.__locales[category])) 36 37 38LocaleCtypeDataBridge::LocaleCtypeDataBridge(bool isGlobal) 39 : 40 localClassInfoTable(__ctype_b), 41 localToLowerTable(__ctype_tolower), 42 localToUpperTable(__ctype_toupper), 43 posixClassInfo(gPosixClassInfo), 44 posixToLowerMap(gPosixToLowerMap), 45 posixToUpperMap(gPosixToUpperMap), 46 isGlobal(isGlobal) 47{ 48 if (isGlobal) { 49 addrOfClassInfoTable = &__ctype_b; 50 addrOfToLowerTable = &__ctype_tolower; 51 addrOfToUpperTable = &__ctype_toupper; 52 } else { 53 addrOfClassInfoTable = &localClassInfoTable; 54 addrOfToLowerTable = &localToLowerTable; 55 addrOfToUpperTable = &localToUpperTable; 56 } 57} 58 59 60void LocaleCtypeDataBridge::setMbCurMax(unsigned short mbCurMax) 61{ 62 __ctype_mb_cur_max = mbCurMax; 63} 64 65 66void 67LocaleCtypeDataBridge::ApplyToCurrentThread() 68{ 69 *__ctype_b_loc() = *addrOfClassInfoTable; 70 *__ctype_tolower_loc() = *addrOfToLowerTable; 71 *__ctype_toupper_loc() = *addrOfToUpperTable; 72} 73 74 75LocaleMessagesDataBridge::LocaleMessagesDataBridge() 76 : 77 posixLanginfo(gPosixLanginfo) 78{ 79} 80 81 82LocaleMonetaryDataBridge::LocaleMonetaryDataBridge() 83 : 84 posixLocaleConv(&gPosixLocaleConv) 85{ 86} 87 88 89LocaleNumericDataBridge::LocaleNumericDataBridge(bool isGlobal) 90 : 91 posixLocaleConv(&gPosixLocaleConv), 92 glibcNumericLocale(&glibcNumericLocaleData), 93 isGlobal(isGlobal) 94{ 95 96 memcpy(glibcNumericLocale, _NL_GLOBAL_DATA(GLIBC_LC_NUMERIC), 97 sizeof(GlibcNumericLocale)); 98 99 if (isGlobal) { 100 originalGlibcLocale = _NL_GLOBAL_DATA(GLIBC_LC_NUMERIC); 101 _NL_GLOBAL_DATA(GLIBC_LC_NUMERIC) = (locale_data*)glibcNumericLocale; 102 } 103} 104 105 106LocaleNumericDataBridge::~LocaleNumericDataBridge() 107{ 108 if (isGlobal) { 109 _NL_GLOBAL_DATA(GLIBC_LC_NUMERIC) = originalGlibcLocale; 110 } else if (_NL_CURRENT_DATA(GLIBC_LC_NUMERIC) == (locale_data*)glibcNumericLocale) { 111 _NL_CURRENT_DATA(GLIBC_LC_NUMERIC) = _NL_GLOBAL_DATA(GLIBC_LC_NUMERIC); 112 } 113} 114 115 116void 117LocaleNumericDataBridge::ApplyToCurrentThread() 118{ 119 _NL_CURRENT_DATA(GLIBC_LC_NUMERIC) = (locale_data*)glibcNumericLocale; 120} 121 122 123LocaleTimeDataBridge::LocaleTimeDataBridge() 124 : 125 posixLCTimeInfo(&gPosixLCTimeInfo) 126{ 127} 128 129 130TimeConversionDataBridge::TimeConversionDataBridge(bool isGlobal) 131 : 132 localDaylight(daylight), 133 localTimezone(timezone), 134 isGlobal(isGlobal) 135{ 136 if (isGlobal) { 137 addrOfDaylight = &daylight; 138 addrOfTimezone = &timezone; 139 addrOfTZName = tzname; 140 } else { 141 addrOfDaylight = &localDaylight; 142 addrOfTimezone = &localTimezone; 143 addrOfTZName = localTZName; 144 addrOfTZName[0] = localTZName0; 145 addrOfTZName[1] = localTZName1; 146 strlcpy(localTZName0, tzname[0], sizeof(localTZName0)); 147 strlcpy(localTZName1, tzname[1], sizeof(localTZName1)); 148 } 149} 150 151 152LocaleDataBridge::LocaleDataBridge(bool isGlobal) 153 : 154 ctypeDataBridge(isGlobal), 155 numericDataBridge(isGlobal), 156 timeConversionDataBridge(isGlobal), 157 posixLanginfo(gPosixLanginfo), 158 isGlobal(isGlobal) 159{ 160} 161 162 163void 164LocaleDataBridge::ApplyToCurrentThread() 165{ 166 ctypeDataBridge.ApplyToCurrentThread(); 167 numericDataBridge.ApplyToCurrentThread(); 168 // While timeConverstionDataBridge stores read-write variables, 169 // these variables are global (by POSIX definition). Furthermore, 170 // none of the backends seem to access these variables 171 // directly. The values are set in the bridge mostly for 172 // synchronization purposes. Therefore, don't call 173 // ApplyToCurrentThread for this object. 174} 175 176 177} // namespace Libroot 178} // namespace BPrivate 179