1//
2// DoubleByteEncoding.cpp
3//
4// Library: Encodings
5// Package: Encodings
6// Module: DoubleByteEncoding
7//
8// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/DoubleByteEncoding.h"
16#include "Poco/String.h"
17#include <algorithm>
18
19
20namespace Poco {
21
22
23DoubleByteEncoding::DoubleByteEncoding(const char* names[], const TextEncoding::CharacterMap& charMap, const Mapping mappingTable[], std::size_t mappingTableSize, const Mapping reverseMappingTable[], std::size_t reverseMappingTableSize):
24 _names(names),
25 _charMap(charMap),
26 _mappingTable(mappingTable),
27 _mappingTableSize(mappingTableSize),
28 _reverseMappingTable(reverseMappingTable),
29 _reverseMappingTableSize(reverseMappingTableSize)
30{
31}
32
33
34DoubleByteEncoding::~DoubleByteEncoding()
35{
36}
37
38
39const char* DoubleByteEncoding::canonicalName() const
40{
41 return _names[0];
42}
43
44
45bool DoubleByteEncoding::isA(const std::string& encodingName) const
46{
47 for (const char** name = _names; *name; ++name)
48 {
49 if (Poco::icompare(encodingName, *name) == 0)
50 return true;
51 }
52 return false;
53}
54
55
56const TextEncoding::CharacterMap& DoubleByteEncoding::characterMap() const
57{
58 return _charMap;
59}
60
61
62int DoubleByteEncoding::convert(const unsigned char* bytes) const
63{
64 int n = _charMap[*bytes];
65 switch (n)
66 {
67 case -1:
68 return -1;
69 case -2:
70 return map(static_cast<Poco::UInt16>(bytes[0] << 8) | bytes[1]);
71 default:
72 return n;
73 }
74}
75
76
77int DoubleByteEncoding::convert(int ch, unsigned char* bytes, int length) const
78{
79 int n = reverseMap(ch);
80 if (n < 0) return 0;
81 if (!bytes || !length)
82 {
83 return n > 0xFF ? 2 : 1;
84 }
85 if (n > 0xFF && length < 2) return 0;
86
87 if (n > 0xFF)
88 {
89 bytes[0] = static_cast<unsigned char>(n >> 8);
90 bytes[1] = static_cast<unsigned char>(n & 0xFF);
91 return 2;
92 }
93 else
94 {
95 bytes[0] = static_cast<unsigned char>(n);
96 return 1;
97 }
98}
99
100
101int DoubleByteEncoding::queryConvert(const unsigned char* bytes, int length) const
102{
103 int n = _charMap[*bytes];
104 switch (n)
105 {
106 case -1:
107 return -1;
108 case -2:
109 if (length >= 2)
110 return map((bytes[0] << 8) | bytes[1]);
111 else
112 return -2;
113 default:
114 return n;
115 }
116}
117
118
119int DoubleByteEncoding::sequenceLength(const unsigned char* bytes, int length) const
120{
121 if (1 <= length)
122 {
123 int cc = _charMap[*bytes];
124 if (cc >= 0)
125 return 1;
126 else if (cc < -1)
127 return -cc;
128 else
129 return -1;
130 }
131 else return -1;
132}
133
134
135struct MappingLessThan
136{
137 bool operator () (const DoubleByteEncoding::Mapping& mapping, const Poco::UInt16& key) const
138 {
139 return mapping.from < key;
140 }
141};
142
143
144int DoubleByteEncoding::map(Poco::UInt16 encoded) const
145{
146 const Mapping* begin = _mappingTable;
147 const Mapping* end = begin + _mappingTableSize;
148 const Mapping* it = std::lower_bound(begin, end, encoded, MappingLessThan());
149 if (it != end && it->from == encoded)
150 return it->to;
151 else
152 return -1;
153}
154
155
156int DoubleByteEncoding::reverseMap(int cp) const
157{
158 const Mapping* begin = _reverseMappingTable;
159 const Mapping* end = begin + _reverseMappingTableSize;
160 const Mapping* it = std::lower_bound(begin, end, static_cast<Poco::UInt16>(cp), MappingLessThan());
161 if (it != end && it->from == cp)
162 return it->to;
163 else
164 return -1;
165}
166
167
168} // namespace Poco
169