]> pd.if.org Git - pdclib/blob - internals/_PDCLIB_locale.h
PDCLIB-3 Change _PDCLIB_wcinfo_t to use wint_t
[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 typedef struct _PDCLIB_ctype
63 {
64     _PDCLIB_uint16_t flags;
65     unsigned char upper;
66     unsigned char lower;
67     unsigned char collation;
68 } _PDCLIB_ctype_t;
69
70 typedef struct _PDCLIB_wcinfo
71 {
72     _PDCLIB_wint_t   num;
73     _PDCLIB_uint16_t flags;
74     _PDCLIB_wint_t   lower;
75     _PDCLIB_wint_t   upper;
76 } _PDCLIB_wcinfo_t;
77
78 extern _PDCLIB_wcinfo_t _PDCLIB_wcinfo[];
79 extern size_t           _PDCLIB_wcinfo_size;
80
81 static inline int _PDCLIB_wcinfo_cmp( const void * _key, const void * _obj )
82 {
83     _PDCLIB_uint32_t * key = (_PDCLIB_uint32_t *) _key;
84     _PDCLIB_wcinfo_t * obj = (_PDCLIB_wcinfo_t *) _obj;
85     return *key - obj->num;
86 }
87
88 static inline _PDCLIB_wcinfo_t * _PDCLIB_wcgetinfo( _PDCLIB_uint32_t num )
89 {
90     _PDCLIB_wcinfo_t *info = (_PDCLIB_wcinfo_t*) 
91         bsearch( &num, _PDCLIB_wcinfo, _PDCLIB_wcinfo_size, 
92                  sizeof( _PDCLIB_wcinfo[0] ), _PDCLIB_wcinfo_cmp );
93
94     return info;
95 }
96
97 static inline _PDCLIB_wint_t _PDCLIB_unpackwint( _PDCLIB_wint_t wc )
98 {
99     if( sizeof(_PDCLIB_wchar_t) == 2 && sizeof(_PDCLIB_wint_t) == 4 ) {
100         /* On UTF-16 platforms, as an extension accept a "packed surrogate"
101          * encoding. We accept the surrogate pairs either way
102          */
103
104         _PDCLIB_wint_t c = (wc & 0xF800F800);
105         if(c == (_PDCLIB_wint_t) 0xD800DC00) {
106             // MSW: Lead, LSW: Trail
107             _PDCLIB_wint_t lead  = wc >> 16 & 0x3FF;
108             _PDCLIB_wint_t trail = wc       & 0x3FF;
109             wc = lead << 10 | trail;
110         } else if(c == (_PDCLIB_wint_t) 0xDC00D800) {
111             // MSW: Trail, LSW: Lead
112             _PDCLIB_wint_t trail = wc >> 16 & 0x3FF;
113             _PDCLIB_wint_t lead  = wc       & 0x3FF;
114             wc = lead << 10 | trail;
115         }
116
117     }
118     return wc;
119 }
120
121 struct _PDCLIB_locale {
122     _PDCLIB_charcodec_t          _Codec;
123     struct lconv                 _Conv;
124
125     /* ctype */
126     _PDCLIB_ctype_t             *_CType; 
127
128     /* perror/strerror */
129     char                        *_ErrnoStr[_PDCLIB_ERRNO_MAX];
130 };
131
132 #endif