]> pd.if.org Git - pdclib/blob - internals/_PDCLIB_locale.h
PDCLIB-3 #resolve Implement towctrans/wctrans. Completes wctype.h
[pdclib] / internals / _PDCLIB_locale.h
1 #ifndef __PDCLIB_LOCALE_H
2 #define __PDCLIB_LOCALE_H __PDCLIB_LOCALE_H
3 #include <_PDCLIB_int.h>
4 #include <locale.h>
5 #include <threads.h>
6 #include <stdlib.h>
7
8 #define _PDCLIB_LOCALE_METHOD_TSS           't'
9 #define _PDCLIB_LOCALE_METHOD_THREAD_LOCAL  'T'
10
11 #if !defined(_PDCLIB_LOCALE_METHOD)
12     #error _PDCLIB_LOCALE_METHOD undefined: don't know where I'm storing the thread locale
13 #elif _PDCLIB_LOCALE_METHOD == _PDCLIB_LOCALE_METHOD_TSS
14     extern tss_t _PDCLIB_locale_tss;
15     static inline locale_t _PDCLIB_threadlocale( void )
16     {
17         locale_t l = tss_get(_PDCLIB_locale_tss);
18         if(l == NULL)
19             l = &_PDCLIB_global_locale;
20         return l;
21     }
22
23     static inline void _PDCLIB_setthreadlocale( locale_t l )
24     {
25         if(tss_set(_PDCLIB_locale_tss, l) != thrd_success)
26             abort();
27     }
28 #elif _PDCLIB_LOCALE_METHOD == _PDCLIB_LOCALE_METHOD_THREAD_LOCAL
29     extern thread_local locale_t _PDCLIB_locale_tls;
30     #define _PDCLIB_threadlocale() (_PDCLIB_locale_tls || &_PDCLIB_global_locale)
31     static inline locale_t _PDCLIB_threadlocale( void )
32     {
33         locale_t l = _PDCLIB_locale_tls;
34         if(l == NULL)
35             l = &_PDCLIB_global_locale;
36         return l;
37     }
38
39     static inline void _PDCLIB_setthreadlocale( locale_t l )
40     {
41         _PDCLIB_locale_tls = l;
42     }
43 #else
44     #error Locale TSS method unspecified
45 #endif
46
47 /* -------------------------------------------------------------------------- */
48 /* <ctype.h> lookup tables                                                    */
49 /* -------------------------------------------------------------------------- */
50
51 #define _PDCLIB_CTYPE_ALPHA   1
52 #define _PDCLIB_CTYPE_BLANK   2
53 #define _PDCLIB_CTYPE_CNTRL   4
54 #define _PDCLIB_CTYPE_GRAPH   8
55 #define _PDCLIB_CTYPE_PUNCT  16
56 #define _PDCLIB_CTYPE_SPACE  32
57 #define _PDCLIB_CTYPE_LOWER  64
58 #define _PDCLIB_CTYPE_UPPER 128
59 #define _PDCLIB_CTYPE_DIGIT 256
60 #define _PDCLIB_CTYPE_XDIGT 512
61
62 #define _PDCLIB_WCTRANS_TOLOWER 1
63 #define _PDCLIB_WCTRANS_TOUPPER 2
64
65 typedef struct _PDCLIB_ctype
66 {
67     _PDCLIB_uint16_t flags;
68     unsigned char upper;
69     unsigned char lower;
70     unsigned char collation;
71 } _PDCLIB_ctype_t;
72
73 typedef struct _PDCLIB_wcinfo
74 {
75     _PDCLIB_wint_t   num;
76     _PDCLIB_uint16_t flags;
77     _PDCLIB_wint_t   lower;
78     _PDCLIB_wint_t   upper;
79 } _PDCLIB_wcinfo_t;
80
81 extern _PDCLIB_wcinfo_t _PDCLIB_wcinfo[];
82 extern size_t           _PDCLIB_wcinfo_size;
83
84 static inline int _PDCLIB_wcinfo_cmp( const void * _key, const void * _obj )
85 {
86     _PDCLIB_uint32_t * key = (_PDCLIB_uint32_t *) _key;
87     _PDCLIB_wcinfo_t * obj = (_PDCLIB_wcinfo_t *) _obj;
88     return *key - obj->num;
89 }
90
91 static inline _PDCLIB_wcinfo_t * _PDCLIB_wcgetinfo( _PDCLIB_uint32_t num )
92 {
93     _PDCLIB_wcinfo_t *info = (_PDCLIB_wcinfo_t*) 
94         bsearch( &num, _PDCLIB_wcinfo, _PDCLIB_wcinfo_size, 
95                  sizeof( _PDCLIB_wcinfo[0] ), _PDCLIB_wcinfo_cmp );
96
97     return info;
98 }
99
100 static inline _PDCLIB_wint_t _PDCLIB_unpackwint( _PDCLIB_wint_t wc )
101 {
102     if( sizeof(_PDCLIB_wchar_t) == 2 && sizeof(_PDCLIB_wint_t) == 4 ) {
103         /* On UTF-16 platforms, as an extension accept a "packed surrogate"
104          * encoding. We accept the surrogate pairs either way
105          */
106
107         _PDCLIB_wint_t c = (wc & 0xF800F800);
108         if(c == (_PDCLIB_wint_t) 0xD800DC00) {
109             // MSW: Lead, LSW: Trail
110             _PDCLIB_wint_t lead  = wc >> 16 & 0x3FF;
111             _PDCLIB_wint_t trail = wc       & 0x3FF;
112             wc = lead << 10 | trail;
113         } else if(c == (_PDCLIB_wint_t) 0xDC00D800) {
114             // MSW: Trail, LSW: Lead
115             _PDCLIB_wint_t trail = wc >> 16 & 0x3FF;
116             _PDCLIB_wint_t lead  = wc       & 0x3FF;
117             wc = lead << 10 | trail;
118         }
119
120     }
121     return wc;
122 }
123
124 struct _PDCLIB_locale {
125     _PDCLIB_charcodec_t          _Codec;
126     struct lconv                 _Conv;
127
128     /* ctype */
129     _PDCLIB_ctype_t             *_CType; 
130
131     /* perror/strerror */
132     char                        *_ErrnoStr[_PDCLIB_ERRNO_MAX];
133 };
134
135 #endif