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
19namespace Poco {
20
21
22StreamConverterBuf::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
35StreamConverterBuf::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
48StreamConverterBuf::~StreamConverterBuf()
49{
50}
51
52
53int 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
98int 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
131int StreamConverterBuf::errors() const
132{
133 return _errors;
134}
135
136
137StreamConverterIOS::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
144StreamConverterIOS::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
151StreamConverterIOS::~StreamConverterIOS()
152{
153}
154
155
156StreamConverterBuf* StreamConverterIOS::rdbuf()
157{
158 return &_buf;
159}
160
161
162int StreamConverterIOS::errors() const
163{
164 return _buf.errors();
165}
166
167
168InputStreamConverter::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
175InputStreamConverter::~InputStreamConverter()
176{
177}
178
179
180OutputStreamConverter::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
187OutputStreamConverter::~OutputStreamConverter()
188{
189}
190
191
192} // namespace Poco
193