]> arthur.barton.de Git - netatalk.git/blob - libatalk/unicode/charsets/mac_hebrew.c
big merge for db frontend and unicode.
[netatalk.git] / libatalk / unicode / charsets / mac_hebrew.c
1 /* 
2    Unix SMB/CIFS implementation.
3    minimal iconv implementation
4    Copyright (C) Andrew Tridgell 2001
5    Copyright (C) Jelmer Vernooij 2002,2003
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21    From samba 3.0 beta and GNU libiconv-1.8
22    It's bad but most of the time we can't use libc iconv service:
23    - it doesn't round trip for most encoding
24    - it doesn't know about Apple extension
25 */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif /* HAVE_CONFIG_H */
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <netatalk/endian.h>
34 #include <atalk/unicode.h>
35
36
37 #include <atalk/logger.h>
38 #include <errno.h>
39
40 #include <atalk/unicode.h>
41
42 #include "mac_hebrew.h"
43
44 static size_t   mac_hebrew_pull(void *,char **, size_t *, char **, size_t *);
45 static size_t   mac_hebrew_push(void *,char **, size_t *, char **, size_t *);
46
47 struct charset_functions charset_mac_hebrew =
48 {
49         "MAC_HEBREW",
50         5,
51         mac_hebrew_pull,
52         mac_hebrew_push,
53         CHARSET_CLIENT | CHARSET_MULTIBYTE      
54 };
55
56
57 /* ------------------------ 
58  * from unicode to mac hebrew code page
59 */
60 static int
61 char_ucs2_to_mac_hebrew ( unsigned char *r, ucs2_t wc)
62 {
63     unsigned char c = 0;
64     if (wc < 0x0080) {
65        *r = wc;
66        return 1;
67     }
68     else if (wc >= 0x00a0 && wc < 0x0100)
69         c = mac_hebrew_page00[wc-0x00a0];
70     else if (wc >= 0x05b0 && wc < 0x05f0)
71         c = mac_hebrew_page05[wc-0x05b0];
72     else if (wc >= 0x2010 && wc < 0x2028)
73         c = mac_hebrew_page20[wc-0x2010];
74     else if (wc == 0x20aa)
75         c = 0xa6;
76     else if (wc >= 0xfb18 && wc < 0xfb50)
77         c = mac_hebrew_pagefb[wc-0xfb18];
78     if (c != 0) {
79        *r = c;
80        return 1;
81     }
82     return 0;
83 }
84
85 static size_t mac_hebrew_push( void *cd, char **inbuf, size_t *inbytesleft,
86                          char **outbuf, size_t *outbytesleft)
87 {
88     unsigned char c = 0;
89     int len = 0;
90     unsigned char *tmpptr = (unsigned char *) *outbuf;
91
92     while (*inbytesleft >= 2 && *outbytesleft >= 1) {
93         ucs2_t *inptr = (ucs2_t *) *inbuf;
94         if (*inptr == 0x05b8) {
95             (*inbuf) += 2;
96             (*inbytesleft)  -= 2;
97             if (*inbytesleft >= 2 && *((ucs2_t *)*inbuf) == 0xf87f ) {
98                 (*inbuf) += 2;
99                 (*inbytesleft)  -= 2;
100                 c = 0xde;
101             }
102             else {
103                 c = 0xcb;
104             }
105             *tmpptr = c; 
106         }
107         else if (*inptr == 0x05f2 && *inbytesleft >= 4 && *(inptr +1) == 0x05b7) {
108             (*inbuf) += 4;
109             (*inbytesleft)  -= 4;
110             *tmpptr = 0x81;
111         }
112         else if (*inptr == 0xf86a && *inbytesleft >= 6 && *(inptr +1) == 0x05dc && *(inptr +2) == 0x05b9) {
113             (*inbuf) += 6;
114             (*inbytesleft)  -= 6;
115             *tmpptr = 0xc0;
116         }
117         else if (char_ucs2_to_mac_hebrew ( tmpptr, *inptr)) {
118             (*inbuf) += 2;
119             (*inbytesleft)  -= 2;
120         }
121         else {
122             errno = EILSEQ;
123             return (size_t) -1;
124         }
125         (*outbytesleft) -= 1;
126         tmpptr++;
127         len++;
128     }
129
130     if (*inbytesleft > 0) {
131         errno = E2BIG;
132         return -1;
133     }
134
135     return len;
136 }
137
138 /* ------------------------ */
139 static int
140 char_mac_hebrew_to_ucs2 (ucs2_t *pwc, const unsigned char *s)
141 {
142         unsigned char c = *s;
143         if (c < 0x80) {
144                 *pwc = (ucs2_t) c;
145                 return 1;
146         }
147         else {
148                 unsigned short wc = mac_hebrew_2uni[c-0x80];
149                 if (wc != 0xfffd) {
150                     *pwc = (ucs2_t) wc;
151                     return 1;
152                 }
153         }
154         return 0;
155 }
156
157 static size_t mac_hebrew_pull ( void *cd, char **inbuf, size_t *inbytesleft,
158                          char **outbuf, size_t *outbytesleft)
159 {
160     ucs2_t         *temp;
161     unsigned char  *inptr;
162     size_t         len = 0;
163
164     while (*inbytesleft >= 1 && *outbytesleft >= 2) {
165         inptr = (unsigned char *) *inbuf;
166         temp  = (ucs2_t*) *outbuf;      
167         if (char_mac_hebrew_to_ucs2 ( temp, inptr)) {
168             if (*temp == 1) {       /* 0x81 --> 0x05f2+0x05b7 */
169                 if (*outbytesleft < 4) {
170                     errno = E2BIG;
171                     return (size_t) -1; 
172                 }
173                 *temp = 0x05f2;
174                 *(temp +1) = 0x05b7;
175                 (*outbuf)      +=4;
176                 (*outbytesleft)-=4;
177                 len += 2;
178             }
179             else if (*temp == 2) { /* 0xc0 -> 0xf86a 0x05dc 0x05b9*/
180                 if (*outbytesleft < 6) {
181                     errno = E2BIG;
182                     return (size_t) -1; 
183                 }
184                 *temp = 0xf86a;
185                 *(temp +1) = 0x05dc;
186                 *(temp +2) = 0x05b9;
187                 (*outbuf)      +=6;
188                 (*outbytesleft)-=6;
189                 len += 3;
190             }
191             else if (*temp == 3) { /* 0xde --> 0x05b8 0xf87f */
192                 if (*outbytesleft < 4) {
193                     errno = E2BIG;
194                     return (size_t) -1; 
195                 }
196                 *temp = 0x05b8;
197                 *(temp +1) = 0xf87f;
198                 (*outbuf)      +=4;
199                 (*outbytesleft)-=4;
200                 len += 2;
201             }
202             else {
203                 (*outbuf)      +=2;
204                 (*outbytesleft)-=2;
205                 len++;
206             }
207             (*inbuf)        +=1;
208             (*inbytesleft) -=1;
209         }
210         else    
211         {
212             errno = EILSEQ;
213             return (size_t) -1; 
214         }
215     }
216
217     if (*inbytesleft > 0) {
218         errno = E2BIG;
219         return (size_t) -1;
220     }
221     return len;
222 }
223