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