| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #if !defined(XALANUTF8WRITER_HEADER_GUARD_1357924680) |
| #define XALANUTF8WRITER_HEADER_GUARD_1357924680 |
| |
| |
| #include <xalanc/XMLSupport/XalanFormatterWriter.hpp> |
| |
| |
| |
| namespace XALAN_CPP_NAMESPACE { |
| |
| |
| |
| inline char |
| bits19to21(XalanUnicodeChar theChar) |
| { |
| return static_cast<char>((theChar >> 18) & 0x7); |
| } |
| |
| |
| |
| inline char |
| bits13to18(XalanUnicodeChar theChar) |
| { |
| return static_cast<char>((theChar >> 12) & 0x3F); |
| } |
| |
| |
| |
| inline char |
| bits13to16(XalanUnicodeChar theChar) |
| { |
| return static_cast<char>((theChar >> 12) & 0xF); |
| } |
| |
| |
| |
| inline char |
| bits7to12(XalanUnicodeChar theChar) |
| { |
| return static_cast<char>((theChar >> 6) & 0x3f); |
| } |
| |
| |
| |
| inline char |
| bits7to11(XalanUnicodeChar theChar) |
| { |
| return static_cast<char>((theChar >> 6) & 0x1f); |
| } |
| |
| |
| |
| inline char |
| bits1to6(XalanUnicodeChar theChar) |
| { |
| return static_cast<char>(theChar & 0x3f); |
| } |
| |
| |
| |
| inline char |
| leadingByteOf2(char theBits) |
| { |
| return static_cast<char>(0xC0 + theBits); |
| } |
| |
| |
| |
| inline char |
| leadingByteOf3(char theBits) |
| { |
| return static_cast<char>(0xE0 + theBits); |
| } |
| |
| |
| |
| inline char |
| leadingByteOf4(char theBits) |
| { |
| return static_cast<char>(0xF0 + theBits); |
| } |
| |
| |
| |
| inline char |
| trailingByte(char theBits) |
| { |
| return static_cast<char>(0x80 + theBits); |
| } |
| |
| |
| |
| class XalanUTF8Writer : public XalanFormatterWriter |
| { |
| public: |
| |
| typedef char value_type; |
| |
| |
| XalanUTF8Writer( |
| Writer& writer, |
| MemoryManager& theMemoryManager); |
| |
| virtual |
| ~XalanUTF8Writer() |
| { |
| } |
| |
| /** |
| * Output a line break. |
| */ |
| void |
| outputNewline() |
| { |
| assert(m_newlineString != 0); |
| assert(length(m_newlineString) == m_newlineStringLength); |
| |
| write( |
| m_newlineString, |
| m_newlineStringLength); |
| } |
| |
| size_type |
| writeCDATAChar( |
| const XalanDOMChar chars[], |
| size_type start, |
| size_type length, |
| bool& /* outsideCDATA */) |
| { |
| assert(chars != 0 && length != 0 && start < length); |
| |
| return write(chars, start, length); |
| } |
| |
| /** |
| * Writes name characters. If characters that are not |
| * representable are encountered, an exception is thrown. |
| */ |
| void |
| writeNameChar( |
| const XalanDOMChar* data, |
| size_type theLength) |
| { |
| write(data, theLength); |
| } |
| |
| /** |
| * Writes PI characters. If characters that are not |
| * representable are encountered, an exception is thrown. |
| */ |
| void |
| writePIChars( |
| const XalanDOMChar* data, |
| size_type theLength) |
| { |
| write(data, theLength); |
| } |
| |
| /** |
| * Writes comment characters. If characters that are not |
| * representable are encountered, an exception is thrown. |
| */ |
| void |
| writeCommentChars( |
| const XalanDOMChar* data, |
| size_type theLength) |
| { |
| write(data, theLength); |
| } |
| |
| void |
| safeWriteContent( |
| const XalanDOMChar* theChars, |
| size_type theLength) |
| { |
| for(size_type i = 0; i < theLength; ++i) |
| { |
| write(value_type(theChars[i])); |
| } |
| } |
| |
| void |
| write( |
| const value_type* theChars, |
| size_type theLength) |
| { |
| #if defined(NDEBUG) |
| if (theLength > sizeof(m_buffer)) |
| { |
| flushBuffer(); |
| |
| m_writer.write(theChars, 0, theLength); |
| } |
| else |
| { |
| if (m_bufferRemaining < theLength) |
| { |
| flushBuffer(); |
| } |
| |
| for(size_type i = 0; i < theLength; ++i) |
| { |
| *m_bufferPosition = theChars[i]; |
| |
| ++m_bufferPosition; |
| } |
| |
| m_bufferRemaining -= theLength; |
| } |
| #else |
| for(size_type i = 0; i < theLength; ++i) |
| { |
| write(theChars[i]); |
| } |
| #endif |
| } |
| |
| void |
| write(const XalanDOMChar* theChars) |
| { |
| write(theChars, XalanDOMString::length(theChars)); |
| } |
| |
| void |
| write(const XalanDOMString& theChars) |
| { |
| write(theChars.c_str(), theChars.length()); |
| } |
| |
| void |
| write(value_type theChar) |
| { |
| assert(theChar < 128); |
| |
| if (m_bufferRemaining == 0) |
| { |
| flushBuffer(); |
| } |
| |
| *m_bufferPosition = theChar; |
| |
| ++m_bufferPosition; |
| --m_bufferRemaining; |
| } |
| |
| void |
| write( |
| const XalanDOMChar* theChars, |
| size_type theLength) |
| { |
| for(size_type i = 0; i < theLength; ++i) |
| { |
| if (isUTF16HighSurrogate(theChars[i]) == false) |
| { |
| write(static_cast<XalanUnicodeChar>(theChars[i])); |
| } |
| else if (i + 1 >= theLength) |
| { |
| throwInvalidUTF16SurrogateException( |
| theChars[i], |
| 0, |
| getMemoryManager()); |
| } |
| else |
| { |
| write( |
| decodeUTF16SurrogatePair( |
| theChars[i], |
| theChars[i + 1], |
| getMemoryManager())); |
| |
| ++i; |
| } |
| } |
| } |
| |
| size_type |
| write( |
| const XalanDOMChar chars[], |
| size_type start, |
| size_type length) |
| { |
| const XalanDOMChar ch = chars[start]; |
| |
| if (isUTF16HighSurrogate(ch) == false) |
| { |
| write(static_cast<XalanUnicodeChar>(ch)); |
| } |
| else if (start + 1 >= length) |
| { |
| throwInvalidUTF16SurrogateException( |
| ch, |
| 0, |
| getMemoryManager()); |
| } |
| else |
| { |
| write( |
| decodeUTF16SurrogatePair( |
| ch, |
| chars[++start], |
| getMemoryManager())); |
| } |
| |
| return start; |
| } |
| |
| void |
| writeSafe( |
| const XalanDOMChar* theChars, |
| size_type theLength) |
| { |
| for(size_type i = 0; i < theLength; ++i) |
| { |
| const XalanDOMChar ch = theChars[i]; |
| |
| if (isUTF16HighSurrogate(ch) == true) |
| { |
| if (i + 1 >= theLength) |
| { |
| throwInvalidUTF16SurrogateException( |
| ch, |
| 0, |
| getMemoryManager()); |
| } |
| else |
| { |
| write( |
| decodeUTF16SurrogatePair( |
| ch, |
| theChars[i + 1], |
| getMemoryManager())); |
| |
| ++i; |
| } |
| } |
| else |
| { |
| write(static_cast<XalanUnicodeChar>(ch)); |
| } |
| } |
| |
| } |
| |
| void |
| write(const value_type* theChars) |
| { |
| write(theChars, XalanDOMString::length(theChars)); |
| } |
| |
| void |
| flushWriter() |
| { |
| m_writer.flush(); |
| } |
| |
| void |
| flushBuffer() |
| { |
| m_writer.write(m_buffer, 0, m_bufferPosition - m_buffer); |
| |
| m_bufferPosition = m_buffer; |
| m_bufferRemaining = kBufferSize; |
| } |
| |
| private: |
| |
| void |
| write(XalanUnicodeChar theChar) |
| { |
| if (theChar <= 0x7F) |
| { |
| write(char(theChar)); |
| } |
| else if (theChar <= 0x7FF) |
| { |
| if (m_bufferRemaining < 2) |
| { |
| flushBuffer(); |
| } |
| |
| *m_bufferPosition = leadingByteOf2(bits7to11(theChar)); |
| ++m_bufferPosition; |
| *m_bufferPosition = trailingByte(bits1to6(theChar)); |
| ++m_bufferPosition; |
| |
| m_bufferRemaining -= 2; |
| } |
| else if (theChar <= 0xFFFF) |
| { |
| // We should never get a high or low surrogate here... |
| assert(theChar < 0xD800 || theChar > 0xDBFF); |
| assert(theChar < 0xDC00 || theChar > 0xDFFF); |
| |
| if (m_bufferRemaining < 3) |
| { |
| flushBuffer(); |
| } |
| |
| *m_bufferPosition = leadingByteOf3(bits13to16(theChar)); |
| ++m_bufferPosition; |
| *m_bufferPosition = trailingByte(bits7to12(theChar)); |
| ++m_bufferPosition; |
| *m_bufferPosition = trailingByte(bits1to6(theChar)); |
| ++m_bufferPosition; |
| |
| m_bufferRemaining -= 3; |
| } |
| else if (theChar <= 0x10FFFF) |
| { |
| if (m_bufferRemaining < 4) |
| { |
| flushBuffer(); |
| } |
| |
| *m_bufferPosition = leadingByteOf4(bits19to21(theChar)); |
| ++m_bufferPosition; |
| *m_bufferPosition = trailingByte(bits13to18(theChar)); |
| ++m_bufferPosition; |
| *m_bufferPosition = trailingByte(bits7to12(theChar)); |
| ++m_bufferPosition; |
| *m_bufferPosition = trailingByte(bits1to6(theChar)); |
| ++m_bufferPosition; |
| |
| m_bufferRemaining -= 4; |
| } |
| else |
| { |
| throwInvalidCharacterException(theChar, getMemoryManager()); |
| } |
| } |
| |
| enum |
| { |
| kBufferSize = 512 // The size of the buffer |
| }; |
| |
| |
| // Data members... |
| value_type m_buffer[kBufferSize]; |
| |
| value_type* m_bufferPosition; |
| |
| size_type m_bufferRemaining; |
| }; |
| |
| |
| |
| } |
| |
| |
| |
| #endif // XALANUTF8WRITER_HEADER_GUARD_1357924680 |