GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (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 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00023 // --------------------------------------------------------------------------- 00024 // Includes 00025 // --------------------------------------------------------------------------- 00026 #include <xercesc/util/PlatformUtils.hpp> 00027 #include <xercesc/util/XMLUniDefs.hpp> 00028 #include <xercesc/util/XMLString.hpp> 00029 #include <xercesc/util/TransService.hpp> 00030 #include <xercesc/util/TranscodingException.hpp> 00031 #include <xercesc/util/XMLExceptMsgs.hpp> 00032 #include <xercesc/framework/XMLFormatter.hpp> 00033 #include <xercesc/util/Janitor.hpp> 00034 #include <xercesc/util/XMLChar.hpp> 00035 00036 #include <string.h> 00037 00038 XERCES_CPP_NAMESPACE_BEGIN 00039 00040 // --------------------------------------------------------------------------- 00041 // Local data 00042 // 00043 // gXXXRef 00044 // These are hard coded versions of the char refs we put out for the 00045 // standard char refs. 00046 // 00047 // gEscapeChars 00048 // For each style of escape, we have a list of the chars that must 00049 // be escaped for that style. The first null hit in each list indicates 00050 // no more valid entries in that list. The first entry is a dummy for 00051 // the NoEscapes style. 00052 // --------------------------------------------------------------------------- 00053 static const XMLCh gAmpRef[] = 00054 { 00055 chAmpersand, chLatin_a, chLatin_m, chLatin_p, chSemiColon, chNull 00056 }; 00057 00058 static const XMLCh gAposRef[] = 00059 { 00060 chAmpersand, chLatin_a, chLatin_p, chLatin_o, chLatin_s, chSemiColon, chNull 00061 }; 00062 00063 static const XMLCh gGTRef[] = 00064 { 00065 chAmpersand, chLatin_g, chLatin_t, chSemiColon, chNull 00066 }; 00067 00068 static const XMLCh gLTRef[] = 00069 { 00070 chAmpersand, chLatin_l, chLatin_t, chSemiColon, chNull 00071 }; 00072 00073 static const XMLCh gQuoteRef[] = 00074 { 00075 chAmpersand, chLatin_q, chLatin_u, chLatin_o, chLatin_t, chSemiColon, chNull 00076 }; 00077 00078 static const unsigned int kEscapeCount = 7; 00079 static const XMLCh gEscapeChars[XMLFormatter::EscapeFlags_Count][kEscapeCount] = 00080 { 00081 { chNull , chNull , chNull , chNull , chNull , chNull , chNull } 00082 , { chAmpersand , chCloseAngle , chDoubleQuote , chOpenAngle , chSingleQuote , chNull , chNull } 00083 , { chAmpersand , chOpenAngle , chDoubleQuote , chLF , chCR , chHTab , chNull } 00084 , { chAmpersand , chOpenAngle , chCloseAngle , chNull , chNull , chNull , chNull } 00085 }; 00086 00087 // --------------------------------------------------------------------------- 00088 // Local methods 00089 // --------------------------------------------------------------------------- 00090 bool XMLFormatter::inEscapeList(const XMLFormatter::EscapeFlags escStyle 00091 , const XMLCh toCheck) 00092 { 00093 const XMLCh* escList = gEscapeChars[escStyle]; 00094 while (*escList) 00095 { 00096 if (*escList++ == toCheck) 00097 return true; 00098 } 00099 00100 /*** 00101 * XML1.1 00102 * 00103 * Finally, there is considerable demand to define a standard representation of 00104 * arbitrary Unicode characters in XML documents. Therefore, XML 1.1 allows the 00105 * use of character references to the control characters #x1 through #x1F, 00106 * most of which are forbidden in XML 1.0. For reasons of robustness, however, 00107 * these characters still cannot be used directly in documents. 00108 * In order to improve the robustness of character encoding detection, the 00109 * additional control characters #x7F through #x9F, which were freely allowed in 00110 * XML 1.0 documents, now must also appear only as character references. 00111 * (Whitespace characters are of course exempt.) The minor sacrifice of backward 00112 * compatibility is considered not significant. 00113 * Due to potential problems with APIs, #x0 is still forbidden both directly and 00114 * as a character reference. 00115 * 00116 ***/ 00117 if (fIsXML11) 00118 { 00119 // for XML11 00120 if ( XMLChar1_1::isControlChar(toCheck, 0) && 00121 !XMLChar1_1::isWhitespace(toCheck, 0) ) 00122 { 00123 return true; 00124 } 00125 else 00126 { 00127 return false; 00128 } 00129 } 00130 else 00131 { 00132 return false; 00133 } 00134 00135 } 00136 00137 00138 // --------------------------------------------------------------------------- 00139 // XMLFormatter: Constructors and Destructor 00140 // --------------------------------------------------------------------------- 00141 XMLFormatter::XMLFormatter( const char* const outEncoding 00142 , const char* const docVersion 00143 , XMLFormatTarget* const target 00144 , const EscapeFlags escapeFlags 00145 , const UnRepFlags unrepFlags 00146 , MemoryManager* const manager) 00147 : fEscapeFlags(escapeFlags) 00148 , fOutEncoding(0) 00149 , fTarget(target) 00150 , fUnRepFlags(unrepFlags) 00151 , fXCoder(0) 00152 , fAposRef(0) 00153 , fAposLen(0) 00154 , fAmpRef(0) 00155 , fAmpLen(0) 00156 , fGTRef(0) 00157 , fGTLen(0) 00158 , fLTRef(0) 00159 , fLTLen(0) 00160 , fQuoteRef(0) 00161 , fQuoteLen(0) 00162 , fIsXML11(false) 00163 , fMemoryManager(manager) 00164 { 00165 // Transcode the encoding string 00166 fOutEncoding = XMLString::transcode(outEncoding, fMemoryManager); 00167 00168 // Try to create a transcoder for this encoding 00169 XMLTransService::Codes resCode; 00170 fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor 00171 ( 00172 fOutEncoding 00173 , resCode 00174 , kTmpBufSize 00175 , fMemoryManager 00176 ); 00177 00178 if (!fXCoder) 00179 { 00180 fMemoryManager->deallocate(fOutEncoding); //delete [] fOutEncoding; 00181 ThrowXMLwithMemMgr1 00182 ( 00183 TranscodingException 00184 , XMLExcepts::Trans_CantCreateCvtrFor 00185 , outEncoding 00186 , fMemoryManager 00187 ); 00188 } 00189 00190 XMLCh* const tmpDocVer = XMLString::transcode(docVersion, fMemoryManager); 00191 ArrayJanitor<XMLCh> jname(tmpDocVer, fMemoryManager); 00192 fIsXML11 = XMLString::equals(tmpDocVer, XMLUni::fgVersion1_1); 00193 } 00194 00195 00196 XMLFormatter::XMLFormatter( const XMLCh* const outEncoding 00197 , const XMLCh* const docVersion 00198 , XMLFormatTarget* const target 00199 , const EscapeFlags escapeFlags 00200 , const UnRepFlags unrepFlags 00201 , MemoryManager* const manager) 00202 : fEscapeFlags(escapeFlags) 00203 , fOutEncoding(0) 00204 , fTarget(target) 00205 , fUnRepFlags(unrepFlags) 00206 , fXCoder(0) 00207 , fAposRef(0) 00208 , fAposLen(0) 00209 , fAmpRef(0) 00210 , fAmpLen(0) 00211 , fGTRef(0) 00212 , fGTLen(0) 00213 , fLTRef(0) 00214 , fLTLen(0) 00215 , fQuoteRef(0) 00216 , fQuoteLen(0) 00217 , fIsXML11(false) 00218 , fMemoryManager(manager) 00219 { 00220 // Try to create a transcoder for this encoding 00221 XMLTransService::Codes resCode; 00222 fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor 00223 ( 00224 outEncoding 00225 , resCode 00226 , kTmpBufSize 00227 , fMemoryManager 00228 ); 00229 00230 if (!fXCoder) 00231 { 00232 ThrowXMLwithMemMgr1 00233 ( 00234 TranscodingException 00235 , XMLExcepts::Trans_CantCreateCvtrFor 00236 , outEncoding 00237 , fMemoryManager 00238 ); 00239 } 00240 00241 // Copy the encoding string 00242 fOutEncoding = XMLString::replicate(outEncoding, fMemoryManager); 00243 00244 00245 fIsXML11 = XMLString::equals(docVersion, XMLUni::fgVersion1_1); 00246 } 00247 00248 XMLFormatter::XMLFormatter( const char* const outEncoding 00249 , XMLFormatTarget* const target 00250 , const EscapeFlags escapeFlags 00251 , const UnRepFlags unrepFlags 00252 , MemoryManager* const manager) 00253 : fEscapeFlags(escapeFlags) 00254 , fOutEncoding(0) 00255 , fTarget(target) 00256 , fUnRepFlags(unrepFlags) 00257 , fXCoder(0) 00258 , fAposRef(0) 00259 , fAposLen(0) 00260 , fAmpRef(0) 00261 , fAmpLen(0) 00262 , fGTRef(0) 00263 , fGTLen(0) 00264 , fLTRef(0) 00265 , fLTLen(0) 00266 , fQuoteRef(0) 00267 , fQuoteLen(0) 00268 , fIsXML11(false) 00269 , fMemoryManager(manager) 00270 { 00271 // this constructor uses "1.0" for the docVersion 00272 00273 // Transcode the encoding string 00274 fOutEncoding = XMLString::transcode(outEncoding, fMemoryManager); 00275 00276 // Try to create a transcoder for this encoding 00277 XMLTransService::Codes resCode; 00278 fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor 00279 ( 00280 fOutEncoding 00281 , resCode 00282 , kTmpBufSize 00283 , fMemoryManager 00284 ); 00285 00286 if (!fXCoder) 00287 { 00288 fMemoryManager->deallocate(fOutEncoding); //delete [] fOutEncoding; 00289 ThrowXMLwithMemMgr1 00290 ( 00291 TranscodingException 00292 , XMLExcepts::Trans_CantCreateCvtrFor 00293 , outEncoding 00294 , fMemoryManager 00295 ); 00296 } 00297 00298 //XMLCh* const tmpDocVer = XMLString::transcode("1.0", fMemoryManager); 00299 //ArrayJanitor<XMLCh> jname(tmpDocVer, fMemoryManager); 00300 //fIsXML11 = XMLString::equals(tmpDocVer, XMLUni::fgVersion1_1); 00301 fIsXML11 = false; // docVersion 1.0 is not 1.1! 00302 } 00303 00304 00305 XMLFormatter::XMLFormatter( const XMLCh* const outEncoding 00306 , XMLFormatTarget* const target 00307 , const EscapeFlags escapeFlags 00308 , const UnRepFlags unrepFlags 00309 , MemoryManager* const manager) 00310 : fEscapeFlags(escapeFlags) 00311 , fOutEncoding(0) 00312 , fTarget(target) 00313 , fUnRepFlags(unrepFlags) 00314 , fXCoder(0) 00315 , fAposRef(0) 00316 , fAposLen(0) 00317 , fAmpRef(0) 00318 , fAmpLen(0) 00319 , fGTRef(0) 00320 , fGTLen(0) 00321 , fLTRef(0) 00322 , fLTLen(0) 00323 , fQuoteRef(0) 00324 , fQuoteLen(0) 00325 , fIsXML11(false) 00326 , fMemoryManager(manager) 00327 { 00328 // this constructor uses XMLUni::fgVersion1_0 for the docVersion 00329 00330 // Try to create a transcoder for this encoding 00331 XMLTransService::Codes resCode; 00332 fXCoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor 00333 ( 00334 outEncoding 00335 , resCode 00336 , kTmpBufSize 00337 , fMemoryManager 00338 ); 00339 00340 if (!fXCoder) 00341 { 00342 ThrowXMLwithMemMgr1 00343 ( 00344 TranscodingException 00345 , XMLExcepts::Trans_CantCreateCvtrFor 00346 , outEncoding 00347 , fMemoryManager 00348 ); 00349 } 00350 00351 // Copy the encoding string 00352 fOutEncoding = XMLString::replicate(outEncoding, fMemoryManager); 00353 00354 //fIsXML11 = XMLString::equals(docVersion, XMLUni::fgVersion1_1); 00355 fIsXML11 = false; // docVersion 1.0 is not 1.1! 00356 } 00357 00358 XMLFormatter::~XMLFormatter() 00359 { 00360 fMemoryManager->deallocate(fAposRef); //delete [] fAposRef; 00361 fMemoryManager->deallocate(fAmpRef); //delete [] fAmpRef; 00362 fMemoryManager->deallocate(fGTRef); //delete [] fGTRef; 00363 fMemoryManager->deallocate(fLTRef); //delete [] fLTRef; 00364 fMemoryManager->deallocate(fQuoteRef); //delete [] fQuoteRef; 00365 fMemoryManager->deallocate(fOutEncoding); //delete [] fOutEncoding; 00366 delete fXCoder; 00367 00368 // We DO NOT own the target object! 00369 } 00370 00371 00372 // --------------------------------------------------------------------------- 00373 // XMLFormatter: Formatting methods 00374 // --------------------------------------------------------------------------- 00375 void 00376 XMLFormatter::formatBuf(const XMLCh* const toFormat 00377 , const XMLSize_t count 00378 , const EscapeFlags escapeFlags 00379 , const UnRepFlags unrepFlags) 00380 { 00381 // 00382 // Figure out the actual escape flag value. If the parameter is not 00383 // the default, then take it. Else take the current default. 00384 // 00385 const EscapeFlags actualEsc = (escapeFlags == DefaultEscape) 00386 ? fEscapeFlags : escapeFlags; 00387 00388 // And do the same for the unrep flags 00389 const UnRepFlags actualUnRep = (unrepFlags == DefaultUnRep) 00390 ? fUnRepFlags : unrepFlags; 00391 00392 // 00393 // If the actual unrep action is that they want to provide char refs 00394 // for unrepresentable chars, then this one is a much more difficult 00395 // one to do cleanly, and we handle it separately. 00396 // 00397 if (actualUnRep == UnRep_CharRef) 00398 { 00399 specialFormat(toFormat, count, actualEsc); 00400 return; 00401 } 00402 00403 // 00404 // If we don't have any escape flags set, then we can do the most 00405 // efficient loop, else we have to do it the hard way. 00406 // 00407 const XMLCh* srcPtr = toFormat; 00408 const XMLCh* endPtr = toFormat + count; 00409 if (actualEsc == NoEscapes) 00410 { 00411 // 00412 // Just do a whole buffer at a time into the temp buffer, cap 00413 // it off, and send it to the target. 00414 // 00415 if (srcPtr < endPtr) 00416 srcPtr += handleUnEscapedChars(srcPtr, endPtr - srcPtr, actualUnRep); 00417 } 00418 else 00419 { 00420 // 00421 // Escape chars that require it according tot he scale flags 00422 // we were given. For the others, try to accumulate them and 00423 // format them in as big as bulk as we can. 00424 // 00425 while (srcPtr < endPtr) 00426 { 00427 // 00428 // Run a temp pointer up until we hit a character that we have 00429 // to escape. Then we can convert all the chars between our 00430 // current source pointer and here all at once. 00431 // 00432 const XMLCh* tmpPtr = srcPtr; 00433 while ((tmpPtr < endPtr) && !inEscapeList(actualEsc, *tmpPtr)) 00434 tmpPtr++; 00435 00436 // 00437 // If we got any chars, then lets convert them and write them 00438 // out. 00439 // 00440 if (tmpPtr > srcPtr) 00441 srcPtr += handleUnEscapedChars(srcPtr, tmpPtr - srcPtr, 00442 actualUnRep); 00443 00444 else if (tmpPtr < endPtr) 00445 { 00446 // 00447 // Ok, so we've hit a char that must be escaped. So do 00448 // this one specially. 00449 // 00450 const XMLByte * theChars; 00451 switch (*srcPtr) { 00452 case chAmpersand : 00453 theChars = getCharRef(fAmpLen, fAmpRef, gAmpRef); 00454 fTarget->writeChars(theChars, fAmpLen, this); 00455 break; 00456 00457 case chSingleQuote : 00458 theChars = getCharRef(fAposLen, fAposRef, gAposRef); 00459 fTarget->writeChars(theChars, fAposLen, this); 00460 break; 00461 00462 case chDoubleQuote : 00463 theChars = getCharRef(fQuoteLen, fQuoteRef, gQuoteRef); 00464 fTarget->writeChars(theChars, fQuoteLen, this); 00465 break; 00466 00467 case chCloseAngle : 00468 theChars = getCharRef(fGTLen, fGTRef, gGTRef); 00469 fTarget->writeChars(theChars, fGTLen, this); 00470 break; 00471 00472 case chOpenAngle : 00473 theChars = getCharRef(fLTLen, fLTRef, gLTRef); 00474 fTarget->writeChars(theChars, fLTLen, this); 00475 break; 00476 00477 default: 00478 // control characters 00479 writeCharRef(*srcPtr); 00480 break; 00481 } 00482 srcPtr++; 00483 } 00484 } 00485 } 00486 } 00487 00488 00489 XMLSize_t 00490 XMLFormatter::handleUnEscapedChars(const XMLCh * srcPtr, 00491 const XMLSize_t oCount, 00492 const UnRepFlags actualUnRep) 00493 { 00494 // 00495 // Use that to figure out what I should pass to the transcoder. If we 00496 // are doing character references or failing for unrepresentable chars, 00497 // then we just throw, since we should never get a call for something 00498 // we cannot represent. Else, we tell it to just use the replacement 00499 // char. 00500 // 00501 const XMLTranscoder::UnRepOpts unRepOpts = (actualUnRep == UnRep_Replace) 00502 ? XMLTranscoder::UnRep_RepChar 00503 : XMLTranscoder::UnRep_Throw; 00504 00505 XMLSize_t charsEaten; 00506 XMLSize_t count = oCount; 00507 00508 while (count) { 00509 const XMLSize_t srcChars = (count > XMLSize_t (kTmpBufSize)) 00510 ? XMLSize_t (kTmpBufSize) : count; 00511 00512 const XMLSize_t outBytes 00513 = fXCoder->transcodeTo(srcPtr, srcChars, 00514 fTmpBuf, kTmpBufSize, 00515 charsEaten, unRepOpts); 00516 00517 if (outBytes) { 00518 fTmpBuf[outBytes] = 0; fTmpBuf[outBytes + 1] = 0; 00519 fTmpBuf[outBytes + 2] = 0; fTmpBuf[outBytes + 3] = 0; 00520 fTarget->writeChars(fTmpBuf, outBytes, this); 00521 } 00522 00523 srcPtr += charsEaten; 00524 count -= charsEaten; 00525 } 00526 00527 return oCount; // This should be an assertion that count == 0. 00528 } 00529 00530 00531 XMLFormatter& XMLFormatter::operator<<(const XMLCh* const toFormat) 00532 { 00533 const XMLSize_t len = XMLString::stringLen(toFormat); 00534 formatBuf(toFormat, len); 00535 return *this; 00536 } 00537 00538 XMLFormatter& XMLFormatter::operator<<(const XMLCh toFormat) 00539 { 00540 // Make a temp string format that 00541 XMLCh szTmp[2]; 00542 szTmp[0] = toFormat; 00543 szTmp[1] = 0; 00544 00545 formatBuf(szTmp, 1); 00546 return *this; 00547 } 00548 00554 void XMLFormatter::writeBOM(const XMLByte* const toFormat 00555 , const XMLSize_t count) 00556 { 00557 fTarget->writeChars(toFormat, count, this); 00558 } 00559 00560 // --------------------------------------------------------------------------- 00561 // XMLFormatter: Private helper methods 00562 // --------------------------------------------------------------------------- 00563 void XMLFormatter::writeCharRef(const XMLCh &toWrite) 00564 { 00565 XMLCh tmpBuf[32]; 00566 tmpBuf[0] = chAmpersand; 00567 tmpBuf[1] = chPound; 00568 tmpBuf[2] = chLatin_x; 00569 00570 // Build a char ref for the current char 00571 XMLString::binToText(toWrite, &tmpBuf[3], 8, 16, fMemoryManager); 00572 const XMLSize_t bufLen = XMLString::stringLen(tmpBuf); 00573 tmpBuf[bufLen] = chSemiColon; 00574 tmpBuf[bufLen+1] = chNull; 00575 00576 // write it out 00577 formatBuf(tmpBuf 00578 , bufLen + 1 00579 , XMLFormatter::NoEscapes 00580 , XMLFormatter::UnRep_Fail); 00581 00582 } 00583 00584 void XMLFormatter::writeCharRef(XMLSize_t toWrite) 00585 { 00586 XMLCh tmpBuf[64]; 00587 tmpBuf[0] = chAmpersand; 00588 tmpBuf[1] = chPound; 00589 tmpBuf[2] = chLatin_x; 00590 00591 // Build a char ref for the current char 00592 XMLString::sizeToText(toWrite, &tmpBuf[3], 32, 16, fMemoryManager); 00593 const XMLSize_t bufLen = XMLString::stringLen(tmpBuf); 00594 tmpBuf[bufLen] = chSemiColon; 00595 tmpBuf[bufLen+1] = chNull; 00596 00597 // write it out 00598 formatBuf(tmpBuf 00599 , bufLen + 1 00600 , XMLFormatter::NoEscapes 00601 , XMLFormatter::UnRep_Fail); 00602 00603 } 00604 00605 00606 const XMLByte* XMLFormatter::getCharRef(XMLSize_t &count, 00607 XMLByte* &ref, 00608 const XMLCh * stdRef) 00609 { 00610 if (!ref) { 00611 00612 XMLSize_t charsEaten; 00613 const XMLSize_t outBytes = 00614 fXCoder->transcodeTo(stdRef, XMLString::stringLen(stdRef), 00615 fTmpBuf, kTmpBufSize, charsEaten, 00616 XMLTranscoder::UnRep_Throw); 00617 00618 fTmpBuf[outBytes] = 0; 00619 fTmpBuf[outBytes + 1] = 0; 00620 fTmpBuf[outBytes + 2] = 0; 00621 fTmpBuf[outBytes + 3] = 0; 00622 00623 ref = (XMLByte*) fMemoryManager->allocate 00624 ( 00625 (outBytes + 4) * sizeof(XMLByte) 00626 );//new XMLByte[outBytes + 4]; 00627 memcpy(ref, fTmpBuf, outBytes + 4); 00628 count = outBytes; 00629 } 00630 00631 return ref; 00632 } 00633 00634 void XMLFormatter::specialFormat(const XMLCh* const toFormat 00635 , const XMLSize_t count 00636 , const EscapeFlags escapeFlags) 00637 { 00638 // 00639 // We have to check each character and see if it could be represented. 00640 // As long as it can, we just keep up with where we started and how 00641 // many chars we've checked. When we hit an unrepresentable one, we 00642 // stop, transcode everything we've collected, then start handling 00643 // the unrepresentables via char refs. We repeat this until we get all 00644 // the chars done. 00645 // 00646 const XMLCh* srcPtr = toFormat; 00647 const XMLCh* endPtr = toFormat + count; 00648 00649 while (srcPtr < endPtr) 00650 { 00651 const XMLCh* tmpPtr = srcPtr; 00652 while (tmpPtr < endPtr) 00653 { 00654 if (fXCoder->canTranscodeTo(*tmpPtr)) 00655 tmpPtr++; 00656 else 00657 break; 00658 } 00659 00660 if (tmpPtr > srcPtr) 00661 { 00662 // We got at least some chars that can be done normally 00663 formatBuf 00664 ( 00665 srcPtr 00666 , tmpPtr - srcPtr 00667 , escapeFlags 00668 , XMLFormatter::UnRep_Fail 00669 ); 00670 00671 // Update the source pointer to our new spot 00672 srcPtr = tmpPtr; 00673 } 00674 else 00675 { 00676 00677 // We hit something unrepresentable. So continue forward doing 00678 // char refs until we hit something representable again or the 00679 // end of input. 00680 // 00681 while (srcPtr < endPtr) 00682 { 00683 if ((*srcPtr & 0xFC00) == 0xD800) { 00684 // we have encountered a surrogate, need to recombine before printing out 00685 // use writeCharRef that takes XMLSize_t to get values larger than 00686 // hex 0xFFFF printed. 00687 tmpPtr = srcPtr; 00688 tmpPtr++; // point at low surrogate 00689 writeCharRef((XMLSize_t) (0x10000+((*srcPtr-0xD800)<<10)+*tmpPtr-0xDC00)); 00690 srcPtr++; // advance to low surrogate (will advance again below) 00691 } 00692 else { 00693 writeCharRef(*srcPtr); 00694 } 00695 00696 // Move up the source pointer and break out if needed 00697 srcPtr++; 00698 if (fXCoder->canTranscodeTo(*srcPtr)) 00699 break; 00700 } 00701 } 00702 } 00703 } 00704 00705 XERCES_CPP_NAMESPACE_END