xref: /haiku/src/system/libroot/posix/locale/LocaleDataBridge.cpp (revision 445d4fd926c569e7b9ae28017da86280aaecbae2)
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