Back to index

lightning-sunbird  0.9+nobinonly
nsUCSupport.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "pratom.h"
00040 #include "nsIComponentManager.h"
00041 #include "nsICharRepresentable.h"
00042 #include "nsUCSupport.h"
00043 
00044 static NS_DEFINE_CID(kUnicodeEncodeHelperCID, NS_UNICODEENCODEHELPER_CID);
00045 static NS_DEFINE_CID(kUnicodeDecodeHelperCID, NS_UNICODEDECODEHELPER_CID);
00046 
00047 #define DEFAULT_BUFFER_CAPACITY 16
00048 
00049 // XXX review the buffer growth limitation code
00050 
00051 //----------------------------------------------------------------------
00052 // Class nsBasicDecoderSupport [implementation]
00053 
00054 nsBasicDecoderSupport::nsBasicDecoderSupport() 
00055 {
00056 }
00057 
00058 nsBasicDecoderSupport::~nsBasicDecoderSupport() 
00059 {
00060 }
00061 
00062 //----------------------------------------------------------------------
00063 // Interface nsISupports [implementation]
00064 
00065 NS_IMPL_ADDREF(nsBasicDecoderSupport)
00066 NS_IMPL_RELEASE(nsBasicDecoderSupport)
00067 #ifdef NS_DEBUG
00068 NS_IMPL_QUERY_INTERFACE2(nsBasicDecoderSupport, nsIUnicodeDecoder, nsIBasicDecoder)
00069 #else
00070 NS_IMPL_QUERY_INTERFACE1(nsBasicDecoderSupport, nsIUnicodeDecoder)
00071 #endif
00072 
00073 //----------------------------------------------------------------------
00074 // Interface nsIUnicodeDecoder [implementation]
00075 
00076 //----------------------------------------------------------------------
00077 // Class nsBufferDecoderSupport [implementation]
00078 
00079 nsBufferDecoderSupport::nsBufferDecoderSupport(PRUint32 aMaxLengthFactor) 
00080   : nsBasicDecoderSupport(),
00081     mMaxLengthFactor(aMaxLengthFactor)
00082 {
00083   mBufferCapacity = DEFAULT_BUFFER_CAPACITY;
00084   mBuffer = new char[mBufferCapacity];
00085 
00086   Reset();
00087 }
00088 
00089 nsBufferDecoderSupport::~nsBufferDecoderSupport() 
00090 {
00091   delete [] mBuffer;
00092 }
00093 
00094 void nsBufferDecoderSupport::FillBuffer(const char ** aSrc, PRInt32 aSrcLength)
00095 {
00096   PRInt32 bcr = PR_MIN(mBufferCapacity - mBufferLength, aSrcLength);
00097   memcpy(mBuffer + mBufferLength, *aSrc, bcr);
00098   mBufferLength += bcr;
00099   (*aSrc) += bcr;
00100 }
00101 
00102 void nsBufferDecoderSupport::DoubleBuffer()
00103 {
00104   mBufferCapacity *= 2;
00105   char * newBuffer = new char [mBufferCapacity];
00106   if (mBufferLength > 0) memcpy(newBuffer, mBuffer, mBufferLength);
00107   delete [] mBuffer;
00108   mBuffer = newBuffer;
00109 }
00110 
00111 //----------------------------------------------------------------------
00112 // Subclassing of nsBasicDecoderSupport class [implementation]
00113 
00114 NS_IMETHODIMP nsBufferDecoderSupport::Convert(const char * aSrc, 
00115                                               PRInt32 * aSrcLength,
00116                                               PRUnichar * aDest, 
00117                                               PRInt32 * aDestLength)
00118 {
00119   // we do all operations using pointers internally
00120   const char * src = aSrc;
00121   const char * srcEnd = aSrc + *aSrcLength;
00122   PRUnichar * dest = aDest;
00123   PRUnichar * destEnd = aDest + *aDestLength;
00124 
00125   PRInt32 bcr, bcw; // byte counts for read & write;
00126   nsresult res = NS_OK;
00127 
00128   // do we have some residual data from the last conversion?
00129   if (mBufferLength > 0) if (dest == destEnd) {
00130     res = NS_OK_UDEC_MOREOUTPUT;
00131   } else for (;;) {
00132     // we need new data to add to the buffer
00133     if (src == srcEnd) {
00134       res = NS_OK_UDEC_MOREINPUT;
00135       break;
00136     }
00137 
00138     // fill that buffer
00139     PRInt32 buffLen = mBufferLength;  // initial buffer length
00140     FillBuffer(&src, srcEnd - src);
00141 
00142     // convert that buffer
00143     bcr = mBufferLength;
00144     bcw = destEnd - dest;
00145     res = ConvertNoBuff(mBuffer, &bcr, dest, &bcw);
00146     dest += bcw;
00147 
00148     if ((res == NS_OK_UDEC_MOREINPUT) && (bcw == 0)) {
00149         res = NS_ERROR_UNEXPECTED;
00150 #if defined(DEBUG_yokoyama) || defined(DEBUG_ftang)
00151         NS_ASSERTION(0, "This should not happen. Internal buffer may be corrupted.");
00152 #endif
00153         break;
00154     } else {
00155       if (bcr < buffLen) {
00156         // we didn't convert that residual data - unfill the buffer
00157         src -= mBufferLength - buffLen;
00158         mBufferLength = buffLen;
00159 #if defined(DEBUG_yokoyama) || defined(DEBUG_ftang)
00160         NS_ASSERTION(0, "This should not happen. Internal buffer may be corrupted.");
00161 #endif
00162       } else {
00163         // the buffer and some extra data was converted - unget the rest
00164         src -= mBufferLength - bcr;
00165         mBufferLength = 0;
00166         res = NS_OK;
00167       }
00168       break;
00169     }
00170   }
00171 
00172   if (res == NS_OK) {
00173     bcr = srcEnd - src;
00174     bcw = destEnd - dest;
00175     res = ConvertNoBuff(src, &bcr, dest, &bcw);
00176     src += bcr;
00177     dest += bcw;
00178 
00179     // if we have partial input, store it in our internal buffer.
00180     if (res == NS_OK_UDEC_MOREINPUT) {
00181       bcr = srcEnd - src;
00182       // make sure buffer is large enough
00183       if (bcr > mBufferCapacity) {
00184           // somehow we got into an error state and the buffer is growing out of control
00185           res = NS_ERROR_UNEXPECTED;
00186       } else {
00187           FillBuffer(&src, bcr);
00188       }
00189     }
00190   }
00191 
00192   *aSrcLength   -= srcEnd - src;
00193   *aDestLength  -= destEnd - dest;
00194   return res;
00195 }
00196 
00197 NS_IMETHODIMP nsBufferDecoderSupport::Reset()
00198 {
00199   mBufferLength = 0;
00200   return NS_OK;
00201 }
00202 
00203 NS_IMETHODIMP nsBufferDecoderSupport::GetMaxLength(const char* aSrc,
00204                                                    PRInt32 aSrcLength,
00205                                                    PRInt32* aDestLength)
00206 {
00207   NS_ASSERTION(mMaxLengthFactor != 0, "Must override GetMaxLength!");
00208   *aDestLength = aSrcLength * mMaxLengthFactor;
00209   return NS_OK;
00210 }
00211 
00212 //----------------------------------------------------------------------
00213 // Class nsTableDecoderSupport [implementation]
00214 
00215 nsTableDecoderSupport::nsTableDecoderSupport(uShiftTable * aShiftTable, 
00216                                              uMappingTable  * aMappingTable,
00217                                              PRUint32 aMaxLengthFactor) 
00218 : nsBufferDecoderSupport(aMaxLengthFactor)
00219 {
00220   mHelper = NULL;
00221   mShiftTable = aShiftTable;
00222   mMappingTable = aMappingTable;
00223 }
00224 
00225 nsTableDecoderSupport::~nsTableDecoderSupport() 
00226 {
00227   NS_IF_RELEASE(mHelper);
00228 }
00229 
00230 //----------------------------------------------------------------------
00231 // Subclassing of nsBufferDecoderSupport class [implementation]
00232 
00233 NS_IMETHODIMP nsTableDecoderSupport::ConvertNoBuff(const char * aSrc, 
00234                                                    PRInt32 * aSrcLength, 
00235                                                    PRUnichar * aDest, 
00236                                                    PRInt32 * aDestLength)
00237 {
00238   nsresult res;
00239 
00240   if (mHelper == nsnull) {
00241     res = CallCreateInstance(kUnicodeDecodeHelperCID, &mHelper);
00242     if (NS_FAILED(res)) return NS_ERROR_UDEC_NOHELPER;
00243   }
00244 
00245   res = mHelper->ConvertByTable(aSrc, aSrcLength, aDest, aDestLength, 
00246       mShiftTable, mMappingTable);
00247   return res;
00248 }
00249 
00250 //----------------------------------------------------------------------
00251 // Class nsMultiTableDecoderSupport [implementation]
00252 
00253 nsMultiTableDecoderSupport::nsMultiTableDecoderSupport(
00254                             PRInt32 aTableCount,
00255                             const uRange * aRangeArray, 
00256                             uShiftTable ** aShiftTable, 
00257                             uMappingTable ** aMappingTable,
00258                             PRUint32 aMaxLengthFactor) 
00259 : nsBufferDecoderSupport(aMaxLengthFactor)
00260 {
00261   mHelper = NULL;
00262   mTableCount = aTableCount;
00263   mRangeArray = aRangeArray;
00264   mShiftTable = aShiftTable;
00265   mMappingTable = aMappingTable;
00266 }
00267 
00268 nsMultiTableDecoderSupport::~nsMultiTableDecoderSupport() 
00269 {
00270   NS_IF_RELEASE(mHelper);
00271 }
00272 
00273 //----------------------------------------------------------------------
00274 // Subclassing of nsBufferDecoderSupport class [implementation]
00275 
00276 NS_IMETHODIMP nsMultiTableDecoderSupport::ConvertNoBuff(const char * aSrc, 
00277                                                         PRInt32 * aSrcLength, 
00278                                                         PRUnichar * aDest, 
00279                                                         PRInt32 * aDestLength)
00280 {
00281   nsresult res;
00282 
00283   if (mHelper == nsnull) {
00284     res = CallCreateInstance(kUnicodeDecodeHelperCID, &mHelper);
00285     if (NS_FAILED(res)) return NS_ERROR_UDEC_NOHELPER;
00286   }
00287 
00288   res = mHelper->ConvertByMultiTable(aSrc, aSrcLength, aDest, aDestLength, 
00289       mTableCount, mRangeArray, mShiftTable, mMappingTable);
00290   return res;
00291 }
00292 
00293 //----------------------------------------------------------------------
00294 // Class nsOneByteDecoderSupport [implementation]
00295 
00296 nsOneByteDecoderSupport::nsOneByteDecoderSupport(
00297                          uShiftTable * aShiftTable, 
00298                          uMappingTable  * aMappingTable) 
00299 : nsBasicDecoderSupport()
00300 {
00301   mHelper = NULL;
00302   mShiftTable = aShiftTable;
00303   mMappingTable = aMappingTable;
00304 }
00305 
00306 nsOneByteDecoderSupport::~nsOneByteDecoderSupport() 
00307 {
00308   NS_IF_RELEASE(mHelper);
00309 }
00310 
00311 //----------------------------------------------------------------------
00312 // Subclassing of nsBasicDecoderSupport class [implementation]
00313 
00314 NS_IMETHODIMP nsOneByteDecoderSupport::Convert(const char * aSrc, 
00315                                               PRInt32 * aSrcLength, 
00316                                               PRUnichar * aDest, 
00317                                               PRInt32 * aDestLength)
00318 {
00319   nsresult res;
00320 
00321   if (mHelper == nsnull) {
00322     res = CallCreateInstance(kUnicodeDecodeHelperCID, &mHelper);
00323     if (NS_FAILED(res)) return NS_ERROR_UDEC_NOHELPER;
00324 
00325     res = mHelper -> CreateFastTable(mShiftTable, mMappingTable, mFastTable, 
00326         ONE_BYTE_TABLE_SIZE);
00327     if (NS_FAILED(res)) return res;
00328   }
00329 
00330   res = mHelper->ConvertByFastTable(aSrc, aSrcLength, aDest, aDestLength, 
00331       mFastTable, ONE_BYTE_TABLE_SIZE);
00332   return res;
00333 }
00334 
00335 NS_IMETHODIMP nsOneByteDecoderSupport::GetMaxLength(const char * aSrc, 
00336                                                     PRInt32 aSrcLength, 
00337                                                     PRInt32 * aDestLength)
00338 {
00339   // single byte to Unicode converter
00340   *aDestLength = aSrcLength;
00341   return NS_OK_UDEC_EXACTLENGTH;
00342 }
00343 
00344 NS_IMETHODIMP nsOneByteDecoderSupport::Reset()
00345 {
00346   // nothing to reset, no internal state in this case
00347   return NS_OK;
00348 }
00349 
00350 //----------------------------------------------------------------------
00351 // Class nsBasicEncoder [implementation]
00352 nsBasicEncoder::nsBasicEncoder() 
00353 {
00354 }
00355 
00356 nsBasicEncoder::~nsBasicEncoder() 
00357 {
00358 }
00359 
00360 //----------------------------------------------------------------------
00361 // Interface nsISupports [implementation]
00362 
00363 NS_IMPL_ADDREF(nsBasicEncoder)
00364 NS_IMPL_RELEASE(nsBasicEncoder)
00365 #ifdef NS_DEBUG
00366 NS_IMPL_QUERY_INTERFACE3(nsBasicEncoder,
00367                          nsIUnicodeEncoder,
00368                          nsICharRepresentable, nsIBasicEncoder)
00369 #else
00370 NS_IMPL_QUERY_INTERFACE2(nsBasicEncoder,
00371                          nsIUnicodeEncoder,
00372                          nsICharRepresentable)
00373 #endif
00374 //----------------------------------------------------------------------
00375 // Class nsEncoderSupport [implementation]
00376 
00377 nsEncoderSupport::nsEncoderSupport(PRUint32 aMaxLengthFactor) :
00378   mMaxLengthFactor(aMaxLengthFactor)
00379 {
00380   mBufferCapacity = DEFAULT_BUFFER_CAPACITY;
00381   mBuffer = new char[mBufferCapacity];
00382 
00383   mErrBehavior = kOnError_Signal;
00384   mErrChar = 0;
00385 
00386   Reset();
00387 }
00388 
00389 nsEncoderSupport::~nsEncoderSupport() 
00390 {
00391   delete [] mBuffer;
00392 }
00393 
00394 NS_IMETHODIMP nsEncoderSupport::ConvertNoBuff(const PRUnichar * aSrc, 
00395                                               PRInt32 * aSrcLength, 
00396                                               char * aDest, 
00397                                               PRInt32 * aDestLength)
00398 {
00399   // we do all operations using pointers internally
00400   const PRUnichar * src = aSrc;
00401   const PRUnichar * srcEnd = aSrc + *aSrcLength;
00402   char * dest = aDest;
00403   char * destEnd = aDest + *aDestLength;
00404 
00405   PRInt32 bcr, bcw; // byte counts for read & write;
00406   nsresult res;
00407 
00408   for (;;) {
00409     bcr = srcEnd - src;
00410     bcw = destEnd - dest;
00411     res = ConvertNoBuffNoErr(src, &bcr, dest, &bcw);
00412     src += bcr;
00413     dest += bcw;
00414 
00415     if (res == NS_ERROR_UENC_NOMAPPING) {
00416       if (mErrBehavior == kOnError_Replace) {
00417         const PRUnichar buff[] = {mErrChar};
00418         bcr = 1;
00419         bcw = destEnd - dest;
00420         src--; // back the input: maybe the guy won't consume consume anything.
00421         res = ConvertNoBuffNoErr(buff, &bcr, dest, &bcw);
00422         src += bcr;
00423         dest += bcw;
00424         if (res != NS_OK) break;
00425       } else if (mErrBehavior == kOnError_CallBack) {
00426         bcw = destEnd - dest;
00427         src--;
00428         res = mErrEncoder->Convert(*src, dest, &bcw);
00429         dest += bcw;
00430         // if enought output space then the last char was used
00431         if (res != NS_OK_UENC_MOREOUTPUT) src++;
00432         if (res != NS_OK) break;
00433       } else break;
00434     }
00435     else break;
00436   }
00437 
00438   *aSrcLength   -= srcEnd - src;
00439   *aDestLength  -= destEnd - dest;
00440   return res;
00441 }
00442 
00443 NS_IMETHODIMP nsEncoderSupport::FinishNoBuff(char * aDest, 
00444                                              PRInt32 * aDestLength)
00445 {
00446   *aDestLength = 0;
00447   return NS_OK;
00448 }
00449 
00450 nsresult nsEncoderSupport::FlushBuffer(char ** aDest, const char * aDestEnd)
00451 {
00452   PRInt32 bcr, bcw; // byte counts for read & write;
00453   nsresult res = NS_OK;
00454   char * dest = *aDest;
00455 
00456   if (mBufferStart < mBufferEnd) {
00457     bcr = mBufferEnd - mBufferStart;
00458     bcw = aDestEnd - dest;
00459     if (bcw < bcr) bcr = bcw;
00460     memcpy(dest, mBufferStart, bcr);
00461     dest += bcr;
00462     mBufferStart += bcr;
00463 
00464     if (mBufferStart < mBufferEnd) res = NS_OK_UENC_MOREOUTPUT;
00465   }
00466 
00467   *aDest = dest;
00468   return res;
00469 }
00470 
00471 
00472 //----------------------------------------------------------------------
00473 // Interface nsIUnicodeEncoder [implementation]
00474 
00475 NS_IMETHODIMP nsEncoderSupport::Convert(const PRUnichar * aSrc, 
00476                                         PRInt32 * aSrcLength, 
00477                                         char * aDest, 
00478                                         PRInt32 * aDestLength)
00479 {
00480   // we do all operations using pointers internally
00481   const PRUnichar * src = aSrc;
00482   const PRUnichar * srcEnd = aSrc + *aSrcLength;
00483   char * dest = aDest;
00484   char * destEnd = aDest + *aDestLength;
00485 
00486   PRInt32 bcr, bcw; // byte counts for read & write;
00487   nsresult res;
00488 
00489   res = FlushBuffer(&dest, destEnd);
00490   if (res == NS_OK_UENC_MOREOUTPUT) goto final;
00491 
00492   bcr = srcEnd - src;
00493   bcw = destEnd - dest;
00494   res = ConvertNoBuff(src, &bcr, dest, &bcw);
00495   src += bcr;
00496   dest += bcw;
00497   if ((res == NS_OK_UENC_MOREOUTPUT) && (dest < destEnd)) {
00498     // convert exactly one character into the internal buffer
00499     // at this point, there should be at least a char in the input
00500     for (;;) {
00501       bcr = 1;
00502       bcw = mBufferCapacity;
00503       res = ConvertNoBuff(src, &bcr, mBuffer, &bcw);
00504 
00505       if (res == NS_OK_UENC_MOREOUTPUT) {
00506         delete [] mBuffer;
00507         mBufferCapacity *= 2;
00508         mBuffer = new char [mBufferCapacity];
00509       } else {
00510         src += bcr;
00511         mBufferStart = mBufferEnd = mBuffer;
00512         mBufferEnd += bcw;
00513         break;
00514       }
00515     }
00516 
00517     res = FlushBuffer(&dest, destEnd);
00518   }
00519 
00520 final:
00521   *aSrcLength   -= srcEnd - src;
00522   *aDestLength  -= destEnd - dest;
00523   return res;
00524 }
00525 
00526 NS_IMETHODIMP nsEncoderSupport::Finish(char * aDest, PRInt32 * aDestLength)
00527 {
00528   // we do all operations using pointers internally
00529   char * dest = aDest;
00530   char * destEnd = aDest + *aDestLength;
00531 
00532   PRInt32 bcw; // byte count for write;
00533   nsresult res;
00534 
00535   res = FlushBuffer(&dest, destEnd);
00536   if (res == NS_OK_UENC_MOREOUTPUT) goto final;
00537 
00538   // do the finish into the internal buffer.
00539   for (;;) {
00540     bcw = mBufferCapacity;
00541     res = FinishNoBuff(mBuffer, &bcw);
00542 
00543     if (res == NS_OK_UENC_MOREOUTPUT) {
00544       delete [] mBuffer;
00545       mBufferCapacity *= 2;
00546       mBuffer = new char [mBufferCapacity];
00547     } else {
00548       mBufferStart = mBufferEnd = mBuffer;
00549       mBufferEnd += bcw;
00550       break;
00551     }
00552   }
00553 
00554   res = FlushBuffer(&dest, destEnd);
00555 
00556 final:
00557   *aDestLength  -= destEnd - dest;
00558   return res;
00559 }
00560 
00561 NS_IMETHODIMP nsEncoderSupport::Reset()
00562 {
00563   mBufferStart = mBufferEnd = mBuffer;
00564   return NS_OK;
00565 }
00566 
00567 NS_IMETHODIMP nsEncoderSupport::SetOutputErrorBehavior(
00568                                 PRInt32 aBehavior, 
00569                                 nsIUnicharEncoder * aEncoder, 
00570                                 PRUnichar aChar)
00571 {
00572   if (aBehavior == kOnError_CallBack && aEncoder == nsnull) 
00573     return NS_ERROR_NULL_POINTER;
00574 
00575   mErrEncoder = aEncoder;
00576   mErrBehavior = aBehavior;
00577   mErrChar = aChar;
00578   return NS_OK;
00579 }
00580 
00581 NS_IMETHODIMP
00582 nsEncoderSupport::GetMaxLength(const PRUnichar * aSrc, 
00583                                PRInt32 aSrcLength, 
00584                                PRInt32 * aDestLength)
00585 {
00586   *aDestLength = aSrcLength * mMaxLengthFactor;
00587   return NS_OK;
00588 }
00589 
00590 
00591 //----------------------------------------------------------------------
00592 // Class nsTableEncoderSupport [implementation]
00593 
00594 nsTableEncoderSupport::nsTableEncoderSupport(uShiftTable * aShiftTable, 
00595                                              uMappingTable  * aMappingTable,
00596                                              PRUint32 aMaxLengthFactor) 
00597 : nsEncoderSupport(aMaxLengthFactor)
00598 {
00599   mHelper = NULL;
00600   mShiftTable = aShiftTable;
00601   mMappingTable = aMappingTable;
00602 }
00603 
00604 nsTableEncoderSupport::~nsTableEncoderSupport() 
00605 {
00606   NS_IF_RELEASE(mHelper);
00607 }
00608 
00609 NS_IMETHODIMP nsTableEncoderSupport::FillInfo(PRUint32 *aInfo) 
00610 {
00611   nsresult res;
00612 
00613   if (mHelper == nsnull) {
00614     res = CallCreateInstance(kUnicodeEncodeHelperCID, &mHelper);
00615     if (NS_FAILED(res)) return NS_ERROR_UENC_NOHELPER;
00616   }
00617 
00618   res = mHelper->FillInfo(aInfo, mMappingTable);
00619   return res;
00620 }
00621 //----------------------------------------------------------------------
00622 // Subclassing of nsEncoderSupport class [implementation]
00623 
00624 NS_IMETHODIMP nsTableEncoderSupport::ConvertNoBuffNoErr(
00625                                      const PRUnichar * aSrc, 
00626                                      PRInt32 * aSrcLength, 
00627                                      char * aDest, 
00628                                      PRInt32 * aDestLength)
00629 {
00630   nsresult res;
00631 
00632   if (mHelper == nsnull) {
00633     res = CallCreateInstance(kUnicodeEncodeHelperCID, &mHelper);
00634     if (NS_FAILED(res)) return NS_ERROR_UENC_NOHELPER;
00635   }
00636 
00637   res = mHelper->ConvertByTable(aSrc, aSrcLength, aDest, aDestLength, 
00638       mShiftTable, mMappingTable);
00639   return res;
00640 }
00641 
00642 //----------------------------------------------------------------------
00643 // Class nsMultiTableEncoderSupport [implementation]
00644 
00645 nsMultiTableEncoderSupport::nsMultiTableEncoderSupport(
00646                             PRInt32 aTableCount,
00647                             uShiftTable ** aShiftTable, 
00648                             uMappingTable  ** aMappingTable,
00649                             PRUint32 aMaxLengthFactor) 
00650 : nsEncoderSupport(aMaxLengthFactor)
00651 {
00652   mHelper = NULL;
00653   mTableCount = aTableCount;
00654   mShiftTable = aShiftTable;
00655   mMappingTable = aMappingTable;
00656 }
00657 
00658 nsMultiTableEncoderSupport::~nsMultiTableEncoderSupport() 
00659 {
00660   NS_IF_RELEASE(mHelper);
00661 }
00662 
00663 NS_IMETHODIMP nsMultiTableEncoderSupport::FillInfo(PRUint32 *aInfo) 
00664 {
00665   nsresult res;
00666 
00667   if (mHelper == nsnull) {
00668     res = CallCreateInstance(kUnicodeEncodeHelperCID, &mHelper);
00669     if (NS_FAILED(res)) return NS_ERROR_UENC_NOHELPER;
00670   }
00671 
00672   res = mHelper->FillInfo(aInfo,mTableCount, mMappingTable);
00673   return res;
00674 }
00675 //----------------------------------------------------------------------
00676 // Subclassing of nsEncoderSupport class [implementation]
00677 
00678 NS_IMETHODIMP nsMultiTableEncoderSupport::ConvertNoBuffNoErr(
00679                                           const PRUnichar * aSrc, 
00680                                           PRInt32 * aSrcLength, 
00681                                           char * aDest, 
00682                                           PRInt32 * aDestLength)
00683 {
00684   nsresult res;
00685 
00686   if (mHelper == nsnull) {
00687     res = CallCreateInstance(kUnicodeEncodeHelperCID, &mHelper);
00688     if (NS_FAILED(res)) return NS_ERROR_UENC_NOHELPER;
00689   }
00690 
00691   res = mHelper->ConvertByMultiTable(aSrc, aSrcLength, aDest, aDestLength, 
00692       mTableCount, mShiftTable, mMappingTable);
00693   return res;
00694 }