buffer everything, not just GetLine
This commit is contained in:
+77
-38
@@ -6,7 +6,7 @@
|
|||||||
RageFile::RageFile()
|
RageFile::RageFile()
|
||||||
{
|
{
|
||||||
m_File = NULL;
|
m_File = NULL;
|
||||||
m_BufUsed = 0;
|
m_BufAvail = 0;
|
||||||
m_EOF = false;
|
m_EOF = false;
|
||||||
m_FilePos = 0;
|
m_FilePos = 0;
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ RageFile::RageFile()
|
|||||||
RageFile::RageFile( const CString& path, int mode )
|
RageFile::RageFile( const CString& path, int mode )
|
||||||
{
|
{
|
||||||
m_File = NULL;
|
m_File = NULL;
|
||||||
m_BufUsed = 0;
|
m_BufAvail = 0;
|
||||||
m_EOF = false;
|
m_EOF = false;
|
||||||
m_FilePos = 0;
|
m_FilePos = 0;
|
||||||
Open(path, mode);
|
Open(path, mode);
|
||||||
@@ -31,8 +31,8 @@ RageFile::RageFile( const RageFile &cpy )
|
|||||||
m_Error = cpy.m_Error;
|
m_Error = cpy.m_Error;
|
||||||
m_EOF = cpy.m_EOF;
|
m_EOF = cpy.m_EOF;
|
||||||
m_FilePos = cpy.m_FilePos;
|
m_FilePos = cpy.m_FilePos;
|
||||||
memcpy( this->m_Buffer, cpy.m_Buffer, cpy.m_BufUsed );
|
memcpy( this->m_Buffer, cpy.m_Buffer, cpy.m_BufAvail );
|
||||||
m_BufUsed = cpy.m_BufUsed;
|
m_BufAvail = cpy.m_BufAvail;
|
||||||
}
|
}
|
||||||
|
|
||||||
CString RageFile::GetPath() const
|
CString RageFile::GetPath() const
|
||||||
@@ -86,9 +86,27 @@ void RageFile::Close()
|
|||||||
m_File = NULL;
|
m_File = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fill the internal buffer. This never marks EOF, since this is an internal, hidden
|
||||||
|
* read; EOF should only be set as a result of a real read. (That is, disabling buffering
|
||||||
|
* shouldn't cause the results of AtEOF to change.) */
|
||||||
|
int RageFile::FillBuf()
|
||||||
|
{
|
||||||
|
/* The buffer starts at m_Buffer; any data in it starts at m_pBuf; space between
|
||||||
|
* the two is old data that we've read. (Don't mangle that data; we can use it
|
||||||
|
* for seeking backwards.) */
|
||||||
|
const int iBufAvail = sizeof(m_Buffer) - (m_pBuf-m_Buffer);
|
||||||
|
ASSERT_M( iBufAvail >= 0, ssprintf("%p, %p, %i", m_pBuf, m_Buffer, (int) sizeof(m_Buffer) ) );
|
||||||
|
const int size = m_File->Read( m_pBuf+m_BufAvail, iBufAvail );
|
||||||
|
|
||||||
|
if( size > 0 )
|
||||||
|
m_BufAvail += size;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
void RageFile::ResetBuf()
|
void RageFile::ResetBuf()
|
||||||
{
|
{
|
||||||
m_BufUsed = 0;
|
m_BufAvail = 0;
|
||||||
m_pBuf = m_Buffer;
|
m_pBuf = m_Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,26 +122,29 @@ int RageFile::GetLine( CString &out )
|
|||||||
if( !(m_Mode&READ) )
|
if( !(m_Mode&READ) )
|
||||||
RageException::Throw("\"%s\" is not open for reading", GetPath().c_str());
|
RageException::Throw("\"%s\" is not open for reading", GetPath().c_str());
|
||||||
|
|
||||||
|
if( m_EOF )
|
||||||
|
return 0;
|
||||||
|
|
||||||
bool GotData = false;
|
bool GotData = false;
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
/* Find the end of the block we'll move to out. */
|
/* Find the end of the block we'll move to out. */
|
||||||
char *p = (char *) memchr( m_pBuf, '\n', m_BufUsed );
|
char *p = (char *) memchr( m_pBuf, '\n', m_BufAvail );
|
||||||
bool ReAddCR = false;
|
bool ReAddCR = false;
|
||||||
if( p == NULL )
|
if( p == NULL )
|
||||||
{
|
{
|
||||||
/* Hack: If the last character of the buffer is \r, then it's likely that an
|
/* Hack: If the last character of the buffer is \r, then it's likely that an
|
||||||
* \r\n has been split across buffers. Move everything else, then move the
|
* \r\n has been split across buffers. Move everything else, then move the
|
||||||
* \r to the beginning of the buffer and handle it the next time around the loop. */
|
* \r to the beginning of the buffer and handle it the next time around the loop. */
|
||||||
if( m_pBuf[m_BufUsed-1] == '\r' )
|
if( m_pBuf[m_BufAvail-1] == '\r' )
|
||||||
{
|
{
|
||||||
ReAddCR = true;
|
ReAddCR = true;
|
||||||
--m_BufUsed;
|
--m_BufAvail;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = m_pBuf+m_BufUsed; /* everything */
|
p = m_pBuf+m_BufAvail; /* everything */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
done = true;
|
done = true;
|
||||||
@@ -141,7 +162,7 @@ int RageFile::GetLine( CString &out )
|
|||||||
const int used = p-m_pBuf;
|
const int used = p-m_pBuf;
|
||||||
if( used )
|
if( used )
|
||||||
{
|
{
|
||||||
m_BufUsed -= used;
|
m_BufAvail -= used;
|
||||||
m_FilePos += used;
|
m_FilePos += used;
|
||||||
GotData = true;
|
GotData = true;
|
||||||
m_pBuf = p;
|
m_pBuf = p;
|
||||||
@@ -150,10 +171,10 @@ int RageFile::GetLine( CString &out )
|
|||||||
|
|
||||||
if( ReAddCR )
|
if( ReAddCR )
|
||||||
{
|
{
|
||||||
ASSERT( m_BufUsed == 0 );
|
ASSERT( m_BufAvail == 0 );
|
||||||
m_pBuf = m_Buffer;
|
m_pBuf = m_Buffer;
|
||||||
m_Buffer[m_BufUsed] = '\r';
|
m_Buffer[m_BufAvail] = '\r';
|
||||||
++m_BufUsed;
|
++m_BufAvail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( done )
|
if( done )
|
||||||
@@ -162,7 +183,7 @@ int RageFile::GetLine( CString &out )
|
|||||||
/* We need more data. */
|
/* We need more data. */
|
||||||
m_pBuf = m_Buffer;
|
m_pBuf = m_Buffer;
|
||||||
|
|
||||||
const int size = m_File->Read( m_pBuf+m_BufUsed, sizeof(m_Buffer)-m_BufUsed );
|
const int size = FillBuf();
|
||||||
|
|
||||||
/* If we've read data already, then don't mark EOF yet. Wait until the
|
/* If we've read data already, then don't mark EOF yet. Wait until the
|
||||||
* next time we're called. */
|
* next time we're called. */
|
||||||
@@ -171,11 +192,10 @@ int RageFile::GetLine( CString &out )
|
|||||||
m_EOF = true;
|
m_EOF = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if( size < 0 )
|
if( size == -1 )
|
||||||
return -1; // error
|
return -1; // error
|
||||||
if( size == 0 )
|
if( size == 0 )
|
||||||
break; // EOF or error
|
break; // EOF or error
|
||||||
m_BufUsed += size;
|
|
||||||
}
|
}
|
||||||
return GotData? 1:0;
|
return GotData? 1:0;
|
||||||
}
|
}
|
||||||
@@ -206,26 +226,45 @@ int RageFile::Read( void *buffer, size_t bytes )
|
|||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
int FromBuffer = min( (int) bytes, m_BufUsed );
|
while( !m_EOF && bytes > 0 )
|
||||||
memcpy( buffer, m_pBuf, FromBuffer );
|
|
||||||
|
|
||||||
ret += FromBuffer;
|
|
||||||
m_FilePos += FromBuffer;
|
|
||||||
bytes -= FromBuffer;
|
|
||||||
m_BufUsed -= FromBuffer;
|
|
||||||
m_pBuf += FromBuffer;
|
|
||||||
|
|
||||||
buffer = (char *) buffer + FromBuffer;
|
|
||||||
|
|
||||||
if( bytes )
|
|
||||||
{
|
{
|
||||||
int FromFile = m_File->Read( buffer, bytes );
|
/* Copy data out of the buffer first. */
|
||||||
if( FromFile < 0 )
|
int FromBuffer = min( (int) bytes, m_BufAvail );
|
||||||
return -1;
|
memcpy( buffer, m_pBuf, FromBuffer );
|
||||||
if( FromFile == 0 )
|
|
||||||
|
ret += FromBuffer;
|
||||||
|
m_FilePos += FromBuffer;
|
||||||
|
bytes -= FromBuffer;
|
||||||
|
m_BufAvail -= FromBuffer;
|
||||||
|
m_pBuf += FromBuffer;
|
||||||
|
|
||||||
|
buffer = (char *) buffer + FromBuffer;
|
||||||
|
|
||||||
|
if( !bytes )
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* We need more; either fill the buffer and keep going, or just read directly
|
||||||
|
* into the destination buffer. */
|
||||||
|
if( bytes >= sizeof(m_Buffer) )
|
||||||
|
{
|
||||||
|
/* We have a lot more to read, so don't waste time copying it into the
|
||||||
|
* buffer. */
|
||||||
|
int FromFile = m_File->Read( buffer, bytes );
|
||||||
|
if( FromFile < 0 )
|
||||||
|
return FromFile;
|
||||||
|
if( FromFile == 0 )
|
||||||
|
m_EOF = true;
|
||||||
|
ret += FromFile;
|
||||||
|
m_FilePos += FromFile;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pBuf = m_Buffer;
|
||||||
|
int got = FillBuf();
|
||||||
|
if( got < 0 )
|
||||||
|
return got;
|
||||||
|
if( got == 0 )
|
||||||
m_EOF = true;
|
m_EOF = true;
|
||||||
ret += FromFile;
|
|
||||||
m_FilePos += FromFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -243,10 +282,10 @@ int RageFile::Seek( int offset )
|
|||||||
|
|
||||||
/* If the new position is within the buffer, just eat the buffered data. */
|
/* If the new position is within the buffer, just eat the buffered data. */
|
||||||
int FromBuffer = offset - m_FilePos;
|
int FromBuffer = offset - m_FilePos;
|
||||||
if( 0 <= FromBuffer && FromBuffer <= m_BufUsed )
|
if( 0 <= FromBuffer && FromBuffer <= m_BufAvail )
|
||||||
{
|
{
|
||||||
m_FilePos += FromBuffer;
|
m_FilePos += FromBuffer;
|
||||||
m_BufUsed -= FromBuffer;
|
m_BufAvail -= FromBuffer;
|
||||||
m_pBuf += FromBuffer;
|
m_pBuf += FromBuffer;
|
||||||
|
|
||||||
return m_FilePos;
|
return m_FilePos;
|
||||||
@@ -283,10 +322,10 @@ int RageFile::SeekCur( int offset )
|
|||||||
if( !offset || m_EOF )
|
if( !offset || m_EOF )
|
||||||
return m_FilePos;
|
return m_FilePos;
|
||||||
|
|
||||||
int FromBuffer = min( offset, m_BufUsed );
|
int FromBuffer = min( offset, m_BufAvail );
|
||||||
m_FilePos += FromBuffer;
|
m_FilePos += FromBuffer;
|
||||||
offset -= FromBuffer;
|
offset -= FromBuffer;
|
||||||
m_BufUsed -= FromBuffer;
|
m_BufAvail -= FromBuffer;
|
||||||
m_pBuf += FromBuffer;
|
m_pBuf += FromBuffer;
|
||||||
|
|
||||||
if( offset )
|
if( offset )
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ protected:
|
|||||||
void SetError( const CString &err ) { m_Error = err; } /* called by RageFileObj::SetError */
|
void SetError( const CString &err ) { m_Error = err; } /* called by RageFileObj::SetError */
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int FillBuf();
|
||||||
void ResetBuf();
|
void ResetBuf();
|
||||||
|
|
||||||
RageFileObj *m_File;
|
RageFileObj *m_File;
|
||||||
@@ -88,7 +89,7 @@ private:
|
|||||||
enum { BSIZE = 1024*16 };
|
enum { BSIZE = 1024*16 };
|
||||||
char m_Buffer[BSIZE];
|
char m_Buffer[BSIZE];
|
||||||
char *m_pBuf;
|
char *m_pBuf;
|
||||||
int m_BufUsed;
|
int m_BufAvail;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user