1 | // |
2 | // StreamConverter.cpp |
3 | // |
4 | // Library: Foundation |
5 | // Package: Text |
6 | // Module: StreamConverter |
7 | // |
8 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/StreamConverter.h" |
16 | #include "Poco/TextEncoding.h" |
17 | |
18 | |
19 | namespace Poco { |
20 | |
21 | |
22 | StreamConverterBuf::StreamConverterBuf(std::istream& istr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): |
23 | _pIstr(&istr), |
24 | _pOstr(0), |
25 | _inEncoding(inEncoding), |
26 | _outEncoding(outEncoding), |
27 | _defaultChar(defaultChar), |
28 | _sequenceLength(0), |
29 | _pos(0), |
30 | _errors(0) |
31 | { |
32 | } |
33 | |
34 | |
35 | StreamConverterBuf::StreamConverterBuf(std::ostream& ostr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): |
36 | _pIstr(0), |
37 | _pOstr(&ostr), |
38 | _inEncoding(inEncoding), |
39 | _outEncoding(outEncoding), |
40 | _defaultChar(defaultChar), |
41 | _sequenceLength(0), |
42 | _pos(0), |
43 | _errors(0) |
44 | { |
45 | } |
46 | |
47 | |
48 | StreamConverterBuf::~StreamConverterBuf() |
49 | { |
50 | } |
51 | |
52 | |
53 | int StreamConverterBuf::readFromDevice() |
54 | { |
55 | poco_assert_dbg (_pIstr); |
56 | |
57 | if (_pos < _sequenceLength) return _buffer[_pos++]; |
58 | |
59 | _pos = 0; |
60 | _sequenceLength = 0; |
61 | int c = _pIstr->get(); |
62 | if (c == -1) return -1; |
63 | |
64 | poco_assert (c < 256); |
65 | int uc; |
66 | _buffer [0] = (unsigned char) c; |
67 | int n = _inEncoding.queryConvert(_buffer, 1); |
68 | int read = 1; |
69 | |
70 | while (-1 > n) |
71 | { |
72 | poco_assert_dbg(-n <= sizeof(_buffer)); |
73 | _pIstr->read((char*) _buffer + read, -n - read); |
74 | read = -n; |
75 | n = _inEncoding.queryConvert(_buffer, -n); |
76 | } |
77 | |
78 | if (-1 >= n) |
79 | { |
80 | uc = _defaultChar; |
81 | ++_errors; |
82 | } |
83 | else |
84 | { |
85 | uc = n; |
86 | } |
87 | |
88 | _sequenceLength = _outEncoding.convert(uc, _buffer, sizeof(_buffer)); |
89 | if (_sequenceLength == 0) |
90 | _sequenceLength = _outEncoding.convert(_defaultChar, _buffer, sizeof(_buffer)); |
91 | if (_sequenceLength == 0) |
92 | return -1; |
93 | else |
94 | return _buffer[_pos++]; |
95 | } |
96 | |
97 | |
98 | int StreamConverterBuf::writeToDevice(char c) |
99 | { |
100 | poco_assert_dbg (_pOstr); |
101 | |
102 | _buffer[_pos++] = (unsigned char) c; |
103 | if (_sequenceLength == 0 || _sequenceLength == _pos) |
104 | { |
105 | int n = _inEncoding.queryConvert(_buffer, _pos); |
106 | if (-1 <= n) |
107 | { |
108 | int uc = n; |
109 | if (-1 == n) |
110 | { |
111 | ++_errors; |
112 | return -1; |
113 | } |
114 | int number = _outEncoding.convert(uc, _buffer, sizeof(_buffer)); |
115 | if (number == 0) number = _outEncoding.convert(_defaultChar, _buffer, sizeof(_buffer)); |
116 | poco_assert_dbg (number <= sizeof(_buffer)); |
117 | _pOstr->write((char*) _buffer, number); |
118 | _sequenceLength = 0; |
119 | _pos = 0; |
120 | } |
121 | else |
122 | { |
123 | _sequenceLength = -n; |
124 | } |
125 | } |
126 | |
127 | return charToInt(c); |
128 | } |
129 | |
130 | |
131 | int StreamConverterBuf::errors() const |
132 | { |
133 | return _errors; |
134 | } |
135 | |
136 | |
137 | StreamConverterIOS::StreamConverterIOS(std::istream& istr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): |
138 | _buf(istr, inEncoding, outEncoding, defaultChar) |
139 | { |
140 | poco_ios_init(&_buf); |
141 | } |
142 | |
143 | |
144 | StreamConverterIOS::StreamConverterIOS(std::ostream& ostr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): |
145 | _buf(ostr, inEncoding, outEncoding, defaultChar) |
146 | { |
147 | poco_ios_init(&_buf); |
148 | } |
149 | |
150 | |
151 | StreamConverterIOS::~StreamConverterIOS() |
152 | { |
153 | } |
154 | |
155 | |
156 | StreamConverterBuf* StreamConverterIOS::rdbuf() |
157 | { |
158 | return &_buf; |
159 | } |
160 | |
161 | |
162 | int StreamConverterIOS::errors() const |
163 | { |
164 | return _buf.errors(); |
165 | } |
166 | |
167 | |
168 | InputStreamConverter::InputStreamConverter(std::istream& istr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): |
169 | StreamConverterIOS(istr, inEncoding, outEncoding, defaultChar), |
170 | std::istream(&_buf) |
171 | { |
172 | } |
173 | |
174 | |
175 | InputStreamConverter::~InputStreamConverter() |
176 | { |
177 | } |
178 | |
179 | |
180 | OutputStreamConverter::OutputStreamConverter(std::ostream& ostr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar): |
181 | StreamConverterIOS(ostr, inEncoding, outEncoding, defaultChar), |
182 | std::ostream(&_buf) |
183 | { |
184 | } |
185 | |
186 | |
187 | OutputStreamConverter::~OutputStreamConverter() |
188 | { |
189 | } |
190 | |
191 | |
192 | } // namespace Poco |
193 | |