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
StreamConverterBuf(std::istream & istr,const TextEncoding & inEncoding,const TextEncoding & outEncoding,int defaultChar)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
StreamConverterBuf(std::ostream & ostr,const TextEncoding & inEncoding,const TextEncoding & outEncoding,int defaultChar)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
~StreamConverterBuf()48 StreamConverterBuf::~StreamConverterBuf()
49 {
50 }
51
52
readFromDevice()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
writeToDevice(char c)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 n = _outEncoding.convert(uc, _buffer, sizeof(_buffer));
115 if (n == 0) n = _outEncoding.convert(_defaultChar, _buffer, sizeof(_buffer));
116 poco_assert_dbg (n <= sizeof(_buffer));
117 _pOstr->write((char*) _buffer, n);
118 _sequenceLength = 0;
119 _pos = 0;
120 }
121 else
122 {
123 _sequenceLength = -n;
124 }
125 }
126
127 return charToInt(c);
128 }
129
130
errors() const131 int StreamConverterBuf::errors() const
132 {
133 return _errors;
134 }
135
136
StreamConverterIOS(std::istream & istr,const TextEncoding & inEncoding,const TextEncoding & outEncoding,int defaultChar)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
StreamConverterIOS(std::ostream & ostr,const TextEncoding & inEncoding,const TextEncoding & outEncoding,int defaultChar)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
~StreamConverterIOS()151 StreamConverterIOS::~StreamConverterIOS()
152 {
153 }
154
155
rdbuf()156 StreamConverterBuf* StreamConverterIOS::rdbuf()
157 {
158 return &_buf;
159 }
160
161
errors() const162 int StreamConverterIOS::errors() const
163 {
164 return _buf.errors();
165 }
166
167
InputStreamConverter(std::istream & istr,const TextEncoding & inEncoding,const TextEncoding & outEncoding,int defaultChar)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
~InputStreamConverter()175 InputStreamConverter::~InputStreamConverter()
176 {
177 }
178
179
OutputStreamConverter(std::ostream & ostr,const TextEncoding & inEncoding,const TextEncoding & outEncoding,int defaultChar)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
~OutputStreamConverter()187 OutputStreamConverter::~OutputStreamConverter()
188 {
189 }
190
191
192 } // namespace Poco
193