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 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
* 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 <http://www.gnu.org/licenses/>.
*/
#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<T>
{
public:
ScopedAlloc( size_t size=0 ) : BaseScopedAlloc<T>()
{
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<T>
{
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 <http://www.gnu.org/licenses/>.
*/
#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<T>
{
public:
ScopedAlloc( size_t size=0 ) : BaseScopedAlloc<T>()
{
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<T>
{
public:
ScopedAlignedAlloc( size_t size=0 ) : BaseScopedAlloc<T>()
{
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");
}
};

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "wxBaseTools.h"
#include "pxStreams.h"
#include <wx/stream.h>
// --------------------------------------------------------------------------------------
// pxStreamReader (implementations)
// --------------------------------------------------------------------------------------
// Interface for reading data from a gzip stream.
//
pxStreamReader::pxStreamReader(const wxString& filename, ScopedPtr<wxInputStream>& 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<wxInputStream>& 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<wxOutputStream>& 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<wxOutputStream>& 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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "wxBaseTools.h"
#include "pxStreams.h"
#include <wx/stream.h>
#include <errno.h>
// --------------------------------------------------------------------------------------
// pxStreamReader (implementations)
// --------------------------------------------------------------------------------------
// Interface for reading data from a gzip stream.
//
pxStreamReader::pxStreamReader(const wxString& filename, ScopedPtr<wxInputStream>& 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<wxInputStream>& 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<wxOutputStream>& 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<wxOutputStream>& 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());
}