00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one 00003 * or more contributor license agreements. See the NOTICE file 00004 * distributed with this work for additional information 00005 * regarding copyright ownership. The ASF licenses this file 00006 * to you under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 #if !defined(XALANUNICODESUBSETWRITER_HEADER_GUARD_1357924680) 00019 #define XALANUNICODESUBSETWRITER_HEADER_GUARD_1357924680 00020 00021 00022 #include <xalanc/XMLSupport/XalanFormatterWriter.hpp> 00023 00024 00025 00026 XALAN_CPP_NAMESPACE_BEGIN 00027 00028 00029 00030 00031 template <class Predicate, 00032 class ConstantsType> 00033 class XalanOtherEncodingWriter : public XalanFormatterWriter 00034 { 00035 public: 00036 00037 typedef XalanOtherEncodingWriter<Predicate, ConstantsType> ThisType; 00038 00039 class WriteCharRef 00040 { 00041 public: 00042 00043 WriteCharRef(ThisType& writer) : 00044 m_writer(writer) 00045 { 00046 } 00047 00048 void 00049 operator()(XalanUnicodeChar value) const 00050 { 00051 m_writer.writeNumericCharacterReference(value); 00052 } 00053 00054 private: 00055 00056 ThisType& m_writer; 00057 }; 00058 00059 class ThrowTranscodingException 00060 { 00061 public: 00062 00063 ThrowTranscodingException(ThisType& writer) : 00064 m_writer(writer) 00065 { 00066 } 00067 00068 void 00069 operator()(XalanUnicodeChar value) const 00070 { 00071 m_writer.throwUnrepresentableCharacterException( 00072 value, 00073 m_writer.getMemoryManager()); 00074 } 00075 00076 private: 00077 00078 ThisType& m_writer; 00079 }; 00080 00081 friend class WriteCharRef; 00082 friend class ThrowTranscodingException; 00083 00084 typedef XalanDOMChar value_type; 00085 00086 XalanOtherEncodingWriter( 00087 Writer& writer, 00088 MemoryManager& theMemoryManager) : 00089 XalanFormatterWriter( 00090 writer, 00091 theMemoryManager), 00092 m_buffer(), 00093 m_bufferPosition(m_buffer), 00094 m_bufferRemaining(kBufferSize), 00095 m_predicate(writer.getStream()), 00096 m_constants(), 00097 m_charRefFunctor(*this), 00098 m_exceptionFunctor(*this) 00099 { 00100 } 00101 00102 virtual 00103 ~XalanOtherEncodingWriter() 00104 { 00105 } 00106 00107 /** 00108 * Output a line break. 00109 */ 00110 void 00111 outputNewline() 00112 { 00113 assert(m_newlineString != 0); 00114 assert(length(m_newlineString) == m_newlineStringLength); 00115 00116 write( 00117 m_newlineString, 00118 m_newlineStringLength); 00119 } 00120 00121 /** 00122 * Writes CDATA chars , if not presentable, fixes it 00123 * with addition CDATA sections 00124 */ 00125 size_type 00126 writeCDATAChar( 00127 const XalanDOMChar chars[], 00128 size_type start, 00129 size_type length, 00130 bool& outsideCDATA) 00131 { 00132 assert(chars != 0 && length > 0 && start < length); 00133 00134 const XalanDOMChar theChar = chars[start]; 00135 00136 XalanUnicodeChar value = theChar; 00137 00138 size_type result = start; 00139 00140 if (isUTF16HighSurrogate(theChar) == true) 00141 { 00142 if (start + 1 >= length) 00143 { 00144 throwInvalidUTF16SurrogateException( 00145 theChar, 00146 0, 00147 getMemoryManager()); 00148 } 00149 else 00150 { 00151 value = decodeUTF16SurrogatePair(theChar, chars[start+1], getMemoryManager()); 00152 00153 ++result; 00154 } 00155 } 00156 00157 if(m_predicate(value)) 00158 { 00159 if (outsideCDATA == false) 00160 { 00161 // We have a representable char in the normal state, 00162 // so just print it. 00163 write(value); 00164 } 00165 else 00166 { 00167 // The previous character was a not representable. 00168 // Open the CDATA section again, print the character, 00169 // then change the flag. 00170 write( 00171 m_constants.s_cdataOpenString, 00172 m_constants.s_cdataOpenStringLength); 00173 00174 write(value); 00175 00176 outsideCDATA = false; 00177 } 00178 } 00179 else 00180 { 00181 if(outsideCDATA == false) 00182 { 00183 // we have a non-representable char in the normal state - 00184 // close the CDATA section and print the value 00185 write( 00186 m_constants.s_cdataCloseString, 00187 m_constants.s_cdataCloseStringLength); 00188 00189 writeNumericCharacterReference(value); 00190 00191 outsideCDATA = true; 00192 } 00193 else 00194 { 00195 writeNumericCharacterReference(value); 00196 } 00197 } 00198 00199 return result; 00200 } 00201 00202 /** 00203 * Writes name characters. If a character is not representable, 00204 * an exception is thrown. 00205 */ 00206 void 00207 writeNameChar( 00208 const XalanDOMChar* data, 00209 size_type theLength) 00210 { 00211 for( size_type i = 0; i < theLength; ++i) 00212 { 00213 i = write(data, i , theLength, m_exceptionFunctor); 00214 } 00215 } 00216 00217 /** 00218 * Writes PI characters. If a character is not representable, 00219 * an exception is thrown. 00220 */ 00221 void 00222 writePIChars( 00223 const XalanDOMChar* data, 00224 size_type theLength) 00225 { 00226 for( size_type i = 0; i < theLength; ) 00227 { 00228 i = write(data, i , theLength, m_exceptionFunctor); 00229 } 00230 } 00231 00232 /** 00233 * Writes comment characters. If a character is not representable, 00234 * or must be written as a character reference for compatibility with 00235 * XML 1.1, an exception is thrown. 00236 */ 00237 void 00238 writeCommentChars( 00239 const XalanDOMChar* data, 00240 size_type theLength) 00241 { 00242 for( size_type i = 0; i < theLength; ) 00243 { 00244 i = write(data, i , theLength, m_exceptionFunctor); 00245 } 00246 } 00247 00248 void 00249 write( 00250 const XalanDOMChar* theChars, 00251 size_type theLength) 00252 { 00253 for(size_type i = 0; i < theLength; ++i) 00254 { 00255 write(theChars[i]); 00256 } 00257 } 00258 00259 void 00260 write(const XalanDOMString& theChars) 00261 { 00262 write(theChars.c_str(), theChars.length()); 00263 } 00264 00265 /** 00266 * Writes writes a UTF-16 code unit that isn't 00267 * part of the surrogate pair 00268 */ 00269 void 00270 write(XalanDOMChar theChar) 00271 { 00272 assert( 00273 isUTF16HighSurrogate(theChar) == false && 00274 isUTF16LowSurrogate(theChar) == false); 00275 00276 if (m_bufferRemaining == 0) 00277 { 00278 flushBuffer(); 00279 } 00280 00281 if(m_predicate(theChar)) 00282 { 00283 *m_bufferPosition = theChar; 00284 00285 ++m_bufferPosition; 00286 --m_bufferRemaining; 00287 } 00288 else 00289 { 00290 writeNumericCharacterReference(theChar); 00291 } 00292 } 00293 00294 size_type 00295 write( 00296 const XalanDOMChar chars[], 00297 size_type start, 00298 size_type length) 00299 { 00300 00301 return write(chars, start, length, m_charRefFunctor); 00302 } 00303 00304 void 00305 writeSafe( 00306 const XalanDOMChar* theChars, 00307 size_type theLength) 00308 { 00309 for(size_type i = 0; i < theLength; ++i) 00310 { 00311 const XalanDOMChar ch = theChars[i]; 00312 00313 if (isUTF16HighSurrogate(ch) == true) 00314 { 00315 if (i + 1 >= theLength) 00316 { 00317 throwInvalidUTF16SurrogateException(ch, 0, getMemoryManager()); 00318 } 00319 else 00320 { 00321 XalanUnicodeChar value = decodeUTF16SurrogatePair(ch, theChars[i+1], getMemoryManager()); 00322 00323 if (this->m_isPresentable(value)) 00324 { 00325 write(value); 00326 } 00327 else 00328 { 00329 this->writeNumberedEntityReference(value); 00330 } 00331 00332 ++i; 00333 } 00334 } 00335 else 00336 { 00337 write(static_cast<XalanUnicodeChar>(ch)); 00338 } 00339 } 00340 } 00341 00342 void 00343 write(const XalanDOMChar* theChars) 00344 { 00345 write(theChars, XalanDOMString::length(theChars)); 00346 } 00347 00348 void 00349 flushWriter() 00350 { 00351 m_writer.flush(); 00352 } 00353 00354 void 00355 flushBuffer() 00356 { 00357 m_writer.write(m_buffer, 0, m_bufferPosition - m_buffer); 00358 00359 m_bufferPosition = m_buffer; 00360 m_bufferRemaining = kBufferSize; 00361 } 00362 00363 private: 00364 00365 /** 00366 * Writes a representable code point 00367 * 00368 * @param chars Array of the characters for transcoding 00369 * 00370 * @param start Place int the array the transcoding should start 00371 * 00372 * @param length The length of the array 00373 * 00374 * @param failureHandler The functor handles the non-representable characters 00375 * 00376 * @return Place int the array of the next character 00377 */ 00378 00379 template <class TranscodingFailureFunctor> 00380 size_type 00381 write( 00382 const XalanDOMChar chars[], 00383 size_type start, 00384 size_type length, 00385 TranscodingFailureFunctor& failureHandler) 00386 { 00387 assert(chars != 0 && length > 0); 00388 assert(start <= length); 00389 00390 size_type result = start; 00391 00392 const XalanDOMChar ch = chars[start]; 00393 00394 XalanUnicodeChar value = ch; 00395 00396 if (isUTF16HighSurrogate(ch) == true) 00397 { 00398 if (start + 1 >= length) 00399 { 00400 throwInvalidUTF16SurrogateException( 00401 ch, 00402 0, 00403 getMemoryManager()); 00404 } 00405 else 00406 { 00407 value = decodeUTF16SurrogatePair(ch, chars[start+1], getMemoryManager()); 00408 00409 ++result; 00410 } 00411 } 00412 00413 if(m_predicate(value)) 00414 { 00415 write(value); 00416 } 00417 else 00418 { 00419 failureHandler(value); 00420 } 00421 00422 return result; 00423 } 00424 00425 /** 00426 * Writes a representable code point 00427 * 00428 * @param theChar UTF-32 code point . For passing it to the Xerces 00429 * transcoder, we convert it back to UTF-16 00430 */ 00431 void 00432 write(XalanUnicodeChar theChar) 00433 { 00434 // encode back UTF-32 into UTF-16 00435 00436 if (theChar > 0xFFFF) 00437 { 00438 if (m_bufferRemaining < 2) 00439 { 00440 flushBuffer(); 00441 } 00442 00443 *m_bufferPosition = static_cast<XalanDOMChar>((theChar >> 10) + 0xD7C0); 00444 00445 ++m_bufferPosition; 00446 00447 *m_bufferPosition = static_cast<XalanDOMChar>((theChar & 0x03FF) + 0xDC00); 00448 00449 ++m_bufferPosition; 00450 00451 m_bufferRemaining = m_bufferRemaining - size_type(2); 00452 } 00453 else 00454 { 00455 if (m_bufferRemaining == 0) 00456 { 00457 flushBuffer(); 00458 } 00459 00460 *m_bufferPosition = XalanDOMChar(theChar); 00461 00462 ++m_bufferPosition; 00463 --m_bufferRemaining; 00464 } 00465 } 00466 00467 void 00468 writeNumericCharacterReference(XalanUnicodeChar theChar) 00469 { 00470 const XalanDOMString& theString = 00471 formatNumericCharacterReference(theChar); 00472 00473 const XalanDOMString::size_type theLength = 00474 theString.length(); 00475 00476 if (m_bufferRemaining < theLength) 00477 { 00478 flushBuffer(); 00479 } 00480 00481 XALAN_USING_STD(copy) 00482 00483 assert(theString.size() <= m_bufferRemaining); 00484 00485 m_bufferPosition = 00486 copy( 00487 theString.begin(), 00488 theString.end(), 00489 m_bufferPosition); 00490 00491 m_bufferRemaining -= theLength; 00492 } 00493 00494 enum 00495 { 00496 // The size of the buffer. The minimum for this 00497 // is the length of the longest numeric character 00498 // reference that can be written. 00499 kBufferSize = 512u 00500 }; 00501 00502 00503 // Data members... 00504 XalanDOMChar m_buffer[kBufferSize]; 00505 00506 XalanDOMChar* m_bufferPosition; 00507 00508 size_type m_bufferRemaining; 00509 00510 const Predicate m_predicate; 00511 00512 const ConstantsType m_constants; 00513 00514 const WriteCharRef m_charRefFunctor; 00515 00516 const ThrowTranscodingException m_exceptionFunctor; 00517 }; 00518 00519 00520 00521 XALAN_CPP_NAMESPACE_END 00522 00523 00524 00525 #endif // XALANUNICODESUBSETWRITER_HEADER_GUARD_1357924680
Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.
Xalan-C++ XSLT Processor Version 1.11 |
|