wxIsoFile: ... and some more fixes.

git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxIsoFile@3944 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-10-19 09:25:44 +00:00
parent ca9e250837
commit e30892cf34
3 changed files with 438 additions and 435 deletions

View File

@ -176,14 +176,3 @@ extern u64 GetTickFrequency();
extern u64 GetCPUTicks(); extern u64 GetCPUTicks();
extern wxString GetOSVersionString(); 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

View File

@ -1,220 +1,233 @@
/* PCSX2 - PS2 Emulator for PCs /* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team * Copyright (C) 2002-2010 PCSX2 Dev Team
* *
* PCSX2 is free software: you can redistribute it and/or modify it under the terms * 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- * 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. * 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; * 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 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details. * 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. * You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "Exceptions.h" #include "Exceptions.h"
// pxUSE_SECURE_MALLOC - enables bounds checking on scoped malloc allocations. // pxUSE_SECURE_MALLOC - enables bounds checking on scoped malloc allocations.
#ifndef pxUSE_SECURE_MALLOC #ifndef pxUSE_SECURE_MALLOC
#define pxUSE_SECURE_MALLOC 0 #define pxUSE_SECURE_MALLOC 0
#endif #endif
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Safe deallocation macros -- checks pointer validity (non-null) when needed, and sets // Safe deallocation macros -- checks pointer validity (non-null) when needed, and sets
// pointer to null after deallocation. // pointer to null after deallocation.
#define safe_delete( ptr ) \ #define safe_delete( ptr ) \
((void) (delete (ptr)), (ptr) = NULL) ((void) (delete (ptr)), (ptr) = NULL)
#define safe_delete_array( ptr ) \ #define safe_delete_array( ptr ) \
((void) (delete[] (ptr)), (ptr) = NULL) ((void) (delete[] (ptr)), (ptr) = NULL)
// No checks for NULL -- wxWidgets says it's safe to skip NULL checks and it runs on // 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. // just about every compiler and libc implementation of any recentness.
#define safe_free( ptr ) \ #define safe_free( ptr ) \
( (void) (free( ptr ), !!0), (ptr) = NULL ) ( (void) (free( ptr ), !!0), (ptr) = NULL )
//((void) (( ( (ptr) != NULL ) && (free( ptr ), !!0) ), (ptr) = NULL)) //((void) (( ( (ptr) != NULL ) && (free( ptr ), !!0) ), (ptr) = NULL))
#define safe_fclose( ptr ) \ #define safe_fclose( ptr ) \
((void) (( ( (ptr) != NULL ) && (fclose( ptr ), !!0) ), (ptr) = NULL)) ((void) (( ( (ptr) != NULL ) && (fclose( ptr ), !!0) ), (ptr) = NULL))
// Implementation note: all known implementations of _aligned_free check the pointer for // 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 // NULL status (our implementation under GCC, and microsoft's under MSVC), so no need to
// do it here. // do it here.
#define safe_aligned_free( ptr ) \ #define safe_aligned_free( ptr ) \
((void) ( _aligned_free( ptr ), (ptr) = NULL )) ((void) ( _aligned_free( ptr ), (ptr) = NULL ))
// --------------------------------------------------------------------------------------
// BaseScopedAlloc 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);
// Base class that allows various ScopedMalloc types to be passed to functions that act extern void pcsx2_aligned_free(void* pmem);
// on them.
// // aligned_malloc: Implement/declare linux equivalents here!
// Rationale: This class and the derived varieties are provided as a simple autonomous self- #if !defined(_MSC_VER) && !defined(HAVE_ALIGNED_MALLOC)
// destructing container for malloc. The entire class is almost completely dependency free, # define _aligned_malloc pcsx2_aligned_malloc
// and thus can be included everywhere and anywhere without dependency hassles. # define _aligned_free pcsx2_aligned_free
// # define _aligned_realloc pcsx2_aligned_realloc
template< typename T > #endif
class BaseScopedAlloc
{
protected: // --------------------------------------------------------------------------------------
T* m_buffer; // BaseScopedAlloc
uint m_size; // --------------------------------------------------------------------------------------
// Base class that allows various ScopedMalloc types to be passed to functions that act
public: // on them.
BaseScopedAlloc() //
{ // Rationale: This class and the derived varieties are provided as a simple autonomous self-
m_buffer = NULL; // destructing container for malloc. The entire class is almost completely dependency free,
m_size = 0; // and thus can be included everywhere and anywhere without dependency hassles.
} //
template< typename T >
virtual ~BaseScopedAlloc() throw() class BaseScopedAlloc
{ {
//pxAssume(m_buffer==NULL); protected:
} T* m_buffer;
uint m_size;
public:
size_t GetSize() const { return m_size; } public:
size_t GetLength() const { return m_size; } BaseScopedAlloc()
{
// Allocates the object to the specified size. If an existing allocation is in m_buffer = NULL;
// place, it is freed and replaced with the new allocation, and all data is lost. m_size = 0;
// 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 ~BaseScopedAlloc() throw()
virtual void Alloc( size_t newsize )=0; {
//pxAssume(m_buffer==NULL);
// 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 public:
// size is 0, the the allocation is freed, same as calling Free(). size_t GetSize() const { return m_size; }
virtual void Resize( size_t newsize )=0; size_t GetLength() const { return m_size; }
void Free() // 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.
Alloc( 0 ); // 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().
// Makes enough room for the requested size. Existing data in the array is retained. virtual void Alloc( size_t newsize )=0;
void MakeRoomFor( uint size )
{ // Re-sizes the allocation to the requested size, without any data loss.
if (size <= m_size) return; // Parameter:
Resize( size ); // 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;
T* GetPtr( uint idx=0 ) const
{ void Free()
#if pxUSE_SECURE_MALLOC {
IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size ); Alloc( 0 );
#endif }
return &m_buffer[idx];
} // Makes enough room for the requested size. Existing data in the array is retained.
void MakeRoomFor( uint size )
T& operator[]( uint idx ) {
{ if (size <= m_size) return;
#if pxUSE_SECURE_MALLOC Resize( size );
IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size ); }
#endif
return m_buffer[idx]; T* GetPtr( uint idx=0 ) const
} {
#if pxUSE_SECURE_MALLOC
const T& operator[]( uint idx ) const IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size );
{ #endif
#if pxUSE_SECURE_MALLOC return &m_buffer[idx];
IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size ); }
#endif
return m_buffer[idx]; T& operator[]( uint idx )
} {
}; #if pxUSE_SECURE_MALLOC
IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size );
// -------------------------------------------------------------------------------------- #endif
// ScopedAlloc return m_buffer[idx];
// -------------------------------------------------------------------------------------- }
// 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 const T& operator[]( uint idx ) const
// other features are needed, use the more robust SafeArray<> instead. {
// #if pxUSE_SECURE_MALLOC
// See docs for BaseScopedAlloc for details and rationale. IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size );
// #endif
template< typename T > return m_buffer[idx];
class ScopedAlloc : public BaseScopedAlloc<T> }
{ };
public:
ScopedAlloc( size_t size=0 ) : BaseScopedAlloc<T>() // --------------------------------------------------------------------------------------
{ // ScopedAlloc
Alloc(size); // --------------------------------------------------------------------------------------
} // 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
virtual ~ScopedAlloc() throw() // other features are needed, use the more robust SafeArray<> instead.
{ //
Alloc(0); // See docs for BaseScopedAlloc for details and rationale.
} //
template< typename T >
virtual void Alloc( size_t newsize ) class ScopedAlloc : public BaseScopedAlloc<T>
{ {
safe_free(this->m_buffer); public:
this->m_size = newsize; ScopedAlloc( size_t size=0 ) : BaseScopedAlloc<T>()
if (!this->m_size) return; {
Alloc(size);
this->m_buffer = (T*)malloc( this->m_size * sizeof(T) ); }
if (!this->m_buffer)
throw Exception::OutOfMemory("ScopedAlloc"); virtual ~ScopedAlloc() throw()
} {
Alloc(0);
virtual void Resize( size_t newsize ) }
{
this->m_size = newsize; virtual void Alloc( size_t newsize )
this->m_buffer = (T*)realloc(this->m_buffer * sizeof(T), newsize); {
safe_free(this->m_buffer);
if (!this->m_buffer) this->m_size = newsize;
throw Exception::OutOfMemory("ScopedAlloc::Resize"); if (!this->m_size) return;
}
}; this->m_buffer = (T*)malloc( this->m_size * sizeof(T) );
if (!this->m_buffer)
// -------------------------------------------------------------------------------------- throw Exception::OutOfMemory("ScopedAlloc");
// ScopedAlignedAlloc }
// --------------------------------------------------------------------------------------
// A simple container class for an aligned allocation. By default, no bounds checking is virtual void Resize( size_t newsize )
// performed, and there is no option for enabling bounds checking. If bounds checking and {
// other features are needed, use the more robust SafeArray<> instead. this->m_size = newsize;
// this->m_buffer = (T*)realloc(this->m_buffer * sizeof(T), newsize);
// See docs for BaseScopedAlloc for details and rationale.
// if (!this->m_buffer)
template< typename T, uint align > throw Exception::OutOfMemory("ScopedAlloc::Resize");
class ScopedAlignedAlloc : public BaseScopedAlloc<T> }
{ };
public:
ScopedAlignedAlloc( size_t size=0 ) : BaseScopedAlloc() // --------------------------------------------------------------------------------------
{ // ScopedAlignedAlloc
Alloc(size); // --------------------------------------------------------------------------------------
} // 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
virtual ~ScopedAlignedAlloc() throw() // other features are needed, use the more robust SafeArray<> instead.
{ //
Alloc(0); // See docs for BaseScopedAlloc for details and rationale.
} //
template< typename T, uint align >
virtual void Alloc( size_t newsize ) class ScopedAlignedAlloc : public BaseScopedAlloc<T>
{ {
safe_aligned_free(this->m_buffer); public:
this->m_size = newsize; ScopedAlignedAlloc( size_t size=0 ) : BaseScopedAlloc<T>()
if (!this->m_size) return; {
Alloc(size);
this->m_buffer = (T*)_aligned_malloc( this->m_size * sizeof(T), align ); }
if (!this->m_buffer)
throw Exception::OutOfMemory(L"ScopedAlignedAlloc"); virtual ~ScopedAlignedAlloc() throw()
} {
Alloc(0);
virtual void Resize( size_t newsize ) }
{
this->m_size = newsize; virtual void Alloc( size_t newsize )
this->m_buffer = (T*)_aligned_realloc(this->m_buffer, newsize * sizeof(T), align); {
safe_aligned_free(this->m_buffer);
if (!this->m_buffer) this->m_size = newsize;
throw Exception::OutOfMemory(L"ScopedAlignedAlloc::Resize"); 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");
}
};

View File

@ -1,204 +1,205 @@
/* PCSX2 - PS2 Emulator for PCs /* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team * Copyright (C) 2002-2010 PCSX2 Dev Team
* *
* PCSX2 is free software: you can redistribute it and/or modify it under the terms * 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- * 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. * 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; * 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 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details. * 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. * You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "wxBaseTools.h" #include "wxBaseTools.h"
#include "pxStreams.h" #include "pxStreams.h"
#include <wx/stream.h> #include <wx/stream.h>
#include <errno.h>
// --------------------------------------------------------------------------------------
// pxStreamReader (implementations) // --------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------- // pxStreamReader (implementations)
// Interface for reading data from a gzip stream. // --------------------------------------------------------------------------------------
// // Interface for reading data from a gzip stream.
//
pxStreamReader::pxStreamReader(const wxString& filename, ScopedPtr<wxInputStream>& input)
: m_filename( filename ) pxStreamReader::pxStreamReader(const wxString& filename, ScopedPtr<wxInputStream>& input)
, m_stream( input.DetachPtr() ) : m_filename( filename )
{ , m_stream( input.DetachPtr() )
} {
}
pxStreamReader::pxStreamReader(const wxString& filename, wxInputStream* input)
: m_filename( filename ) pxStreamReader::pxStreamReader(const wxString& filename, wxInputStream* input)
, m_stream( input ) : m_filename( filename )
{ , m_stream( input )
} {
}
void pxStreamReader::SetStream( const wxString& filename, ScopedPtr<wxInputStream>& stream )
{ void pxStreamReader::SetStream( const wxString& filename, ScopedPtr<wxInputStream>& stream )
m_filename = filename; {
m_stream = stream.DetachPtr(); m_filename = filename;
} m_stream = stream.DetachPtr();
}
void pxStreamReader::SetStream( const wxString& filename, wxInputStream* stream )
{ void pxStreamReader::SetStream( const wxString& filename, wxInputStream* stream )
m_filename = filename; {
m_stream = stream; m_filename = filename;
} m_stream = stream;
}
void pxStreamReader::Read( void* dest, size_t size )
{ void pxStreamReader::Read( void* dest, size_t size )
m_stream->Read(dest, size); {
if (m_stream->GetLastError() == wxSTREAM_READ_ERROR) m_stream->Read(dest, size);
{ if (m_stream->GetLastError() == wxSTREAM_READ_ERROR)
int err = errno; {
if (!err) int err = errno;
throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot read from file (bad file handle?)"); 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() ); ScopedExcept ex(Exception::FromErrno(m_filename, err));
ex->Rethrow(); 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 // IMPORTANT! The underlying file/source Eof() stuff is not really reliable, so we
// end-of-stream conditions. // 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 ); if ((size_t)m_stream->LastRead() < size)
} throw Exception::EndOfStream( m_filename );
}
// --------------------------------------------------------------------------------------
// pxStreamWriter // --------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------- // pxStreamWriter
pxStreamWriter::pxStreamWriter(const wxString& filename, ScopedPtr<wxOutputStream>& output) // --------------------------------------------------------------------------------------
: m_filename( filename ) pxStreamWriter::pxStreamWriter(const wxString& filename, ScopedPtr<wxOutputStream>& output)
, m_outstream( output.DetachPtr() ) : m_filename( filename )
{ , m_outstream( output.DetachPtr() )
{
}
}
pxStreamWriter::pxStreamWriter(const wxString& filename, wxOutputStream* output)
: m_filename( filename ) pxStreamWriter::pxStreamWriter(const wxString& filename, wxOutputStream* output)
, m_outstream( output ) : m_filename( filename )
{ , m_outstream( output )
} {
}
void pxStreamWriter::SetStream( const wxString& filename, ScopedPtr<wxOutputStream>& stream )
{ void pxStreamWriter::SetStream( const wxString& filename, ScopedPtr<wxOutputStream>& stream )
m_filename = filename; {
m_outstream = stream.DetachPtr(); m_filename = filename;
} m_outstream = stream.DetachPtr();
}
void pxStreamWriter::SetStream( const wxString& filename, wxOutputStream* stream )
{ void pxStreamWriter::SetStream( const wxString& filename, wxOutputStream* stream )
m_filename = filename; {
m_outstream = stream; m_filename = filename;
} m_outstream = stream;
}
void pxStreamWriter::Write( const void* src, size_t size )
{ void pxStreamWriter::Write( const void* src, size_t size )
m_outstream->Write(src, size); {
if(m_outstream->GetLastError() == wxSTREAM_WRITE_ERROR) m_outstream->Write(src, size);
{ if(m_outstream->GetLastError() == wxSTREAM_WRITE_ERROR)
int err = errno; {
if (!err) int err = errno;
throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot write to file/stream."); 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() ); ScopedExcept ex(Exception::FromErrno(m_filename, err));
ex->Rethrow(); ex->SetDiagMsg( L"Cannot write to file: " + ex->DiagMsg() );
} ex->Rethrow();
} }
}
// --------------------------------------------------------------------------------------
// pxTextStream // --------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------- // pxTextStream
// --------------------------------------------------------------------------------------
// Returns TRUE if the source is UTF8, or FALSE if it's just ASCII crap.
bool pxReadLine( wxInputStream& input, std::string& dest ) // 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; dest.clear();
while ( true ) bool isUTF8 = false;
{ while ( true )
char c; {
input.Read(&c, sizeof(c)); char c;
if( c == 0 ) break; input.Read(&c, sizeof(c));
if( input.Eof() ) break; if( c == 0 ) break;
if( c == '\n' ) break; // eat on UNIX if( input.Eof() ) break;
if( c == '\r' ) if( c == '\n' ) break; // eat on UNIX
{ if( c == '\r' )
input.Read(&c, sizeof(c)); {
if( c == 0 ) break; input.Read(&c, sizeof(c));
if( input.Eof() ) break; if( c == 0 ) break;
if( c == '\n' ) break; if( input.Eof() ) break;
if( c == '\n' ) break;
input.Ungetch(c);
break; input.Ungetch(c);
} break;
dest += c; }
if( c & 0x80 ) isUTF8 = true; dest += c;
} if( c & 0x80 ) isUTF8 = true;
}
return isUTF8;
} return isUTF8;
}
void pxReadLine( wxInputStream& input, wxString& dest, std::string& intermed )
{ void pxReadLine( wxInputStream& input, wxString& dest, std::string& intermed )
dest.clear(); {
if( pxReadLine( input, intermed ) ) dest.clear();
dest = fromUTF8(intermed.c_str()); if( pxReadLine( input, intermed ) )
else dest = fromUTF8(intermed.c_str());
{ else
// Optimized ToAscii conversion. {
// wx3.0 : NOT COMPATIBLE!! (on linux anyway) // Optimized ToAscii conversion.
const char* ascii = intermed.c_str(); // wx3.0 : NOT COMPATIBLE!! (on linux anyway)
while( *ascii != 0 ) dest += (wchar_t)(unsigned char)*ascii++; const char* ascii = intermed.c_str();
} while( *ascii != 0 ) dest += (wchar_t)(unsigned char)*ascii++;
} }
}
void pxReadLine( wxInputStream& input, wxString& dest )
{ void pxReadLine( wxInputStream& input, wxString& dest )
std::string line; {
pxReadLine( input, dest, line ); std::string line;
} pxReadLine( input, dest, line );
}
wxString pxReadLine( wxInputStream& input )
{ wxString pxReadLine( wxInputStream& input )
wxString result; {
pxReadLine( input, result ); wxString result;
return result; pxReadLine( input, result );
} return result;
}
void pxWriteLine( wxOutputStream& output )
{ void pxWriteLine( wxOutputStream& output )
output.Write( "\n", 1 ); {
} output.Write( "\n", 1 );
}
void pxWriteLine( wxOutputStream& output, const wxString& text )
{ void pxWriteLine( wxOutputStream& output, const wxString& text )
if( !text.IsEmpty() ) {
{ if( !text.IsEmpty() )
pxToUTF8 utf8(text); {
output.Write(utf8, utf8.Length()); pxToUTF8 utf8(text);
} output.Write(utf8, utf8.Length());
pxWriteLine( output ); }
} pxWriteLine( output );
}
void pxWriteMultiline( wxOutputStream& output, const wxString& src )
{ void pxWriteMultiline( wxOutputStream& output, const wxString& src )
if( src.IsEmpty() ) return; {
if( src.IsEmpty() ) return;
wxString result( src );
result.Replace( L"\r\n", L"\n" ); wxString result( src );
result.Replace( L"\r", L"\n" ); result.Replace( L"\r\n", L"\n" );
result.Replace( L"\r", L"\n" );
pxToUTF8 utf8(result);
output.Write(utf8, utf8.Length()); pxToUTF8 utf8(result);
} output.Write(utf8, utf8.Length());
}