diff options
| author | Marcin Bukat <marcin.bukat@gmail.com> | 2013-01-18 16:16:59 +0100 |
|---|---|---|
| committer | Franklin Wei <git@fwei.tk> | 2017-12-23 20:54:56 -0500 |
| commit | a8423321b802bff39fe2ba22f2b0a26220a57535 (patch) | |
| tree | 10ec3a75a1547c6232202664d091388b57917c38 /apps/plugins/lib/stdio_compat.c | |
| parent | d35a18f6b4f6b0871cf5369fa9bc2d6ea990fa82 (diff) | |
| download | rockbox-a8423321b802bff39fe2ba22f2b0a26220a57535.zip rockbox-a8423321b802bff39fe2ba22f2b0a26220a57535.tar.gz rockbox-a8423321b802bff39fe2ba22f2b0a26220a57535.tar.bz2 rockbox-a8423321b802bff39fe2ba22f2b0a26220a57535.tar.xz | |
stdio compat layer for plugins
This is attempt to simplify porting programs to rockbox (as plugins).
Currently this compat layer implements:
fopen(), fclose(), fflush(), fread(), fwrite(), fseek(), fseeko(),
ftell(), ftello(), fgetc(), ungetc(), fputc(), fgets(), clearerr(),
ferror(), feof(), fprintf()
In order to use it you need to include in ported sources
"lib/stdio_compat.h"
Change-Id: I5add615dd19c5af9c767ccbfb1bd5a4e466741cb
Diffstat (limited to 'apps/plugins/lib/stdio_compat.c')
| -rw-r--r-- | apps/plugins/lib/stdio_compat.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/apps/plugins/lib/stdio_compat.c b/apps/plugins/lib/stdio_compat.c new file mode 100644 index 0000000..d2b8f9b --- /dev/null +++ b/apps/plugins/lib/stdio_compat.c @@ -0,0 +1,231 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2013 by Marcin Bukat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "plugin.h" +#include "stdio_compat.h" + +static _FILE_ __file__[MAX_STDIO_FILES] = { + {-1,-1,0},{-1,-1,0},{-1,-1,0},{-1,-1,0}, + {-1,-1,0},{-1,-1,0},{-1,-1,0},{-1,-1,0} +}; + +_FILE_ *_fopen_(const char *path, const char *mode) +{ + _FILE_ *f = __file__; + int flags = O_RDONLY; + int fd = -1; + int i; + + /* look for free slot */ + for (i=0; i<MAX_OPEN_FILES; i++, f++) + if (f->fd == -1) + break; + + /* no empty slots */ + if (i == MAX_STDIO_FILES) + return NULL; + + if (*mode != 'r') + { + /* Not read */ + flags = (O_WRONLY | O_CREAT | O_TRUNC); + if (*mode != 'w') + { + /* Not write (create of append) */ + flags = (O_WRONLY | O_CREAT | O_APPEND); + if (*mode != 'a') + { + /* Illegal */ + return NULL; + } + } + } + + if (mode[1] == 'b') + { + /* Ignore */ + mode++; + } + + if (mode[1] == '+') + { + /* Read and Write. */ + flags |= (O_RDONLY | O_WRONLY); + flags += (O_RDWR - (O_RDONLY | O_WRONLY)); + } + + + fd = rb->open(path, flags); + + if (fd == -1) + return NULL; + + /* initialize */ + f->fd = fd; + f->unget_char = -1; + + return f; +} + +int _fflush_(_FILE_ *stream) +{ + (void)stream; + /* no buffering so we are always in sync */ + return 0; +} + +size_t _fread_(void *ptr, size_t size, size_t nmemb, _FILE_ *stream) +{ + ssize_t ret = rb->read(stream->fd, (char *)ptr, size*nmemb); + + if (ret < (ssize_t)(size*nmemb)) + stream->error = -1; + + return ret; +} + +size_t _fwrite_(const void *ptr, size_t size, size_t nmemb, _FILE_ *stream) +{ + ssize_t ret = rb->write(stream->fd, ptr, size*nmemb); + + if (ret < (ssize_t)(size*nmemb)) + stream->error = -1; + + return ret; +} + +int _fseek_(_FILE_ *stream, long offset, int whence) +{ + return rb->lseek(stream->fd, offset, whence); +} + +long _ftell_(_FILE_ *stream) +{ + return rb->lseek(stream->fd, 0, SEEK_CUR); +} + +int _fclose_(_FILE_ *stream) +{ + if (stream->fd == -1) + return EOF; + + if (rb->close(stream->fd) == -1) + return EOF; + + /* free the resource */ + stream->fd = -1; + + return 0; +} + +int _fgetc_(_FILE_ *stream) +{ + unsigned char c; + + if (stream->unget_char != -1) + { + c = stream->unget_char; + stream->unget_char = -1; + return c; + } + + if ( rb->read(stream->fd, &c, 1) != 1) + return EOF; + + return c; +} + +int _ungetc_(int c, _FILE_ *stream) +{ + stream->unget_char = c; + + return c; +} + +int _fputc_(int c, _FILE_ *stream) +{ + unsigned char cb = c; + + if (rb->write(stream->fd, &cb, 1) != 1) + return EOF; + + return cb; +} + +char *_fgets_(char *s, int size, _FILE_ *stream) +{ + char *p = s; + char c = '\0'; + + for (int i=0; i<size; i++) + { + if ( rb->read(stream->fd, &c, 1) != 1) + break; + + *p++ = c; + + if (c == '\n') + break; + } + + if (p == s) + return NULL; + + *p = '\0'; + + return s; +} + +void _clearerr_(_FILE_ *stream) +{ + if (stream) + stream->error = 0; +} + +int _ferror_(_FILE_ *stream) +{ + return (stream) ? stream->error : -1; +} + +int _feof_(_FILE_ *stream) +{ + int c = _fgetc_(stream); + + if (c != EOF) + { + _ungetc_(c, stream); + return 0; + } + + return 0; +} + +int _fprintf_(_FILE_ *stream, const char *format, ...) +{ + int len; + va_list ap; + char buf[256]; + + va_start(ap, format); + len = rb->vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + return _fwrite_(buf, 1, len, stream); +} |