LCOV - code coverage report
Current view: directory - intl/uconv/ucvlatin - nsUnicodeToUTF7.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 173 150 86.7 %
Date: 2012-06-02 Functions: 11 10 90.9 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #include "nsUnicodeToUTF7.h"
      39                 : #include <string.h>
      40                 : 
      41                 : //----------------------------------------------------------------------
      42                 : // Global functions and data [declaration]
      43                 : 
      44                 : #define ENC_DIRECT      0
      45                 : #define ENC_BASE64      1
      46                 : 
      47                 : //----------------------------------------------------------------------
      48                 : // Class nsBasicUTF7Encoder [implementation]
      49                 : 
      50              27 : nsBasicUTF7Encoder::nsBasicUTF7Encoder(char aLastChar, char aEscChar) 
      51              27 : : nsEncoderSupport(5)
      52                 : {
      53              27 :   mLastChar = aLastChar;
      54              27 :   mEscChar = aEscChar;
      55              27 :   Reset();
      56              27 : }
      57                 : 
      58             120 : nsresult nsBasicUTF7Encoder::ShiftEncoding(PRInt32 aEncoding,
      59                 :                                           char * aDest, 
      60                 :                                           PRInt32 * aDestLength)
      61                 : {
      62             120 :   if (aEncoding == mEncoding) {
      63              12 :     *aDestLength = 0;
      64              12 :     return NS_OK;
      65                 :   } 
      66                 : 
      67             108 :   nsresult res = NS_OK;
      68             108 :   char * dest = aDest;
      69             108 :   char * destEnd = aDest + *aDestLength;
      70                 : 
      71             108 :   if (mEncStep != 0) {
      72              36 :     if (dest >= destEnd) return NS_OK_UENC_MOREOUTPUT;
      73              36 :     *(dest++)=ValueToChar(mEncBits);
      74              36 :     mEncStep = 0;
      75              36 :     mEncBits = 0;
      76                 :   }
      77                 : 
      78             108 :   if (dest >= destEnd) {
      79               0 :     res = NS_OK_UENC_MOREOUTPUT;
      80                 :   } else {
      81             108 :     switch (aEncoding) {
      82                 :       case 0:
      83              54 :         *(dest++) = '-';
      84              54 :         mEncStep = 0;
      85              54 :         mEncBits = 0;
      86              54 :         break;
      87                 :       case 1:
      88              54 :         *(dest++) = mEscChar;
      89              54 :         break;
      90                 :     }
      91             108 :     mEncoding = aEncoding;
      92                 :   }
      93                 : 
      94             108 :   *aDestLength  = dest - aDest;
      95             108 :   return res;
      96                 : }
      97                 : 
      98              54 : nsresult nsBasicUTF7Encoder::EncodeDirect(
      99                 :                             const PRUnichar * aSrc, 
     100                 :                             PRInt32 * aSrcLength, 
     101                 :                             char * aDest, 
     102                 :                             PRInt32 * aDestLength)
     103                 : {
     104              54 :   nsresult res = NS_OK;
     105              54 :   const PRUnichar * src = aSrc;
     106              54 :   const PRUnichar * srcEnd = aSrc + *aSrcLength;
     107              54 :   char * dest = aDest;
     108              54 :   char * destEnd = aDest + *aDestLength;
     109                 :   PRUnichar ch;
     110                 : 
     111             222 :   while (src < srcEnd) {
     112             162 :     ch = *src;
     113                 : 
     114                 :     // stop when we reach Unicode chars
     115             162 :     if (!DirectEncodable(ch)) break;
     116                 : 
     117             114 :     if (ch == mEscChar) {
     118                 :       // special case for the escape char
     119               0 :       if (destEnd - dest < 1) {
     120               0 :         res = NS_OK_UENC_MOREOUTPUT;
     121               0 :         break;
     122                 :       } else {
     123               0 :         *dest++ = (char)ch;
     124               0 :         *dest++ = (char)'-';
     125               0 :         src++;
     126                 :       }
     127                 :     } else {
     128                 :       //classic direct encoding
     129             114 :       if (dest >= destEnd) {
     130               0 :         res = NS_OK_UENC_MOREOUTPUT;
     131               0 :         break;
     132                 :       } else {
     133             114 :         *dest++ = (char)ch;
     134             114 :         src++;
     135                 :       }
     136                 :     }
     137                 :   }
     138                 : 
     139              54 :   *aSrcLength = src - aSrc;
     140              54 :   *aDestLength  = dest - aDest;
     141              54 :   return res;
     142                 : }
     143                 : 
     144              54 : nsresult nsBasicUTF7Encoder::EncodeBase64(
     145                 :                              const PRUnichar * aSrc, 
     146                 :                              PRInt32 * aSrcLength, 
     147                 :                              char * aDest, 
     148                 :                              PRInt32 * aDestLength)
     149                 : {
     150              54 :   nsresult res = NS_OK;
     151              54 :   const PRUnichar * src = aSrc;
     152              54 :   const PRUnichar * srcEnd = aSrc + *aSrcLength;
     153              54 :   char * dest = aDest;
     154              54 :   char * destEnd = aDest + *aDestLength;
     155                 :   PRUnichar ch;
     156                 :   PRUint32 value;
     157                 : 
     158             216 :   while (src < srcEnd) {
     159             162 :     ch = *src;
     160                 : 
     161                 :     // stop when we reach printable US-ASCII chars
     162             162 :     if (DirectEncodable(ch)) break;
     163                 : 
     164             108 :     switch (mEncStep) {
     165                 :       case 0:
     166              54 :         if (destEnd - dest < 2) {
     167               0 :           res = NS_OK_UENC_MOREOUTPUT;
     168               0 :           break;
     169                 :         }
     170              54 :         value=ch>>10;
     171              54 :         *(dest++)=ValueToChar(value);
     172              54 :         value=(ch>>4)&0x3f;
     173              54 :         *(dest++)=ValueToChar(value);
     174              54 :         mEncBits=(ch&0x0f)<<2;
     175              54 :         break;
     176                 :       case 1:
     177              36 :         if (destEnd - dest < 3) {
     178               0 :           res = NS_OK_UENC_MOREOUTPUT;
     179               0 :           break;
     180                 :         }
     181              36 :         value=mEncBits+(ch>>14);
     182              36 :         *(dest++)=ValueToChar(value);
     183              36 :         value=(ch>>8)&0x3f;
     184              36 :         *(dest++)=ValueToChar(value);
     185              36 :         value=(ch>>2)&0x3f;
     186              36 :         *(dest++)=ValueToChar(value);
     187              36 :         mEncBits=(ch&0x03)<<4;
     188              36 :         break;
     189                 :       case 2:
     190              18 :         if (destEnd - dest < 3) {
     191               0 :           res = NS_OK_UENC_MOREOUTPUT;
     192               0 :           break;
     193                 :         }
     194              18 :         value=mEncBits+(ch>>12);
     195              18 :         *(dest++)=ValueToChar(value);
     196              18 :         value=(ch>>6)&0x3f;
     197              18 :         *(dest++)=ValueToChar(value);
     198              18 :         value=ch&0x3f;
     199              18 :         *(dest++)=ValueToChar(value);
     200              18 :         mEncBits=0;
     201              18 :         break;
     202                 :     }
     203                 : 
     204             108 :     if (res != NS_OK) break;
     205                 : 
     206             108 :     src++;
     207             108 :     (++mEncStep)%=3;
     208                 :   }
     209                 : 
     210              54 :   *aSrcLength = src - aSrc;
     211              54 :   *aDestLength  = dest - aDest;
     212              54 :   return res;
     213                 : }
     214                 : 
     215             306 : char nsBasicUTF7Encoder::ValueToChar(PRUint32 aValue) { 
     216             306 :   if (aValue < 26) 
     217             204 :     return (char)('A'+aValue);
     218             102 :   else if (aValue < 26 + 26) 
     219              72 :     return (char)('a' + aValue - 26);
     220              30 :   else if (aValue < 26 + 26 + 10)
     221              30 :     return (char)('0' + aValue - 26 - 26);
     222               0 :   else if (aValue == 26 + 26 + 10)
     223               0 :     return '+';
     224               0 :   else if (aValue == 26 + 26 + 10 + 1)
     225               0 :     return mLastChar;
     226                 :   else
     227               0 :     return -1;
     228                 : }
     229                 : 
     230               0 : bool nsBasicUTF7Encoder::DirectEncodable(PRUnichar aChar) {
     231                 :   // spec says: printable US-ASCII chars
     232               0 :   if ((aChar >= 0x20) && (aChar <= 0x7e)) return true;
     233               0 :   else return false;
     234                 : }
     235                 : 
     236                 : //----------------------------------------------------------------------
     237                 : // Subclassing of nsEncoderSupport class [implementation]
     238                 : 
     239               6 : NS_IMETHODIMP nsBasicUTF7Encoder::ConvertNoBuffNoErr(
     240                 :                                   const PRUnichar * aSrc, 
     241                 :                                   PRInt32 * aSrcLength, 
     242                 :                                   char * aDest, 
     243                 :                                   PRInt32 * aDestLength)
     244                 : {
     245               6 :   nsresult res = NS_OK;
     246               6 :   const PRUnichar * src = aSrc;
     247               6 :   const PRUnichar * srcEnd = aSrc + *aSrcLength;
     248               6 :   char * dest = aDest;
     249               6 :   char * destEnd = aDest + *aDestLength;
     250                 :   PRInt32 bcr,bcw;
     251                 :   PRUnichar ch;
     252                 :   PRInt32 enc;
     253                 : 
     254             120 :   while (src < srcEnd) {
     255                 :     // find the encoding for the next char
     256             108 :     ch = *src;
     257             108 :     if (DirectEncodable(ch)) 
     258              54 :       enc = ENC_DIRECT;
     259                 :     else
     260              54 :       enc = ENC_BASE64;
     261                 : 
     262                 :     // if necessary, shift into the required encoding
     263             108 :     bcw = destEnd - dest;
     264             108 :     res = ShiftEncoding(enc, dest, &bcw);
     265             108 :     dest += bcw;
     266             108 :     if (res != NS_OK) break;
     267                 : 
     268                 :     // now encode (as much as you can)
     269             108 :     bcr = srcEnd - src;
     270             108 :     bcw = destEnd - dest;
     271             108 :     if (enc == ENC_DIRECT) 
     272              54 :       res = EncodeDirect(src, &bcr, dest, &bcw);
     273                 :     else 
     274              54 :       res = EncodeBase64(src, &bcr, dest, &bcw);
     275             108 :     src += bcr;
     276             108 :     dest += bcw;
     277                 : 
     278             108 :     if (res != NS_OK) break;
     279                 :   }
     280                 : 
     281               6 :   *aSrcLength = src - aSrc;
     282               6 :   *aDestLength  = dest - aDest;
     283               6 :   return res;
     284                 : }
     285                 : 
     286              12 : NS_IMETHODIMP nsBasicUTF7Encoder::FinishNoBuff(char * aDest, 
     287                 :                                                PRInt32 * aDestLength)
     288                 : {
     289              12 :   return ShiftEncoding(ENC_DIRECT, aDest, aDestLength);
     290                 : }
     291                 : 
     292              27 : NS_IMETHODIMP nsBasicUTF7Encoder::Reset()
     293                 : {
     294              27 :   mEncoding = ENC_DIRECT;
     295              27 :   mEncBits = 0;
     296              27 :   mEncStep = 0;
     297              27 :   return nsEncoderSupport::Reset();
     298                 : }
     299                 : 
     300                 : //----------------------------------------------------------------------
     301                 : // Class nsUnicodeToUTF7 [implementation]
     302                 : 
     303              26 : nsUnicodeToUTF7::nsUnicodeToUTF7() 
     304              26 : : nsBasicUTF7Encoder('/', '+')
     305                 : {
     306              26 : }
     307                 : 
     308                 : 
     309             432 : bool nsUnicodeToUTF7::DirectEncodable(PRUnichar aChar) {
     310             432 :   if ((aChar >= 'A') && (aChar <= 'Z')) return true;
     311             414 :   else if ((aChar >= 'a') && (aChar <= 'z')) return true;
     312             342 :   else if ((aChar >= '0') && (aChar <= '9')) return true;
     313             342 :   else if ((aChar >= 39) && (aChar <= 41)) return true;
     314             342 :   else if ((aChar >= 44) && (aChar <= 47)) return true;
     315             324 :   else if (aChar == 58) return true;
     316             324 :   else if (aChar == 63) return true;
     317             324 :   else if (aChar == ' ') return true;
     318             210 :   else if (aChar == 9) return true;
     319             210 :   else if (aChar == 13) return true;
     320             210 :   else if (aChar == 10) return true;
     321             210 :   else if (aChar == 60) return true;  // '<'
     322             210 :   else if (aChar == 33) return true;  // '!'
     323             210 :   else if (aChar == 34) return true;  // '"'
     324             210 :   else if (aChar == 62) return true;  // '>'
     325             210 :   else if (aChar == 61) return true;  // '='
     326             210 :   else if (aChar == 59) return true;  // ';'
     327             210 :   else if (aChar == 91) return true;  // '['
     328             210 :   else if (aChar == 93) return true;  // ']'
     329             210 :   else return false;
     330                 : }

Generated by: LCOV version 1.7