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 21 extern const unsigned short* __ctype_b; 22 extern const int* __ctype_tolower; 23 extern const int* __ctype_toupper; 24 25 26 namespace BPrivate { 27 namespace Libroot { 28 29 30 extern "C" GlibcLocaleStruct* _nl_current_locale(); 31 extern "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 38 LocaleCtypeDataBridge::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 60 void LocaleCtypeDataBridge::setMbCurMax(unsigned short mbCurMax) 61 { 62 __ctype_mb_cur_max = mbCurMax; 63 } 64 65 66 void 67 LocaleCtypeDataBridge::ApplyToCurrentThread() 68 { 69 *__ctype_b_loc() = *addrOfClassInfoTable; 70 *__ctype_tolower_loc() = *addrOfToLowerTable; 71 *__ctype_toupper_loc() = *addrOfToUpperTable; 72 } 73 74 75 LocaleMessagesDataBridge::LocaleMessagesDataBridge() 76 : 77 posixLanginfo(gPosixLanginfo) 78 { 79 } 80 81 82 LocaleMonetaryDataBridge::LocaleMonetaryDataBridge() 83 : 84 posixLocaleConv(&gPosixLocaleConv) 85 { 86 } 87 88 89 LocaleNumericDataBridge::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 106 LocaleNumericDataBridge::~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 116 void 117 LocaleNumericDataBridge::ApplyToCurrentThread() 118 { 119 _NL_CURRENT_DATA(GLIBC_LC_NUMERIC) = (locale_data*)glibcNumericLocale; 120 } 121 122 123 LocaleTimeDataBridge::LocaleTimeDataBridge() 124 : 125 posixLCTimeInfo(&gPosixLCTimeInfo) 126 { 127 } 128 129 130 TimeConversionDataBridge::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 152 LocaleDataBridge::LocaleDataBridge(bool isGlobal) 153 : 154 ctypeDataBridge(isGlobal), 155 numericDataBridge(isGlobal), 156 timeConversionDataBridge(isGlobal), 157 posixLanginfo(gPosixLanginfo), 158 isGlobal(isGlobal) 159 { 160 } 161 162 163 void 164 LocaleDataBridge::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