msvcrt: Handle CR at buffer boundary and test case.

This commit is contained in:
Uwe Bonnes 2010-01-16 17:24:19 +01:00 committed by Alexandre Julliard
parent 2bfce6cfdc
commit e6f1ae029e
2 changed files with 62 additions and 2 deletions

View File

@ -60,6 +60,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
#define WX_OPEN 0x01 #define WX_OPEN 0x01
#define WX_ATEOF 0x02 #define WX_ATEOF 0x02
#define WX_READEOF 0x04 /* like ATEOF, but for underlying file rather than buffer */ #define WX_READEOF 0x04 /* like ATEOF, but for underlying file rather than buffer */
#define WX_READCR 0x08 /* underlying file is at \r */
#define WX_DONTINHERIT 0x10 #define WX_DONTINHERIT 0x10
#define WX_APPEND 0x20 #define WX_APPEND 0x20
#define WX_TEXT 0x80 #define WX_TEXT 0x80
@ -941,6 +942,9 @@ int CDECL MSVCRT_fseek(MSVCRT_FILE* file, MSVCRT_long offset, int whence)
if (file->_ptr[i] == '\n') if (file->_ptr[i] == '\n')
offset--; offset--;
} }
/* Black magic when reading CR at buffer boundary*/
if(MSVCRT_fdesc[file->_file].wxflag & WX_READCR)
offset--;
} }
} }
/* Discard buffered input */ /* Discard buffered input */
@ -1742,6 +1746,10 @@ int CDECL _rmtmp(void)
/********************************************************************* /*********************************************************************
* (internal) read_i * (internal) read_i
*
* When reading \r as last character in text mode, read() positions
* the file pointer on the \r character while getc() goes on to
* the following \n
*/ */
static int read_i(int fd, void *buf, unsigned int count) static int read_i(int fd, void *buf, unsigned int count)
{ {
@ -1768,6 +1776,13 @@ static int read_i(int fd, void *buf, unsigned int count)
if (MSVCRT_fdesc[fd].wxflag & WX_TEXT) if (MSVCRT_fdesc[fd].wxflag & WX_TEXT)
{ {
DWORD i, j; DWORD i, j;
if (bufstart[num_read-1] == '\r')
{
MSVCRT_fdesc[fd].wxflag |= WX_READCR;
num_read--;
}
else
MSVCRT_fdesc[fd].wxflag &= ~WX_READCR;
for (i=0, j=0; i<num_read; i++) for (i=0, j=0; i<num_read; i++)
{ {
/* in text mode, a ctrl-z signals EOF */ /* in text mode, a ctrl-z signals EOF */
@ -2890,6 +2905,10 @@ LONG CDECL MSVCRT_ftell(MSVCRT_FILE* file)
if (file->_ptr[i] == '\n') if (file->_ptr[i] == '\n')
off--; off--;
} }
/* Black magic when reading CR at buffer boundary*/
if(MSVCRT_fdesc[file->_file].wxflag & WX_READCR)
off--;
} }
} }
} }
@ -2916,6 +2935,9 @@ int CDECL MSVCRT_fgetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
if (file->_ptr[i] == '\n') if (file->_ptr[i] == '\n')
off--; off--;
} }
/* Black magic when reading CR at buffer boundary*/
if(MSVCRT_fdesc[file->_file].wxflag & WX_READCR)
off--;
} }
} }
} }

View File

@ -422,6 +422,35 @@ static WCHAR* AtoW( const char* p )
return buffer; return buffer;
} }
/* Test reading in text mode when the 512'th character read is \r*/
static void test_readboundary(void)
{
FILE *fp;
char buf[513], rbuf[513];
int i, j;
for (i = 0; i < 511; i++)
{
j = (i%('~' - ' ')+ ' ');
buf[i] = j;
}
buf[511] = '\n';
buf[512] =0;
fp = fopen("boundary.tst", "wt");
fwrite(buf, 512,1,fp);
fclose(fp);
fp = fopen("boundary.tst", "rt");
for(i=0; i<512; i++)
{
fseek(fp,0 , SEEK_CUR);
rbuf[i] = fgetc(fp);
}
rbuf[512] =0;
fclose(fp);
unlink("boundary.tst");
ok(strcmp(buf, rbuf) == 0,"CRLF on buffer boundary failure\n");
}
static void test_fgetc( void ) static void test_fgetc( void )
{ {
char* tempf; char* tempf;
@ -808,15 +837,23 @@ static void test_file_write_read( void )
tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */ tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
_lseek(tempfd, -1, FILE_END); _lseek(tempfd, -1, FILE_END);
ret = _read(tempfd,btext,LLEN); ret = _read(tempfd,btext,LLEN);
ok(ret == 1, "_read expected 1 got bad length: %d\n", ret); ok(ret == 1 && *btext == '\n', "_read expected 1 got bad length: %d\n", ret);
_lseek(tempfd, -2, FILE_END); _lseek(tempfd, -2, FILE_END);
ret = _read(tempfd,btext,LLEN); ret = _read(tempfd,btext,LLEN);
ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret); ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
_lseek(tempfd, -3, FILE_END); _lseek(tempfd, -3, FILE_END);
ret = _read(tempfd,btext,1);
ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd));
_lseek(tempfd, -3, FILE_END);
ret = _read(tempfd,btext,2); ret = _read(tempfd,btext,2);
ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret); ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd)); ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
_close(tempfd); _lseek(tempfd, -3, FILE_END);
ret = _read(tempfd,btext,3);
ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd));
_close(tempfd);
ret = unlink(tempf); ret = unlink(tempf);
ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno); ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
@ -1402,6 +1439,7 @@ START_TEST(file)
test_asciimode2(); test_asciimode2();
test_readmode(FALSE); /* binary mode */ test_readmode(FALSE); /* binary mode */
test_readmode(TRUE); /* ascii mode */ test_readmode(TRUE); /* ascii mode */
test_readboundary();
test_fgetc(); test_fgetc();
test_fputc(); test_fputc();
test_flsbuf(); test_flsbuf();