#define _stdin 0\r
#define _stdout 1\r
\r
+#define FD_NOTOPEN -1\r
+#define FD_MEMFILE -2\r
+#define FD_MEMSTREAM -3\r
+\r
// === PROTOTYPES ===\r
struct sFILE *get_file_struct();\r
\r
// Sanity Check Arguments\r
if(!fp || !file || !mode) return NULL;\r
\r
- if(fp->FD != -1) {\r
+ if(fp->FD != FD_NOTOPEN) {\r
fflush(fp);\r
}\r
\r
}\r
\r
//Open File\r
- if(fp->FD != -1)\r
+ if(fp->FD != FD_NOTOPEN)\r
fp->FD = _SysReopen(fp->FD, file, openFlags);\r
else\r
fp->FD = _SysOpen(file, openFlags);\r
\r
ret = get_file_struct();\r
\r
- ret->FD = -2;\r
+ ret->FD = FD_MEMFILE;\r
ret->Flags = _fopen_modetoflags(mode);\r
if(ret->Flags == -1) {\r
ret->Flags = 0;\r
return ret;\r
}\r
\r
+EXPORT FILE *open_memstream(char **bufferptr, size_t *lengthptr)\r
+{\r
+ FILE *ret = get_file_struct();\r
+ ret->FD = FD_MEMSTREAM;\r
+ ret->Flags = FILE_FLAG_MODE_WRITE;\r
+ \r
+ ret->Buffer = NULL;\r
+ ret->BufferPos = 0;\r
+ ret->BufferSpace = 0;\r
+ ret->BufPtr = bufferptr;\r
+ ret->LenPtr = lengthptr;\r
+ \r
+ return ret;\r
+}\r
+\r
EXPORT int fclose(FILE *fp)\r
{\r
if( !(fp->Flags & FILE_FLAG_ALLOC) )\r
_SysClose(fp->FD);\r
}\r
fp->Flags = 0;\r
- fp->FD = -1;\r
+ fp->FD = FD_NOTOPEN;\r
return 0;\r
}\r
\r
}\r
\r
// Check for memory files\r
- if( fp->FD == -2 ) {\r
+ if( fp->FD == FD_MEMFILE || fp->FD == FD_MEMSTREAM ) {\r
errno = EINVAL;\r
return 2;\r
} \r
\r
EXPORT void fflush(FILE *fp)\r
{\r
- if( !fp || fp->FD == -1 )\r
+ if( !fp || fp->FD == FD_NOTOPEN )\r
return ;\r
\r
// Nothing to do for memory files\r
- if( fp->FD == -2 )\r
+ if( fp->FD == FD_MEMFILE )\r
+ return ;\r
+ // Memory streams, update pointers\r
+ if( fp->FD == FD_MEMSTREAM ) {\r
+ *fp->BufPtr = fp->Buffer;\r
+ *fp->LenPtr = fp->BufferPos;\r
return ;\r
+ }\r
\r
_fflush_int(fp);\r
}\r
\r
EXPORT void clearerr(FILE *fp)\r
{\r
- if( !fp || fp->FD == -1 )\r
+ if( !fp || fp->FD == FD_NOTOPEN )\r
return ;\r
\r
// TODO: Impliment clearerr()\r
\r
EXPORT int feof(FILE *fp)\r
{\r
- if( !fp || fp->FD == -1 )\r
+ if( !fp || fp->FD == FD_NOTOPEN )\r
return 0;\r
return !!(fp->Flags & FILE_FLAG_EOF);\r
}\r
\r
EXPORT int ferror(FILE *fp)\r
{\r
- if( !fp || fp->FD == -1 )\r
+ if( !fp || fp->FD == FD_NOTOPEN )\r
return 0;\r
return 0;\r
}\r
\r
EXPORT off_t ftell(FILE *fp)\r
{\r
- if(!fp || fp->FD == -1) return -1;\r
+ if(!fp || fp->FD == FD_NOTOPEN) {\r
+ errno = EBADF;\r
+ return -1;\r
+ }\r
\r
- if( fp->FD == -2 )\r
+ if( fp->FD == FD_MEMFILE || fp->FD == FD_MEMSTREAM )\r
return fp->Pos; \r
else\r
return _SysTell(fp->FD);\r
}\r
\r
+int _fseek_memfile(FILE *fp, long int amt, int whence)\r
+{\r
+ switch(whence)\r
+ {\r
+ case SEEK_CUR:\r
+ fp->Pos += amt;\r
+ break;\r
+ case SEEK_SET:\r
+ fp->Pos = amt;\r
+ break;\r
+ case SEEK_END:\r
+ if( fp->BufferSpace < (size_t)amt )\r
+ fp->Pos = 0;\r
+ else\r
+ fp->Pos = fp->BufferSpace - amt;\r
+ break;\r
+ }\r
+ if(fp->Pos > (off_t)fp->BufferSpace) {\r
+ fp->Pos = fp->BufferSpace;\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ }\r
+ return 0;\r
+}\r
+\r
+int _fseek_memstream(FILE *fp, long int amt, int whence)\r
+{\r
+ switch(whence)\r
+ {\r
+ case SEEK_CUR:\r
+ fp->Pos += amt;\r
+ break;\r
+ case SEEK_SET:\r
+ fp->Pos = amt;\r
+ break;\r
+ case SEEK_END:\r
+ if( fp->BufferSpace < (size_t)amt )\r
+ fp->Pos = 0;\r
+ else\r
+ fp->Pos = fp->BufferSpace - amt;\r
+ break;\r
+ }\r
+ if(fp->Pos > (off_t)fp->BufferSpace) {\r
+ fp->Pos = fp->BufferSpace;\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ }\r
+ return 0;\r
+}\r
+\r
EXPORT int fseek(FILE *fp, long int amt, int whence)\r
{\r
- if(!fp || fp->FD == -1) return -1;\r
+ if(!fp || fp->FD == FD_NOTOPEN) {\r
+ errno = EBADF;\r
+ return -1;\r
+ }\r
\r
- if( fp->FD == -2 ) {\r
- switch(whence)\r
- {\r
- case SEEK_CUR:\r
- fp->Pos += amt;\r
- break;\r
- case SEEK_SET:\r
- fp->Pos = amt;\r
- break;\r
- case SEEK_END:\r
- if( fp->BufferSpace < (size_t)amt )\r
- fp->Pos = 0;\r
- else\r
- fp->Pos = fp->BufferSpace - amt;\r
- break;\r
- }\r
- if(fp->Pos > (off_t)fp->BufferSpace) {\r
- fp->Pos = fp->BufferSpace;\r
- fp->Flags |= FILE_FLAG_EOF;\r
- }\r
- return 0;\r
+ if( fp->FD == FD_MEMFILE ) {\r
+ return _fseek_memfile(fp, amt, whence);\r
+ }\r
+ else if( fp->FD == FD_MEMSTREAM ) {\r
+ return _fseek_memstream(fp, amt, whence);\r
}\r
else {\r
fflush(fp);\r
return ret;\r
}\r
\r
+size_t _fwrite_memfile(const void *ptr, size_t size, size_t num, FILE *fp)\r
+{\r
+ size_t avail = (fp->BufferSpace - fp->Pos) / size;\r
+ if( avail == 0 )\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ if( num > avail )\r
+ num = avail;\r
+ size_t bytes = num * size;\r
+ memcpy(fp->Buffer + fp->Pos, ptr, bytes);\r
+ fp->Pos += bytes;\r
+ return num;\r
+}\r
+\r
+size_t _fwrite_memstream(const void *ptr, size_t size, size_t num, FILE *fp)\r
+{\r
+ size_t bytes = size*num;\r
+ // #1. Check if we need to expand\r
+ if( fp->Pos + bytes > fp->BufferSpace )\r
+ {\r
+ void *newbuf = realloc(fp->Buffer, fp->BufferSpace + bytes);\r
+ if( !newbuf ) {\r
+ errno = ENOMEM;\r
+ return -1;\r
+ }\r
+ fp->Buffer = newbuf;\r
+ fp->BufferSpace = fp->Pos + bytes;\r
+ }\r
+ // #2. Write (use the memfile code for that)\r
+ return _fwrite_memfile(ptr, size, num, fp);\r
+}\r
+\r
/**\r
* \fn EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)\r
* \brief Write to a stream\r
if( size == 0 || num == 0 )\r
return 0;\r
\r
- // Handle memory files first\r
- if( fp->FD == -2 ) {\r
- size_t avail = (fp->BufferSpace - fp->Pos) / size;\r
- if( avail == 0 )\r
- fp->Flags |= FILE_FLAG_EOF;\r
- if( num > avail )\r
- num = avail;\r
- size_t bytes = num * size;\r
- memcpy(fp->Buffer + fp->Pos, ptr, bytes);\r
- fp->Pos += bytes;\r
- return num;\r
- }\r
-\r
switch( _GetFileMode(fp) )\r
{\r
case FILE_FLAG_MODE_READ:\r
case FILE_FLAG_MODE_EXEC:\r
+ errno = EBADF;\r
return 0;\r
case FILE_FLAG_MODE_APPEND:\r
fseek(fp, 0, SEEK_END);\r
case FILE_FLAG_MODE_WRITE:\r
- if( fp->BufferSpace )\r
+ // Handle memory files first\r
+ if( fp->FD == FD_MEMFILE ) {\r
+ return _fwrite_memfile(ptr, size, num, fp);\r
+ }\r
+ else if( fp->FD == FD_MEMSTREAM ) {\r
+ return _fwrite_memstream(ptr, size, num, fp);\r
+ }\r
+ else if( fp->BufferSpace )\r
{\r
// Buffering enabled\r
if( fp->BufferSpace - fp->BufferPos < size*num )\r
return ret;\r
}\r
\r
+size_t _fread_memfile(void *ptr, size_t size, size_t num, FILE *fp)\r
+{\r
+ size_t avail = (fp->BufferSpace - fp->Pos) / size;\r
+ if( avail == 0 )\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ if( num > avail ) num = avail;\r
+ size_t bytes = num * size;\r
+ memcpy(ptr, fp->Buffer + fp->Pos, bytes);\r
+ fp->Pos += bytes;\r
+ return num;\r
+}\r
+\r
+#if 0\r
+size_t _fread_memstream(void *ptr, size_t size, size_t num, FILE *fp)\r
+{\r
+ errno = ENOTIMPL;\r
+ return -1;\r
+}\r
+#endif\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
if( size == 0 || num == 0 )\r
return 0;\r
+ \r
+ if( _GetFileMode(fp) != FILE_FLAG_MODE_READ ) {\r
+ errno = 0;\r
+ return -1;\r
+ }\r
\r
- if( fp->FD == -2 ) {\r
- size_t avail = (fp->BufferSpace - fp->Pos) / size;\r
- if( avail == 0 )\r
- fp->Flags |= FILE_FLAG_EOF;\r
- if( num > avail ) num = avail;\r
- size_t bytes = num * size;\r
- memcpy(ptr, fp->Buffer + fp->Pos, bytes);\r
- fp->Pos += bytes;\r
- return num;\r
+ if( fp->FD == FD_MEMFILE ) {\r
+ return _fread_memfile(ptr, size, num, fp);\r
+ }\r
+ else if( fp->FD == FD_MEMSTREAM ) {\r
+ //return _fread_memstream(ptr, size, num, fp);\r
+ errno = EBADF;\r
+ return 0;\r
}\r
\r
// Standard file\r
return ret;\r
}\r
\r
+EXPORT int puts(const char *str)\r
+{\r
+ int len;\r
+ \r
+ if(!str) return 0;\r
+ len = strlen(str);\r
+ \r
+ len = _SysWrite(_stdout, str, len);\r
+ _SysWrite(_stdout, "\n", 1);\r
+ return len;\r
+}\r
+\r
// --- INTERNAL ---\r
/**\r
* \fn FILE *get_file_struct()\r
return NULL;\r
}\r
\r
-EXPORT int puts(const char *str)\r
-{\r
- int len;\r
- \r
- if(!str) return 0;\r
- len = strlen(str);\r
- \r
- len = _SysWrite(_stdout, str, len);\r
- _SysWrite(_stdout, "\n", 1);\r
- return len;\r
-}\r
-\r