1/////////////////////////////////////////////////////////////////////////////// 2// Name: src/common/txtstrm.cpp 3// Purpose: Text stream classes 4// Author: Guilhem Lavaux 5// Modified by: 6// Created: 28/06/98 7// RCS-ID: $Id: txtstrm.cpp 48920 2007-09-24 13:11:36Z JS $ 8// Copyright: (c) Guilhem Lavaux 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#ifdef __BORLANDC__ 16 #pragma hdrstop 17#endif 18 19#if wxUSE_STREAMS 20 21#include "wx/txtstrm.h" 22#include <ctype.h> 23 24 25// ---------------------------------------------------------------------------- 26// constants 27// ---------------------------------------------------------------------------- 28 29// Unix: "\n" 30// Dos: "\r\n" 31// Mac: "\r" 32 33// ---------------------------------------------------------------------------- 34// wxTextInputStream 35// ---------------------------------------------------------------------------- 36 37#if wxUSE_UNICODE 38wxTextInputStream::wxTextInputStream(wxInputStream &s, 39 const wxString &sep, 40 const wxMBConv& conv) 41 : m_input(s), m_separators(sep), m_conv(conv.Clone()) 42{ 43 memset((void*)m_lastBytes, 0, 10); 44} 45#else 46wxTextInputStream::wxTextInputStream(wxInputStream &s, const wxString &sep) 47 : m_input(s), m_separators(sep) 48{ 49 memset((void*)m_lastBytes, 0, 10); 50} 51#endif 52 53wxTextInputStream::~wxTextInputStream() 54{ 55#if wxUSE_UNICODE 56 delete m_conv; 57#endif // wxUSE_UNICODE 58} 59 60void wxTextInputStream::UngetLast() 61{ 62 size_t byteCount = 0; 63 while(m_lastBytes[byteCount]) // pseudo ANSI strlen (even for Unicode!) 64 byteCount++; 65 m_input.Ungetch(m_lastBytes, byteCount); 66 memset((void*)m_lastBytes, 0, 10); 67} 68 69wxChar wxTextInputStream::NextChar() 70{ 71#if wxUSE_UNICODE 72 wxChar wbuf[2]; 73 memset((void*)m_lastBytes, 0, 10); 74 for(size_t inlen = 0; inlen < 9; inlen++) 75 { 76 // actually read the next character 77 m_lastBytes[inlen] = m_input.GetC(); 78 79 if(m_input.LastRead() <= 0) 80 return wxEOT; 81 82 if ( m_conv->ToWChar(wbuf, WXSIZEOF(wbuf), m_lastBytes, inlen + 1) 83 != wxCONV_FAILED ) 84 return wbuf[0]; 85 } 86 // there should be no encoding which requires more than nine bytes for one character... 87 return wxEOT; 88#else 89 m_lastBytes[0] = m_input.GetC(); 90 91 if(m_input.LastRead() <= 0) 92 return wxEOT; 93 94 return m_lastBytes[0]; 95#endif 96 97} 98 99wxChar wxTextInputStream::NextNonSeparators() 100{ 101 for (;;) 102 { 103 wxChar c = NextChar(); 104 if (c == wxEOT) return (wxChar) 0; 105 106 if (c != wxT('\n') && 107 c != wxT('\r') && 108 !m_separators.Contains(c)) 109 return c; 110 } 111 112} 113 114bool wxTextInputStream::EatEOL(const wxChar &c) 115{ 116 if (c == wxT('\n')) return true; // eat on UNIX 117 118 if (c == wxT('\r')) // eat on both Mac and DOS 119 { 120 wxChar c2 = NextChar(); 121 if(c2 == wxEOT) return true; // end of stream reached, had enough :-) 122 123 if (c2 != wxT('\n')) UngetLast(); // Don't eat on Mac 124 return true; 125 } 126 127 return false; 128} 129 130wxUint32 wxTextInputStream::Read32(int base) 131{ 132 wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); 133 if(!m_input) return 0; 134 135 wxString word = ReadWord(); 136 if(word.empty()) 137 return 0; 138 return wxStrtoul(word.c_str(), 0, base); 139} 140 141wxUint16 wxTextInputStream::Read16(int base) 142{ 143 return (wxUint16)Read32(base); 144} 145 146wxUint8 wxTextInputStream::Read8(int base) 147{ 148 return (wxUint8)Read32(base); 149} 150 151wxInt32 wxTextInputStream::Read32S(int base) 152{ 153 wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); 154 if(!m_input) return 0; 155 156 wxString word = ReadWord(); 157 if(word.empty()) 158 return 0; 159 return wxStrtol(word.c_str(), 0, base); 160} 161 162wxInt16 wxTextInputStream::Read16S(int base) 163{ 164 return (wxInt16)Read32S(base); 165} 166 167wxInt8 wxTextInputStream::Read8S(int base) 168{ 169 return (wxInt8)Read32S(base); 170} 171 172double wxTextInputStream::ReadDouble() 173{ 174 if(!m_input) return 0; 175 wxString word = ReadWord(); 176 if(word.empty()) 177 return 0; 178 return wxStrtod(word.c_str(), 0); 179} 180 181#if WXWIN_COMPATIBILITY_2_6 182 183wxString wxTextInputStream::ReadString() 184{ 185 return ReadLine(); 186} 187 188#endif // WXWIN_COMPATIBILITY_2_6 189 190wxString wxTextInputStream::ReadLine() 191{ 192 wxString line; 193 194 while ( !m_input.Eof() ) 195 { 196 wxChar c = NextChar(); 197 if(c == wxEOT) 198 break; 199 200 if (EatEOL(c)) 201 break; 202 203 line += c; 204 } 205 206 return line; 207} 208 209wxString wxTextInputStream::ReadWord() 210{ 211 wxString word; 212 213 if ( !m_input ) 214 return word; 215 216 wxChar c = NextNonSeparators(); 217 if ( !c ) 218 return word; 219 220 word += c; 221 222 while ( !m_input.Eof() ) 223 { 224 c = NextChar(); 225 if(c == wxEOT) 226 break; 227 228 if (m_separators.Contains(c)) 229 break; 230 231 if (EatEOL(c)) 232 break; 233 234 word += c; 235 } 236 237 return word; 238} 239 240wxTextInputStream& wxTextInputStream::operator>>(wxString& word) 241{ 242 word = ReadWord(); 243 return *this; 244} 245 246wxTextInputStream& wxTextInputStream::operator>>(char& c) 247{ 248 c = m_input.GetC(); 249 if(m_input.LastRead() <= 0) c = 0; 250 251 if (EatEOL(c)) 252 c = '\n'; 253 254 return *this; 255} 256 257#if wxUSE_UNICODE && wxWCHAR_T_IS_REAL_TYPE 258 259wxTextInputStream& wxTextInputStream::operator>>(wchar_t& wc) 260{ 261 wc = GetChar(); 262 263 return *this; 264} 265 266#endif // wxUSE_UNICODE 267 268wxTextInputStream& wxTextInputStream::operator>>(wxInt16& i) 269{ 270 i = (wxInt16)Read16(); 271 return *this; 272} 273 274wxTextInputStream& wxTextInputStream::operator>>(wxInt32& i) 275{ 276 i = (wxInt32)Read32(); 277 return *this; 278} 279 280wxTextInputStream& wxTextInputStream::operator>>(wxUint16& i) 281{ 282 i = Read16(); 283 return *this; 284} 285 286wxTextInputStream& wxTextInputStream::operator>>(wxUint32& i) 287{ 288 i = Read32(); 289 return *this; 290} 291 292wxTextInputStream& wxTextInputStream::operator>>(double& i) 293{ 294 i = ReadDouble(); 295 return *this; 296} 297 298wxTextInputStream& wxTextInputStream::operator>>(float& f) 299{ 300 f = (float)ReadDouble(); 301 return *this; 302} 303 304 305 306#if wxUSE_UNICODE 307wxTextOutputStream::wxTextOutputStream(wxOutputStream& s, 308 wxEOL mode, 309 const wxMBConv& conv) 310 : m_output(s), m_conv(conv.Clone()) 311#else 312wxTextOutputStream::wxTextOutputStream(wxOutputStream& s, wxEOL mode) 313 : m_output(s) 314#endif 315{ 316 m_mode = mode; 317 if (m_mode == wxEOL_NATIVE) 318 { 319#if defined(__WXMSW__) || defined(__WXPM__) 320 m_mode = wxEOL_DOS; 321#elif defined(__WXMAC__) && !defined(__DARWIN__) 322 m_mode = wxEOL_MAC; 323#else 324 m_mode = wxEOL_UNIX; 325#endif 326 } 327} 328 329wxTextOutputStream::~wxTextOutputStream() 330{ 331#if wxUSE_UNICODE 332 delete m_conv; 333#endif // wxUSE_UNICODE 334} 335 336void wxTextOutputStream::SetMode(wxEOL mode) 337{ 338 m_mode = mode; 339 if (m_mode == wxEOL_NATIVE) 340 { 341#if defined(__WXMSW__) || defined(__WXPM__) 342 m_mode = wxEOL_DOS; 343#elif defined(__WXMAC__) && !defined(__DARWIN__) 344 m_mode = wxEOL_MAC; 345#else 346 m_mode = wxEOL_UNIX; 347#endif 348 } 349} 350 351void wxTextOutputStream::Write32(wxUint32 i) 352{ 353 wxString str; 354 str.Printf(wxT("%u"), i); 355 356 WriteString(str); 357} 358 359void wxTextOutputStream::Write16(wxUint16 i) 360{ 361 wxString str; 362 str.Printf(wxT("%u"), (unsigned)i); 363 364 WriteString(str); 365} 366 367void wxTextOutputStream::Write8(wxUint8 i) 368{ 369 wxString str; 370 str.Printf(wxT("%u"), (unsigned)i); 371 372 WriteString(str); 373} 374 375void wxTextOutputStream::WriteDouble(double d) 376{ 377 wxString str; 378 379 str.Printf(wxT("%f"), d); 380 WriteString(str); 381} 382 383void wxTextOutputStream::WriteString(const wxString& string) 384{ 385 size_t len = string.length(); 386 387 wxString out; 388 out.reserve(len); 389 390 for ( size_t i = 0; i < len; i++ ) 391 { 392 const wxChar c = string[i]; 393 if ( c == wxT('\n') ) 394 { 395 switch ( m_mode ) 396 { 397 case wxEOL_DOS: 398 out << _T("\r\n"); 399 continue; 400 401 case wxEOL_MAC: 402 out << _T('\r'); 403 continue; 404 405 default: 406 wxFAIL_MSG( _T("unknown EOL mode in wxTextOutputStream") ); 407 // fall through 408 409 case wxEOL_UNIX: 410 // don't treat '\n' specially 411 ; 412 } 413 } 414 415 out << c; 416 } 417 418#if wxUSE_UNICODE 419 wxCharBuffer buffer = m_conv->cWC2MB(out, out.length(), &len); 420 m_output.Write(buffer, len); 421#else 422 m_output.Write(out.c_str(), out.length() ); 423#endif 424} 425 426wxTextOutputStream& wxTextOutputStream::PutChar(wxChar c) 427{ 428#if wxUSE_UNICODE 429 WriteString( wxString(&c, *m_conv, 1) ); 430#else 431 WriteString( wxString(&c, wxConvLocal, 1) ); 432#endif 433 return *this; 434} 435 436wxTextOutputStream& wxTextOutputStream::operator<<(const wxChar *string) 437{ 438 WriteString( wxString(string) ); 439 return *this; 440} 441 442wxTextOutputStream& wxTextOutputStream::operator<<(const wxString& string) 443{ 444 WriteString( string ); 445 return *this; 446} 447 448wxTextOutputStream& wxTextOutputStream::operator<<(char c) 449{ 450 WriteString( wxString::FromAscii(c) ); 451 452 return *this; 453} 454 455#if wxUSE_UNICODE && wxWCHAR_T_IS_REAL_TYPE 456 457wxTextOutputStream& wxTextOutputStream::operator<<(wchar_t wc) 458{ 459 WriteString( wxString(&wc, *m_conv, 1) ); 460 461 return *this; 462} 463 464#endif // wxUSE_UNICODE 465 466wxTextOutputStream& wxTextOutputStream::operator<<(wxInt16 c) 467{ 468 wxString str; 469 str.Printf(wxT("%d"), (signed int)c); 470 WriteString(str); 471 472 return *this; 473} 474 475wxTextOutputStream& wxTextOutputStream::operator<<(wxInt32 c) 476{ 477 wxString str; 478 str.Printf(wxT("%ld"), (signed long)c); 479 WriteString(str); 480 481 return *this; 482} 483 484wxTextOutputStream& wxTextOutputStream::operator<<(wxUint16 c) 485{ 486 wxString str; 487 str.Printf(wxT("%u"), (unsigned int)c); 488 WriteString(str); 489 490 return *this; 491} 492 493wxTextOutputStream& wxTextOutputStream::operator<<(wxUint32 c) 494{ 495 wxString str; 496 str.Printf(wxT("%lu"), (unsigned long)c); 497 WriteString(str); 498 499 return *this; 500} 501 502wxTextOutputStream &wxTextOutputStream::operator<<(double f) 503{ 504 WriteDouble(f); 505 return *this; 506} 507 508wxTextOutputStream& wxTextOutputStream::operator<<(float f) 509{ 510 WriteDouble((double)f); 511 return *this; 512} 513 514wxTextOutputStream &endl( wxTextOutputStream &stream ) 515{ 516 return stream.PutChar(wxT('\n')); 517} 518 519#endif 520 // wxUSE_STREAMS 521