From a8f81aaade065db9da6940abb84f205fcafa88b2 Mon Sep 17 00:00:00 2001
From: Tinny Ng <tng@apache.org>
Date: Mon, 14 Jan 2002 19:45:15 +0000
Subject: [PATCH] Support IconvFBSD in multi-threading environment with all the
 possible combinations of threading and transcoding options.  By Max Gotlib.

git-svn-id: https://svn.apache.org/repos/asf/xerces/c/trunk@173413 13f79535-47bb-0310-9956-ffa450edef68
---
 .../IconvFBSD/IconvFBSDTransService.cpp       | 536 +++++++++++-------
 .../IconvFBSD/IconvFBSDTransService.hpp       |  45 +-
 2 files changed, 326 insertions(+), 255 deletions(-)

diff --git a/src/util/Transcoders/IconvFBSD/IconvFBSDTransService.cpp b/src/util/Transcoders/IconvFBSD/IconvFBSDTransService.cpp
index c59e30ca6..fefc7364b 100644
--- a/src/util/Transcoders/IconvFBSD/IconvFBSDTransService.cpp
+++ b/src/util/Transcoders/IconvFBSD/IconvFBSDTransService.cpp
@@ -56,6 +56,9 @@
 
 /*
  * $Log$
+ * Revision 1.4  2002/01/14 19:45:15  tng
+ * Support IconvFBSD in multi-threading environment with all the possible combinations of threading and transcoding options.  By Max Gotlib.
+ *
  * Revision 1.3  2001/12/12 14:48:16  tng
  * More bug fixes in IconvFBSD Transcoder.  By Max Gotlib.
  *
@@ -168,6 +171,7 @@ static const IconvFBSDEncoding	gIconvFBSDEncodings[] = {
 
 #endif /* XML_USE_LIBICONV */
 
+#include <util/XMLString.hpp>
 #include <util/XMLUniDefs.hpp>
 #include <util/XMLUni.hpp>
 #include <util/PlatformUtils.hpp>
