Xml
4C
Perfect compatible Chinese supplement
xml
4C
Compatible with Chinese issues have always been a headache, there are many discussions on this area, but there is no good conclusion. On the website of IBM DeveloperWorks, I found an article in Mr. Zou Yueming. "Analysis XML
4C
Source code, perfect compatible Chinese XML ", this article is XML
4C
The source code analyzes, for XML
4C
The source code has been modified to achieve the purpose of Chinese compatibility. I also target XML
4C
The source code has been modified according to the statement in the article, which is really perfect in my Debug version to solve XML
4C
Perfect compatibility of Chinese. However, the problem has appeared in my Release version, there has been confusing Chinese parsing.
In order to understand the problem, decide to XML
4C
The Release version is tracking, and the result is that the problem is
Zou Yueming
The modifications pointed out in Mr.'s article. This code returned for DEBUG and RELEASE (first need to declare, I have called setLocale (lc_all, "chinese-siimplified") before using the library), as long as Chinese is included in the string, in Release The result of the VALCREQUIREDSIZE (Const Char * Const srcText) function calls MBstowcs is incorrect. Below is a function of the "Analyzing XML4C Source Code" modified function CALCREQUIREDSIZE code:
Unsigned int win32lcptranscoder :: CalcRequiredSize (const char * const srctext)
{
/ *
IF (! srctext)
Return 0;
Unsigned charlen = :: mblen (srctext, mb_cur_max);
IF (charlen == -1)
Return 0;
Else IF (Charlen! = 0)
Charlen = Strlen (srctext) / charlen
IF (charlen == -1)
Return 0;
Return charlen;
* /
IF (! srctext) {
Return 0;
}
Unsigned int RetVal = :: mbstowcs (0, srctext, 0);
IF (retval == -1) {
Return 0;
}
Return RetVal;
}
This code runs correctly under Debug, but under Release, the calculation length will have problems, and the result is incorrect. Start thinking is that the local environmental service started by the program is modified, but it is not changed when tracking the code, which makes people feel confused, do not know what is caused. When the current local environmental service (SetLocale (lc_all, null) is set before MBstowCS, the function MBstowcs can work correctly. If anyone knows, you can tell (email: flyelfsky@hotmail.com).
So, the code after modification is as follows:
Unsigned int win32lcptranscoder :: CalcRequiredSize (const char * const srctext)
{
IF (! srctext) {
Return 0;
}
#ifndef _debug
/ / Ensure that the correct result can be obtained under Release
SetLocale (lc_all, null);
#ENDIF
Unsigned int RetVal = :: mbstowcs (0, srctext, 0); if (RetVal == -1) {
Return 0;
}
Return RetVal;
}
Of course, not only this function needs to add this, add this code for all MBstowcs functions: setLocale (lc_all, null); The following is the function you need to modify:
Unsigned int win32lcptranscoder :: CalcRequiredSize (const char * const srctext
, MemoryManager * const manager)
Char * Win32lcptranscoder :: Transcode (const Xmlch * const today);
Char * Win32lcptranscoder :: Transcode (const Xmlch * const today,
MemoryManager * Const Manager)
XMLCH * Win32lcptranscoder :: Transcode (const char * const today ") CODE (Const Char * Const Totranscode)
XMLCH * Win32lcptranscoder :: Transcode (const char * const today,
MemoryManager * Const Manager)
Bool Win32lcptranscoder :: Transcode (Const Char * Const Totranscode
, XMLCH * Const Tofill
Const unsigned int maxchars
, MemoryManager * const manager)
Bool Win32lcptranscoder :: Transcode (const Xmlch * Const Totranscode
Char * const tofill
, Const unsigned int Maxbytes
, MemoryManager * const manager)
Conversion using functions MBstowcs and WCSTOMBS, but for porting, additional APIs have been provided in Win32 to perform conversion: WideChartomultibyte and multibytetowideChar, in these conversion functions, replace MBSTOWCS to multibytetowidechar, replace WCSTOMBS to WideChartomultibyte. This will not have this problem after so.
Appendix: Some cold content of Win32Transservice.cpp after modification
/ / -------------------------------------------------------------------------------------------- ---------------------------
// Win32lcptranscoder: Implementation of the Virtual Transcoder Interface
/ / -------------------------------------------------------------------------------------------- ---------------------------
Unsigned int win32lcptranscoder :: CalcRequiredSize (const char * const srctext
, MemoryManager * const manager)
{
IF (! srctext)
{
Return 0;
}
#ifdef _win32
Unsigned int Retval = :: MultibyTetowideChar (CP_ACP, 0,
SrcText,
-1,
NULL,
0);
#ELSE
#ifndef _debug
SetLocale (lc_all, ");
#ENDIF
Unsigned int RetVal = :: mbstowcs (0, srctext, 0);
#ENDIF
IF (RetVal == -1)
{
Return 0;
}
Return RetVal;
}
Char * Win32lcptranscoder :: Transcode (const Xmlch * const today)
{
IF (! totranscode)
Return 0;
Char * retval = 0;
IF (* Totranscode)
{
// Calc the needed size
Const unsigned int neededledlen = CALCREQUIREDSIZE (TOTRANSCODE);
// Allocate a Buffer of That Size Plus One for the Null and Transcode
Retval = new char [Neededlen 1];
#ifdef _win32
:: WideChartomultibyte (CP_ACP,
0,
TOTRANSCODE,
-1,
RetVal,
Neededlen,
""
NULL);
#ELSE
#ifndef _debug
SetLocale (lc_all, ");
#ENDIF
:: WCSTombs (Retval, Totranscode, Neededlen 1);
#ENDIF
// and cap it off off, just to make sure
RetVal [Neededledlen] = 0;
}
Else
{
Retval = new char [1];
RetVal [0] = 0;
}
Return RetVal;
}
Char * Win32lcptranscoder :: Transcode (const Xmlch * const today,
MemoryManager * Const Manager)
{
IF (! totranscode)
Return 0;
Char * retval = 0;
IF (* Totranscode)
{
// Calc the needed size
Const unsigned int neededledlen = CALCREQUIREDSIZE (TOTRANSCODE, MANAGER);
// Allocate a Buffer of That Size Plus One for the Null and Transcode
Retval = (char *) Manager-> Allocate ((NEEDELEN 1) * Sizeof (char)); // new char [needededledlen 1];
#ifdef _win32
:: WideChartomultibyte (CP_ACP,
0,
TOTRANSCODE,
-1,
RetVal,
Neededlen,
""
NULL);
#ELSE
#ifndef _debug
SetLocale (lc_all, ");
#ENDIF
:: WCSTombs (Retval, Totranscode, Neededlen 1);
#ENDIF
// and cap it off off the anyway just to makeretval [neededledlen] = 0;
}
Else
{
Retval = (char *) Manager-> Allocate (Sizeof (Char)); // New char [1];
RetVal [0] = 0;
}
Return RetVal;
}
XMLCH * Win32lcptranscoder :: Transcode (const char * const today ") CODE (Const Char * Const Totranscode)
{
IF (! totranscode)
Return 0;
XMLCH * RETVAL = 0;
IF (* Totranscode)
{
// Calculate The Buffer Size Required
Const unsigned int neededledlen = CALCREQUIREDSIZE (TOTRANSCODE);
IF (Neededlen == 0)
{
Retval = new XMLCH [1];
RetVal [0] = 0;
Return RetVal;
}
// Allocate a Buffer of That Size Plus One for the Null and Transcode
Retval = new XMLCH [Neededlen 1];
#ifdef _win32
:: MultibyTetowideChar (CP_ACP,
0,
TOTRANSCODE,
-1,
RetVal,
Neededlen;
#ELSE
#ifndef _debug
SetLocale (lc_all, ");
#ENDIF
:: Mbstowcs (Retval, Totranscode, Neededlen 1);
#ENDIF
// CAP IT Off Just to make Sure. WE Are So Paranoid!
RetVal [Neededledlen] = 0;
}
Else
{
Retval = new XMLCH [1];
RetVal [0] = 0;
}
Return RetVal;
}
XMLCH * Win32lcptranscoder :: Transcode (const char * const today,
MemoryManager * Const Manager)
{
IF (! totranscode)
Return 0;
XMLCH * RETVAL = 0;
IF (* Totranscode)
{
// Calculate The Buffer Size Required
Const unsigned int neededledlen = CALCREQUIREDSIZE (TOTRANSCODE, MANAGER);
IF (Neededlen == 0)
{
Retval = (xmlch *) manager-> allocate (sizeof (xmlch)); // new XMLCH [1];
RetVal [0] = 0;
Return RetVal;
}
// Allocate a Buffer of That Size Plus One for the Null and Transcode
Retval = (xmlch *) Manager-> Allocate ((Neededlen 1) * sizeof (XMLCH)); // new XMLCH [Neededelen 1];
#ifdef _win32
:: MultibyTetowideChar (CP_ACP,
0,
TOTRANSCODE,
-1,
RetVal, Neededledlen;
#ELSE
#ifndef _debug
SetLocale (lc_all, ");
#ENDIF
:: Mbstowcs (Retval, Totranscode, Neededlen 1);
#ENDIF
// CAP IT Off Just to make Sure. WE Are So Paranoid!
RetVal [Neededledlen] = 0;
}
Else
{
Retval = (xmlch *) manager-> allocate (sizeof (xmlch)); // new XMLCH [1];
RetVal [0] = 0;
}
Return RetVal;
}
Bool Win32lcptranscoder :: Transcode (Const Char * Const Totranscode
, XMLCH * Const Tofill
Const unsigned int maxchars
, MemoryManager * const manager)
{
// Check for a couple of psycho corner case
IF (! Totranscode ||! Maxchars)
{
TOFILL [0] = 0;
Return True;
}
IF (! * Totranscode)
{
TOFILL [0] = 0;
Return True;
}
// this One Has A Fixed Size Output, SO TRY IT and if IT Fails It Fails
#ifdef _win32
SIZE_T TO_ = :: MultibyTetowideChar (CP_ACP,
0,
TOTRANSCODE,
-1,
TOFILL,
Maxchars);
#ELSE
#ifndef _debug
SetLocale (lc_all, ");
#ENDIF
Size_t to_ = :: MBSTOWCS (Tofill, Totranscode, Maxchars 1);
#ENDIF
Return (TO_! = size_t (-1));
//
}
Bool Win32lcptranscoder :: Transcode (const Xmlch * Const Totranscode
Char * const tofill
, Const unsigned int Maxbytes
, MemoryManager * const manager)
{
// Watch for a couple of pyscho corner case
IF (! Totranscode ||! Maxbytes)
{
TOFILL [0] = 0;
Return True;
}
IF (! * Totranscode)
{
TOFILL [0] = 0;
Return True;
}
// this One Has A Fixed Size Output, SO TRY IT and if IT Fails It Fails
//
#ifdef _win32
Size_t to_ = :: widechartomultibyte (cp_acp,
0,
TOTRANSCODE,
-1,
TOFILL,
Maxbytes,
""
NULL);
#ELSE
#ifndef _debug
SetLocale (lc_all, ");
#ENDIF
Size_t to_ = :: WCSTombs (Tofill, Totranscode, MaxBytes 1); # Endif
IF (TO_ == SIZE_T (-1))
{
Return False;
}
// CAP IT Off Just In Case
TOFILL [MAXBYTES] = 0;
Return True;
}