public: add Q_memfgets, replacement for COM_MemFgets rewritten using crtlib functions. Add a test

This commit is contained in:
Alibek Omarov
2026-03-01 03:04:33 +05:00
parent 53c5a33ffd
commit c19a824a42
8 changed files with 79 additions and 58 deletions

View File

@@ -22,6 +22,30 @@ GNU General Public License for more details.
#include "xash3d_mathlib.h"
#include "crtlib.h"
char *GAME_EXPORT Q_memfgets( byte *data, int data_len, int *data_offset, char *dst, int dst_size )
{
// sanity check
if( !data || !data_offset || !dst || *data_offset >= data_len )
return NULL;
const char *start = (const char *)data + *data_offset;
int remaining = data_len - *data_offset;
// do not assume the data is null terminated, as we have data_len anyway :)
const char *end = memchr( start, '\n', remaining );
if( end )
remaining = end - start + 1;
// include null terminator
Q_strncpy( dst, start, Q_min( remaining + 1, dst_size ));
*data_offset += remaining;
return dst;
}
void Q_strnlwr( const char *in, char *out, size_t size_out )
{
size_t len, i;

View File

@@ -98,6 +98,7 @@ int Q_atoi_hex( int sign, const char *str );
int Q_atoi( const char *str );
float Q_atof( const char *str );
void Q_atov( float *vec, const char *str, size_t siz );
char *Q_memfgets( byte *data, int data_len, int *data_offset, char *dst, int dst_size );
#define Q_strchr strchr
#define Q_strrchr strrchr
qboolean Q_stricmpext( const char *pattern, const char *text );

View File

@@ -99,6 +99,47 @@ static int Test_TrimSpace( void )
return 0;
}
#include <stdio.h>
static int Test_memgets( qboolean include_null_terminator )
{
char data[] =
"First line\n"
"Second line\n"
"Third line with long text\n"
"Last line without newline";
int data_len = sizeof( data ) - ( include_null_terminator ? 1 : 0 );
string buffer;
int data_offset = 0;
int check_offset = sizeof( "First line\n" ) - 1;
char *p;
p = Q_memfgets( data, data_len, &data_offset, buffer, sizeof( buffer ));
if( !p || Q_strcmp( buffer, "First line\n" ) || data_offset != check_offset )
return 1;
check_offset += sizeof( "Second line\n" ) - 1;
p = Q_memfgets( data, data_len, &data_offset, buffer, sizeof( buffer ));
if( !p || Q_strcmp( buffer, "Second line\n" ) || data_offset != check_offset )
return 2;
check_offset += sizeof( "Third line with long text\n" ) - 1;
p = Q_memfgets( data, data_len, &data_offset, buffer, sizeof( buffer ));
if( !p || Q_strcmp( buffer, "Third line with long text\n" ) || data_offset != check_offset )
return 3;
check_offset += sizeof( "Last line without newline" ) - ( include_null_terminator ? 1 : 0 );
p = Q_memfgets( data, data_len, &data_offset, buffer, sizeof( buffer ));
if( !p || Q_strcmp( buffer, "Last line without newline" ) || data_offset != check_offset )
return 4;
p = Q_memfgets( data, data_len, &data_offset, buffer, sizeof( buffer ));
if( p )
return 5;
return 0;
}
int main( void )
{
int ret = Test_Strcpycatcmp();
@@ -121,5 +162,15 @@ int main( void )
if( ret > 0 )
return ret + 48;
ret = Test_memgets( true );
if( ret > 0 )
return ret + 64;
ret = Test_memgets( false );
if( ret > 0 )
return ret + 64;
return 0;
}