From e30892cf34265760d8bf1117ddc8f5629efc832d Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Tue, 19 Oct 2010 09:25:44 +0000 Subject: [PATCH] wxIsoFile: ... and some more fixes. git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxIsoFile@3944 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/include/Utilities/General.h | 11 - common/include/Utilities/ScopedAlloc.h | 453 +++++++++++++------------ common/src/Utilities/pxStreams.cpp | 409 +++++++++++----------- 3 files changed, 438 insertions(+), 435 deletions(-) diff --git a/common/include/Utilities/General.h b/common/include/Utilities/General.h index cd997fc7fd..4cba92cd50 100644 --- a/common/include/Utilities/General.h +++ b/common/include/Utilities/General.h @@ -176,14 +176,3 @@ extern u64 GetTickFrequency(); extern u64 GetCPUTicks(); extern wxString GetOSVersionString(); - -extern void* __fastcall pcsx2_aligned_malloc(size_t size, size_t align); -extern void* __fastcall pcsx2_aligned_realloc(void* handle, size_t size, size_t align); -extern void pcsx2_aligned_free(void* pmem); - -// aligned_malloc: Implement/declare linux equivalents here! -#if !defined(_MSC_VER) && !defined(HAVE_ALIGNED_MALLOC) -# define _aligned_malloc pcsx2_aligned_malloc -# define _aligned_free pcsx2_aligned_free -# define _aligned_realloc pcsx2_aligned_realloc -#endif diff --git a/common/include/Utilities/ScopedAlloc.h b/common/include/Utilities/ScopedAlloc.h index 60751fafc3..8aa2084e96 100644 --- a/common/include/Utilities/ScopedAlloc.h +++ b/common/include/Utilities/ScopedAlloc.h @@ -1,220 +1,233 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#pragma once - -#include "Exceptions.h" - -// pxUSE_SECURE_MALLOC - enables bounds checking on scoped malloc allocations. - -#ifndef pxUSE_SECURE_MALLOC -#define pxUSE_SECURE_MALLOC 0 -#endif - -////////////////////////////////////////////////////////////////////////////////////////// -// Safe deallocation macros -- checks pointer validity (non-null) when needed, and sets -// pointer to null after deallocation. - -#define safe_delete( ptr ) \ - ((void) (delete (ptr)), (ptr) = NULL) - -#define safe_delete_array( ptr ) \ - ((void) (delete[] (ptr)), (ptr) = NULL) - -// No checks for NULL -- wxWidgets says it's safe to skip NULL checks and it runs on -// just about every compiler and libc implementation of any recentness. -#define safe_free( ptr ) \ - ( (void) (free( ptr ), !!0), (ptr) = NULL ) -//((void) (( ( (ptr) != NULL ) && (free( ptr ), !!0) ), (ptr) = NULL)) - -#define safe_fclose( ptr ) \ - ((void) (( ( (ptr) != NULL ) && (fclose( ptr ), !!0) ), (ptr) = NULL)) - -// Implementation note: all known implementations of _aligned_free check the pointer for -// NULL status (our implementation under GCC, and microsoft's under MSVC), so no need to -// do it here. -#define safe_aligned_free( ptr ) \ - ((void) ( _aligned_free( ptr ), (ptr) = NULL )) - -// -------------------------------------------------------------------------------------- -// BaseScopedAlloc -// -------------------------------------------------------------------------------------- -// Base class that allows various ScopedMalloc types to be passed to functions that act -// on them. -// -// Rationale: This class and the derived varieties are provided as a simple autonomous self- -// destructing container for malloc. The entire class is almost completely dependency free, -// and thus can be included everywhere and anywhere without dependency hassles. -// -template< typename T > -class BaseScopedAlloc -{ -protected: - T* m_buffer; - uint m_size; - -public: - BaseScopedAlloc() - { - m_buffer = NULL; - m_size = 0; - } - - virtual ~BaseScopedAlloc() throw() - { - //pxAssume(m_buffer==NULL); - } - -public: - size_t GetSize() const { return m_size; } - size_t GetLength() const { return m_size; } - - // Allocates the object to the specified size. If an existing allocation is in - // place, it is freed and replaced with the new allocation, and all data is lost. - // Parameter: - // newSize - size of the new allocation, in elements (not bytes!). If the specified - // size is 0, the the allocation is freed, same as calling Free(). - virtual void Alloc( size_t newsize )=0; - - // Re-sizes the allocation to the requested size, without any data loss. - // Parameter: - // newSize - size of the new allocation, in elements (not bytes!). If the specified - // size is 0, the the allocation is freed, same as calling Free(). - virtual void Resize( size_t newsize )=0; - - void Free() - { - Alloc( 0 ); - } - - // Makes enough room for the requested size. Existing data in the array is retained. - void MakeRoomFor( uint size ) - { - if (size <= m_size) return; - Resize( size ); - } - - T* GetPtr( uint idx=0 ) const - { - #if pxUSE_SECURE_MALLOC - IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size ); - #endif - return &m_buffer[idx]; - } - - T& operator[]( uint idx ) - { - #if pxUSE_SECURE_MALLOC - IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size ); - #endif - return m_buffer[idx]; - } - - const T& operator[]( uint idx ) const - { - #if pxUSE_SECURE_MALLOC - IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size ); - #endif - return m_buffer[idx]; - } -}; - -// -------------------------------------------------------------------------------------- -// ScopedAlloc -// -------------------------------------------------------------------------------------- -// A simple container class for a standard malloc allocation. By default, no bounds checking -// is performed, and there is no option for enabling bounds checking. If bounds checking and -// other features are needed, use the more robust SafeArray<> instead. -// -// See docs for BaseScopedAlloc for details and rationale. -// -template< typename T > -class ScopedAlloc : public BaseScopedAlloc -{ -public: - ScopedAlloc( size_t size=0 ) : BaseScopedAlloc() - { - Alloc(size); - } - - virtual ~ScopedAlloc() throw() - { - Alloc(0); - } - - virtual void Alloc( size_t newsize ) - { - safe_free(this->m_buffer); - this->m_size = newsize; - if (!this->m_size) return; - - this->m_buffer = (T*)malloc( this->m_size * sizeof(T) ); - if (!this->m_buffer) - throw Exception::OutOfMemory("ScopedAlloc"); - } - - virtual void Resize( size_t newsize ) - { - this->m_size = newsize; - this->m_buffer = (T*)realloc(this->m_buffer * sizeof(T), newsize); - - if (!this->m_buffer) - throw Exception::OutOfMemory("ScopedAlloc::Resize"); - } -}; - -// -------------------------------------------------------------------------------------- -// ScopedAlignedAlloc -// -------------------------------------------------------------------------------------- -// A simple container class for an aligned allocation. By default, no bounds checking is -// performed, and there is no option for enabling bounds checking. If bounds checking and -// other features are needed, use the more robust SafeArray<> instead. -// -// See docs for BaseScopedAlloc for details and rationale. -// -template< typename T, uint align > -class ScopedAlignedAlloc : public BaseScopedAlloc -{ -public: - ScopedAlignedAlloc( size_t size=0 ) : BaseScopedAlloc() - { - Alloc(size); - } - - virtual ~ScopedAlignedAlloc() throw() - { - Alloc(0); - } - - virtual void Alloc( size_t newsize ) - { - safe_aligned_free(this->m_buffer); - this->m_size = newsize; - if (!this->m_size) return; - - this->m_buffer = (T*)_aligned_malloc( this->m_size * sizeof(T), align ); - if (!this->m_buffer) - throw Exception::OutOfMemory(L"ScopedAlignedAlloc"); - } - - virtual void Resize( size_t newsize ) - { - this->m_size = newsize; - this->m_buffer = (T*)_aligned_realloc(this->m_buffer, newsize * sizeof(T), align); - - if (!this->m_buffer) - throw Exception::OutOfMemory(L"ScopedAlignedAlloc::Resize"); - } -}; +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2010 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#pragma once + +#include "Exceptions.h" + +// pxUSE_SECURE_MALLOC - enables bounds checking on scoped malloc allocations. + +#ifndef pxUSE_SECURE_MALLOC +#define pxUSE_SECURE_MALLOC 0 +#endif + +////////////////////////////////////////////////////////////////////////////////////////// +// Safe deallocation macros -- checks pointer validity (non-null) when needed, and sets +// pointer to null after deallocation. + +#define safe_delete( ptr ) \ + ((void) (delete (ptr)), (ptr) = NULL) + +#define safe_delete_array( ptr ) \ + ((void) (delete[] (ptr)), (ptr) = NULL) + +// No checks for NULL -- wxWidgets says it's safe to skip NULL checks and it runs on +// just about every compiler and libc implementation of any recentness. +#define safe_free( ptr ) \ + ( (void) (free( ptr ), !!0), (ptr) = NULL ) +//((void) (( ( (ptr) != NULL ) && (free( ptr ), !!0) ), (ptr) = NULL)) + +#define safe_fclose( ptr ) \ + ((void) (( ( (ptr) != NULL ) && (fclose( ptr ), !!0) ), (ptr) = NULL)) + +// Implementation note: all known implementations of _aligned_free check the pointer for +// NULL status (our implementation under GCC, and microsoft's under MSVC), so no need to +// do it here. +#define safe_aligned_free( ptr ) \ + ((void) ( _aligned_free( ptr ), (ptr) = NULL )) + + +extern void* __fastcall pcsx2_aligned_malloc(size_t size, size_t align); +extern void* __fastcall pcsx2_aligned_realloc(void* handle, size_t size, size_t align); +extern void pcsx2_aligned_free(void* pmem); + +// aligned_malloc: Implement/declare linux equivalents here! +#if !defined(_MSC_VER) && !defined(HAVE_ALIGNED_MALLOC) +# define _aligned_malloc pcsx2_aligned_malloc +# define _aligned_free pcsx2_aligned_free +# define _aligned_realloc pcsx2_aligned_realloc +#endif + + +// -------------------------------------------------------------------------------------- +// BaseScopedAlloc +// -------------------------------------------------------------------------------------- +// Base class that allows various ScopedMalloc types to be passed to functions that act +// on them. +// +// Rationale: This class and the derived varieties are provided as a simple autonomous self- +// destructing container for malloc. The entire class is almost completely dependency free, +// and thus can be included everywhere and anywhere without dependency hassles. +// +template< typename T > +class BaseScopedAlloc +{ +protected: + T* m_buffer; + uint m_size; + +public: + BaseScopedAlloc() + { + m_buffer = NULL; + m_size = 0; + } + + virtual ~BaseScopedAlloc() throw() + { + //pxAssume(m_buffer==NULL); + } + +public: + size_t GetSize() const { return m_size; } + size_t GetLength() const { return m_size; } + + // Allocates the object to the specified size. If an existing allocation is in + // place, it is freed and replaced with the new allocation, and all data is lost. + // Parameter: + // newSize - size of the new allocation, in elements (not bytes!). If the specified + // size is 0, the the allocation is freed, same as calling Free(). + virtual void Alloc( size_t newsize )=0; + + // Re-sizes the allocation to the requested size, without any data loss. + // Parameter: + // newSize - size of the new allocation, in elements (not bytes!). If the specified + // size is 0, the the allocation is freed, same as calling Free(). + virtual void Resize( size_t newsize )=0; + + void Free() + { + Alloc( 0 ); + } + + // Makes enough room for the requested size. Existing data in the array is retained. + void MakeRoomFor( uint size ) + { + if (size <= m_size) return; + Resize( size ); + } + + T* GetPtr( uint idx=0 ) const + { + #if pxUSE_SECURE_MALLOC + IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size ); + #endif + return &m_buffer[idx]; + } + + T& operator[]( uint idx ) + { + #if pxUSE_SECURE_MALLOC + IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size ); + #endif + return m_buffer[idx]; + } + + const T& operator[]( uint idx ) const + { + #if pxUSE_SECURE_MALLOC + IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size ); + #endif + return m_buffer[idx]; + } +}; + +// -------------------------------------------------------------------------------------- +// ScopedAlloc +// -------------------------------------------------------------------------------------- +// A simple container class for a standard malloc allocation. By default, no bounds checking +// is performed, and there is no option for enabling bounds checking. If bounds checking and +// other features are needed, use the more robust SafeArray<> instead. +// +// See docs for BaseScopedAlloc for details and rationale. +// +template< typename T > +class ScopedAlloc : public BaseScopedAlloc +{ +public: + ScopedAlloc( size_t size=0 ) : BaseScopedAlloc() + { + Alloc(size); + } + + virtual ~ScopedAlloc() throw() + { + Alloc(0); + } + + virtual void Alloc( size_t newsize ) + { + safe_free(this->m_buffer); + this->m_size = newsize; + if (!this->m_size) return; + + this->m_buffer = (T*)malloc( this->m_size * sizeof(T) ); + if (!this->m_buffer) + throw Exception::OutOfMemory("ScopedAlloc"); + } + + virtual void Resize( size_t newsize ) + { + this->m_size = newsize; + this->m_buffer = (T*)realloc(this->m_buffer * sizeof(T), newsize); + + if (!this->m_buffer) + throw Exception::OutOfMemory("ScopedAlloc::Resize"); + } +}; + +// -------------------------------------------------------------------------------------- +// ScopedAlignedAlloc +// -------------------------------------------------------------------------------------- +// A simple container class for an aligned allocation. By default, no bounds checking is +// performed, and there is no option for enabling bounds checking. If bounds checking and +// other features are needed, use the more robust SafeArray<> instead. +// +// See docs for BaseScopedAlloc for details and rationale. +// +template< typename T, uint align > +class ScopedAlignedAlloc : public BaseScopedAlloc +{ +public: + ScopedAlignedAlloc( size_t size=0 ) : BaseScopedAlloc() + { + Alloc(size); + } + + virtual ~ScopedAlignedAlloc() throw() + { + Alloc(0); + } + + virtual void Alloc( size_t newsize ) + { + safe_aligned_free(this->m_buffer); + this->m_size = newsize; + if (!this->m_size) return; + + this->m_buffer = (T*)_aligned_malloc( this->m_size * sizeof(T), align ); + if (!this->m_buffer) + throw Exception::OutOfMemory(L"ScopedAlignedAlloc"); + } + + virtual void Resize( size_t newsize ) + { + this->m_size = newsize; + this->m_buffer = (T*)_aligned_realloc(this->m_buffer, newsize * sizeof(T), align); + + if (!this->m_buffer) + throw Exception::OutOfMemory(L"ScopedAlignedAlloc::Resize"); + } +}; diff --git a/common/src/Utilities/pxStreams.cpp b/common/src/Utilities/pxStreams.cpp index 9966f2360f..3d960a430c 100644 --- a/common/src/Utilities/pxStreams.cpp +++ b/common/src/Utilities/pxStreams.cpp @@ -1,204 +1,205 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#include "PrecompiledHeader.h" -#include "wxBaseTools.h" -#include "pxStreams.h" - -#include - - -// -------------------------------------------------------------------------------------- -// pxStreamReader (implementations) -// -------------------------------------------------------------------------------------- -// Interface for reading data from a gzip stream. -// - -pxStreamReader::pxStreamReader(const wxString& filename, ScopedPtr& input) - : m_filename( filename ) - , m_stream( input.DetachPtr() ) -{ -} - -pxStreamReader::pxStreamReader(const wxString& filename, wxInputStream* input) - : m_filename( filename ) - , m_stream( input ) -{ -} - -void pxStreamReader::SetStream( const wxString& filename, ScopedPtr& stream ) -{ - m_filename = filename; - m_stream = stream.DetachPtr(); -} - -void pxStreamReader::SetStream( const wxString& filename, wxInputStream* stream ) -{ - m_filename = filename; - m_stream = stream; -} - -void pxStreamReader::Read( void* dest, size_t size ) -{ - m_stream->Read(dest, size); - if (m_stream->GetLastError() == wxSTREAM_READ_ERROR) - { - int err = errno; - if (!err) - throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot read from file (bad file handle?)"); - - ScopedExcept ex(Exception::FromErrno(m_filename, err)); - ex->SetDiagMsg( L"cannot read from file: " + ex->DiagMsg() ); - ex->Rethrow(); - } - - // IMPORTANT! The underlying file/source Eof() stuff is not really reliable, so we - // must always use the explicit check against the number of bytes read to determine - // end-of-stream conditions. - - if ((size_t)m_stream->LastRead() < size) - throw Exception::EndOfStream( m_filename ); -} - -// -------------------------------------------------------------------------------------- -// pxStreamWriter -// -------------------------------------------------------------------------------------- -pxStreamWriter::pxStreamWriter(const wxString& filename, ScopedPtr& output) - : m_filename( filename ) - , m_outstream( output.DetachPtr() ) -{ - -} - -pxStreamWriter::pxStreamWriter(const wxString& filename, wxOutputStream* output) - : m_filename( filename ) - , m_outstream( output ) -{ -} - -void pxStreamWriter::SetStream( const wxString& filename, ScopedPtr& stream ) -{ - m_filename = filename; - m_outstream = stream.DetachPtr(); -} - -void pxStreamWriter::SetStream( const wxString& filename, wxOutputStream* stream ) -{ - m_filename = filename; - m_outstream = stream; -} - - -void pxStreamWriter::Write( const void* src, size_t size ) -{ - m_outstream->Write(src, size); - if(m_outstream->GetLastError() == wxSTREAM_WRITE_ERROR) - { - int err = errno; - if (!err) - throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot write to file/stream."); - - ScopedExcept ex(Exception::FromErrno(m_filename, err)); - ex->SetDiagMsg( L"Cannot write to file: " + ex->DiagMsg() ); - ex->Rethrow(); - } -} - -// -------------------------------------------------------------------------------------- -// pxTextStream -// -------------------------------------------------------------------------------------- - -// Returns TRUE if the source is UTF8, or FALSE if it's just ASCII crap. -bool pxReadLine( wxInputStream& input, std::string& dest ) -{ - dest.clear(); - bool isUTF8 = false; - while ( true ) - { - char c; - input.Read(&c, sizeof(c)); - if( c == 0 ) break; - if( input.Eof() ) break; - if( c == '\n' ) break; // eat on UNIX - if( c == '\r' ) - { - input.Read(&c, sizeof(c)); - if( c == 0 ) break; - if( input.Eof() ) break; - if( c == '\n' ) break; - - input.Ungetch(c); - break; - } - dest += c; - if( c & 0x80 ) isUTF8 = true; - } - - return isUTF8; -} - -void pxReadLine( wxInputStream& input, wxString& dest, std::string& intermed ) -{ - dest.clear(); - if( pxReadLine( input, intermed ) ) - dest = fromUTF8(intermed.c_str()); - else - { - // Optimized ToAscii conversion. - // wx3.0 : NOT COMPATIBLE!! (on linux anyway) - const char* ascii = intermed.c_str(); - while( *ascii != 0 ) dest += (wchar_t)(unsigned char)*ascii++; - } -} - -void pxReadLine( wxInputStream& input, wxString& dest ) -{ - std::string line; - pxReadLine( input, dest, line ); -} - -wxString pxReadLine( wxInputStream& input ) -{ - wxString result; - pxReadLine( input, result ); - return result; -} - -void pxWriteLine( wxOutputStream& output ) -{ - output.Write( "\n", 1 ); -} - -void pxWriteLine( wxOutputStream& output, const wxString& text ) -{ - if( !text.IsEmpty() ) - { - pxToUTF8 utf8(text); - output.Write(utf8, utf8.Length()); - } - pxWriteLine( output ); -} - -void pxWriteMultiline( wxOutputStream& output, const wxString& src ) -{ - if( src.IsEmpty() ) return; - - wxString result( src ); - result.Replace( L"\r\n", L"\n" ); - result.Replace( L"\r", L"\n" ); - - pxToUTF8 utf8(result); - output.Write(utf8, utf8.Length()); -} +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2010 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#include "PrecompiledHeader.h" +#include "wxBaseTools.h" +#include "pxStreams.h" + +#include + +#include + +// -------------------------------------------------------------------------------------- +// pxStreamReader (implementations) +// -------------------------------------------------------------------------------------- +// Interface for reading data from a gzip stream. +// + +pxStreamReader::pxStreamReader(const wxString& filename, ScopedPtr& input) + : m_filename( filename ) + , m_stream( input.DetachPtr() ) +{ +} + +pxStreamReader::pxStreamReader(const wxString& filename, wxInputStream* input) + : m_filename( filename ) + , m_stream( input ) +{ +} + +void pxStreamReader::SetStream( const wxString& filename, ScopedPtr& stream ) +{ + m_filename = filename; + m_stream = stream.DetachPtr(); +} + +void pxStreamReader::SetStream( const wxString& filename, wxInputStream* stream ) +{ + m_filename = filename; + m_stream = stream; +} + +void pxStreamReader::Read( void* dest, size_t size ) +{ + m_stream->Read(dest, size); + if (m_stream->GetLastError() == wxSTREAM_READ_ERROR) + { + int err = errno; + if (!err) + throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot read from file (bad file handle?)"); + + ScopedExcept ex(Exception::FromErrno(m_filename, err)); + ex->SetDiagMsg( L"cannot read from file: " + ex->DiagMsg() ); + ex->Rethrow(); + } + + // IMPORTANT! The underlying file/source Eof() stuff is not really reliable, so we + // must always use the explicit check against the number of bytes read to determine + // end-of-stream conditions. + + if ((size_t)m_stream->LastRead() < size) + throw Exception::EndOfStream( m_filename ); +} + +// -------------------------------------------------------------------------------------- +// pxStreamWriter +// -------------------------------------------------------------------------------------- +pxStreamWriter::pxStreamWriter(const wxString& filename, ScopedPtr& output) + : m_filename( filename ) + , m_outstream( output.DetachPtr() ) +{ + +} + +pxStreamWriter::pxStreamWriter(const wxString& filename, wxOutputStream* output) + : m_filename( filename ) + , m_outstream( output ) +{ +} + +void pxStreamWriter::SetStream( const wxString& filename, ScopedPtr& stream ) +{ + m_filename = filename; + m_outstream = stream.DetachPtr(); +} + +void pxStreamWriter::SetStream( const wxString& filename, wxOutputStream* stream ) +{ + m_filename = filename; + m_outstream = stream; +} + + +void pxStreamWriter::Write( const void* src, size_t size ) +{ + m_outstream->Write(src, size); + if(m_outstream->GetLastError() == wxSTREAM_WRITE_ERROR) + { + int err = errno; + if (!err) + throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot write to file/stream."); + + ScopedExcept ex(Exception::FromErrno(m_filename, err)); + ex->SetDiagMsg( L"Cannot write to file: " + ex->DiagMsg() ); + ex->Rethrow(); + } +} + +// -------------------------------------------------------------------------------------- +// pxTextStream +// -------------------------------------------------------------------------------------- + +// Returns TRUE if the source is UTF8, or FALSE if it's just ASCII crap. +bool pxReadLine( wxInputStream& input, std::string& dest ) +{ + dest.clear(); + bool isUTF8 = false; + while ( true ) + { + char c; + input.Read(&c, sizeof(c)); + if( c == 0 ) break; + if( input.Eof() ) break; + if( c == '\n' ) break; // eat on UNIX + if( c == '\r' ) + { + input.Read(&c, sizeof(c)); + if( c == 0 ) break; + if( input.Eof() ) break; + if( c == '\n' ) break; + + input.Ungetch(c); + break; + } + dest += c; + if( c & 0x80 ) isUTF8 = true; + } + + return isUTF8; +} + +void pxReadLine( wxInputStream& input, wxString& dest, std::string& intermed ) +{ + dest.clear(); + if( pxReadLine( input, intermed ) ) + dest = fromUTF8(intermed.c_str()); + else + { + // Optimized ToAscii conversion. + // wx3.0 : NOT COMPATIBLE!! (on linux anyway) + const char* ascii = intermed.c_str(); + while( *ascii != 0 ) dest += (wchar_t)(unsigned char)*ascii++; + } +} + +void pxReadLine( wxInputStream& input, wxString& dest ) +{ + std::string line; + pxReadLine( input, dest, line ); +} + +wxString pxReadLine( wxInputStream& input ) +{ + wxString result; + pxReadLine( input, result ); + return result; +} + +void pxWriteLine( wxOutputStream& output ) +{ + output.Write( "\n", 1 ); +} + +void pxWriteLine( wxOutputStream& output, const wxString& text ) +{ + if( !text.IsEmpty() ) + { + pxToUTF8 utf8(text); + output.Write(utf8, utf8.Length()); + } + pxWriteLine( output ); +} + +void pxWriteMultiline( wxOutputStream& output, const wxString& src ) +{ + if( src.IsEmpty() ) return; + + wxString result( src ); + result.Replace( L"\r\n", L"\n" ); + result.Replace( L"\r", L"\n" ); + + pxToUTF8 utf8(result); + output.Write(utf8, utf8.Length()); +}