Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/waterbox/libc/internals/_PDCLIB_locale.h
2 views
1
/* PDCLib locale support <_PDCLIB_locale.h>
2
3
This file is part of the Public Domain C Library (PDCLib).
4
Permission is granted to use, modify, and / or redistribute at will.
5
*/
6
7
#ifndef __PDCLIB_LOCALE_H
8
#define __PDCLIB_LOCALE_H __PDCLIB_LOCALE_H
9
10
#include "_PDCLIB_int.h"
11
12
#include <locale.h>
13
#include <wctype.h>
14
#include <threads.h>
15
#include <stdlib.h>
16
17
#define _PDCLIB_LOCALE_METHOD_TSS 't'
18
#define _PDCLIB_LOCALE_METHOD_THREAD_LOCAL 'T'
19
#define _PDCLIB_LOCALE_METHOD_FAKE 'F'
20
21
#if !defined(_PDCLIB_LOCALE_METHOD)
22
/* If undefined, no POSIX per thread locales */
23
#define _PDCLIB_threadlocale() (&_PDCLIB_global_locale)
24
#elif _PDCLIB_LOCALE_METHOD == _PDCLIB_LOCALE_METHOD_TSS
25
extern tss_t _PDCLIB_locale_tss;
26
static inline locale_t _PDCLIB_threadlocale( void )
27
{
28
locale_t l = tss_get(_PDCLIB_locale_tss);
29
if ( l == NULL )
30
l = &_PDCLIB_global_locale;
31
return l;
32
}
33
34
static inline void _PDCLIB_setthreadlocale( locale_t l )
35
{
36
if ( tss_set( _PDCLIB_locale_tss, l ) != thrd_success )
37
abort();
38
}
39
#elif _PDCLIB_LOCALE_METHOD == _PDCLIB_LOCALE_METHOD_THREAD_LOCAL
40
extern thread_local locale_t _PDCLIB_locale_tls;
41
#define _PDCLIB_threadlocale() ( _PDCLIB_locale_tls || &_PDCLIB_global_locale )
42
static inline locale_t _PDCLIB_threadlocale( void )
43
{
44
locale_t l = _PDCLIB_locale_tls;
45
if(l == NULL)
46
l = &_PDCLIB_global_locale;
47
return l;
48
}
49
50
static inline void _PDCLIB_setthreadlocale( locale_t l )
51
{
52
_PDCLIB_locale_tls = l;
53
}
54
#elif _PDCLIB_LOCALE_METHOD == _PDCLIB_LOCALE_METHOD_FAKE
55
extern locale_t _PDCLIB_locale_fake;
56
static inline locale_t _PDCLIB_threadlocale( void )
57
{
58
locale_t l = _PDCLIB_locale_fake;
59
if(l == NULL)
60
l = &_PDCLIB_global_locale;
61
return l;
62
}
63
64
static inline void _PDCLIB_setthreadlocale( locale_t l )
65
{
66
_PDCLIB_locale_fake = l;
67
}
68
#else
69
#error Locale TSS method unspecified
70
#endif
71
72
/* -------------------------------------------------------------------------- */
73
/* <ctype.h> lookup tables */
74
/* -------------------------------------------------------------------------- */
75
76
#define _PDCLIB_CTYPE_ALPHA 1
77
#define _PDCLIB_CTYPE_BLANK 2
78
#define _PDCLIB_CTYPE_CNTRL 4
79
#define _PDCLIB_CTYPE_GRAPH 8
80
#define _PDCLIB_CTYPE_PUNCT 16
81
#define _PDCLIB_CTYPE_SPACE 32
82
#define _PDCLIB_CTYPE_LOWER 64
83
#define _PDCLIB_CTYPE_UPPER 128
84
#define _PDCLIB_CTYPE_DIGIT 256
85
#define _PDCLIB_CTYPE_XDIGT 512
86
87
#define _PDCLIB_WCTRANS_TOLOWER 1
88
#define _PDCLIB_WCTRANS_TOUPPER 2
89
90
typedef struct _PDCLIB_ctype
91
{
92
_PDCLIB_uint16_t flags;
93
unsigned char upper;
94
unsigned char lower;
95
unsigned char collation;
96
} _PDCLIB_ctype_t;
97
98
typedef struct _PDCLIB_wcinfo
99
{
100
_PDCLIB_wint_t start;
101
_PDCLIB_uint16_t length;
102
_PDCLIB_uint16_t flags;
103
_PDCLIB_wint_t lower_delta;
104
_PDCLIB_wint_t upper_delta;
105
} _PDCLIB_wcinfo_t;
106
107
struct _PDCLIB_locale {
108
const struct _PDCLIB_charcodec_t * _Codec;
109
struct lconv _Conv;
110
111
/* ctype / wctype */
112
/* XXX: Maybe re-evaluate constness of these later on? */
113
const _PDCLIB_wcinfo_t *_WCType;
114
_PDCLIB_size_t _WCTypeSize;
115
const _PDCLIB_ctype_t *_CType;
116
117
/* perror/strerror */
118
const char * const _ErrnoStr[_PDCLIB_ERRNO_MAX];
119
};
120
121
extern const _PDCLIB_wcinfo_t _PDCLIB_wcinfo[];
122
extern const size_t _PDCLIB_wcinfo_size;
123
124
static inline int _PDCLIB_wcinfo_cmp( const void * _key, const void * _obj )
125
{
126
_PDCLIB_int32_t * key = (_PDCLIB_int32_t *) _key;
127
_PDCLIB_wcinfo_t * obj = (_PDCLIB_wcinfo_t *) _obj;
128
if ( *key < obj->start )
129
{
130
return -1;
131
}
132
else if ( *key >= obj->start + obj->length )
133
{
134
return 1;
135
}
136
else
137
{
138
return 0;
139
}
140
}
141
142
static inline _PDCLIB_wcinfo_t * _PDCLIB_wcgetinfo( locale_t l, _PDCLIB_int32_t num )
143
{
144
_PDCLIB_wcinfo_t *info = (_PDCLIB_wcinfo_t*)
145
bsearch( &num, l->_WCType, l->_WCTypeSize,
146
sizeof( l->_WCType[0] ), _PDCLIB_wcinfo_cmp );
147
148
return info;
149
}
150
151
static inline wint_t _PDCLIB_unpackwint( wint_t wc )
152
{
153
if( sizeof(_PDCLIB_wchar_t) == 2 && sizeof(_PDCLIB_wint_t) == 4 ) {
154
/* On UTF-16 platforms, as an extension accept a "packed surrogate"
155
* encoding. We accept the surrogate pairs either way
156
*/
157
158
wint_t c = (wc & 0xF800F800);
159
if(c == (_PDCLIB_wint_t) 0xD800DC00) {
160
// MSW: Lead, LSW: Trail
161
wint_t lead = wc >> 16 & 0x3FF;
162
wint_t trail = wc & 0x3FF;
163
wc = lead << 10 | trail;
164
} else if(c == (_PDCLIB_wint_t) 0xDC00D800) {
165
// MSW: Trail, LSW: Lead
166
wint_t trail = wc >> 16 & 0x3FF;
167
wint_t lead = wc & 0x3FF;
168
wc = lead << 10 | trail;
169
}
170
171
}
172
return wc;
173
}
174
175
/* Internal xlocale-style WCType API */
176
int _PDCLIB_iswalnum_l( wint_t _Wc, locale_t l );
177
int _PDCLIB_iswalpha_l( wint_t _Wc, locale_t l );
178
int _PDCLIB_iswblank_l( wint_t _Wc, locale_t l );
179
int _PDCLIB_iswcntrl_l( wint_t _Wc, locale_t l );
180
int _PDCLIB_iswdigit_l( wint_t _Wc, locale_t l );
181
int _PDCLIB_iswgraph_l( wint_t _Wc, locale_t l );
182
int _PDCLIB_iswlower_l( wint_t _Wc, locale_t l );
183
int _PDCLIB_iswprint_l( wint_t _Wc, locale_t l );
184
int _PDCLIB_iswpunct_l( wint_t _Wc, locale_t l );
185
int _PDCLIB_iswspace_l( wint_t _Wc, locale_t l );
186
int _PDCLIB_iswupper_l( wint_t _Wc, locale_t l );
187
int _PDCLIB_iswxdigit_l( wint_t _Wc, locale_t l );
188
int _PDCLIB_iswctype_l( wint_t _Wc, wctype_t _Desc, locale_t l );
189
wint_t _PDCLIB_towlower_l( wint_t _Wc, locale_t l );
190
wint_t _PDCLIB_towupper_l( wint_t _Wc, locale_t l );
191
wint_t _PDCLIB_towctrans_l( wint_t _Wc, wctrans_t _Desc, locale_t l );
192
193
#endif
194
195