@@ -181,8 +185,8 @@ static const IconvFBSDEncoding	gIconvFBSDEncodings[] = {
 // ---------------------------------------------------------------------------
 //  Local, const data
 // ---------------------------------------------------------------------------
-static const int    gTempBuffArraySize = 1024;
-static const XMLCh  gMyServiceId[] =
+static const unsigned int	gTempBuffArraySize = 4096;
+static const XMLCh  		gMyServiceId[] =
 {
     chLatin_I, chLatin_C, chLatin_o, chLatin_n, chLatin_v, chNull
 };
@@ -272,14 +276,26 @@ static wint_t fbsd_towupper(wint_t ch)
 
 #else /* XML_USE_LIBICONV */
 
+#if !defined(APP_NO_THREADS)
+
+#  include <util/Mutexes.hpp>
+// Iconv() access syncronization point
+static XMLMutex	*gIconvMutex = NULL;
+#  define ICONV_LOCK	XMLMutexLock lockConverter(gIconvMutex);
+
+#else /* APP_NO_THREADS */
+
+# define ICONV_LOCK
+
+#endif /* !APP_NO_THREADS */
+
 //----------------------------------------------------------------------------
 // There is implementation of the libiconv for FreeBSD (available through the
 // ports collection). The following is a wrapper around the iconv().
 //----------------------------------------------------------------------------
 
 IconvFBSDCD::IconvFBSDCD ()
-    : fTmpXMLBuf(0), fTmpXMLSize(0), fTmpUBuf(0), fTmpUSize(0),
-      fUChSize(0), fUBO(LITTLE_ENDIAN),
+    : fUChSize(0), fUBO(LITTLE_ENDIAN),
       fCDTo((iconv_t)-1), fCDFrom((iconv_t)-1)
 {
 }
@@ -288,9 +304,7 @@ IconvFBSDCD::IconvFBSDCD ( iconv_t	cd_from,
 			   iconv_t	cd_to,
 			   size_t	uchsize,
 			   unsigned int	ubo )
-    : fTmpXMLBuf(0), fTmpXMLSize(0),
-      fTmpUBuf(0), fTmpUSize(0),
-      fUChSize(uchsize), fUBO(ubo),
+    : fUChSize(uchsize), fUBO(ubo),
       fCDTo(cd_to), fCDFrom(cd_from)
 {
     if (fCDFrom == (iconv_t) -1 || fCDTo == (iconv_t) -1) {
@@ -300,10 +314,6 @@ IconvFBSDCD::IconvFBSDCD ( iconv_t	cd_from,
 
 IconvFBSDCD::~IconvFBSDCD()
 {
-    if (fTmpXMLBuf)
-	delete [] fTmpXMLBuf;
-    if (fTmpUBuf)
-	delete [] fTmpUBuf;
 }
 
 // Convert "native unicode" character into XMLCh
@@ -355,29 +365,27 @@ XMLCh	IconvFBSDCD::toUpper (const XMLCh ch) const
 	return toupper(ch);
     
     char	wcbuf[fUChSize * 2];
-    char	tmpArr[4];
-
     xmlChToMbc (ch, wcbuf);
+
+    char	tmpArr[4];
     char*	ptr = wcbuf;
     size_t	len = fUChSize;
     char	*pTmpArr = tmpArr;
     size_t	bLen = 2;
-    {
-	XMLMutexLock lockConverter(&fMutex);
 
-	if (::iconv (fCDTo, (const char**) &ptr, &len,
-		     &pTmpArr, &bLen) == (size_t) -1)
-	    return 0;
-	tmpArr[1] = toupper (*tmpArr);
-	*tmpArr = tmpArr[1]; 
-	len = 1;
-	pTmpArr = wcbuf;
-	bLen = fUChSize;
-	ptr = tmpArr;
-	if (::iconv (fCDFrom, (const char **)&ptr, &len,
-		     &pTmpArr, &bLen) == (size_t) -1)
-	    return 0;
-    }
+    ICONV_LOCK;
+    if (::iconv (fCDTo, (const char**) &ptr, &len,
+		 &pTmpArr, &bLen) == (size_t) -1)
+	return 0;
+    tmpArr[1] = toupper (*tmpArr);
+    *tmpArr = tmpArr[1]; 
+    len = 1;
+    pTmpArr = wcbuf;
+    bLen = fUChSize;
+    ptr = tmpArr;
+    if (::iconv (fCDFrom, (const char **)&ptr, &len,
+		 &pTmpArr, &bLen) == (size_t) -1)
+	return 0;
     mbcToXMLCh (wcbuf, (XMLCh*) &ch);
     return ch;
 }
@@ -389,14 +397,15 @@ bool	IconvFBSDCD::isSpace(const XMLCh toCheck) const
 	return isspace(toCheck);
     char	wcbuf[fUChSize * 2];
     char	tmpArr[4];
+
     xmlChToMbc (toCheck, wcbuf);
     char*	ptr = wcbuf;
     size_t	len = fUChSize;
     char	*pTmpArr = tmpArr;
     size_t	bLen = 2;
-    {
-	XMLMutexLock lockConverter(&fMutex);
 
+    {
+	ICONV_LOCK;
 	if (::iconv (fCDTo, (const char**) &ptr, &len,
 		     &pTmpArr, &bLen) == (size_t) -1)
 	    return 0;
@@ -404,29 +413,6 @@ bool	IconvFBSDCD::isSpace(const XMLCh toCheck) const
     return isspace(*tmpArr);
 }
 
-// Allocate internal buffer space, large enough to hold 'cnt'
-// XMLCh characters, and fill it with data, supplyed in the array
-// of "native unicode" characters.
-XMLCh*	IconvFBSDCD::xmlFromMbs (const char *str, size_t cnt )
-{
-    if (str == NULL && cnt == 0)
-	return NULL;
-    if (cnt > fTmpXMLSize) {
-	delete [] fTmpXMLBuf;
-	fTmpXMLBuf = NULL;
-	fTmpXMLSize = 0;
-    }
-    if (fTmpXMLBuf == NULL) {
-	fTmpXMLBuf = new XMLCh[cnt];
-	if (fTmpXMLBuf == NULL)
-	    return NULL;
-	fTmpXMLSize = cnt;
-    }
-    if (str == NULL)
-	return fTmpXMLBuf;
-    return mbsToXML (str, cnt, fTmpXMLBuf, cnt);
-}
-
 // Fill array of XMLCh characters with data, supplyed in the array
 // of "native unicode" characters.
 XMLCh*	IconvFBSDCD::mbsToXML
@@ -467,29 +453,6 @@ XMLCh*	IconvFBSDCD::mbsToXML
     return xml_str;
 }
 
-// Allocate internal buffer space, large enough to hold 'cnt'
-// "native unicode" characters, and fill it with data, supplyed
-// in the array of XMLCh characters.
-char*	IconvFBSDCD::mbsFromXML (const XMLCh *str, size_t cnt)
-{
-    if (str == NULL && cnt == 0)
-	return NULL;
-    if (cnt > fTmpUSize) {
-	delete [] fTmpUBuf;
-	fTmpUBuf = NULL;
-	fTmpUSize = 0;
-    }
-    if (fTmpUBuf == NULL) {
-	fTmpUBuf = new char[cnt * fUChSize];
-	if (fTmpUBuf == NULL)
-	    return NULL;
-	fTmpUSize = cnt;
-    }
-    if (str == NULL)
-	return fTmpUBuf;
-    return xmlToMbs (str, cnt, fTmpUBuf, cnt);
-}
-
 // Fill array of "native unicode" characters with data, supplyed
 // in the array of XMLCh characters.
 char*	IconvFBSDCD::xmlToMbs
@@ -536,7 +499,7 @@ size_t	IconvFBSDCD::iconvFrom ( const char	*fromPtr,
 				 char		**toPtr,
 				 size_t		toLen ) const
 {
-    XMLMutexLock lockConverter(&fMutex);
+    ICONV_LOCK;
     return ::iconv (fCDFrom, &fromPtr, fromLen, toPtr, &toLen);
 }
 
@@ -545,7 +508,7 @@ size_t	IconvFBSDCD::iconvTo ( const char	*fromPtr,
 			       char		**toPtr,
 			       size_t		toLen ) const
 {
-    XMLMutexLock lockConverter(&fMutex);
+    ICONV_LOCK;
     return ::iconv (fCDTo, &fromPtr, fromLen, toPtr, &toLen);
 }
 
@@ -557,12 +520,20 @@ size_t	IconvFBSDCD::iconvTo ( const char	*fromPtr,
 // ---------------------------------------------------------------------------
 
 IconvFBSDTransService::IconvFBSDTransService()
-#ifdef XML_USE_LIBICONV
+#ifndef XML_USE_LIBICONV
+{}
+#else  /* XML_USE_LIBICONV */
     : IconvFBSDCD(), fUnicodeCP(0)
-#endif /* XML_USE_LIBICONV */
 {
-#ifdef XML_USE_LIBICONV
-
+#if !defined(APP_NO_THREADS)
+    // Create global lock object
+    if (gIconvMutex == NULL) {
+	gIconvMutex = new XMLMutex;
+	if (gIconvMutex == NULL)
+	    XMLPlatformUtils::panic (XMLPlatformUtils::Panic_NoTransService);
+    }
+#endif
+    
     // Try to obtain local (host) characterset through the environment
     char*	fLocalCP = setlocale (LC_CTYPE, "");
     if (fLocalCP == NULL)
@@ -581,6 +552,7 @@ IconvFBSDTransService::IconvFBSDTransService()
     for (eptr = gIconvFBSDEncodings; eptr->fSchema; eptr++) {
 	if (eptr->fUChSize != sizeof(XMLCh))
 	    continue;
+	ICONV_LOCK;
 	// try to create conversion descriptor
 	iconv_t	cd_to = iconv_open(fLocalCP, eptr->fSchema);
 	if (cd_to == (iconv_t)-1)
@@ -602,6 +574,7 @@ IconvFBSDTransService::IconvFBSDTransService()
 	// try to use any known schema
 	for (eptr = gIconvFBSDEncodings; eptr->fSchema; eptr++) {
 	    // try to create conversion descriptor
+	    ICONV_LOCK;
 	    iconv_t	cd_to = iconv_open(fLocalCP, eptr->fSchema);
 	    if (cd_to == (iconv_t)-1)
 		continue;
@@ -621,17 +594,20 @@ IconvFBSDTransService::IconvFBSDTransService()
 
     if (fUnicodeCP == NULL || cdTo() == (iconv_t)-1 || cdFrom() == (iconv_t)-1)
 	XMLPlatformUtils::panic (XMLPlatformUtils::Panic_NoTransService);
-    
-#endif /* XML_USE_LIBICONV */
 }
+#endif /* XML_USE_LIBICONV */
 
 IconvFBSDTransService::~IconvFBSDTransService()
 {
 #ifdef XML_USE_LIBICONV
-    if (cdTo() != (iconv_t) -1)
+    if (cdTo() != (iconv_t) -1) {
 	iconv_close (cdTo());
-    if (cdFrom() != (iconv_t) -1)
+	setCDTo ((iconv_t)-1);
+    }
+    if (cdFrom() != (iconv_t) -1) {
 	iconv_close (cdFrom());
+	setCDFrom ((iconv_t)-1);
+    }
 #endif /* XML_USE_LIBICONV */
 }
 
@@ -663,8 +639,6 @@ int IconvFBSDTransService::compareIString(const XMLCh* const	comp1
     while ( (*cptr1 != 0) && (*cptr2 != 0) ) {
         if (c1 != c2)
             break;
-        cptr1++;
-        cptr2++;  
 	c1 = toUpper(*(++cptr1));
 	c2 = toUpper(*(++cptr2));
 
@@ -800,37 +774,37 @@ IconvFBSDTransService::makeNewXMLTranscoder
 #else /* XML_USE_LIBICONV */
 
     resValue = XMLTransService::UnsupportedEncoding;
-
     IconvFBSDTranscoder	*newTranscoder = NULL;
-    size_t	wLent = getWideCharLength (encodingName);
-    char*	encWName = mbsFromXML (encodingName, wLent);
-    char	encLocal[wLent+1];
-    char*	pEnclocal = encLocal;
-    size_t	len = wLent;
-    wLent *= uChSize();
-    if (iconvTo (encWName, &wLent, &pEnclocal, len) == (size_t) -1 &&
-	errno != E2BIG)
-	return 0;
-    encLocal[len] = 0;
 
+    char	*encLocal = XMLString::transcode(encodingName);
     iconv_t	cd_from, cd_to;
-    cd_from = iconv_open (fUnicodeCP, encLocal);
-    if (cd_from == (iconv_t)-1) {
-	resValue = XMLTransService::SupportFilesNotFound;
-	return NULL;
-    }
-    cd_to = iconv_open (encLocal, fUnicodeCP);
-    if (cd_to == (iconv_t)-1) {
-	resValue = XMLTransService::SupportFilesNotFound;
-	iconv_close (cd_from);
-	return NULL;
+
+    {
+	ICONV_LOCK;
+	cd_from = iconv_open (fUnicodeCP, encLocal);
+	if (cd_from == (iconv_t)-1) {
+	    resValue = XMLTransService::SupportFilesNotFound;
+	    if (encLocal)
+		delete [] encLocal;
+	    return NULL;
+	}
+	cd_to = iconv_open (encLocal, fUnicodeCP);
+	if (cd_to == (iconv_t)-1) {
+	    resValue = XMLTransService::SupportFilesNotFound;
+	    iconv_close (cd_from);
+	    if (encLocal)
+		delete [] encLocal;
+	    return NULL;
+	}
+	newTranscoder = new IconvFBSDTranscoder (encodingName,
+						 blockSize,
+						 cd_from, cd_to,
+						 uChSize(), UBO());
     }
-    newTranscoder = new IconvFBSDTranscoder (encodingName,
-					     blockSize,
-					     cd_from, cd_to,
-					     uChSize(), UBO());
     if (newTranscoder)
 	resValue = XMLTransService::Ok;
+    if (encLocal)
+	delete [] encLocal;
     return newTranscoder;
     
 #endif /* !XML_USE_LIBICONV */
@@ -847,7 +821,7 @@ void IconvFBSDTransService::upperCase(XMLCh* const toUpperCase) const
 	*outPtr = toUpper(*outPtr);
 #endif /* !XML_USE_LIBICONV */
         outPtr++;
-    }    
+    }
 }
 
 
@@ -869,26 +843,23 @@ IconvFBSDLCPTranscoder::calcRequiredSize (const char* const srcText)
 
 #else /* XML_USE_LIBICONV */
 
-    char	*tmpWideArr = mbsFromXML (NULL, gTempBuffArraySize);
-    if (tmpWideArr == NULL)
-	return 0;
     size_t      len, srcLen;
-    size_t	totalLen = 0;
-    
     len = srcLen = strlen(srcText);
     if (len == 0)
         return 0;
 
-    size_t	bLen = gTempBuffArraySize * uChSize();
+    char	tmpWideArr[gTempBuffArraySize];
+    size_t	totalLen = 0;
+
     for (;;) {
 	char		*pTmpArr = tmpWideArr;
 	const char	*ptr = srcText + srcLen - len;
-	size_t	rc = iconvFrom(ptr, &len, &pTmpArr, bLen);
+	size_t	rc = iconvFrom(ptr, &len, &pTmpArr, gTempBuffArraySize);
 	if (rc == (size_t) -1 && errno != E2BIG)
 	    return 0;
-	size_t	sz = pTmpArr - (char *) tmpWideArr;
-	totalLen += sz;
-	if (sz == 0 || len == 0)
+	rc = pTmpArr - (char *) tmpWideArr;
+	totalLen += rc;
+	if (rc == 0 || len == 0)
 	    break;
     }
     return totalLen / uChSize();
@@ -902,10 +873,12 @@ IconvFBSDLCPTranscoder::calcRequiredSize(const XMLCh* const srcText)
 {
     if (!srcText)
         return 0;
+    unsigned int  wLent = getWideCharLength(srcText);
+    if (wLent == 0)
+        return 0;
 
 #ifndef XML_USE_LIBICONV
     
-    unsigned int  wLent = getWideCharLength(srcText);
     wchar_t       tmpWideCharArr[gTempBuffArraySize];
     wchar_t*      allocatedArray = 0;
     wchar_t*      wideCharBuf = 0;
@@ -916,43 +889,55 @@ IconvFBSDLCPTranscoder::calcRequiredSize(const XMLCh* const srcText)
         wideCharBuf = tmpWideCharArr;
 
     for (unsigned int i = 0; i < wLent; i++)
-    {
         wideCharBuf[i] = srcText[i];
-    }
     wideCharBuf[wLent] = 0x00;
 
     const unsigned int retVal = fbsd_wcstombs(NULL, wideCharBuf, 0);
+
     if (allocatedArray)
 	delete [] allocatedArray;
-
     if (retVal == ~0)
         return 0;
     return retVal;
 
 #else /* XML_USE_LIBICONV */
 
-    size_t	wLent = getWideCharLength(srcText);
-    if (wLent == 0)
-        return 0;
-    char	*wBuf = mbsFromXML (srcText, wLent);
-    if (wBuf == NULL)
-	return 0;
-    char	tmpBuff[ gTempBuffArraySize ];
-    size_t      len;
+    char	tmpWBuff[gTempBuffArraySize];
+    char	*wBuf = 0;
+    char	*wBufPtr = 0;
+    size_t      len = wLent * uChSize();
+    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
+	if (len > gTempBuffArraySize) {
+	    wBufPtr = new char[len];
+	    if (wBufPtr == NULL)
+		return 0;
+	    wBuf = wBufPtr;
+	} else
+	    wBuf = tmpWBuff;
+	xmlToMbs (srcText, wLent, wBuf, wLent);
+    } else
+	wBuf = (char *) srcText;
+    
+    char	tmpBuff[gTempBuffArraySize];
     size_t	totalLen = 0;
+    char	*srcEnd = wBuf + wLent * uChSize();
     
-    len = wLent * uChSize();
     for (;;) {
 	char		*pTmpArr = tmpBuff;
-	const char	*ptr = wBuf + wLent * uChSize() - len;
+	const char	*ptr = srcEnd - len;
 	size_t	rc = iconvTo(ptr, &len, &pTmpArr, gTempBuffArraySize);
-	if (rc == (size_t) -1 && errno != E2BIG)
+	if (rc == (size_t) -1 && errno != E2BIG) {
+	    if (wBufPtr)
+		delete [] wBufPtr;
 	    return 0;
-	size_t	sz = pTmpArr - tmpBuff;
-	totalLen += sz;
-	if (sz == 0 || len == 0)
+	}
+	rc = pTmpArr - tmpBuff;
+	totalLen += rc;
+	if (rc == 0 || len == 0)
 	    break;
     }
+    if (wBufPtr)
+	delete [] wBufPtr;
     return totalLen;
 
 #endif /* !XML_USE_LIBICONV */
@@ -965,8 +950,7 @@ char* IconvFBSDLCPTranscoder::transcode(const XMLCh* const toTranscode)
         return 0;
 
     char* retVal = 0;
-    if (*toTranscode)
-    {
+    if (*toTranscode) {
         unsigned int  wLent = getWideCharLength(toTranscode);
 
 #ifndef XML_USE_LIBICONV
@@ -981,25 +965,22 @@ char* IconvFBSDLCPTranscoder::transcode(const XMLCh* const toTranscode)
             wideCharBuf = tmpWideCharArr;
 
         for (unsigned int i = 0; i < wLent; i++)
-        {
             wideCharBuf[i] = toTranscode[i];
-        }
         wideCharBuf[wLent] = 0x00;
 
         // Calc the needed size.
         const size_t neededLen = fbsd_wcstombs(NULL, wideCharBuf, 0);
-        if (neededLen == -1)
-        {
+        if (neededLen == -1) {
 	    if (allocatedArray)
 		delete [] allocatedArray;
             return 0;
-        }
-
+	}
+	
         retVal = new char[neededLen + 1];
         fbsd_wcstombs(retVal, wideCharBuf, neededLen);
-        retVal[neededLen] = 0;
 	if (allocatedArray)
 	    delete [] allocatedArray;
+        retVal[neededLen] = 0;
 
 #else /* XML_USE_LIBICONV */
 
@@ -1012,21 +993,39 @@ char* IconvFBSDLCPTranscoder::transcode(const XMLCh* const toTranscode)
 	if (retVal == NULL)
             return 0;
 	// prepare the original
-	char	*wideCharBuf = mbsFromXML (toTranscode, wLent);
-	if (wideCharBuf == NULL)
-	    return 0;
+	char	tmpWBuff[gTempBuffArraySize];
+	char	*wideCharBuf = 0;
+	char	*wBufPtr = 0;
+	size_t  len = wLent * uChSize();
+	
+	if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
+	    if (len > gTempBuffArraySize) {
+		wBufPtr = new char[len];
+		if (wBufPtr == NULL)
+		    return 0;
+		wideCharBuf = wBufPtr;
+	    } else
+		wideCharBuf = tmpWBuff;
+	    xmlToMbs (toTranscode, wLent, wideCharBuf, wLent);
+	} else
+	    wideCharBuf = (char *) toTranscode;
+
 	// perform conversion
 	wLent *= uChSize();
 	char	*ptr = retVal;
-	if (iconvTo(wideCharBuf, &wLent, &ptr, neededLen) == (size_t)-1)
+	size_t	rc = iconvTo(wideCharBuf, &wLent, &ptr, neededLen);
+	if (rc == (size_t)-1) {
+	    if (wBufPtr)
+		delete [] wBufPtr;
 	    return 0;
+	}
+	if (wBufPtr)
+	    delete [] wBufPtr;
         retVal[neededLen] = 0;
 
 #endif /* !XML_USE_LIBICONV */
 
-    }
-    else
-    {
+    } else {
         retVal = new char[1];
 	if (retVal == NULL)
 	    return 0;
@@ -1081,13 +1080,33 @@ bool IconvFBSDLCPTranscoder::transcode( const   XMLCh* const	toTranscode
 #else /* XML_USE_LIBICONV */
 
     // Fill the "unicode" string
-    char	*wideCharBuf = mbsFromXML (toTranscode, wLent);
-    
+    char	tmpWBuff[gTempBuffArraySize];
+    char	*wideCharBuf = 0;
+    char	*wBufPtr = 0;
+    size_t  len = wLent * uChSize();
+
+    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
+	if (len > gTempBuffArraySize) {
+	    wBufPtr = new char[len];
+	    if (wBufPtr == NULL)
+		return 0;
+	    wideCharBuf = wBufPtr;
+	} else
+	    wideCharBuf = tmpWBuff;
+	xmlToMbs (toTranscode, wLent, wideCharBuf, wLent);
+    } else
+	wideCharBuf = (char *) toTranscode;
+
     // Ok, go ahead and try the transcoding. If it fails, then ...
     char	*ptr = toFill;
-    size_t	len = wLent * uChSize();
-    if (iconvTo(wideCharBuf, &len, &ptr, maxBytes) == (size_t)-1)
+    size_t	rc = iconvTo(wideCharBuf, &len, &ptr, maxBytes);
+    if (rc == (size_t)-1) {
+	if (wBufPtr)
+	    delete [] wBufPtr;
 	return false;
+    }
+    if (wBufPtr)
+	delete [] wBufPtr;
     
 #endif /* !XML_USE_LIBICONV */
 
@@ -1105,8 +1124,8 @@ XMLCh* IconvFBSDLCPTranscoder::transcode(const char* const toTranscode)
 
     XMLCh* retVal = 0;
     if (*toTranscode) {
-        const unsigned int len = calcRequiredSize(toTranscode);
-        if (len == 0) {
+        const unsigned int wLent = calcRequiredSize(toTranscode);
+        if (wLent == 0) {
             retVal = new XMLCh[1];
             retVal[0] = 0;
             return retVal;
@@ -1118,36 +1137,58 @@ XMLCh* IconvFBSDLCPTranscoder::transcode(const char* const toTranscode)
         wchar_t*      allocatedArray = 0;
         wchar_t*      wideCharBuf = 0;
 
-        if (len >= gTempBuffArraySize)
-            wideCharBuf = allocatedArray = new wchar_t[len + 1];
+        if (wLent >= gTempBuffArraySize)
+            wideCharBuf = allocatedArray = new wchar_t[wLent + 1];
         else
             wideCharBuf = tmpWideCharArr;
 
-        fbsd_mbstowcs(wideCharBuf, toTranscode, len);
-        retVal = new XMLCh[len + 1];
-        for (unsigned int i = 0; i < len; i++)
+        fbsd_mbstowcs(wideCharBuf, toTranscode, wLent);
+        retVal = new XMLCh[wLent + 1];
+	if (retVal == NULL) {
+	    if (allocatedArray)
+		delete [] allocatedArray;
+	    return NULL;
+	}
+        for (unsigned int i = 0; i < wLent; i++)
             retVal[i] = (XMLCh) wideCharBuf[i];
-        retVal[len] = 0x00;
+        retVal[wLent] = 0x00;
 	if (allocatedArray)
 	    delete [] allocatedArray;
 
 #else /* XML_USE_LIBICONV */
 
-	char		*wideCharBuf = mbsFromXML(NULL, len + 1);
-	if (wideCharBuf == NULL)
-	    return 0;
-	size_t		flen = strlen(toTranscode);
-	char		*ptr = wideCharBuf;
-	if (iconvFrom(toTranscode, &flen, &ptr, len*uChSize()) == (size_t) -1)
-	    return 0;
-	retVal = xmlFromMbs (wideCharBuf, len + 1);
-	if (retVal == NULL) {
-	    if (wideCharBuf)
-		delete [] wideCharBuf;
-	    return 0;
+	char	tmpWBuff[gTempBuffArraySize];
+	char	*wideCharBuf = 0;
+	char	*wBufPtr = 0;
+	size_t  len = wLent * uChSize();
+
+	retVal = new XMLCh[wLent + 1];
+	if (retVal == NULL)
+	    return NULL;
+	if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
+	    if (len > gTempBuffArraySize) {
+		wBufPtr = new char[len];
+		if (wBufPtr == NULL)
+		    return 0;
+		wideCharBuf = wBufPtr;
+	    } else
+		wideCharBuf = tmpWBuff;
+	} else
+	    wideCharBuf = (char *) retVal;
+
+	size_t	flen = strlen(toTranscode);
+	char	*ptr = wideCharBuf;
+	size_t	rc = iconvFrom(toTranscode, &flen, &ptr, len);
+	if (rc == (size_t) -1) {
+	    if (wBufPtr)
+		delete [] wBufPtr;
+	    return NULL;
 	}
-	setTmpXMLBuf(NULL, 0);
-        retVal[len] = 0x00;
+	if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER)
+	    mbsToXML (wideCharBuf, wLent, retVal, wLent);
+	if (wBufPtr)
+	    delete [] wBufPtr;
+        retVal[wLent] = 0x00;
 	
 #endif /* !XML_USE_LIBICONV */
 
@@ -1179,9 +1220,9 @@ bool IconvFBSDLCPTranscoder::transcode(const   char* const	toTranscode
         return true;
     }
 
-    size_t len = calcRequiredSize(toTranscode);
-    if (len > maxChars)
-        len = maxChars;
+    size_t wLent = calcRequiredSize(toTranscode);
+    if (wLent > maxChars)
+        wLent = maxChars;
 
 #ifndef XML_USE_LIBICONV
 
@@ -1190,34 +1231,55 @@ bool IconvFBSDLCPTranscoder::transcode(const   char* const	toTranscode
     wchar_t*      wideCharBuf = 0;
 
     if (maxChars >= gTempBuffArraySize)
-        wideCharBuf = allocatedArray = new wchar_t[len + 1];
+        wideCharBuf = allocatedArray = new wchar_t[wLent + 1];
     else
         wideCharBuf = tmpWideCharArr;
 
-    if (fbsd_mbstowcs(wideCharBuf, toTranscode, len) == -1) {
+    if (fbsd_mbstowcs(wideCharBuf, toTranscode, wLent) == -1) {
 	if (allocatedArray)
 	    delete [] allocatedArray;
         return false;
     }
-    for (unsigned int i = 0; i < len; i++)
+    for (unsigned int i = 0; i < wLent; i++)
         toFill[i] = (XMLCh) wideCharBuf[i];
     if (allocatedArray)
 	delete [] allocatedArray;
 
 #else /* XML_USE_LIBICONV */
 
-    char	*wideCharBuf = mbsFromXML (toFill, maxChars);
-    if (wideCharBuf == NULL)
-	return 0;
-    size_t	flen = len;
+    char	tmpWBuff[gTempBuffArraySize];
+    char	*wideCharBuf = 0;
+    char	*wBufPtr = 0;
+    size_t	len = wLent * uChSize();
+
+    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
+	if (len > gTempBuffArraySize) {
+	    wBufPtr = new char[len];
+	    if (wBufPtr == NULL)
+		return 0;
+	    wideCharBuf = wBufPtr;
+	} else
+	    wideCharBuf = tmpWBuff;
+    } else
+	wideCharBuf = (char *) toFill;
+
+    size_t	flen = strlen(toTranscode); // wLent;
     char	*ptr = wideCharBuf;
-    if (iconvFrom(toTranscode, &flen, &ptr, maxChars*uChSize()) == (size_t)-1)
+    size_t	rc = iconvFrom(toTranscode, &flen, &ptr, len);
+    if (rc == (size_t)-1) {
+	if (wBufPtr)
+	    delete [] wBufPtr;
 	return false;
-    mbsToXML (wideCharBuf, maxChars, toFill, maxChars);
+    }
+    
+    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER)
+	mbsToXML (wideCharBuf, wLent, toFill, wLent);
+    if (wBufPtr)
+	delete [] wBufPtr;
     
 #endif /* !XML_USE_LIBICONV */
 
-    toFill[maxChars] = 0x00;
+    toFill[wLent] = 0x00;
     return true;
 }
 
@@ -1271,10 +1333,15 @@ IconvFBSDTranscoder::IconvFBSDTranscoder (const	XMLCh* const	encodingName
 
 IconvFBSDTranscoder::~IconvFBSDTranscoder()
 {
-    if (cdTo() != (iconv_t)-1)
+    ICONV_LOCK;
+    if (cdTo() != (iconv_t)-1) {
 	iconv_close (cdTo());
-    if (cdFrom() != (iconv_t)-1)
+	setCDTo ((iconv_t)-1);
+    }
+    if (cdFrom() != (iconv_t)-1) {
 	iconv_close (cdFrom());
+	setCDFrom ((iconv_t)-1);
+    }
 }
 
 // ---------------------------------------------------------------------------
@@ -1290,31 +1357,51 @@ unsigned int	IconvFBSDTranscoder::transcodeFrom
     ,       unsigned char* const    charSizes )
 {
     // Transcode TO XMLCh
-
     const char*  startSrc = (const char*) srcData;
     const char*  endSrc = (const char*) srcData + srcCount;
-    char* startTarget = mbsFromXML (NULL, maxChars);
-    if (startTarget == NULL)
-	return 0;
-    char* orgTarget = startTarget;
+
+    char	tmpWBuff[gTempBuffArraySize];
+    char	*startTarget = 0;
+    char	*wBufPtr = 0;
+    size_t	len = maxChars * uChSize();
+
+    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
+	if (len > gTempBuffArraySize) {
+	    wBufPtr = new char[len];
+	    if (wBufPtr == NULL)
+		return 0;
+	    startTarget = wBufPtr;
+	} else
+	    startTarget = tmpWBuff;
+    } else
+	startTarget = (char *) toFill;    
 
     // Do character-by-character transcoding
+    char	*orgTarget = startTarget;
     size_t	srcLen = srcCount;
+    size_t	prevSrcLen = srcLen;
     unsigned int toReturn = 0;
     bytesEaten = 0;
-    for (size_t cnt = 0; cnt < maxChars; cnt++) {
+    for (size_t cnt = 0; cnt < maxChars && srcLen; cnt++) {
 	size_t	rc = iconvFrom(startSrc, &srcLen, &orgTarget, uChSize());
 	if (rc == (size_t)-1) {
-	    if (errno != E2BIG)
+	    if (errno != E2BIG) {
+		if (wBufPtr)
+		    delete [] wBufPtr;
 		ThrowXML(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
+	    }
 	    break;
 	}
-	charSizes[cnt] = endSrc - srcLen - startSrc;
+	charSizes[cnt] = prevSrcLen - srcLen;
+	prevSrcLen = srcLen;
 	bytesEaten += charSizes[cnt];
 	startSrc = endSrc - srcLen;
 	toReturn++;
-    }
-    mbsToXML (startTarget, maxChars, toFill, maxChars);
+    }    
+    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER)
+	mbsToXML (startTarget, toReturn, toFill, toReturn);
+    if (wBufPtr)
+	delete [] wBufPtr;
     return toReturn;
 }
 
@@ -1328,14 +1415,34 @@ unsigned int	IconvFBSDTranscoder::transcodeTo
     , const UnRepOpts		options )
 {
     // Transcode FROM XMLCh
+    char	tmpWBuff[gTempBuffArraySize];
+    char	*startSrc = tmpWBuff;
+    char	*wBufPtr = 0;
+    size_t	len = srcCount * uChSize();
 
-    const char*  startSrc = mbsFromXML(srcData, srcCount);
-    char* startTarget = (char *) toFill;
-    size_t	srcLen = srcCount * sizeof(XMLCh);
+    if (uChSize() != sizeof(XMLCh) || UBO() != BYTE_ORDER) {
+	if (len > gTempBuffArraySize) {
+	    wBufPtr = new char[len];
+	    if (wBufPtr == NULL)
+		return 0;
+	    startSrc = wBufPtr;
+	} else
+	    startSrc = tmpWBuff;
+	xmlToMbs (srcData, srcCount, startSrc, srcCount);
+    } else
+	startSrc = (char *) srcData;
+
+    char*	startTarget = (char *) toFill;
+    size_t	srcLen = len;
     size_t	rc = iconvTo (startSrc, &srcLen, &startTarget, maxBytes);
-    if (rc == (size_t)-1 && errno != E2BIG)
+    if (rc == (size_t)-1 && errno != E2BIG) {
+	if (wBufPtr)
+	    delete [] wBufPtr;
 	ThrowXML(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
-    charsEaten = srcCount - srcLen / sizeof(XMLCh);
+    }
+    charsEaten = srcCount - srcLen / uChSize();
+    if (wBufPtr)
+	delete [] wBufPtr;
     return startTarget - (char *)toFill;
 }
 
@@ -1361,6 +1468,7 @@ bool		IconvFBSDTranscoder::canTranscodeTo
     size_t	len = srcCount * uChSize();
     char	tmpBuf[64];
     char*	pTmpBuf = tmpBuf;
+
     size_t	rc = iconvTo( srcBuf, &len, &pTmpBuf, 64);
     return (rc != (size_t)-1) && (len == 0);
 }
diff --git a/src/util/Transcoders/IconvFBSD/IconvFBSDTransService.hpp b/src/util/Transcoders/IconvFBSD/IconvFBSDTransService.hpp
index 7981513d3..005072d45 100644
--- a/src/util/Transcoders/IconvFBSD/IconvFBSDTransService.hpp
+++ b/src/util/Transcoders/IconvFBSD/IconvFBSDTransService.hpp
@@ -56,6 +56,9 @@
 
 /*
  * $Log$
+ * Revision 1.3  2002/01/14 19:45:15  tng
+ * Support IconvFBSD in multi-threading environment with all the possible combinations of threading and transcoding options.  By Max Gotlib.
+ *
  * Revision 1.2  2001/12/11 15:10:14  tng
  * More changes to IconvFBSDTransService.  Allow using "old" TransServece implementation (via '-t native' option to runConfigure) or
  * to employ libiconv (it is a part of FreeBSD ports-collection) services.  By Max Gotlib.
@@ -72,7 +75,6 @@
 
 #ifdef XML_USE_LIBICONV
 
-#  include <util/Mutexes.hpp>
 #  include <iconv.h>
 
 // ---------------------------------------------------------------------------
@@ -104,16 +106,7 @@ public:
     XMLCh 	toUpper (const XMLCh ch) const;
 
     // Check if passed characters belongs to the :space: class
-    virtual bool isSpace(const XMLCh toCheck) const;
-    
-    // Allocate internal buffer space, large enough to hold 'cnt'
-    // XMLCh characters, and fill it with data, supplyed in the array
-    // of "native unicode" characters.
-    XMLCh*	xmlFromMbs
-    (
-	const char*	str,
-	size_t		cnt
-    );
+    virtual bool isSpace(const XMLCh toCheck) const;    
 
     // Fill array of XMLCh characters with data, supplyed in the array
     // of "native unicode" characters.
@@ -124,14 +117,6 @@ public:
 	size_t		xml_cnt
     ) const;
 
-    // Allocate internal buffer space, large enough to hold 'cnt'
-    // "native unicode" characters, and fill it with data, supplyed
-    // in the array of XMLCh characters.
-    char*	mbsFromXML
-    (
-	const XMLCh*	str,
-	size_t		cnt
-    );
 
     // Fill array of "native unicode" characters with data, supplyed
     // in the array of XMLCh characters.
@@ -177,9 +162,6 @@ protected:
     inline void	setCDFrom (iconv_t cd) { fCDFrom = cd; }
     inline void	setUChSize (size_t sz) { fUChSize = sz; }
     inline void	setUBO (unsigned int u) { fUBO = u; }
-    inline void	setTmpXMLBuf (XMLCh* b, size_t s) {
-	fTmpXMLBuf = b; fTmpXMLSize = s;
-    }
     
 private:
     // -----------------------------------------------------------------------
@@ -191,36 +173,19 @@ private:
     // -----------------------------------------------------------------------
     //  Private data members
     //
-    //  fTmpXMLBuf
-    //      Temporary buffer for holding arrays of XMLCh characters
-    //  fTmpXMLSize
-    //      Size of the XMLCh temporary buffer
-    //  fTmpUBuf
-    //      Temporary buffer for holding arrays of "native unicode" characters
-    //  fTmpUSize
-    //      Size of the "native unicode" temporary buffer
     //  fCDTo
     //	    Characterset conversion descriptor TO the local-host encoding
     //  fCDFrom
     //	    Characterset conversion descriptor FROM the local-host encoding
-    //  fTmpUSize
-    //      Size of the "native unicode" temporary buffer
     //  fUChSize
     //      Sizeof the "native unicode" character in bytes
     //  fUBO
     //      "Native unicode" characters byte order
-    //  fMutex
-    //      We have to synchronize threaded calls to the converter.
     // -----------------------------------------------------------------------
-    XMLCh*	fTmpXMLBuf;
-    size_t	fTmpXMLSize;
-    char*	fTmpUBuf;
-    size_t	fTmpUSize;
     size_t	fUChSize;
     unsigned int fUBO;
     iconv_t	fCDTo;
     iconv_t	fCDFrom;
-    mutable XMLMutex	fMutex;
 };
 
 #endif /* XML_USE_LIBICONV */
@@ -294,8 +259,6 @@ private :
     // -----------------------------------------------------------------------
     //  Private data members
     //
-    //  fLocalCP
-    //      Local (host) character set name
     //  fUnicodeCP
     //      Unicode encoding schema name
     // -----------------------------------------------------------------------
-- 
GitLab