d98d519aa9e0075265c704f278d8a76c3c8f6fb4
[WebKit-https.git] / Source / WebCore / platform / text / TextCodecUTF16.cpp
1 /*
2  * Copyright (C) 2004, 2006, 2008, 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "TextCodecUTF16.h"
28
29 #include <wtf/PassOwnPtr.h>
30 #include <wtf/text/CString.h>
31 #include <wtf/text/StringBuffer.h>
32 #include <wtf/text/WTFString.h>
33
34 namespace WebCore {
35
36 void TextCodecUTF16::registerEncodingNames(EncodingNameRegistrar registrar)
37 {
38     registrar("UTF-16LE", "UTF-16LE");
39     registrar("UTF-16BE", "UTF-16BE");
40
41     registrar("ISO-10646-UCS-2", "UTF-16LE");
42     registrar("UCS-2", "UTF-16LE");
43     registrar("UTF-16", "UTF-16LE");
44     registrar("Unicode", "UTF-16LE");
45     registrar("csUnicode", "UTF-16LE");
46     registrar("unicodeFEFF", "UTF-16LE");
47
48     registrar("unicodeFFFE", "UTF-16BE");
49 }
50
51 static PassOwnPtr<TextCodec> newStreamingTextDecoderUTF16LE(const TextEncoding&, const void*)
52 {
53     return adoptPtr(new TextCodecUTF16(true));
54 }
55
56 static PassOwnPtr<TextCodec> newStreamingTextDecoderUTF16BE(const TextEncoding&, const void*)
57 {
58     return adoptPtr(new TextCodecUTF16(false));
59 }
60
61 void TextCodecUTF16::registerCodecs(TextCodecRegistrar registrar)
62 {
63     registrar("UTF-16LE", newStreamingTextDecoderUTF16LE, 0);
64     registrar("UTF-16BE", newStreamingTextDecoderUTF16BE, 0);
65 }
66
67 String TextCodecUTF16::decode(const char* bytes, size_t length, bool, bool, bool&)
68 {
69     if (!length)
70         return String();
71
72     // FIXME: This should generate an error if there is an unpaired surrogate.
73
74     const unsigned char* p = reinterpret_cast<const unsigned char*>(bytes);
75     size_t numBytes = length + m_haveBufferedByte;
76     size_t numChars = numBytes / 2;
77
78     StringBuffer<UChar> buffer(numChars);
79     UChar* q = buffer.characters();
80
81     if (m_haveBufferedByte) {
82         UChar c;
83         if (m_littleEndian)
84             c = m_bufferedByte | (p[0] << 8);
85         else
86             c = (m_bufferedByte << 8) | p[0];
87         *q++ = c;
88         m_haveBufferedByte = false;
89         p += 1;
90         numChars -= 1;
91     }
92
93     if (m_littleEndian) {
94         for (size_t i = 0; i < numChars; ++i) {
95             UChar c = p[0] | (p[1] << 8);
96             p += 2;
97             *q++ = c;
98         }
99     } else {
100         for (size_t i = 0; i < numChars; ++i) {
101             UChar c = (p[0] << 8) | p[1];
102             p += 2;
103             *q++ = c;
104         }
105     }
106
107     if (numBytes & 1) {
108         ASSERT(!m_haveBufferedByte);
109         m_haveBufferedByte = true;
110         m_bufferedByte = p[0];
111     }
112
113     buffer.shrink(q - buffer.characters());
114
115     return String::adopt(buffer);
116 }
117
118 CString TextCodecUTF16::encode(const UChar* characters, size_t length, UnencodableHandling)
119 {
120     // We need to be sure we can double the length without overflowing.
121     // Since the passed-in length is the length of an actual existing
122     // character buffer, each character is two bytes, and we know
123     // the buffer doesn't occupy the entire address space, we can
124     // assert here that doubling the length does not overflow size_t
125     // and there's no need for a runtime check.
126     ASSERT(length <= std::numeric_limits<size_t>::max() / 2);
127
128     char* bytes;
129     CString string = CString::newUninitialized(length * 2, bytes);
130
131     // FIXME: CString is not a reasonable data structure for encoded UTF-16, which will have
132     // null characters inside it. Perhaps the result of encode should not be a CString.
133     if (m_littleEndian) {
134         for (size_t i = 0; i < length; ++i) {
135             UChar c = characters[i];
136             bytes[i * 2] = c;
137             bytes[i * 2 + 1] = c >> 8;
138         }
139     } else {
140         for (size_t i = 0; i < length; ++i) {
141             UChar c = characters[i];
142             bytes[i * 2] = c >> 8;
143             bytes[i * 2 + 1] = c;
144         }
145     }
146
147     return string;
148 }
149
150 } // namespace WebCore