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