]> pd.if.org Git - pdclib/blob - internals/_PDCLIB_locale.h
PDCLIB-3: Add _PDCLIB_unpackwint to enable UTF-16 platforms to pass a "packed UTF...
[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_uint32_t num;
73     _PDCLIB_uint16_t flags;
74     _PDCLIB_uint32_t lower;
75     _PDCLIB_uint32_t upper;
76 } _PDCLIB_wcinfo_t;
77
78 static inline _PDCLIB_wint_t _PDCLIB_unpackwint( _PDCLIB_wint_t wc )
79 {
80     if( sizeof(_PDCLIB_wchar_t) == 2 && sizeof(_PDCLIB_wint_t) == 4 ) {
81         /* On UTF-16 platforms, as an extension accept a "packed surrogate"
82          * encoding. We accept the surrogate pairs either way
83          */
84
85         _PDCLIB_wint_t c = (wc & 0xF800F800);
86         if(c == (_PDCLIB_wint_t) 0xD800DC00) {
87             // MSW: Lead, LSW: Trail
88             _PDCLIB_wint_t lead  = wc >> 16 & 0x3FF;
89             _PDCLIB_wint_t trail = wc       & 0x3FF;
90             wc = lead << 10 | trail;
91         } else if(c == (_PDCLIB_wint_t) 0xDC00D800) {
92             // MSW: Trail, LSW: Lead
93             _PDCLIB_wint_t trail = wc >> 16 & 0x3FF;
94             _PDCLIB_wint_t lead  = wc       & 0x3FF;
95             wc = lead << 10 | trail;
96         }
97
98     }
99     return wc;
100 }
101
102 struct _PDCLIB_locale {
103     _PDCLIB_charcodec_t          _Codec;
104     struct lconv                 _Conv;
105
106     /* ctype */
107     _PDCLIB_ctype_t             *_CType; 
108
109     /* perror/strerror */
110     char                        *_ErrnoStr[_PDCLIB_ERRNO_MAX];
111 };
112
113 #endif