1/*
2 * Copyright 2010-2011, Oliver Tappe, zooey@hirschkaefer.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _LOCALE_BACKEND_H
6#define _LOCALE_BACKEND_H
7
8
9#include <SupportDefs.h>
10
11#include <locale.h>
12#include <time.h>
13#include <wctype.h>
14
15
16struct lc_time_t;
17struct locale_data;		// glibc
18
19
20namespace BPrivate {
21namespace Libroot {
22
23
24struct LocaleCtypeDataBridge {
25private:
26	const unsigned short*		localClassInfoTable;
27	const int*					localToLowerTable;
28	const int*					localToUpperTable;
29
30public:
31	const unsigned short**		addrOfClassInfoTable;
32	const int**					addrOfToLowerTable;
33	const int**					addrOfToUpperTable;
34
35	const unsigned short* const	posixClassInfo;
36	const int* const			posixToLowerMap;
37	const int* const			posixToUpperMap;
38
39	bool						isGlobal;
40
41	LocaleCtypeDataBridge(bool isGlobal);
42
43	void setMbCurMax(unsigned short mbCurMax);
44	void ApplyToCurrentThread();
45};
46
47
48struct LocaleMessagesDataBridge {
49	const char** const 	posixLanginfo;
50
51	LocaleMessagesDataBridge();
52};
53
54
55struct LocaleMonetaryDataBridge {
56	const struct lconv* const posixLocaleConv;
57
58	LocaleMonetaryDataBridge();
59};
60
61
62struct LocaleNumericDataBridge {
63private:
64	// struct used by glibc to store numeric locale data
65	struct GlibcNumericLocale {
66		const char* name;
67		const char* filedata;
68		off_t filesize;
69		int mmaped;
70		unsigned int usage_count;
71		int use_translit;
72		const char *options;
73		unsigned int nstrings;
74		union locale_data_value
75		{
76			const uint32_t* wstr;
77			const char* string;
78			unsigned int word;
79		}
80		values[6];
81	};
82	locale_data* originalGlibcLocale;
83	GlibcNumericLocale  		glibcNumericLocaleData;
84
85public:
86	const struct lconv* const 	posixLocaleConv;
87	GlibcNumericLocale*  		glibcNumericLocale;
88	bool						isGlobal;
89
90	LocaleNumericDataBridge(bool isGlobal);
91	~LocaleNumericDataBridge();
92
93	void ApplyToCurrentThread();
94};
95
96
97struct LocaleTimeDataBridge {
98	const struct lc_time_t* const posixLCTimeInfo;
99
100	LocaleTimeDataBridge();
101};
102
103
104struct TimeConversionDataBridge {
105	static const int32 		kTZNameLength = 64;
106
107private:
108	int						localDaylight;
109	long					localTimezone;
110	char*					localTZName[2];
111	char					localTZName0[kTZNameLength];
112	char					localTZName1[kTZNameLength];
113
114public:
115	int*					addrOfDaylight;
116	long*					addrOfTimezone;
117	char**					addrOfTZName;
118	bool					isGlobal;
119
120	TimeConversionDataBridge(bool isGlobal);
121};
122
123
124struct LocaleDataBridge {
125	LocaleCtypeDataBridge		ctypeDataBridge;
126	LocaleMessagesDataBridge	messagesDataBridge;
127	LocaleMonetaryDataBridge	monetaryDataBridge;
128	LocaleNumericDataBridge		numericDataBridge;
129	LocaleTimeDataBridge		timeDataBridge;
130	TimeConversionDataBridge	timeConversionDataBridge;
131	const char** const			posixLanginfo;
132	bool						isGlobal;
133
134	LocaleDataBridge(bool isGlobal);
135
136	void ApplyToCurrentThread();
137};
138
139
140class LocaleBackend {
141public:
142								LocaleBackend();
143	virtual						~LocaleBackend();
144
145	virtual	const char*			SetLocale(int category, const char* locale) = 0;
146	virtual	const struct lconv*	LocaleConv() = 0;
147	virtual	const struct lc_time_t*	LCTimeInfo() = 0;
148
149	virtual	int					IsWCType(wint_t wc, wctype_t charClass) = 0;
150	virtual	status_t			ToWCTrans(wint_t wc, wctrans_t transition,
151									wint_t& result) = 0;
152
153	virtual status_t			MultibyteToWchar(wchar_t* wcOut, const char* mb,
154									size_t mbLength, mbstate_t* mbState,
155									size_t& lengthOut) = 0;
156	virtual status_t			MultibyteStringToWchar(wchar_t* wcDest,
157									size_t wcDestLength, const char** mbSource,
158									size_t mbSourceLength, mbstate_t* mbState,
159									size_t& lengthOut) = 0;
160	virtual status_t			WcharToMultibyte(char* mbOut, wchar_t wc,
161									mbstate_t* mbState, size_t& lengthOut) = 0;
162	virtual status_t			WcharStringToMultibyte(char* mbDest,
163									size_t mbDestLength,
164									const wchar_t** wcSource,
165									size_t wcSourceLength, mbstate_t* mbState,
166									size_t& lengthOut) = 0;
167
168	virtual	const char*			GetLanginfo(int index) = 0;
169
170	virtual	status_t			Strcoll(const char* a, const char* b,
171									int& out) = 0;
172	virtual status_t			Strxfrm(char* out, const char* in,
173									size_t outSize, size_t& requiredSize) = 0;
174	virtual	status_t			Wcscoll(const wchar_t* a, const wchar_t* b,
175									int& out) = 0;
176	virtual status_t			Wcsxfrm(wchar_t* out, const wchar_t* in,
177									size_t outSize, size_t& requiredSize) = 0;
178
179	virtual status_t			TZSet(const char* timeZoneID,
180									const char* tz) = 0;
181	virtual	status_t			Localtime(const time_t* inTime,
182									struct tm* tmOut) = 0;
183	virtual	status_t			Gmtime(const time_t* inTime,
184									struct tm* tmOut) = 0;
185	virtual status_t			Mktime(struct tm* inOutTm, time_t& timeOut) = 0;
186
187	virtual status_t			Timegm(struct tm* inOutTm, time_t& timeOut) = 0;
188
189	virtual void				Initialize(LocaleDataBridge* dataBridge) = 0;
190
191	static	status_t			LoadBackend();
192	static  status_t			CreateBackend(LocaleBackend*& backendOut);
193	static  void				DestroyBackend(LocaleBackend* instance);
194};
195
196
197// The real struct behind locale_t
198struct LocaleBackendData {
199	int magic;
200	LocaleBackend* backend;
201	LocaleDataBridge* databridge;
202};
203
204
205LocaleBackendData* GetCurrentLocaleInfo();
206void SetCurrentLocaleInfo(LocaleBackendData* newLocale);
207LocaleBackend* GetCurrentLocaleBackend();
208extern LocaleBackend* gGlobalLocaleBackend;
209extern LocaleDataBridge gGlobalLocaleDataBridge;
210
211}	// namespace Libroot
212}	// namespace BPrivate
213
214
215#endif	// _LOCALE_BACKEND_H
216