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