DCL 4.0
Loading...
Searching...
No Matches
InputStreamReader.cpp
Go to the documentation of this file.
1
2#include <dcl/Config.h>
3
4#if __DCL_WINDOWS
5#include <windows.h>
6#endif
7
8#include <string.h> // memcpy, memmove
9#include <dcl/size_t.h>
10#include <dcl/Charset.h>
12
13#if __DCL_DEBUG
14#undef __THIS_FILE__
15static const char_t __THIS_FILE__[] = __T("dcl/InputStreamReader.cpp");
16#endif
17
18__DCL_BEGIN_NAMESPACE
19
21
22String InputStreamReader::toString() const
23{
24 StringBuilder r = className();
25 if (__input)
26 {
27 r += __T("(") + __input->toString() + __T(",");
28 if (__decoder)
29 r += __decoder->className();
30 else
31 r += __T("null");
32 r += __T(")");
33 }
34 else
35 r += __T(" closed");
36 return r;
37}
38
40{
41 __input = NULL;
43 __closeDestroy = false;
44 __extraBytes = 0;
45}
46
49 CharsetDecoder& _decoder
50 )
51{
52 __input = &_input;
53 __decoder = &_decoder;
54 __closeDestroy = false;
55 __extraBytes = 0;
56}
57
59 InputStream* __destroy__ _pInput , // new InputStream
60 CharsetDecoder* __destroy__ _pDecoder // new CharsetDecoder
62{
63 __DCL_ASSERT_PARAM(_pInput != NULL);
64
65 __input = _pInput;
66 __decoder = _pDecoder;
67 __closeDestroy = true;
68 __extraBytes = 0;
69}
70
72{
73 if (__input)
74 {
75 try
76 {
77 close();
78 }
79 catch (Exception* e)
80 {
81 __DCL_TRACE1(L"%ls\n", e->toString().data());
82 e->destroy();
83 }
84 }
85}
86
89{
91
92 Exception* e = NULL;
93 InputStream* input = __input;
94 CharsetDecoder* decoder = __decoder;
95 __input = NULL;
97 __extraBytes = 0;
98
100 {
101 if (decoder)
102 decoder->destroy();
103
104 try
105 {
106 input->close();
107 }
108 catch (Exception* cause)
109 {
110 e = cause;
111 }
112 input->destroy();
113 }
114
115 if (e)
116 throw e;
117}
118
119size_t InputStreamReader::read(wchar_t* _buf, size_t _n)
121{
123 __DCL_ASSERT_PARAM(_buf != NULL);
124
125 if (!_n)
126 return 0;
127
128 if (!__decoder)
129 {
130 char bom[4];
131 if (__input->available() >= sizeof(bom))
132 {
133 size_t readCount = __input->read(bom, sizeof(bom));
134 if ((readCount == 4) && IS_UTF32(bom))
135 __decoder = new UTF32Decoder();
136 else if ((readCount >= 3) && IS_UTF8(bom))
137 __decoder = new UTF8Decoder();
138 else if ((readCount >= 2) && IS_UTF16(bom))
139 __decoder = new UTF16Decoder();
140
141 memcpy(__extra, bom, readCount);
142 __extraBytes = readCount;
143 }
144
145 if (!__decoder)
146 __decoder = new LocaleDecoder();
147 }
148
149 wchar_t* outCur = _buf;
150 wchar_t* outEnd = _buf + _n;
151
152#define __BUFFER_SIZE__ 1024
154 size_t extraCount = __extraBytes;
155
156 // Non-Block이 가능한 양 만큼
157 size_t availCount = __input->available();
158 memcpy(inBuf, __extra, extraCount);
159
160 size_t outCount;
161 while ((outCount = outEnd - outCur) && availCount)
162 {
163 size_t readCount = __MIN(__MAX(outCount, __EXTRA_MAX), availCount, __BUFFER_SIZE__);
164 readCount = __input->read(inBuf + extraCount, readCount);
165 availCount -= readCount;
166
167 size_t inCount = readCount + extraCount;
168 if (!inCount)
169 break;
170
171 size_t inCountSave = inCount;
172 int r = __decoder->decode(inBuf, inCount, outCur, outCount);
173 /*__DCL_TRACE4(__T("%ls read[%d], extra[%d], out[%d]\n"),
174 __decoder->className(), readCount, extraCount, outCount);*/
175 extraCount = inCountSave - inCount;
176 switch (r)
177 {
178 case CS_SOURCE_FEW :
179 __DCL_ASSERT(extraCount <= __EXTRA_MAX);
180 if (inCount > 0)
181 memmove(inBuf, inBuf + inCount, extraCount);
182 break;
183 case CS_NOERROR :
184 __DCL_ASSERT(extraCount == 0);
185 break;
186 default :
187 throw(new IOException(toString(), new CharsetConvertException(r)));
188 }
189 outCur += outCount;
190 }
191
192 // 이곳에서 Block 될 수 있다.
193 if ((outCount = outEnd - outCur) > 0)
194 {
195 size_t readCount = __MIN(__MAX(outCount, __EXTRA_MAX), __BUFFER_SIZE__);
196 readCount = __input->read(inBuf + extraCount, readCount);
197 size_t inCount = readCount + extraCount;
198
199 if (inCount)
200 {
201 size_t inCountSave = inCount;
202 int r = __decoder->decode(inBuf, inCount, outCur, outCount);
203 /*__DCL_TRACE4(__T("%ls read[%d], extra[%d], out[%d]\n"),
204 __decoder->className(), readCount, extraCount, outCount);*/
205 extraCount = inCountSave - inCount;
206 switch (r)
207 {
208 case CS_SOURCE_FEW :
209 __DCL_ASSERT(extraCount <= __EXTRA_MAX);
210 if (inCount > 0)
211 memmove(inBuf, inBuf + inCount, extraCount);
212 break;
213 case CS_NOERROR :
214 __DCL_ASSERT(extraCount == 0);
215 break;
216 default :
218 }
219 outCur += outCount;
220 }
221 }
222
223 memcpy(__extra, inBuf, extraCount);
224 __extraBytes = extraCount;
225
226 return outCur - _buf;
227}
228
229__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define IS_UTF16(bom)
Definition Charset.h:36
#define IS_UTF8(bom)
Definition Charset.h:33
#define IS_UTF32(bom)
Definition Charset.h:41
@ CS_SOURCE_FEW
Definition Charset.h:65
@ CS_NOERROR
Definition Charset.h:61
#define NULL
Definition Config.h:340
#define __destroy__
Definition Config.h:363
wchar_t char_t
Definition Config.h:275
unsigned char byte_t
Definition Config.h:274
#define __noclose__
Definition Config.h:360
#define __DCL_THROWS1(e)
Definition Config.h:167
#define __BUFFER_SIZE__
#define __EXTRA_MAX
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#define __DCL_ASSERT_PARAM(expr)
Definition Object.h:384
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:228
#define __T(str)
Definition Object.h:44
#define __DCL_ASSERT_HANDLE(expr)
Definition Object.h:383
ByteString r
virtual String toString() const
Definition Exception.cpp:40
virtual void destroy()
Definition Exception.cpp:74
virtual void close() __DCL_THROWS1(IOException *)
CharsetDecoder * __decoder
virtual String toString() const
InputStreamReader(InputStream &__noclose__ _input, CharsetDecoder &_decoder)
virtual size_t read(wchar_t *_buf, size_t _n) __DCL_THROWS1(IOException *)
InputStream * __input
virtual String toString() const
Definition Object.cpp:187
virtual void destroy()
Definition Object.cpp:192
String className() const
Definition Object.cpp:163
size_t __MAX(size_t x, size_t y)
Definition size_t.h:43
size_t __MIN(size_t x, size_t y)
Definition size_t.h:27