Skip to content

Commit

Permalink
Merge pull request #889: Split FuncREAD_STRING_FILE into system depen…
Browse files Browse the repository at this point in the history
…dent bits

The #ifdefs within the function made the function less readable,
so FuncREAD_STRING_FILE now calls SyReadStringFile which is implemented
as two separate functions in sysfiles.c
  • Loading branch information
alex-konovalov authored Aug 19, 2016
2 parents 2dec7e1 + fa6a96c commit a256ddd
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 68 deletions.
71 changes: 3 additions & 68 deletions src/streams.c
Original file line number Diff line number Diff line change
Expand Up @@ -1967,86 +1967,21 @@ Obj FuncWRITE_STRING_FILE_NC (
return True;
}


Obj FuncREAD_STRING_FILE (
Obj self,
Obj fid )
{
Char buf[32769];
Int ret, len;
UInt lstr;
Obj str;
#if !defined(SYS_IS_CYGWIN32) && defined(HAVE_STAT)
Int l;
char *ptr;
#endif

/* check the argument */
while ( ! IS_INTOBJ(fid) ) {
fid = ErrorReturnObj(
"<fid> must be an integer (not a %s)",
(Int)TNAM_OBJ(fid), 0L,
"you can replace <fid> via 'return <fid>;'" );
}

#if !defined(SYS_IS_CYGWIN32) && defined(HAVE_STAT)
/* fstat seems completely broken under CYGWIN */
/* first try to get the whole file as one chunk, this avoids garbage
collections because of the GROW_STRING calls below */
{
struct stat fstatbuf;
if ( syBuf[INT_INTOBJ(fid)].pipe == 0 &&
fstat( syBuf[INT_INTOBJ(fid)].fp, &fstatbuf) == 0 ) {
if((off_t)(Int)fstatbuf.st_size != fstatbuf.st_size) {
ErrorMayQuit(
"The file is too big to fit the current workspace",
(Int)0, (Int)0);
}
len = (Int) fstatbuf.st_size;
str = NEW_STRING( len );
CHARS_STRING(str)[len] = '\0';
SET_LEN_STRING(str, len);
ptr = CSTR_STRING(str);
while (len > 0) {
l = (len > 1048576) ? 1048576 : len;
ret = read( syBuf[INT_INTOBJ(fid)].fp, ptr, l);
if (ret == -1) {
SySetErrorNo();
return Fail;
}
len -= ret;
ptr += ret;
}
return str;
}
if ( syBuf[INT_INTOBJ(fid)].pipe == 1 ) {
ErrorMayQuit("<fid> is a pipe, not a file", 0L, 0L);
}
#else
/* read <fid> until we see eof (in 32kB pieces) */
str = NEW_STRING(0);
len = 0;
do {
ret = read( syBuf[INT_INTOBJ(fid)].fp , buf, 32768);
if (ret < 0) {
SySetErrorNo();
return Fail;
}
len += ret;
GROW_STRING( str, len );
lstr = GET_LEN_STRING(str);
memcpy( CHARS_STRING(str)+lstr, buf, ret );
*(CHARS_STRING(str)+lstr+ret) = '\0';
SET_LEN_STRING(str, lstr+ret);
} while(ret > 0);

/* fix the length of <str> */
len = GET_LEN_STRING(str);
ResizeBag( str, SIZEBAG_STRINGLEN(len) );

/* and return */

syBuf[INT_INTOBJ(fid)].ateof = 1;
return str;
#endif
return SyReadStringFile(INT_INTOBJ(fid));
}

/****************************************************************************
Expand Down
75 changes: 75 additions & 0 deletions src/sysfiles.c
Original file line number Diff line number Diff line change
Expand Up @@ -4024,7 +4024,82 @@ Char * SyTmpdir ( const Char * hint )
#endif
#endif

#if !defined(SYS_IS_CYGWIN32) && defined(HAVE_STAT)
/* fstat seems completely broken under CYGWIN */
/* first try to get the whole file as one chunk, this avoids garbage
collections because of the GROW_STRING calls below */
Obj SyReadStringFile(Int fid)
{
Int ret, len;
Obj str;
Int l;
char *ptr;
struct stat fstatbuf;

if( fstat( syBuf[fid].fp, &fstatbuf) == 0 ) {
if((off_t)(Int)fstatbuf.st_size != fstatbuf.st_size) {
ErrorMayQuit(
"The file is too big to fit the current workspace",
(Int)0, (Int)0);
}
len = (Int) fstatbuf.st_size;
str = NEW_STRING( len );
CHARS_STRING(str)[len] = '\0';
SET_LEN_STRING(str, len);
ptr = CSTR_STRING(str);
while (len > 0) {
l = (len > 1048576) ? 1048576 : len;
ret = read( syBuf[fid].fp, ptr, l);
if (ret == -1) {
SySetErrorNo();
return Fail;
}
len -= ret;
ptr += ret;
}
syBuf[fid].ateof = 1;
return str;
} else {
SySetErrorNo();
return Fail;
}
}

#else

Obj SyReadStringFile(Int fid)
{
Char buf[32769];
Int ret, len;
UInt lstr;
Obj str;

/* read <fid> until we see eof (in 32kB pieces) */
str = NEW_STRING(0);
len = 0;
do {
ret = read( syBuf[fid].fp , buf, 32768);
if (ret < 0) {
SySetErrorNo();
return Fail;
}
len += ret;
GROW_STRING( str, len );
lstr = GET_LEN_STRING(str);
memcpy( CHARS_STRING(str)+lstr, buf, ret );
*(CHARS_STRING(str)+lstr+ret) = '\0';
SET_LEN_STRING(str, lstr+ret);
} while(ret > 0);

/* fix the length of <str> */
len = GET_LEN_STRING(str);
ResizeBag( str, SIZEBAG_STRINGLEN(len) );

syBuf[fid].ateof = 1;
return str;
}

#endif

/****************************************************************************
**
Expand Down
9 changes: 9 additions & 0 deletions src/sysfiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,15 @@ extern void syWinPut (
const Char * cmd,
const Char * str );

/***************************************************************************
**
*F SyReadFileString( <fid> )
** - read file given by <fid> file into a string
*/

extern Obj SyReadStringFile (
Int fid );



/****************************************************************************
Expand Down
9 changes: 9 additions & 0 deletions tst/testinstall/read.tst
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,13 @@ gap> SeekPositionStream(x, 3);
true
gap> ReadAll(x);
"lo\ngoodbye\ni like pies\n"
gap> StringFile(Filename( DirectoriesLibrary("tst"), "example.txt" ));
"hello\ngoodbye\ni like pies\n"
gap> dir := DirectoryTemporary();;
gap> FileString( Filename(dir, "tmp1"), "Hello, world!");
13
gap> StringFile( Filename(dir, "tmp2"));
fail
gap> StringFile( Filename(dir, "tmp1"));
"Hello, world!"
gap> STOP_TEST( "read.tst", 220000);

0 comments on commit a256ddd

Please sign in to comment.