// Init FileIO Pointers\r
stdin = &_iob[0];\r
stdin->FD = 0;\r
- stdin->Flags = FILE_FLAG_ALLOC|FILE_FLAG_MODE_READ|FILE_FLAG_LINEBUFFERED;\r
+ stdin->Flags = FILE_FLAG_ALLOC|FILE_FLAG_MODE_READ|FILE_FLAG_LINEBUFFERED|FILE_FLAG_OURBUFFER;\r
stdin->Buffer = malloc(STDIN_BUFSIZ);\r
stdin->BufferSpace = STDIN_BUFSIZ;\r
\r
stdout = &_iob[1];\r
stdout->FD = 1;\r
- stdout->Flags = FILE_FLAG_ALLOC|FILE_FLAG_MODE_WRITE|FILE_FLAG_LINEBUFFERED;\r
+ stdout->Flags = FILE_FLAG_ALLOC|FILE_FLAG_MODE_WRITE|FILE_FLAG_LINEBUFFERED|FILE_FLAG_OURBUFFER;\r
stdout->Buffer = malloc(STDOUT_BUFSIZ);\r
stdout->BufferSpace = STDOUT_BUFSIZ;\r
\r
return NULL;\r
}\r
\r
+ // Default to buffered\r
+ // - Disabled until fseek() is fixed\r
+ #if 0\r
+ fp->BufferOfs = 0;\r
+ fp->BufferPos = 0;\r
+ fp->BufferSpace = BUFSIZ;\r
+ fp->Buffer = malloc( fp->BufferSpace );\r
+ fp->Flags |= FILE_FLAG_OURBUFFER;\r
+ #endif\r
+ \r
if( (fp->Flags & FILE_FLAG_MODE_MASK) == FILE_FLAG_MODE_APPEND ) {\r
_SysSeek(fp->FD, 0, SEEK_END); //SEEK_END\r
}\r
fflush(fp);\r
if( fp->FD >= 0 ) {\r
_SysClose(fp->FD);\r
+ if( fp->Buffer && (fp->Flags & FILE_FLAG_OURBUFFER) ) {\r
+ free(fp->Buffer);\r
+ }\r
+ fp->Buffer = NULL;\r
}\r
fp->Flags = 0;\r
fp->FD = FD_NOTOPEN;\r
}\r
// Allocate a buffer if one was not provided\r
if( !buffer ) {\r
+ fp->Flags |= FILE_FLAG_OURBUFFER;\r
buffer = malloc(size);\r
assert(buffer);\r
}\r
+ else {\r
+ fp->Flags &= ~FILE_FLAG_OURBUFFER;\r
+ }\r
\r
// Set buffer pointer and size\r
fp->Buffer = buffer;\r
}\r
#endif\r
\r
+size_t _fread_buffered(void *ptr, size_t size, FILE *fp)\r
+{\r
+ _SysDebug("%p: %i-%i <= %i", fp,\r
+ (int)fp->Pos, (int)fp->BufferOfs, (int)fp->BufferPos);\r
+ if( fp->BufferPos > 0 ) {\r
+ assert( fp->Pos - fp->BufferOfs <= fp->BufferPos );\r
+ }\r
+ if( fp->BufferPos == 0 || fp->Pos - fp->BufferOfs == fp->BufferPos )\r
+ {\r
+ int rv = _SysRead(fp->FD, fp->Buffer, fp->BufferSpace);\r
+ if( rv <= 0 ) {\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ return 0;\r
+ }\r
+ \r
+ fp->BufferPos = rv;\r
+ fp->BufferOfs = fp->Pos;\r
+ _SysDebug("%p: Buffered %i at %i", fp, rv, fp->Pos);\r
+ }\r
+ \r
+ size_t inner_ofs = fp->Pos - fp->BufferOfs;\r
+ if(size > fp->BufferPos - inner_ofs)\r
+ size = fp->BufferPos - inner_ofs;\r
+ \r
+ _SysDebug("%p: Read %i from %i+%i", fp, size,\r
+ (int)fp->BufferOfs, inner_ofs);\r
+ memcpy(ptr, fp->Buffer + inner_ofs, size);\r
+ fp->Pos += size;\r
+ return size;\r
+}\r
+\r
/**\r
* \fn EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)\r
* \brief Read from a stream\r
return -1;\r
}\r
\r
+ // Don't read if EOF is set\r
+ if( fp->Flags & FILE_FLAG_EOF )\r
+ return 0;\r
+\r
+ \r
if( fp->FD == FD_MEMFILE ) {\r
return _fread_memfile(ptr, size, num, fp);\r
}\r
errno = EBADF;\r
return 0;\r
}\r
- \r
+\r
// Standard file\r
- ret = _SysRead(fp->FD, ptr, size*num);\r
- if( ret == (size_t)-1)\r
- return -1;\r
- if( ret == 0 && size*num > 0 ) {\r
- fp->Flags |= FILE_FLAG_EOF;\r
- return 0;\r
+ const size_t bytes = size*num;\r
+\r
+ // TODO: Buffered reads\r
+ if( fp->BufferSpace )\r
+ {\r
+ size_t ofs = 0;\r
+ size_t rv;\r
+ // While not done, and buffered read succeeds\r
+ while( ofs < bytes && (rv = _fread_buffered((char*)ptr + ofs, bytes - ofs, fp)) != 0 )\r
+ {\r
+ ofs += rv;\r
+ }\r
+ \r
+ ret = ofs;\r
+ }\r
+ else\r
+ {\r
+ ret = _SysRead(fp->FD, ptr, bytes);\r
+ if( ret == (size_t)-1)\r
+ return -1;\r
+ if( ret == 0 && bytes > 0 ) {\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ return 0;\r
+ }\r
+ }\r
+\r
+ // if read was cut short \r
+ if( ret != bytes )\r
+ {\r
+ size_t extra = ret - (ret / size) * size;\r
+ // And it didn't fall short on a member boundary\r
+ if( extra )\r
+ {\r
+ // Need to roll back the file pointer to the end of the last member\r
+ _SysDebug("fread: TODO Roll back %zi bytes due to incomplete object (sz=%zi,n=%zi)",\r
+ extra, size, num\r
+ );\r
+ }\r
}\r
- ret /= size;\r
\r
- return ret;\r
+ return ret / size;\r
}\r
\r
/**\r
*/\r
EXPORT int fputc(int c, FILE *fp)\r
{\r
- return fwrite(&c, 1, 1, fp);\r
+ char ch = c;\r
+ return fwrite(&ch, 1, 1, fp);\r
}\r
\r
EXPORT int putchar(int c)\r
{\r
c &= 0xFF;\r
- return _SysWrite(_stdout, &c, 1);\r
+ return fputc(c, stdout);\r
}\r
\r
/**\r
\r
EXPORT int getchar(void)\r
{\r
- char ret = 0;\r
- if(_SysRead(_stdin, &ret, 1) != 1) return -1;\r
- return ret;\r
+ return fgetc(stdin);\r
}\r
\r
EXPORT int puts(const char *str)\r
{\r
- int len;\r
\r
if(!str) return 0;\r
- len = strlen(str);\r
+ int len = strlen(str);\r
\r
- len = _SysWrite(_stdout, str, len);\r
- _SysWrite(_stdout, "\n", 1);\r
+ fwrite(str, 1, len, stdout);\r
+ fwrite("\n", 1, 1, stdout);\r
return len;\r
}\r
\r
*/\r
FILE *get_file_struct()\r
{\r
- int i;\r
- for(i=0;i<STDIO_MAX_STREAMS;i++)\r
+ for(int i=0;i<STDIO_MAX_STREAMS;i++)\r
{\r
if(_iob[i].Flags & FILE_FLAG_ALLOC)\r
continue ;\r