//-----------------------------------------------------------------------------
// NOTE: This is an exact copy of code in BaseFileSystem.cpp which
// has to be here because they want to call
// the implementation of Open/Size/Read/Write in CBaseVMPIFileSystem
//-----------------------------------------------------------------------------
bool CBaseVMPIFileSystem::ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes, int nStartingByte, FSAllocFunc_t pfnAlloc )
{
	const char *pReadFlags = "rb";
	if ( buf.IsText() && !buf.ContainsCRLF() )
	{
		pReadFlags = "rt";
	}

	FileHandle_t fp = Open( pFileName, buf.IsText() ? "rt" : "rb", pPath );
	if ( !fp )
		return false;

	int nBytesToRead = Size( fp );
	if ( nMaxBytes > 0 )
	{
		nBytesToRead = min( nMaxBytes, nBytesToRead );
	}
	buf.EnsureCapacity( nBytesToRead + buf.TellPut() );

	if ( nStartingByte != 0 )
	{
		Seek( fp, nStartingByte, FILESYSTEM_SEEK_HEAD );
	}

	int nBytesRead = Read( buf.PeekPut(), nBytesToRead, fp );
	buf.SeekPut( CUtlBuffer::SEEK_CURRENT, nBytesRead );

	Close( fp );
	return (nBytesRead != 0);
}
Esempio n. 2
0
//-----------------------------------------------------------------------------
// Binary buffer attribute
//-----------------------------------------------------------------------------
bool Serialize( CUtlBuffer &buf, const CUtlBinaryBlock &src )
{
	int nLength = src.Length();
	if ( !buf.IsText() )
	{
		buf.PutInt( nLength );
		if ( nLength != 0 )
		{
			buf.Put( src.Get(), nLength );
		}
		return buf.IsValid();
	}

	// Writes out uuencoded binaries
	for ( int i = 0; i < nLength; ++i )
	{
		if ( (i % 40) == 0 )
		{
			buf.PutChar( '\n' );
		}

		char b1 = src[i] & 0xF;
		char b2 = src[i] >> 4;

		char c1 = ( b1 <= 9 ) ? b1 + '0' : b1 - 10 + 'A';
		char c2 = ( b2 <= 9 ) ? b2 + '0' : b2 - 10 + 'A';

		buf.PutChar( c2 );
		buf.PutChar( c1 );
	}

	buf.PutChar( '\n' );
	return buf.IsValid();
}
bool CBaseVMPIFileSystem::WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf )
{
	const char *pWriteFlags = "wb";
	if ( buf.IsText() && !buf.ContainsCRLF() )
	{
		pWriteFlags = "wt";
	}

	FileHandle_t fp = Open( pFileName, buf.IsText() ? "wt" : "wb", pPath );
	if ( !fp )
		return false;

	int nBytesWritten = Write( buf.Base(), buf.TellPut(), fp );

	Close( fp );
	return (nBytesWritten != 0);
}
Esempio n. 4
0
bool Unserialize( CUtlBuffer &buf, int &dest )
{
	if ( buf.IsText() )
	{
		int nRetVal = buf.Scanf( "%d", &dest );
		return (nRetVal == 1) && buf.IsValid();
	}

	dest = buf.GetInt( );
	return buf.IsValid();
}
Esempio n. 5
0
bool Serialize( CUtlBuffer &buf, const float &src )
{
	if ( buf.IsText() )
	{
		SerializeFloat( buf, src );
	}
	else
	{
		buf.PutFloat( src );
	}
	return buf.IsValid();
}
Esempio n. 6
0
//-----------------------------------------------------------------------------
// Serialization methods for basic types
//-----------------------------------------------------------------------------
bool Serialize( CUtlBuffer &buf, const bool &src )
{
	if ( buf.IsText() )
	{
		buf.Printf( "%d", src );
	}
	else
	{
		buf.PutChar( src );
	}
	return buf.IsValid();
}
Esempio n. 7
0
bool Unserialize( CUtlBuffer &buf, float &dest )
{
	if ( buf.IsText() )
	{
		// FIXME: Print this in a way that we never lose precision
		int nRetVal = buf.Scanf( "%f", &dest );
		return (nRetVal == 1) && buf.IsValid();
	}

	dest = buf.GetFloat( );
	return buf.IsValid();
}
Esempio n. 8
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : buf - 
//-----------------------------------------------------------------------------
void CSentence::CacheRestoreFromBuffer( CUtlBuffer& buf )
{
	Assert( !buf.IsText() );

	Reset();

	m_bIsCached = true;

	int version = buf.GetChar();
	if ( version != CACHED_SENTENCE_VERSION )
	{
		// Uh oh, version changed...
		m_bIsValid = false;
		return;
	}

	unsigned short pcount = (unsigned short)buf.GetShort();
	
	CPhonemeTag pt;
	int i;

	for ( i = 0; i < pcount; ++i )
	{
		unsigned short code = buf.GetShort();
		float st = buf.GetFloat();
		float et = buf.GetFloat();

		pt.SetPhonemeCode( code );
		pt.SetStartTime( st );
		pt.SetEndTime( et );

		AddRuntimePhoneme( &pt );
	}

	// Now read emphasis samples
	int c = buf.GetShort();

	for ( i = 0; i < c; i++ )
	{
		CEmphasisSample sample;
		sample.SetSelected( false );

		sample.time = buf.GetFloat();
		sample.value = (float)buf.GetShort() / 32767.0f;

		m_EmphasisSamples.AddToTail( sample );
	}

	// And voice duck
	SetVoiceDuck( buf.GetChar() == 0 ? false : true );
	m_bIsValid = true;
}
Esempio n. 9
0
bool Unserialize( CUtlBuffer &buf, bool &dest )
{
	if ( buf.IsText() )
	{
		int nValue = 0;
		int nRetVal = buf.Scanf( "%d", &nValue );
		dest = ( nValue != 0 );
		return (nRetVal == 1) && buf.IsValid();
	}

	dest = ( buf.GetChar( ) != 0 );
	return buf.IsValid();
}
Esempio n. 10
0
bool Unserialize( CUtlBuffer &buf, Vector2D &dest )
{
	if ( buf.IsText() )
	{
		// FIXME: Print this in a way that we never lose precision
		int nRetVal = buf.Scanf( "%f %f", &dest.x, &dest.y );
		return (nRetVal == 2) && buf.IsValid();
	}

	dest.x = buf.GetFloat( );
	dest.y = buf.GetFloat( );
	return buf.IsValid();
}
Esempio n. 11
0
//-----------------------------------------------------------------------------
// Attribute types related to vector math
//-----------------------------------------------------------------------------
bool Serialize( CUtlBuffer &buf, const Vector2D &src )
{
	if ( buf.IsText() )
	{
		SerializeFloats( buf, 2, src.Base() );
	}
	else
	{
		buf.PutFloat( src.x );
		buf.PutFloat( src.y );
	}
	return buf.IsValid();
}
Esempio n. 12
0
bool Serialize( CUtlBuffer &buf, const Quaternion &src )
{
	if ( buf.IsText() )
	{
		SerializeFloats( buf, 4, &src.x );
	}
	else
	{
		buf.PutFloat( src.x );
		buf.PutFloat( src.y );
		buf.PutFloat( src.z );
		buf.PutFloat( src.w );
	}
	return buf.IsValid();
}
Esempio n. 13
0
//-----------------------------------------------------------------------------
// Color attribute
//-----------------------------------------------------------------------------
bool Serialize( CUtlBuffer &buf, const Color &src )
{
	if ( buf.IsText() )
	{
		buf.Printf( "%d %d %d %d", src[0], src[1], src[2], src[3] );
	}
	else
	{
		buf.PutUnsignedChar( src[0] );
		buf.PutUnsignedChar( src[1] );
		buf.PutUnsignedChar( src[2] );
		buf.PutUnsignedChar( src[3] );
	}
	return buf.IsValid();
}
Esempio n. 14
0
bool Unserialize( CUtlBuffer &buf, Color &dest )
{
	if ( buf.IsText() )
	{
		int r = 0, g = 0, b = 0, a = 255;
		int nRetVal = buf.Scanf( "%d %d %d %d", &r, &g, &b, &a );
		dest.SetColor( r, g, b, a );
		return (nRetVal == 4) && buf.IsValid();
	}

	dest[0] = buf.GetUnsignedChar( );
	dest[1] = buf.GetUnsignedChar( );
	dest[2] = buf.GetUnsignedChar( );
	dest[3] = buf.GetUnsignedChar( );
	return buf.IsValid();
}
Esempio n. 15
0
bool Unserialize( CUtlBuffer &buf, VMatrix &dest )
{
	if ( !buf.IsValid() )
		return false;

	if ( buf.IsText() )
	{
		int nRetVal = buf.Scanf( "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",
			&dest[ 0 ][ 0 ], &dest[ 0 ][ 1 ], &dest[ 0 ][ 2 ], &dest[ 0 ][ 3 ],
			&dest[ 1 ][ 0 ], &dest[ 1 ][ 1 ], &dest[ 1 ][ 2 ], &dest[ 1 ][ 3 ],
			&dest[ 2 ][ 0 ], &dest[ 2 ][ 1 ], &dest[ 2 ][ 2 ], &dest[ 2 ][ 3 ],
			&dest[ 3 ][ 0 ], &dest[ 3 ][ 1 ], &dest[ 3 ][ 2 ], &dest[ 3 ][ 3 ] );
		return (nRetVal == 16);
	}

	buf.Get( &dest, sizeof(VMatrix) );
	return true;
}
Esempio n. 16
0
bool Unserialize( CUtlBuffer &buf, CUtlBinaryBlock &dest )
{
	if ( !buf.IsText() )
	{
		int nLen = buf.GetInt( );
		dest.SetLength( nLen );
		if ( dest.Length() != 0 )
		{
			buf.Get( dest.Get(), dest.Length() );
		}

		if ( nLen != dest.Length() )
		{
			buf.SeekGet( CUtlBuffer::SEEK_CURRENT, nLen - dest.Length() );
			return false;
		}

		return buf.IsValid();
	}

	int nEndGet;
	int nByteCount = CountBinaryBytes( buf, &nEndGet );
	if ( nByteCount < 0 )
		return false;

	buf.EatWhiteSpace();
	int nDest = 0;
	dest.SetLength( nByteCount );
	while( buf.TellGet() < nEndGet )
	{
		char c1 = buf.GetChar();
		char c2 = buf.GetChar();

		unsigned char b1 = HexCharToInt( c1 );
		unsigned char b2 = HexCharToInt( c2 );
		if ( b1 == 0xFF || b2 == 0xFF )
			return false;

		dest[ nDest++ ] = b2 | ( b1 << 4 );
		buf.EatWhiteSpace();
	}

	return true;
}
Esempio n. 17
0
//-----------------------------------------------------------------------------
// Serialize a floating point number in text mode in a readably friendly fashion
//-----------------------------------------------------------------------------
static void SerializeFloat( CUtlBuffer &buf, float f )
{
	Assert( buf.IsText() );

	// FIXME: Print this in a way that we never lose precision
	char pTemp[256];
	int nLen = Q_snprintf( pTemp, sizeof(pTemp), "%.10f", f );
	while ( nLen > 0 && pTemp[nLen-1] == '0' )
	{
		--nLen;
		pTemp[nLen] = 0;
	}
	if ( nLen > 0 && pTemp[nLen-1] == '.' )
	{
		--nLen;
		pTemp[nLen] = 0;
	}
	buf.PutString( pTemp );
}
Esempio n. 18
0
bool Serialize( CUtlBuffer &buf, const VMatrix &src )
{
	if ( buf.IsText() )
	{
		buf.Printf( "\n" );
		SerializeFloats( buf, 4, src[0] );
		buf.Printf( "\n" );
		SerializeFloats( buf, 4, src[1] );
		buf.Printf( "\n" );
		SerializeFloats( buf, 4, src[2] );
		buf.Printf( "\n" );
		SerializeFloats( buf, 4, src[3] );
		buf.Printf( "\n" );
	}
	else
	{
		buf.Put( &src, sizeof(VMatrix) );
	}
	return buf.IsValid();
}
Esempio n. 19
0
// This is a compressed save of just the data needed to drive phonemes in the engine (no word / sentence text, etc )
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : buf - 
//-----------------------------------------------------------------------------
void CSentence::CacheSaveToBuffer( CUtlBuffer& buf )
{
	Assert( !buf.IsText() );
	Assert( m_bIsCached );

	buf.PutChar( CACHED_SENTENCE_VERSION );

	int i;
	unsigned short pcount = GetRuntimePhonemeCount();

	buf.PutShort( pcount );

	for ( i = 0; i < pcount; ++i )
	{
		const CBasePhonemeTag *phoneme = GetRuntimePhoneme( i );
		Assert( phoneme );

		buf.PutShort( phoneme->GetPhonemeCode() );
		buf.PutFloat( phoneme->GetStartTime() );
		buf.PutFloat( phoneme->GetEndTime() );
	}

	// Now save out emphasis samples
	int c = m_EmphasisSamples.Count();
	Assert( c <= 32767 );
	buf.PutShort( c );

	for ( i = 0; i < c; i++ )
	{
		CEmphasisSample *sample = &m_EmphasisSamples[ i ];
		Assert( sample );

		buf.PutFloat( sample->time );
		short scaledValue = clamp( (short)( sample->value * 32767 ), 0, 32767 );

		buf.PutShort( scaledValue );
	}

	// And voice duck
	buf.PutChar( GetVoiceDuck() ? 1 : 0 );
}
Esempio n. 20
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : buf - 
//-----------------------------------------------------------------------------
void CSentence::InitFromBuffer( CUtlBuffer& buf )
{
	Assert( buf.IsText() );

	Reset();

	char token[ 4096 ];
	buf.GetString( token );

	if ( stricmp( token, "VERSION" ) )
		return;

	buf.GetString( token );
	if ( atof( token ) == 1.0f )
	{
		ParseDataVersionOnePointZero( buf );
		m_bIsValid = true;
	}
	else
	{
		assert( 0 );
		return;
	}
}
//-----------------------------------------------------------------------------
// Purpose: Finds the value of a particular server variable
//-----------------------------------------------------------------------------
bool CServerRemoteAccess::LookupValue(const char *variable, CUtlBuffer &value)
{
	Assert(value.IsText());

	// first see if it's a cvar
	const char *strval = LookupStringValue(variable);
	if (strval)
	{
		value.PutString(strval);
		value.PutChar(0);
	}
	else if (!stricmp(variable, "stats"))
	{
		char stats[512];
		GetStatsString(stats, sizeof(stats));
		value.PutString(stats);
		value.PutChar(0);
	}
	else if (!stricmp(variable, "banlist"))
	{
		// returns a list of banned users and ip's
		GetUserBanList(value);
	}
	else if (!stricmp(variable, "playerlist"))
	{
		GetPlayerList(value);		
	}
	else if (!stricmp(variable, "maplist"))
	{
		GetMapList(value);
	}
	else if (!stricmp(variable, "uptime"))
	{
		int timeSeconds = (int)(Plat_FloatTime());
		value.PutInt(timeSeconds);
		value.PutChar(0);
	}
	else if (!stricmp(variable, "ipaddress"))
	{
		char addr[25];
		Q_snprintf( addr, sizeof(addr), "%s:%i", net_local_adr.ToString(true), sv.GetUDPPort());
		value.PutString( addr );
		value.PutChar(0);
	}
	else if (!stricmp(variable, "mapcycle"))
	{
		ConVarRef mapcycle( "mapcyclefile" );
		if ( mapcycle.IsValid() )
		{
			// send the mapcycle list file
			FileHandle_t f = g_pFileSystem->Open(mapcycle.GetString(), "rb" );

			if ( f == FILESYSTEM_INVALID_HANDLE )
				return true;
			
			int len = g_pFileSystem->Size(f);
			char *mapcycleData = (char *)_alloca( len+1 );
			if ( len && g_pFileSystem->Read( mapcycleData, len, f ) )
			{
				mapcycleData[len] = 0; // Make sure it's null terminated.
				value.PutString((const char *)mapcycleData);
				value.PutChar(0);
			}
			else
			{
				value.PutString( "" );
				value.PutChar(0);
			}

			g_pFileSystem->Close( f );


		}
	}
	else
	{
		// value not found, null terminate
		value.PutChar(0);
		return false;
	}
	
	return true;
}
Esempio n. 22
0
bool KeyValues::WriteAsBinary(CUtlBuffer &buffer)
{
	if (buffer.IsText())
		return false;

	if (!buffer.IsValid())
		return false;

	for (KeyValues *dat = this; dat != NULL; dat = dat->m_pPeer)
	{
		buffer.PutUnsignedChar(dat->m_iDataType);
		buffer.PutString(dat->GetName());

		switch (dat->m_iDataType)
		{
			case TYPE_NONE:
			{
				dat->m_pSub->WriteAsBinary(buffer);
				break;
			}

			case TYPE_STRING:
			{
				if (dat->m_sValue && *(dat->m_sValue))
				{
					buffer.PutString(dat->m_sValue);
				}
				else
				{
					buffer.PutString("");
				}

				break;
			}

			case TYPE_WSTRING:
			{
				Assert(!"TYPE_WSTRING");
				break;
			}

			case TYPE_INT:
			{
				buffer.PutInt(dat->m_iValue);
				break;
			}

			case TYPE_UINT64:
			{
				buffer.PutDouble(*((double *)dat->m_sValue));
				break;
			}

			case TYPE_FLOAT:
			{
				buffer.PutFloat(dat->m_flValue);
				break;
			}

			case TYPE_COLOR:
			{
				buffer.PutUnsignedChar(dat->m_Color[0]);
				buffer.PutUnsignedChar(dat->m_Color[1]);
				buffer.PutUnsignedChar(dat->m_Color[2]);
				buffer.PutUnsignedChar(dat->m_Color[3]);
				break;
			}

			case TYPE_PTR:
			{
				buffer.PutUnsignedInt((int)dat->m_pValue);
			}

			default:
			{
				break;
			}
		}
	}

	buffer.PutUnsignedChar(TYPE_NUMTYPES); 
	return buffer.IsValid();
}
Esempio n. 23
0
bool KeyValues::ReadAsBinary(CUtlBuffer &buffer)
{
	if (buffer.IsText())
		return false;

	if (!buffer.IsValid())
		return false;

	RemoveEverything();
	Init();

	char token[KEYVALUES_TOKEN_SIZE];
	KeyValues *dat = this;
	types_t type = (types_t)buffer.GetUnsignedChar();

	while (true)
	{
		if (type == TYPE_NUMTYPES)
			break;

		dat->m_iDataType = type;

		buffer.GetString(token, KEYVALUES_TOKEN_SIZE - 1);
		token[KEYVALUES_TOKEN_SIZE - 1] = 0;

		dat->SetName(token);

		switch (type)
		{
			case TYPE_NONE:
			{
				dat->m_pSub = new KeyValues("");
				dat->m_pSub->ReadAsBinary(buffer);
				break;
			}

			case TYPE_STRING:
			{
				buffer.GetString(token, KEYVALUES_TOKEN_SIZE - 1);
				token[KEYVALUES_TOKEN_SIZE - 1] = 0;

				int len = Q_strlen(token);
				dat->m_sValue = new char[len + 1];
				Q_memcpy(dat->m_sValue, token, len + 1);

				break;
			}

			case TYPE_WSTRING:
			{
				Assert(!"TYPE_WSTRING");
				break;
			}

			case TYPE_INT:
			{
				dat->m_iValue = buffer.GetInt();
				break;
			}

			case TYPE_UINT64:
			{
				dat->m_sValue = new char[sizeof(uint64)];
				*((double *)dat->m_sValue) = buffer.GetDouble();
			}

			case TYPE_FLOAT:
			{
				dat->m_flValue = buffer.GetFloat();
				break;
			}

			case TYPE_COLOR:
			{
				dat->m_Color[0] = buffer.GetUnsignedChar();
				dat->m_Color[1] = buffer.GetUnsignedChar();
				dat->m_Color[2] = buffer.GetUnsignedChar();
				dat->m_Color[3] = buffer.GetUnsignedChar();
				break;
			}

			case TYPE_PTR:
			{
				dat->m_pValue = (void *)buffer.GetUnsignedInt();
			}

			default:
			{
				break;
			}
		}

		if (!buffer.IsValid())
			return false;

		type = (types_t)buffer.GetUnsignedChar();

		if (type == TYPE_NUMTYPES)
			break;

		dat->m_pPeer = new KeyValues("");
		dat = dat->m_pPeer;
	}

	return buffer.IsValid();
}
Esempio n. 24
0
// This is a compressed save of just the data needed to drive phonemes in the engine (no word / sentence text, etc )
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : buf - 
//-----------------------------------------------------------------------------
void CSentence::CacheSaveToBuffer( CUtlBuffer& buf, int version )
{
	Assert( !buf.IsText() );
	Assert( m_bIsCached );

	int i;
	unsigned short pcount = GetRuntimePhonemeCount();

	// header
	if ( version == CACHED_SENTENCE_VERSION_ALIGNED )
	{
		buf.PutChar( version );
		buf.PutChar( 0 );
		buf.PutChar( 0 );
		buf.PutChar( 0 );
		buf.PutInt( pcount );
	}
	else
	{
		buf.PutChar( version );
		buf.PutShort( pcount );
	}

	// phoneme
	if ( version == CACHED_SENTENCE_VERSION_ALIGNED )
	{
		for ( i = 0; i < pcount; ++i )
		{
			const CBasePhonemeTag *phoneme = GetRuntimePhoneme( i );
			Assert( phoneme );
			buf.PutInt( phoneme->GetPhonemeCode() );
			buf.PutFloat( phoneme->GetStartTime() );
			buf.PutFloat( phoneme->GetEndTime() );
		}
	}
	else
	{
		for ( i = 0; i < pcount; ++i )
		{
			const CBasePhonemeTag *phoneme = GetRuntimePhoneme( i );
			Assert( phoneme );
			buf.PutShort( phoneme->GetPhonemeCode() );
			buf.PutFloat( phoneme->GetStartTime() );
			buf.PutFloat( phoneme->GetEndTime() );
		}
	}

	// emphasis samples and voice duck
	int c = m_EmphasisSamples.Count();
	Assert( c <= 32767 );

	if ( version == CACHED_SENTENCE_VERSION_ALIGNED )
	{
		buf.PutInt( c );
		for ( i = 0; i < c; i++ )
		{
			CEmphasisSample *sample = &m_EmphasisSamples[i];
			Assert( sample );
			buf.PutFloat( sample->time );
			buf.PutFloat( sample->value );
		}
		buf.PutInt( GetVoiceDuck() ? 1 : 0 );
	}
	else
	{
		buf.PutShort( c );
		for ( i = 0; i < c; i++ )
		{
			CEmphasisSample *sample = &m_EmphasisSamples[i];
			Assert( sample );
			buf.PutFloat( sample->time );
			short scaledValue = clamp( (short)( sample->value * 32767 ), (short)0, (short)32767 );
			buf.PutShort( scaledValue );
		}
		buf.PutChar( GetVoiceDuck() ? 1 : 0 );
	}
}
Esempio n. 25
0
//-----------------------------------------------------------------------------
// Converts a buffer from a CRLF buffer to a CR buffer (and back)
// Returns false if no conversion was necessary (and outBuf is left untouched)
// If the conversion occurs, outBuf will be cleared.
//-----------------------------------------------------------------------------
bool CUtlBuffer::ConvertCRLF( CUtlBuffer &outBuf )
{
	if ( !IsText() || !outBuf.IsText() )
		return false;

	if ( ContainsCRLF() == outBuf.ContainsCRLF() )
		return false;

	int nInCount = TellMaxPut();

	outBuf.Purge();
	outBuf.EnsureCapacity( nInCount );

	bool bFromCRLF = ContainsCRLF();

	// Start reading from the beginning
	int nGet = TellGet();
	int nPut = TellPut();
	int nGetDelta = 0;
	int nPutDelta = 0;

	const char *pBase = (const char*)Base();
	int nCurrGet = 0;
	while ( nCurrGet < nInCount )
	{
		const char *pCurr = &pBase[nCurrGet];
		if ( bFromCRLF )
		{
			const char *pNext = Q_strnistr( pCurr, "\r\n", nInCount - nCurrGet );
			if ( !pNext )
			{
				outBuf.Put( pCurr, nInCount - nCurrGet );
				break;
			}

			int nBytes = (size_t)pNext - (size_t)pCurr;
			outBuf.Put( pCurr, nBytes );
			outBuf.PutChar( '\n' );
			nCurrGet += nBytes + 2;
			if ( nGet >= nCurrGet - 1 )
			{
				--nGetDelta;
			}
			if ( nPut >= nCurrGet - 1 )
			{
				--nPutDelta;
			}
		}
		else
		{
			const char *pNext = Q_strnchr( pCurr, '\n', nInCount - nCurrGet );
			if ( !pNext )
			{
				outBuf.Put( pCurr, nInCount - nCurrGet );
				break;
			}

			int nBytes = (size_t)pNext - (size_t)pCurr;
			outBuf.Put( pCurr, nBytes );
			outBuf.PutChar( '\r' );
			outBuf.PutChar( '\n' );
			nCurrGet += nBytes + 1;
			if ( nGet >= nCurrGet )
			{
				++nGetDelta;
			}
			if ( nPut >= nCurrGet )
			{
				++nPutDelta;
			}
		}
	}

	Assert(	nPut + nPutDelta <= outBuf.TellMaxPut() );

	outBuf.SeekGet( SEEK_HEAD, nGet + nGetDelta ); 
	outBuf.SeekPut( SEEK_HEAD, nPut + nPutDelta ); 

	return true;
}