2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
40 void Stream::ThrowError(LPCTSTR fmt
, ...)
44 int len
= _vsctprintf(fmt
, args
) + 1;
46 if(len
> 0) _vstprintf_s(str
.GetBufferSetLength(len
), len
, fmt
, args
);
49 throw Exception(_T("Error (Ln %d Col %d): %s"), m_line
+1, m_col
+1, str
);
52 bool Stream::IsWhiteSpace(int c
, LPCWSTR morechars
)
54 return c
!= 0xa0 && iswspace(c
) || morechars
&& wcschr(morechars
, (WCHAR
)c
);
59 InputStream::InputStream()
64 InputStream::~InputStream()
68 int InputStream::NextChar()
70 if(m_encoding
== none
)
77 if(NextByte() == 0xbb && NextByte() == 0xbf) m_encoding
= utf8
;
80 if(NextByte() == 0xfe) m_encoding
= utf16le
;
83 if(NextByte() == 0xff) m_encoding
= utf16be
;
88 if(m_encoding
== unknown
)
90 throw Exception(_T("unknown character encoding, missing BOM"));
100 for(i
= 7; i
>= 0 && (cur
& (1 << i
)); i
--);
102 while(++i
< 7) {c
= NextByte(); if(c
== EOS
) {cur
= EOS
; break;} cur
= (cur
<< 6) | (c
& 0x3f);}
106 if(c
== EOS
) {cur
= EOS
; break;}
107 cur
= (c
<< 8) | cur
;
111 if(c
== EOS
) {cur
= EOS
; break;}
112 cur
= cur
| (c
<< 8);
121 int InputStream::PushChar()
128 int InputStream::PopChar()
130 if(m_queue
.IsEmpty()) ThrowError(_T("fatal stream error"));
132 int c
= m_queue
.RemoveHead();
136 if(c
== '\n') {m_line
++; m_col
= -1;}
143 int InputStream::PeekChar()
145 while(m_queue
.GetCount() < 2) PushChar();
147 ASSERT(m_queue
.GetCount() == 2);
149 if(m_queue
.GetHead() == '/' && m_queue
.GetTail() == '/')
151 while(!m_queue
.IsEmpty()) PopChar();
153 do {PushChar(); c
= PopChar();} while(!(c
== '\n' || c
== EOS
));
156 else if(m_queue
.GetHead() == '/' && m_queue
.GetTail() == '*')
158 while(!m_queue
.IsEmpty()) PopChar();
161 do {c2
= PushChar(); c1
= PopChar();} while(!((c1
== '*' && c2
== '/') || c1
== EOS
));
166 return m_queue
.GetHead();
169 int InputStream::GetChar()
171 if(m_queue
.GetCount() < 2) PeekChar();
175 int InputStream::SkipWhiteSpace(LPCWSTR morechars
)
178 for(; IsWhiteSpace(c
, morechars
); c
= PeekChar())
185 FileInputStream::FileInputStream(const TCHAR
* fn
)
188 if(_tfopen_s(&m_file
, fn
, _T("r")) != 0) ThrowError(_T("cannot open file '%s'"), fn
);
191 FileInputStream::~FileInputStream()
193 if(m_file
) {fclose(m_file
); m_file
= NULL
;}
196 int FileInputStream::NextByte()
198 if(!m_file
) ThrowError(_T("file pointer is NULL"));
199 return fgetc(m_file
);
204 MemoryInputStream::MemoryInputStream(BYTE
* pBytes
, int len
, bool fCopy
, bool fFree
)
211 m_pBytes
= new BYTE
[len
];
212 if(m_pBytes
) memcpy(m_pBytes
, pBytes
, len
);
221 if(!m_pBytes
) ThrowError(_T("memory stream pointer is NULL"));
224 MemoryInputStream::~MemoryInputStream()
226 if(m_fFree
) delete [] m_pBytes
;
230 int MemoryInputStream::NextByte()
232 if(!m_pBytes
) ThrowError(_T("memory stream pointer is NULL"));
233 if(m_pos
>= m_len
) return Stream::EOS
;
234 return (int)m_pBytes
[m_pos
++];
239 WCharInputStream::WCharInputStream(CStringW str
)
243 m_encoding
= Stream::wchar
; // HACK: it should return real bytes from NextByte (two per wchar_t), but this way it's a lot more simple...
246 int WCharInputStream::NextByte()
248 if(m_pos
>= m_str
.GetLength()) return Stream::EOS
;
249 return m_str
[m_pos
++];
254 OutputStream::OutputStream(encoding_t e
)
260 OutputStream::~OutputStream()
264 void OutputStream::PutChar(WCHAR c
)
283 if(0 <= c
&& c
< 0x80) // 0xxxxxxx
287 else if(0x80 <= c
&& c
< 0x800) // 110xxxxx 10xxxxxx
289 NextByte(0xc0 | ((c
<<2)&0x1f));
290 NextByte(0x80 | ((c
<<0)&0x3f));
292 else if(0x800 <= c
&& c
< 0xFFFF) // 1110xxxx 10xxxxxx 10xxxxxx
294 NextByte(0xe0 | ((c
<<4)&0x0f));
295 NextByte(0x80 | ((c
<<2)&0x3f));
296 NextByte(0x80 | ((c
<<0)&0x3f));
305 NextByte((c
>> 8) & 0xff);
308 NextByte((c
>> 8) & 0xff);
317 void OutputStream::PutString(LPCWSTR fmt
, ...)
323 int len
= _vscwprintf(fmt
, args
) + 1;
324 if(len
> 0) vswprintf_s(str
.GetBufferSetLength(len
), len
, fmt
, args
);
328 while(*s
) PutChar(*s
++);
333 WCharOutputStream::WCharOutputStream()
334 : OutputStream(wchar
)
338 void WCharOutputStream::NextByte(int b
)
345 DebugOutputStream::DebugOutputStream()
346 : OutputStream(wchar
)
350 DebugOutputStream::~DebugOutputStream()
352 TRACE(_T("%s\n"), m_str
);
355 void DebugOutputStream::NextByte(int b
)
357 if(b
== '\n') {TRACE(_T("%s\n"), m_str
); m_str
.Empty();}
358 else if(b
!= '\r') m_str
+= (WCHAR
)b
;