xref: /AOO41X/main/sal/textenc/tcvtutf7.c (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #include "tenchelp.h"
29*cdf0e10cSrcweir #include "unichars.h"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #ifndef _RTL_ALLOC_H
32*cdf0e10cSrcweir #include "rtl/alloc.h"
33*cdf0e10cSrcweir #endif
34*cdf0e10cSrcweir #include "rtl/textcvt.h"
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir /* ======================================================================= */
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir static sal_uChar const aImplBase64Tab[64] =
39*cdf0e10cSrcweir {
40*cdf0e10cSrcweir     /* A-Z */
41*cdf0e10cSrcweir           0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
42*cdf0e10cSrcweir     0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
43*cdf0e10cSrcweir     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
44*cdf0e10cSrcweir     0x58, 0x59, 0x5A,
45*cdf0e10cSrcweir     /* a-z */
46*cdf0e10cSrcweir           0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
47*cdf0e10cSrcweir     0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
48*cdf0e10cSrcweir     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
49*cdf0e10cSrcweir     0x78, 0x79, 0x7A,
50*cdf0e10cSrcweir     /* 0-9,+,/ */
51*cdf0e10cSrcweir     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
52*cdf0e10cSrcweir     0x38, 0x39, 0x2B, 0x2F
53*cdf0e10cSrcweir };
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir /* Index in Base64Tab or 0xFF, when is a invalid character */
56*cdf0e10cSrcweir static sal_uChar const aImplBase64IndexTab[128] =
57*cdf0e10cSrcweir {
58*cdf0e10cSrcweir     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,     /* 0x00-0x07 */
59*cdf0e10cSrcweir     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,     /* 0x08-0x0F */
60*cdf0e10cSrcweir     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,     /* 0x10-0x17 */
61*cdf0e10cSrcweir     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,     /* 0x18-0x1F */
62*cdf0e10cSrcweir     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,     /* 0x20-0x27  !"#$%&' */
63*cdf0e10cSrcweir     0xFF, 0xFF, 0xFF,   62, 0xFF, 0xFF, 0xFF,   63,     /* 0x28-0x2F ()*+,-./ */
64*cdf0e10cSrcweir       52,   53,   54,   55,   56,   57,   58,   59,     /* 0x30-0x37 01234567 */
65*cdf0e10cSrcweir       60,   61, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,     /* 0x38-0x3F 89:;<=>? */
66*cdf0e10cSrcweir     0xFF,    0,    1,    2,    3,    4,    5,    6,     /* 0x40-0x47 @ABCDEFG */
67*cdf0e10cSrcweir        7,    8,    9,   10,   11,   12,   13,   14,     /* 0x48-0x4F HIJKLMNO */
68*cdf0e10cSrcweir       15,   16,   17,   18,   19,   20,   21,   22,     /* 0x50-0x57 PQRSTUVW */
69*cdf0e10cSrcweir       23,   24,   25, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,     /* 0x58-0x5F XYZ[\]^_ */
70*cdf0e10cSrcweir     0xFF,   26,   27,   28,   29,   30,   31,   32,     /* 0x60-0x67 `abcdefg */
71*cdf0e10cSrcweir       33,   34,   35,   36,   37,   38,   39,   40,     /* 0x68-0x6F hijklmno */
72*cdf0e10cSrcweir       41,   42,   43,   44,   45,   46,   47,   48,     /* 0x70-0x77 pqrstuvw */
73*cdf0e10cSrcweir       49,   50,   51, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF      /* 0x78-0x7F xyz{|}~ */
74*cdf0e10cSrcweir };
75*cdf0e10cSrcweir 
76*cdf0e10cSrcweir static sal_uChar const aImplMustShiftTab[128] =
77*cdf0e10cSrcweir {
78*cdf0e10cSrcweir     1, 1, 1, 1, 1, 1, 1, 1,     /* 0x00-0x07 */
79*cdf0e10cSrcweir     1, 0, 0, 1, 0, 1, 1, 1,     /* 0x08-0x0F 0x09 == HTAB, 0x0A == LF 0x0C == CR */
80*cdf0e10cSrcweir     1, 1, 1, 1, 1, 1, 1, 1,     /* 0x10-0x17 */
81*cdf0e10cSrcweir     1, 1, 1, 1, 1, 1, 1, 1,     /* 0x18-0x1F */
82*cdf0e10cSrcweir     0, 1, 1, 1, 1, 1, 1, 0,     /* 0x20-0x27  !"#$%&' */
83*cdf0e10cSrcweir     0, 0, 1, 1, 0, 1, 0, 0,     /* 0x28-0x2F ()*+,-./ */
84*cdf0e10cSrcweir     0, 0, 0, 0, 0, 0, 0, 0,     /* 0x30-0x37 01234567 */
85*cdf0e10cSrcweir     0, 0, 0, 1, 1, 1, 1, 0,     /* 0x38-0x3F 89:;<=>? */
86*cdf0e10cSrcweir     1, 0, 0, 0, 0, 0, 0, 0,     /* 0x40-0x47 @ABCDEFG */
87*cdf0e10cSrcweir     0, 0, 0, 0, 0, 0, 0, 0,     /* 0x48-0x4F HIJKLMNO */
88*cdf0e10cSrcweir     0, 0, 0, 0, 0, 0, 0, 0,     /* 0x50-0x57 PQRSTUVW */
89*cdf0e10cSrcweir     0, 0, 0, 1, 1, 1, 1, 1,     /* 0x58-0x5F XYZ[\]^_ */
90*cdf0e10cSrcweir     1, 0, 0, 0, 0, 0, 0, 0,     /* 0x60-0x67 `abcdefg */
91*cdf0e10cSrcweir     0, 0, 0, 0, 0, 0, 0, 0,     /* 0x68-0x6F hijklmno */
92*cdf0e10cSrcweir     0, 0, 0, 0, 0, 0, 0, 0,     /* 0x70-0x77 pqrstuvw */
93*cdf0e10cSrcweir     0, 0, 0, 1, 1, 1, 1, 1      /* 0x78-0x7F xyz{|}~ */
94*cdf0e10cSrcweir };
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir /* + */
97*cdf0e10cSrcweir #define IMPL_SHIFT_IN_CHAR      0x2B
98*cdf0e10cSrcweir /* - */
99*cdf0e10cSrcweir #define IMPL_SHIFT_OUT_CHAR     0x2D
100*cdf0e10cSrcweir 
101*cdf0e10cSrcweir /* ----------------------------------------------------------------------- */
102*cdf0e10cSrcweir 
103*cdf0e10cSrcweir typedef struct
104*cdf0e10cSrcweir {
105*cdf0e10cSrcweir     int                     mbShifted;
106*cdf0e10cSrcweir     int                     mbFirst;
107*cdf0e10cSrcweir     int                     mbWroteOne;
108*cdf0e10cSrcweir     sal_uInt32              mnBitBuffer;
109*cdf0e10cSrcweir     sal_uInt32              mnBufferBits;
110*cdf0e10cSrcweir } ImplUTF7ToUCContextData;
111*cdf0e10cSrcweir 
112*cdf0e10cSrcweir /* ----------------------------------------------------------------------- */
113*cdf0e10cSrcweir 
114*cdf0e10cSrcweir void* ImplUTF7CreateUTF7TextToUnicodeContext( void )
115*cdf0e10cSrcweir {
116*cdf0e10cSrcweir     ImplUTF7ToUCContextData* pContextData;
117*cdf0e10cSrcweir     pContextData = (ImplUTF7ToUCContextData*)rtl_allocateMemory( sizeof( ImplUTF7ToUCContextData ) );
118*cdf0e10cSrcweir     pContextData->mbShifted         = sal_False;
119*cdf0e10cSrcweir     pContextData->mbFirst           = sal_False;
120*cdf0e10cSrcweir     pContextData->mbWroteOne        = sal_False;
121*cdf0e10cSrcweir     pContextData->mnBitBuffer       = 0;
122*cdf0e10cSrcweir     pContextData->mnBufferBits      = 0;
123*cdf0e10cSrcweir     return (void*)pContextData;
124*cdf0e10cSrcweir }
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir /* ----------------------------------------------------------------------- */
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir void ImplUTF7DestroyTextToUnicodeContext( void* pContext )
129*cdf0e10cSrcweir {
130*cdf0e10cSrcweir     rtl_freeMemory( pContext );
131*cdf0e10cSrcweir }
132*cdf0e10cSrcweir 
133*cdf0e10cSrcweir /* ----------------------------------------------------------------------- */
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir void ImplUTF7ResetTextToUnicodeContext( void* pContext )
136*cdf0e10cSrcweir {
137*cdf0e10cSrcweir     ImplUTF7ToUCContextData* pContextData = (ImplUTF7ToUCContextData*)pContext;
138*cdf0e10cSrcweir     pContextData->mbShifted         = sal_False;
139*cdf0e10cSrcweir     pContextData->mbFirst           = sal_False;
140*cdf0e10cSrcweir     pContextData->mbWroteOne        = sal_False;
141*cdf0e10cSrcweir     pContextData->mnBitBuffer       = 0;
142*cdf0e10cSrcweir     pContextData->mnBufferBits      = 0;
143*cdf0e10cSrcweir }
144*cdf0e10cSrcweir 
145*cdf0e10cSrcweir /* ----------------------------------------------------------------------- */
146*cdf0e10cSrcweir 
147*cdf0e10cSrcweir sal_Size ImplUTF7ToUnicode( const ImplTextConverterData* pData, void* pContext,
148*cdf0e10cSrcweir                             const sal_Char* pSrcBuf, sal_Size nSrcBytes,
149*cdf0e10cSrcweir                             sal_Unicode* pDestBuf, sal_Size nDestChars,
150*cdf0e10cSrcweir                             sal_uInt32 nFlags, sal_uInt32* pInfo,
151*cdf0e10cSrcweir                             sal_Size* pSrcCvtBytes )
152*cdf0e10cSrcweir {
153*cdf0e10cSrcweir     ImplUTF7ToUCContextData*    pContextData = (ImplUTF7ToUCContextData*)pContext;
154*cdf0e10cSrcweir     sal_uChar                   c ='\0';
155*cdf0e10cSrcweir     sal_uChar                   nBase64Value = 0;
156*cdf0e10cSrcweir     int                         bEnd = sal_False;
157*cdf0e10cSrcweir     int                         bShifted;
158*cdf0e10cSrcweir     int                         bFirst;
159*cdf0e10cSrcweir     int                         bWroteOne;
160*cdf0e10cSrcweir     int                         bBase64End;
161*cdf0e10cSrcweir     sal_uInt32                  nBitBuffer;
162*cdf0e10cSrcweir     sal_uInt32                  nBitBufferTemp;
163*cdf0e10cSrcweir     sal_uInt32                  nBufferBits;
164*cdf0e10cSrcweir     sal_Unicode*                pEndDestBuf;
165*cdf0e10cSrcweir     const sal_Char*             pEndSrcBuf;
166*cdf0e10cSrcweir 
167*cdf0e10cSrcweir     (void) pData; /* unused */
168*cdf0e10cSrcweir 
169*cdf0e10cSrcweir /* !!! Implementation not finnished !!!
170*cdf0e10cSrcweir     if ( pContextData )
171*cdf0e10cSrcweir     {
172*cdf0e10cSrcweir         bShifted        = pContextData->mbShifted;
173*cdf0e10cSrcweir         bFirst          = pContextData->mbFirst;
174*cdf0e10cSrcweir         bWroteOne       = pContextData->mbWroteOne;
175*cdf0e10cSrcweir         nBitBuffer      = pContextData->mnBitBuffer;
176*cdf0e10cSrcweir         nBufferBits     = pContextData->mnBufferBits;
177*cdf0e10cSrcweir     }
178*cdf0e10cSrcweir     else
179*cdf0e10cSrcweir */
180*cdf0e10cSrcweir     {
181*cdf0e10cSrcweir         bShifted        = sal_False;
182*cdf0e10cSrcweir         bFirst          = sal_False;
183*cdf0e10cSrcweir         bWroteOne       = sal_False;
184*cdf0e10cSrcweir         nBitBuffer      = 0;
185*cdf0e10cSrcweir         nBufferBits     = 0;
186*cdf0e10cSrcweir     }
187*cdf0e10cSrcweir 
188*cdf0e10cSrcweir     *pInfo = 0;
189*cdf0e10cSrcweir     pEndDestBuf = pDestBuf+nDestChars;
190*cdf0e10cSrcweir     pEndSrcBuf  = pSrcBuf+nSrcBytes;
191*cdf0e10cSrcweir     do
192*cdf0e10cSrcweir     {
193*cdf0e10cSrcweir         if ( pSrcBuf < pEndSrcBuf )
194*cdf0e10cSrcweir         {
195*cdf0e10cSrcweir             c = (sal_uChar)*pSrcBuf;
196*cdf0e10cSrcweir 
197*cdf0e10cSrcweir             /* End, when not a base64 character */
198*cdf0e10cSrcweir             bBase64End = sal_False;
199*cdf0e10cSrcweir             if ( c <= 0x7F )
200*cdf0e10cSrcweir             {
201*cdf0e10cSrcweir                 nBase64Value = aImplBase64IndexTab[c];
202*cdf0e10cSrcweir                 if ( nBase64Value == 0xFF )
203*cdf0e10cSrcweir                     bBase64End = sal_True;
204*cdf0e10cSrcweir             }
205*cdf0e10cSrcweir         }
206*cdf0e10cSrcweir         else
207*cdf0e10cSrcweir         {
208*cdf0e10cSrcweir             bEnd = sal_True;
209*cdf0e10cSrcweir             bBase64End = sal_True;
210*cdf0e10cSrcweir         }
211*cdf0e10cSrcweir 
212*cdf0e10cSrcweir         if ( bShifted )
213*cdf0e10cSrcweir         {
214*cdf0e10cSrcweir             if ( bBase64End )
215*cdf0e10cSrcweir             {
216*cdf0e10cSrcweir                 bShifted = sal_False;
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir                 /* If the character causing us to drop out was SHIFT_IN */
219*cdf0e10cSrcweir                 /* or SHIFT_OUT, it may be a special escape for SHIFT_IN. */
220*cdf0e10cSrcweir                 /* The test for SHIFT_IN is not necessary, but allows */
221*cdf0e10cSrcweir                 /* an alternate form of UTF-7 where SHIFT_IN is escaped */
222*cdf0e10cSrcweir                 /* by SHIFT_IN. This only works for some values of */
223*cdf0e10cSrcweir                 /* SHIFT_IN. It is so implemented, because this comes */
224*cdf0e10cSrcweir                 /* from the officel unicode book (The Unicode Standard, */
225*cdf0e10cSrcweir                 /* Version 2.0) and so I think, that someone of the */
226*cdf0e10cSrcweir                 /* world has used this feature. */
227*cdf0e10cSrcweir                 if ( !bEnd )
228*cdf0e10cSrcweir                 {
229*cdf0e10cSrcweir                     if ( (c == IMPL_SHIFT_IN_CHAR) || (c == IMPL_SHIFT_OUT_CHAR) )
230*cdf0e10cSrcweir                     {
231*cdf0e10cSrcweir                         /* If no base64 character, and the terminating */
232*cdf0e10cSrcweir                         /* character of the shift sequence was the */
233*cdf0e10cSrcweir                         /* SHIFT_OUT_CHAR, then it't a special escape */
234*cdf0e10cSrcweir                         /* for SHIFT_IN_CHAR. */
235*cdf0e10cSrcweir                         if ( bFirst && (c == IMPL_SHIFT_OUT_CHAR) )
236*cdf0e10cSrcweir                         {
237*cdf0e10cSrcweir                             if ( pDestBuf >= pEndDestBuf )
238*cdf0e10cSrcweir                             {
239*cdf0e10cSrcweir                                 *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
240*cdf0e10cSrcweir                                 break;
241*cdf0e10cSrcweir                             }
242*cdf0e10cSrcweir                             *pDestBuf = IMPL_SHIFT_IN_CHAR;
243*cdf0e10cSrcweir                             pDestBuf++;
244*cdf0e10cSrcweir                             bWroteOne = sal_True;
245*cdf0e10cSrcweir                         }
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir                         /* Skip character */
248*cdf0e10cSrcweir                         pSrcBuf++;
249*cdf0e10cSrcweir                         if ( pSrcBuf < pEndSrcBuf )
250*cdf0e10cSrcweir                             c = (sal_uChar)*pSrcBuf;
251*cdf0e10cSrcweir                         else
252*cdf0e10cSrcweir                             bEnd = sal_True;
253*cdf0e10cSrcweir                     }
254*cdf0e10cSrcweir                 }
255*cdf0e10cSrcweir 
256*cdf0e10cSrcweir                 /* Empty sequence not allowed, so when we don't write one */
257*cdf0e10cSrcweir                 /* valid char, then the sequence is corrupt */
258*cdf0e10cSrcweir                 if ( !bWroteOne )
259*cdf0e10cSrcweir                 {
260*cdf0e10cSrcweir                     /* When no more bytes in the source buffer, then */
261*cdf0e10cSrcweir                     /* this buffer may be to small */
262*cdf0e10cSrcweir                     if ( bEnd )
263*cdf0e10cSrcweir                         *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR | RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL;
264*cdf0e10cSrcweir                     else
265*cdf0e10cSrcweir                     {
266*cdf0e10cSrcweir                         *pInfo |= RTL_TEXTTOUNICODE_INFO_INVALID;
267*cdf0e10cSrcweir                         if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_INVALID_MASK) == RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR )
268*cdf0e10cSrcweir                         {
269*cdf0e10cSrcweir                             *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR;
270*cdf0e10cSrcweir                             break;
271*cdf0e10cSrcweir                         }
272*cdf0e10cSrcweir                         /* We insert here no default char, because I think */
273*cdf0e10cSrcweir                         /* this is better to ignore this */
274*cdf0e10cSrcweir                     }
275*cdf0e10cSrcweir                 }
276*cdf0e10cSrcweir             }
277*cdf0e10cSrcweir             else
278*cdf0e10cSrcweir             {
279*cdf0e10cSrcweir                 /* Add 6 Bits from character to the bit buffer */
280*cdf0e10cSrcweir                 nBufferBits += 6;
281*cdf0e10cSrcweir                 nBitBuffer |= ((sal_uInt32)(nBase64Value & 0x3F)) << (32-nBufferBits);
282*cdf0e10cSrcweir                 bFirst = sal_False;
283*cdf0e10cSrcweir             }
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir             /* Extract as many full 16 bit characters as possible from the */
286*cdf0e10cSrcweir             /* bit buffer. */
287*cdf0e10cSrcweir             while ( (pDestBuf < pEndDestBuf) && (nBufferBits >= 16) )
288*cdf0e10cSrcweir             {
289*cdf0e10cSrcweir                 nBitBufferTemp = nBitBuffer >> (32-16);
290*cdf0e10cSrcweir                 *pDestBuf = (sal_Unicode)((nBitBufferTemp) & 0xFFFF);
291*cdf0e10cSrcweir                 pDestBuf++;
292*cdf0e10cSrcweir                 nBitBuffer <<= 16;
293*cdf0e10cSrcweir                 nBufferBits -= 16;
294*cdf0e10cSrcweir                 bWroteOne = sal_True;
295*cdf0e10cSrcweir             }
296*cdf0e10cSrcweir 
297*cdf0e10cSrcweir             if ( nBufferBits >= 16 )
298*cdf0e10cSrcweir             {
299*cdf0e10cSrcweir                 *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
300*cdf0e10cSrcweir                 break;
301*cdf0e10cSrcweir             }
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir             if ( bBase64End )
304*cdf0e10cSrcweir             {
305*cdf0e10cSrcweir                 /* Sequence ended and we have some bits, then the */
306*cdf0e10cSrcweir                 /* sequence is corrupted */
307*cdf0e10cSrcweir                 if ( nBufferBits && nBitBuffer )
308*cdf0e10cSrcweir                 {
309*cdf0e10cSrcweir                     /* When no more bytes in the source buffer, then */
310*cdf0e10cSrcweir                     /* this buffer may be to small */
311*cdf0e10cSrcweir                     if ( bEnd )
312*cdf0e10cSrcweir                         *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR | RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL;
313*cdf0e10cSrcweir                     else
314*cdf0e10cSrcweir                     {
315*cdf0e10cSrcweir                         *pInfo |= RTL_TEXTTOUNICODE_INFO_INVALID;
316*cdf0e10cSrcweir                         if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_INVALID_MASK) == RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR )
317*cdf0e10cSrcweir                         {
318*cdf0e10cSrcweir                             *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR;
319*cdf0e10cSrcweir                             break;
320*cdf0e10cSrcweir                         }
321*cdf0e10cSrcweir                         else if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_INVALID_MASK) != RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE )
322*cdf0e10cSrcweir                         {
323*cdf0e10cSrcweir                             if ( pDestBuf >= pEndDestBuf )
324*cdf0e10cSrcweir                             {
325*cdf0e10cSrcweir                                 *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
326*cdf0e10cSrcweir                                 break;
327*cdf0e10cSrcweir                             }
328*cdf0e10cSrcweir                             *pDestBuf++
329*cdf0e10cSrcweir                                 = RTL_TEXTENC_UNICODE_REPLACEMENT_CHARACTER;
330*cdf0e10cSrcweir                         }
331*cdf0e10cSrcweir                     }
332*cdf0e10cSrcweir 
333*cdf0e10cSrcweir                 }
334*cdf0e10cSrcweir 
335*cdf0e10cSrcweir                 nBitBuffer = 0;
336*cdf0e10cSrcweir                 nBufferBits = 0;
337*cdf0e10cSrcweir             }
338*cdf0e10cSrcweir         }
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir         if ( !bEnd )
341*cdf0e10cSrcweir         {
342*cdf0e10cSrcweir             if ( !bShifted )
343*cdf0e10cSrcweir             {
344*cdf0e10cSrcweir                 if ( c == IMPL_SHIFT_IN_CHAR )
345*cdf0e10cSrcweir                 {
346*cdf0e10cSrcweir                     bShifted    = sal_True;
347*cdf0e10cSrcweir                     bFirst      = sal_True;
348*cdf0e10cSrcweir                     bWroteOne   = sal_False;
349*cdf0e10cSrcweir                 }
350*cdf0e10cSrcweir                 else
351*cdf0e10cSrcweir                 {
352*cdf0e10cSrcweir                     /* No direct encoded charcater, then the buffer is */
353*cdf0e10cSrcweir                     /* corrupt */
354*cdf0e10cSrcweir                     if ( c > 0x7F )
355*cdf0e10cSrcweir                     {
356*cdf0e10cSrcweir                         *pInfo |= RTL_TEXTTOUNICODE_INFO_INVALID;
357*cdf0e10cSrcweir                         if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_INVALID_MASK) == RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR )
358*cdf0e10cSrcweir                         {
359*cdf0e10cSrcweir                             *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR;
360*cdf0e10cSrcweir                             break;
361*cdf0e10cSrcweir                         }
362*cdf0e10cSrcweir                         else if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_INVALID_MASK) != RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE )
363*cdf0e10cSrcweir                         {
364*cdf0e10cSrcweir                             if ( pDestBuf >= pEndDestBuf )
365*cdf0e10cSrcweir                             {
366*cdf0e10cSrcweir                                 *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
367*cdf0e10cSrcweir                                 break;
368*cdf0e10cSrcweir                             }
369*cdf0e10cSrcweir                             *pDestBuf++
370*cdf0e10cSrcweir                                 = RTL_TEXTENC_UNICODE_REPLACEMENT_CHARACTER;
371*cdf0e10cSrcweir                         }
372*cdf0e10cSrcweir                     }
373*cdf0e10cSrcweir 
374*cdf0e10cSrcweir                     /* Write char to unicode buffer */
375*cdf0e10cSrcweir                     if ( pDestBuf >= pEndDestBuf )
376*cdf0e10cSrcweir                     {
377*cdf0e10cSrcweir                         *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
378*cdf0e10cSrcweir                         break;
379*cdf0e10cSrcweir                     }
380*cdf0e10cSrcweir                     *pDestBuf = c;
381*cdf0e10cSrcweir                     pDestBuf++;
382*cdf0e10cSrcweir                 }
383*cdf0e10cSrcweir             }
384*cdf0e10cSrcweir 
385*cdf0e10cSrcweir             pSrcBuf++;
386*cdf0e10cSrcweir         }
387*cdf0e10cSrcweir     }
388*cdf0e10cSrcweir     while ( !bEnd );
389*cdf0e10cSrcweir 
390*cdf0e10cSrcweir     if ( pContextData )
391*cdf0e10cSrcweir     {
392*cdf0e10cSrcweir         pContextData->mbShifted         = bShifted;
393*cdf0e10cSrcweir         pContextData->mbFirst           = bFirst;
394*cdf0e10cSrcweir         pContextData->mbWroteOne        = bWroteOne;
395*cdf0e10cSrcweir         pContextData->mnBitBuffer       = nBitBuffer;
396*cdf0e10cSrcweir         pContextData->mnBufferBits      = nBufferBits;
397*cdf0e10cSrcweir     }
398*cdf0e10cSrcweir 
399*cdf0e10cSrcweir     *pSrcCvtBytes = nSrcBytes - (pEndSrcBuf-pSrcBuf);
400*cdf0e10cSrcweir     return (nDestChars - (pEndDestBuf-pDestBuf));
401*cdf0e10cSrcweir }
402*cdf0e10cSrcweir 
403*cdf0e10cSrcweir /* ======================================================================= */
404*cdf0e10cSrcweir 
405*cdf0e10cSrcweir typedef struct
406*cdf0e10cSrcweir {
407*cdf0e10cSrcweir     int                     mbShifted;
408*cdf0e10cSrcweir     sal_uInt32              mnBitBuffer;
409*cdf0e10cSrcweir     sal_uInt32              mnBufferBits;
410*cdf0e10cSrcweir } ImplUTF7FromUCContextData;
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir /* ----------------------------------------------------------------------- */
413*cdf0e10cSrcweir 
414*cdf0e10cSrcweir void* ImplUTF7CreateUnicodeToTextContext( void )
415*cdf0e10cSrcweir {
416*cdf0e10cSrcweir     ImplUTF7FromUCContextData* pContextData;
417*cdf0e10cSrcweir     pContextData = (ImplUTF7FromUCContextData*)rtl_allocateMemory( sizeof( ImplUTF7FromUCContextData ) );
418*cdf0e10cSrcweir     pContextData->mbShifted         = sal_False;
419*cdf0e10cSrcweir     pContextData->mnBitBuffer       = 0;
420*cdf0e10cSrcweir     pContextData->mnBufferBits      = 0;
421*cdf0e10cSrcweir     return (void*)pContextData;
422*cdf0e10cSrcweir }
423*cdf0e10cSrcweir 
424*cdf0e10cSrcweir /* ----------------------------------------------------------------------- */
425*cdf0e10cSrcweir 
426*cdf0e10cSrcweir void ImplUTF7DestroyUnicodeToTextContext( void* pContext )
427*cdf0e10cSrcweir {
428*cdf0e10cSrcweir     rtl_freeMemory( pContext );
429*cdf0e10cSrcweir }
430*cdf0e10cSrcweir 
431*cdf0e10cSrcweir /* ----------------------------------------------------------------------- */
432*cdf0e10cSrcweir 
433*cdf0e10cSrcweir void ImplUTF7ResetUnicodeToTextContext( void* pContext )
434*cdf0e10cSrcweir {
435*cdf0e10cSrcweir     ImplUTF7FromUCContextData* pContextData = (ImplUTF7FromUCContextData*)pContext;
436*cdf0e10cSrcweir     pContextData->mbShifted         = sal_False;
437*cdf0e10cSrcweir     pContextData->mnBitBuffer       = 0;
438*cdf0e10cSrcweir     pContextData->mnBufferBits      = 0;
439*cdf0e10cSrcweir }
440*cdf0e10cSrcweir 
441*cdf0e10cSrcweir /* ----------------------------------------------------------------------- */
442*cdf0e10cSrcweir 
443*cdf0e10cSrcweir sal_Size ImplUnicodeToUTF7( const ImplTextConverterData* pData, void* pContext,
444*cdf0e10cSrcweir                             const sal_Unicode* pSrcBuf, sal_Size nSrcChars,
445*cdf0e10cSrcweir                             sal_Char* pDestBuf, sal_Size nDestBytes,
446*cdf0e10cSrcweir                             sal_uInt32 nFlags, sal_uInt32* pInfo,
447*cdf0e10cSrcweir                             sal_Size* pSrcCvtChars )
448*cdf0e10cSrcweir {
449*cdf0e10cSrcweir     ImplUTF7FromUCContextData*  pContextData = (ImplUTF7FromUCContextData*)pContext;
450*cdf0e10cSrcweir     sal_Unicode                 c = '\0';
451*cdf0e10cSrcweir     int                         bEnd = sal_False;
452*cdf0e10cSrcweir     int                         bShifted;
453*cdf0e10cSrcweir     int                         bNeedShift;
454*cdf0e10cSrcweir     sal_uInt32                  nBitBuffer;
455*cdf0e10cSrcweir     sal_uInt32                  nBitBufferTemp;
456*cdf0e10cSrcweir     sal_uInt32                  nBufferBits;
457*cdf0e10cSrcweir     sal_Char*                   pEndDestBuf;
458*cdf0e10cSrcweir     const sal_Unicode*          pEndSrcBuf;
459*cdf0e10cSrcweir 
460*cdf0e10cSrcweir     (void) pData; /* unused */
461*cdf0e10cSrcweir     (void) nFlags; /* unused */
462*cdf0e10cSrcweir 
463*cdf0e10cSrcweir /* !!! Implementation not finnished !!!
464*cdf0e10cSrcweir     if ( pContextData )
465*cdf0e10cSrcweir     {
466*cdf0e10cSrcweir         bShifted        = pContextData->mbShifted;
467*cdf0e10cSrcweir         nBitBuffer      = pContextData->mnBitBuffer;
468*cdf0e10cSrcweir         nBufferBits     = pContextData->mnBufferBits;
469*cdf0e10cSrcweir     }
470*cdf0e10cSrcweir     else
471*cdf0e10cSrcweir */
472*cdf0e10cSrcweir     {
473*cdf0e10cSrcweir         bShifted        = sal_False;
474*cdf0e10cSrcweir         nBitBuffer      = 0;
475*cdf0e10cSrcweir         nBufferBits     = 0;
476*cdf0e10cSrcweir     }
477*cdf0e10cSrcweir 
478*cdf0e10cSrcweir     *pInfo = 0;
479*cdf0e10cSrcweir     pEndDestBuf = pDestBuf+nDestBytes;
480*cdf0e10cSrcweir     pEndSrcBuf  = pSrcBuf+nSrcChars;
481*cdf0e10cSrcweir     do
482*cdf0e10cSrcweir     {
483*cdf0e10cSrcweir         if ( pSrcBuf < pEndSrcBuf )
484*cdf0e10cSrcweir         {
485*cdf0e10cSrcweir             c = *pSrcBuf;
486*cdf0e10cSrcweir 
487*cdf0e10cSrcweir             bNeedShift = (c > 0x7F) || aImplMustShiftTab[c];
488*cdf0e10cSrcweir             if ( bNeedShift && !bShifted )
489*cdf0e10cSrcweir             {
490*cdf0e10cSrcweir                 if ( pDestBuf >= pEndDestBuf )
491*cdf0e10cSrcweir                 {
492*cdf0e10cSrcweir                     *pInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
493*cdf0e10cSrcweir                     break;
494*cdf0e10cSrcweir                 }
495*cdf0e10cSrcweir                 *pDestBuf = IMPL_SHIFT_IN_CHAR;
496*cdf0e10cSrcweir                 pDestBuf++;
497*cdf0e10cSrcweir                 /* Special case handling for SHIFT_IN_CHAR */
498*cdf0e10cSrcweir                 if ( c == IMPL_SHIFT_IN_CHAR )
499*cdf0e10cSrcweir                 {
500*cdf0e10cSrcweir                     if ( pDestBuf >= pEndDestBuf )
501*cdf0e10cSrcweir                     {
502*cdf0e10cSrcweir                         *pInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
503*cdf0e10cSrcweir                         break;
504*cdf0e10cSrcweir                     }
505*cdf0e10cSrcweir                     *pDestBuf = IMPL_SHIFT_OUT_CHAR;
506*cdf0e10cSrcweir                     pDestBuf++;
507*cdf0e10cSrcweir                 }
508*cdf0e10cSrcweir                 else
509*cdf0e10cSrcweir                     bShifted = sal_True;
510*cdf0e10cSrcweir             }
511*cdf0e10cSrcweir         }
512*cdf0e10cSrcweir         else
513*cdf0e10cSrcweir         {
514*cdf0e10cSrcweir             bEnd = sal_True;
515*cdf0e10cSrcweir             bNeedShift = sal_False;
516*cdf0e10cSrcweir         }
517*cdf0e10cSrcweir 
518*cdf0e10cSrcweir         if ( bShifted )
519*cdf0e10cSrcweir         {
520*cdf0e10cSrcweir             /* Write the character to the bit buffer, or pad the bit */
521*cdf0e10cSrcweir             /* buffer out to a full base64 character */
522*cdf0e10cSrcweir             if ( bNeedShift )
523*cdf0e10cSrcweir             {
524*cdf0e10cSrcweir                 nBufferBits += 16;
525*cdf0e10cSrcweir                 nBitBuffer |= ((sal_uInt32)c) << (32-nBufferBits);
526*cdf0e10cSrcweir             }
527*cdf0e10cSrcweir             else
528*cdf0e10cSrcweir                 nBufferBits += (6-(nBufferBits%6))%6;
529*cdf0e10cSrcweir 
530*cdf0e10cSrcweir             /* Flush out as many full base64 characters as possible */
531*cdf0e10cSrcweir             while ( (pDestBuf < pEndDestBuf) && (nBufferBits >= 6) )
532*cdf0e10cSrcweir             {
533*cdf0e10cSrcweir                 nBitBufferTemp = nBitBuffer >> (32-6);
534*cdf0e10cSrcweir                 *pDestBuf = aImplBase64Tab[nBitBufferTemp];
535*cdf0e10cSrcweir                 pDestBuf++;
536*cdf0e10cSrcweir                 nBitBuffer <<= 6;
537*cdf0e10cSrcweir                 nBufferBits -= 6;
538*cdf0e10cSrcweir             }
539*cdf0e10cSrcweir 
540*cdf0e10cSrcweir             if ( nBufferBits >= 6 )
541*cdf0e10cSrcweir             {
542*cdf0e10cSrcweir                 *pInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
543*cdf0e10cSrcweir                 break;
544*cdf0e10cSrcweir             }
545*cdf0e10cSrcweir 
546*cdf0e10cSrcweir             /* Write SHIFT_OUT_CHAR, when needed */
547*cdf0e10cSrcweir             if ( !bNeedShift )
548*cdf0e10cSrcweir             {
549*cdf0e10cSrcweir                 if ( pDestBuf >= pEndDestBuf )
550*cdf0e10cSrcweir                 {
551*cdf0e10cSrcweir                     *pInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
552*cdf0e10cSrcweir                     break;
553*cdf0e10cSrcweir                 }
554*cdf0e10cSrcweir                 *pDestBuf = IMPL_SHIFT_OUT_CHAR;
555*cdf0e10cSrcweir                 pDestBuf++;
556*cdf0e10cSrcweir                 bShifted = sal_False;
557*cdf0e10cSrcweir             }
558*cdf0e10cSrcweir         }
559*cdf0e10cSrcweir 
560*cdf0e10cSrcweir         if ( !bEnd )
561*cdf0e10cSrcweir         {
562*cdf0e10cSrcweir             /* Character can be directly endcoded */
563*cdf0e10cSrcweir             if ( !bNeedShift )
564*cdf0e10cSrcweir             {
565*cdf0e10cSrcweir                 if ( pDestBuf >= pEndDestBuf )
566*cdf0e10cSrcweir                 {
567*cdf0e10cSrcweir                     *pInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
568*cdf0e10cSrcweir                     break;
569*cdf0e10cSrcweir                 }
570*cdf0e10cSrcweir                 *pDestBuf = (sal_Char)(sal_uChar)c;
571*cdf0e10cSrcweir                 pDestBuf++;
572*cdf0e10cSrcweir             }
573*cdf0e10cSrcweir 
574*cdf0e10cSrcweir             pSrcBuf++;
575*cdf0e10cSrcweir         }
576*cdf0e10cSrcweir     }
577*cdf0e10cSrcweir     while ( !bEnd );
578*cdf0e10cSrcweir 
579*cdf0e10cSrcweir     if ( pContextData )
580*cdf0e10cSrcweir     {
581*cdf0e10cSrcweir         pContextData->mbShifted     = bShifted;
582*cdf0e10cSrcweir         pContextData->mnBitBuffer   = nBitBuffer;
583*cdf0e10cSrcweir         pContextData->mnBufferBits  = nBufferBits;
584*cdf0e10cSrcweir     }
585*cdf0e10cSrcweir 
586*cdf0e10cSrcweir     *pSrcCvtChars = nSrcChars - (pEndSrcBuf-pSrcBuf);
587*cdf0e10cSrcweir     return (nDestBytes - (pEndDestBuf-pDestBuf));
588*cdf0e10cSrcweir }
589