Coverage Report

Created: 2026-10-28 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poco/Foundation/src/UTF16Encoding.cpp
Line
Count
Source
1
//
2
// UTF16Encoding.cpp
3
//
4
// Library: Foundation
5
// Package: Text
6
// Module:  UTF16Encoding
7
//
8
// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
9
// and Contributors.
10
//
11
// SPDX-License-Identifier: BSL-1.0
12
//
13
14
15
#include "Poco/UTF16Encoding.h"
16
#include "Poco/ByteOrder.h"
17
#include "Poco/String.h"
18
19
20
namespace Poco {
21
22
23
const char* UTF16Encoding::_names[] =
24
{
25
  "UTF-16",
26
  "UTF16",
27
  nullptr
28
};
29
30
31
const TextEncoding::CharacterMap UTF16Encoding::_charMap =
32
{
33
  /* 00 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
34
  /* 10 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
35
  /* 20 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
36
  /* 30 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
37
  /* 40 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
38
  /* 50 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
39
  /* 60 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
40
  /* 70 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
41
  /* 80 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
42
  /* 90 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
43
  /* a0 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
44
  /* b0 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
45
  /* c0 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
46
  /* d0 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
47
  /* e0 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
48
  /* f0 */  -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
49
};
50
51
52
UTF16Encoding::UTF16Encoding(ByteOrderType byteOrder)
53
654
{
54
654
  setByteOrder(byteOrder);
55
654
}
56
57
58
UTF16Encoding::UTF16Encoding(int byteOrderMark)
59
0
{
60
0
  setByteOrder(byteOrderMark);
61
0
}
62
63
64
UTF16Encoding::~UTF16Encoding()
65
654
{
66
654
}
67
68
69
UTF16Encoding::ByteOrderType UTF16Encoding::getByteOrder() const
70
0
{
71
#if defined(POCO_ARCH_BIG_ENDIAN)
72
  return _flipBytes ? LITTLE_ENDIAN_BYTE_ORDER : BIG_ENDIAN_BYTE_ORDER;
73
#else
74
0
  return _flipBytes ? BIG_ENDIAN_BYTE_ORDER : LITTLE_ENDIAN_BYTE_ORDER;
75
0
#endif
76
0
}
77
78
79
void UTF16Encoding::setByteOrder(ByteOrderType byteOrder)
80
654
{
81
#if defined(POCO_ARCH_BIG_ENDIAN)
82
  _flipBytes = byteOrder == LITTLE_ENDIAN_BYTE_ORDER;
83
#else
84
654
  _flipBytes = byteOrder == BIG_ENDIAN_BYTE_ORDER;;
85
654
#endif
86
654
}
87
88
89
void UTF16Encoding::setByteOrder(int byteOrderMark)
90
0
{
91
0
  _flipBytes = byteOrderMark != 0xFEFF;
92
0
}
93
94
95
const char* UTF16Encoding::canonicalName() const
96
3
{
97
3
  return _names[0];
98
3
}
99
100
101
bool UTF16Encoding::isA(const std::string& encodingName) const
102
35.3k
{
103
103k
  for (const char** name = _names; *name; ++name)
104
70.7k
  {
105
70.7k
    if (Poco::icompare(encodingName, *name) == 0)
106
2.36k
      return true;
107
70.7k
  }
108
33.0k
  return false;
109
35.3k
}
110
111
112
const TextEncoding::CharacterMap& UTF16Encoding::characterMap() const
113
2
{
114
2
  return _charMap;
115
2
}
116
117
118
int UTF16Encoding::convert(const unsigned char* bytes) const
119
0
{
120
0
  UInt16 uc;
121
0
  unsigned char* p = (unsigned char*) &uc;
122
0
  *p++ = *bytes++;
123
0
  *p++ = *bytes++;
124
125
0
  if (_flipBytes)
126
0
  {
127
0
    uc = ByteOrder::flipBytes(uc);
128
0
  }
129
130
0
  if (uc >= 0xd800 && uc < 0xdc00)
131
0
  {
132
0
    UInt16 uc2;
133
0
    p = (unsigned char*) &uc2;
134
0
    *p++ = *bytes++;
135
0
    *p++ = *bytes++;
136
137
0
    if (_flipBytes)
138
0
    {
139
0
      uc2 = ByteOrder::flipBytes(uc2);
140
0
    }
141
0
    if (uc2 >= 0xdc00 && uc2 < 0xe000)
142
0
    {
143
0
      return ((uc & 0x3ff) << 10) + (uc2 & 0x3ff) + 0x10000;
144
0
    }
145
0
    else
146
0
    {
147
0
      return -1;
148
0
    }
149
0
  }
150
0
  else
151
0
  {
152
0
    return uc;
153
0
  }
154
0
}
155
156
157
int UTF16Encoding::convert(int ch, unsigned char* bytes, int length) const
158
22.2k
{
159
22.2k
  if (ch <= 0xFFFF)
160
22.1k
  {
161
22.1k
    if (bytes && length >= 2)
162
22.1k
    {
163
22.1k
      UInt16 ch1 = _flipBytes ? ByteOrder::flipBytes((UInt16) ch) : (UInt16) ch;
164
22.1k
      unsigned char* p = (unsigned char*) &ch1;
165
22.1k
      *bytes++ = *p++;
166
22.1k
      *bytes++ = *p++;
167
22.1k
    }
168
22.1k
    return 2;
169
22.1k
  }
170
56
  else
171
56
  {
172
56
    if (bytes && length >= 4)
173
56
    {
174
56
      int ch1 = ch - 0x10000;
175
56
      UInt16 w1 = 0xD800 + ((ch1 >> 10) & 0x3FF);
176
56
      UInt16 w2 = 0xDC00 + (ch1 & 0x3FF);
177
56
      if (_flipBytes)
178
0
      {
179
0
        w1 = ByteOrder::flipBytes(w1);
180
0
        w2 = ByteOrder::flipBytes(w2);
181
0
      }
182
56
      unsigned char* p = (unsigned char*) &w1;
183
56
      *bytes++ = *p++;
184
56
      *bytes++ = *p++;
185
56
      p = (unsigned char*) &w2;
186
56
      *bytes++ = *p++;
187
56
      *bytes++ = *p++;
188
56
    }
189
56
    return 4;
190
56
  }
191
22.2k
}
192
193
194
int UTF16Encoding::queryConvert(const unsigned char* bytes, int length) const
195
78.5k
{
196
78.5k
  int ret = -2;
197
198
78.5k
  if (length >= 2)
199
40.9k
  {
200
40.9k
    UInt16 uc;
201
40.9k
    unsigned char* p = (unsigned char*) &uc;
202
40.9k
    *p++ = *bytes++;
203
40.9k
    *p++ = *bytes++;
204
40.9k
    if (_flipBytes)
205
0
    {
206
0
      uc = ByteOrder::flipBytes(uc);
207
0
    }
208
40.9k
    if (uc >= 0xd800 && uc < 0xdc00)
209
8.11k
    {
210
8.11k
      if (length >= 4)
211
4.04k
      {
212
4.04k
        UInt16 uc2;
213
4.04k
        p = (unsigned char*) &uc2;
214
4.04k
        *p++ = *bytes++;
215
4.04k
        *p++ = *bytes++;
216
4.04k
        if (_flipBytes)
217
0
        {
218
0
          uc2 = ByteOrder::flipBytes(uc2);
219
0
        }
220
4.04k
        if (uc2 >= 0xdc00 && uc < 0xe000)
221
736
        {
222
736
          ret = ((uc & 0x3ff) << 10) + (uc2 & 0x3ff) + 0x10000;
223
736
        }
224
3.31k
        else
225
3.31k
        {
226
3.31k
          ret = -1; // Malformed sequence
227
3.31k
        }
228
4.04k
      }
229
4.06k
      else
230
4.06k
      {
231
4.06k
        ret = -4; // surrogate pair, four bytes needed
232
4.06k
      }
233
8.11k
    }
234
32.8k
    else
235
32.8k
    {
236
32.8k
      ret = uc;
237
32.8k
    }
238
40.9k
  }
239
240
78.5k
  return ret;
241
78.5k
}
242
243
244
int UTF16Encoding::sequenceLength(const unsigned char* bytes, int length) const
245
69.8k
{
246
69.8k
  int ret = -2;
247
248
69.8k
  if (_flipBytes)
249
0
  {
250
0
    if (length >= 1)
251
0
    {
252
0
      unsigned char c = *bytes;
253
0
      if (c >= 0xd8 && c < 0xdc)
254
0
        ret = 4;
255
0
      else
256
0
        ret = 2;
257
0
    }
258
0
  }
259
69.8k
  else
260
69.8k
  {
261
69.8k
    if (length >= 2)
262
34.5k
    {
263
34.5k
      UInt16 uc;
264
34.5k
      unsigned char* p = (unsigned char*) &uc;
265
34.5k
      *p++ = *bytes++;
266
34.5k
      *p++ = *bytes++;
267
34.5k
      if (uc >= 0xd800 && uc < 0xdc00)
268
3.95k
        ret = 4;
269
30.5k
      else
270
30.5k
        ret = 2;
271
34.5k
    }
272
69.8k
  }
273
69.8k
  return ret;
274
69.8k
}
275
276
277
} // namespace Poco