|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- /* Arduino RamDisk Library
- * Copyright (C) 2014 by William Greiman
- *
- * This file is part of the Arduino RamDisk Library
- *
- * This Library 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 3 of the License, or
- * (at your option) any later version.
- *
- * This Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the Arduino RamDisk Library. If not, see
- * <http://www.gnu.org/licenses/>.
- */
- /**
- * \file
- * StdioStream implementation
- */
- #include <Arduino.h>
- #include <StdioStream.h>
- #include <utility/FmtNumber.h>
- //------------------------------------------------------------------------------
- int StdioStream::fclose() {
- int rtn = 0;
- if (!m_flags) {
- return EOF;
- }
- if (m_flags & F_SWR) {
- if (!flushBuf()) rtn = EOF;
- }
- if (!SdBaseFile::close()) rtn = EOF;
- m_r = 0;
- m_w = 0;
- m_flags = 0;
- return rtn;
- }
- //------------------------------------------------------------------------------
- int StdioStream::fflush() {
- if ((m_flags & (F_SWR | F_SRW)) && !(m_flags & F_SRD)) {
- if (flushBuf() && SdBaseFile::sync()) return 0;
- }
- return EOF;
- }
- //------------------------------------------------------------------------------
- char* StdioStream::fgets(char* str, int num, size_t* len) {
- char* s = str;
- size_t n;
- if (num-- <= 0) return 0;
- while (num) {
- if ((n = m_r) == 0) {
- if (!fillBuf()) {
- if (s == str) return 0;
- break;
- }
- n = m_r;
- }
- if (n > num) n = num;
- uint8_t* end = reinterpret_cast<uint8_t*>(memchr(m_p, '\n', n));
- if (end != 0) {
- n = ++end - m_p;
- memcpy(s, m_p, n);
- m_r -= n;
- m_p = end;
- s += n;
- break;
- }
- memcpy(s, m_p, n);
- m_r -= n;
- m_p += n;
- s += n;
- num -= n;
- }
- *s = 0;
- if (len) *len = s - str;
- return str;
- }
- //------------------------------------------------------------------------------
- bool StdioStream::fopen(const char* filename, const char* mode) {
- uint8_t oflags;
- switch (*mode++) {
- case 'a':
- m_flags = F_SWR;
- oflags = O_WRITE | O_CREAT | O_APPEND | O_AT_END;
- break;
-
- case 'r':
- m_flags = F_SRD;
- oflags = O_READ;
- break;
-
- case 'w':
- m_flags = F_SWR;
- oflags = O_WRITE | O_CREAT | O_TRUNC;
- break;
-
- default:
- goto fail;
- }
- while (*mode) {
- switch (*mode++) {
- case '+':
- m_flags |= F_SRW;
- oflags |= O_RDWR;
- break;
-
- case 'b':
- break;
-
- case 'x':
- oflags |= O_EXCL;
- break;
-
- default:
- goto fail;
- }
- }
- if ((oflags & O_EXCL) && !(oflags & O_WRITE)) goto fail;
- if (!SdBaseFile::open(filename, oflags)) goto fail;
- m_r = 0;
- m_w = 0;
- m_p = m_buf;
- return true;
-
- fail:
- m_flags = 0;
- return false;
- }
- //------------------------------------------------------------------------------
- int StdioStream::fputs(const char* str) {
- size_t len = strlen(str);
- return fwrite(str, 1, len) == len ? len : EOF;
- }
- //------------------------------------------------------------------------------
- int StdioStream::fputs_P(PGM_P str) {
- PGM_P bgn = str;
- for (char c; (c = pgm_read_byte(str)); str++) {
- if (putc(c) < 0) return EOF;
- }
- return str - bgn;
- }
- //------------------------------------------------------------------------------
- size_t StdioStream::fread(void* ptr, size_t size, size_t count) {
- uint8_t* dst = reinterpret_cast<uint8_t*>(ptr);
- size_t total = size*count;
- if (total == 0) return 0;
- size_t need = total;
- while (need > m_r) {
- memcpy(dst, m_p, m_r);
- dst += m_r;
- m_p += m_r;
- need -= m_r;
- if (!fillBuf()) {
- return (total - need)/size;
- }
- }
- memcpy(dst, m_p, need);
- m_r -= need;
- m_p += need;
- return count;
- }
- //------------------------------------------------------------------------------
- int StdioStream::fseek(int32_t offset, int origin) {
- int32_t pos;
- if (m_flags & F_SWR) {
- if (!flushBuf()) {
- goto fail;
- }
- }
- switch (origin) {
- case SEEK_CUR:
- pos = ftell();
- if (pos < 0) {
- goto fail;
- }
- pos += offset;
- if (!SdBaseFile::seekCur(pos)) {
- goto fail;
- }
- break;
-
- case SEEK_SET:
- if (!SdBaseFile::seekSet(offset)) {
- goto fail;
- }
- break;
-
- case SEEK_END:
- if (!SdBaseFile::seekEnd(offset)) {
- goto fail;
- }
- break;
-
- default:
- goto fail;
- }
- m_r = 0;
- m_p = m_buf;
- return 0;
-
- fail:
- return EOF;
- }
- //------------------------------------------------------------------------------
- int32_t StdioStream::ftell() {
- uint32_t pos = SdBaseFile::curPosition();
- if (m_flags & F_SRD) {
- if (m_r > pos) return -1L;
- pos -= m_r;
- } else if (m_flags & F_SWR) {
- pos += m_p - m_buf;
- }
- return pos;
- }
- //------------------------------------------------------------------------------
- size_t StdioStream::fwrite(const void* ptr, size_t size, size_t count) {
- return write(ptr, count*size) < 0 ? EOF : count;
- #if 0 ////////////////////////////////////////////////////////////////////////////////////
- const uint8_t* src = static_cast<const uint8_t*>(ptr);
- size_t total = count*size;
- if (total == 0) return 0;
- size_t todo = total;
-
- while (todo > m_w) {
- memcpy(m_p, src, m_w);
- m_p += m_w;
- src += m_w;
- todo -= m_w;
- if (!flushBuf()) {
- return (total - todo)/size;
- }
- }
- memcpy(m_p, src, todo);
- m_p += todo;
- m_w -= todo;
- return count;
- #endif //////////////////////////////////////////////////////////////////////////////////
- }
- //------------------------------------------------------------------------------
- int StdioStream::write(const void* buf, size_t count) {
- const uint8_t* src = static_cast<const uint8_t*>(buf);
- size_t todo = count;
-
- while (todo > m_w) {
- memcpy(m_p, src, m_w);
- m_p += m_w;
- src += m_w;
- todo -= m_w;
- if (!flushBuf()) return EOF;
- }
- memcpy(m_p, src, todo);
- m_p += todo;
- m_w -= todo;
- return count;
- }
- //------------------------------------------------------------------------------
- size_t StdioStream::print(const __FlashStringHelper *str) {
- const char PROGMEM *p = (const char PROGMEM *)str;
- uint8_t c;
- while (c = pgm_read_byte(p)) {
- if (putc(c) < 0) return 0;
- p++;
- }
- return p - (const char PROGMEM *)str;
- }
- //------------------------------------------------------------------------------
- int StdioStream::printDec(float value, uint8_t prec) {
- #define FLOAT_NEW_WAY
- #ifdef FLOAT_NEW_WAY
- char buf[24];
- char *ptr = fmtFloat(value, buf + sizeof(buf), prec);
- // return fputs(ptr);
- // uint8_t len = buf + sizeof(buf) - ptr;
- return write(ptr, buf + sizeof(buf) - ptr);
- #else
- char* ptr;
- uint8_t rtn = 0;
- uint8_t sign = 0;
- if (value < 0) {
- value = -value;
- sign = '-';
- }
- // check for NaN INF OVF
- if (isnan(value)) {
- if (fputs_P(PSTR("nan")) < 0) return -1;
- rtn += 3;
- } else if (isinf(value)) {
- if (fputs_P(PSTR("inf")) < 0) return -1;
- rtn += 3;
- } else if (value > 4294967040.0) {
- if (fputs_P(PSTR("ovf")) < 0) return -1;;
- rtn += 3;
- } else {
- if (sign) {
- if (putc(sign) < 0) return -1;
- rtn++;
- }
- if (prec > 9) prec = 9;
-
- /*
- uint32_t s = 1;
- for (uint8_t i = 0; i < prec; i++) {
- // s *= 10;
- s = ((s << 2) + s) << 1;
- }
- // round value
- value += 0.5/s;
- */
- value += scale10(0.5, -prec);
- uint32_t whole = value;
- int np;
- if ((np = printDec(whole)) < 0) return -1;
- rtn += np;
- if (prec) {
- if (putc('.') < 0) return -1;
- char* str = fmtSpace(prec);
- if (!str) return -1;
- char* tmp = str - prec;
-
- // uint32_t fraction = s*(value - whole);
- uint32_t fraction = scale10(value - whole, prec);
- ptr = fmtDec(fraction, str);
- while (ptr > tmp) *--ptr = '0';
- rtn += prec + 1;
- }
- }
- return rtn;
- #endif
- }
- //------------------------------------------------------------------------------
- int StdioStream::printDec(signed char n) {
- uint8_t s = 0;
- if (n < 0) {
- if (fputc('-') < 0) return -1;
- n = -n;
- s = 1;
- }
- printDec((unsigned char)n);
- }
- //------------------------------------------------------------------------------
- int StdioStream::printDec(int16_t n) {
- int s;
- uint8_t rtn = 0;
- if (n < 0) {
- if (fputc('-') < 0) return -1;
- n = -n;
- rtn++;
- }
- if ((s = printDec((uint16_t)n)) < 0) return s;
- return rtn;
- }
- //------------------------------------------------------------------------------
- int StdioStream::printDec(uint16_t n) {
- #define NEW_WAY
- #ifdef NEW_WAY
- char buf[5];
- char *ptr = fmtDec(n, buf + sizeof(buf));
- uint8_t len = buf + sizeof(buf) - ptr;
- return write(ptr, len);
- #else
- uint8_t len;
- if (n < 100) {
- len = n < 10 ? 1 : 2;
- } else {
- len = n < 1000 ? 3 : n < 10000 ? 4 : 5;
- }
- char* str = fmtSpace(len);
- if (!str) return -1;
- fmtDec(n, str);
- return len;
- #endif
- }
- //------------------------------------------------------------------------------
- int StdioStream::printDec(int32_t n) {
- uint8_t s = 0;
- if (n < 0) {
- if (fputc('-') < 0) return -1;
- n = -n;
- s = 1;
- }
- int rtn = printDec((uint32_t)n);
- return rtn > 0 ? rtn + s : -1;
- }
- //------------------------------------------------------------------------------
- int StdioStream::printDec(uint32_t n) {
- #ifdef NEW_WAY
- char buf[10];
- char *ptr = fmtDec(n, buf + sizeof(buf));
- uint8_t len = buf + sizeof(buf) - ptr;
- return write(ptr, len);
- #else
- uint8_t len;
- if (n < 0X10000) {
- return printDec((uint16_t)n);
- }
- if (n < 10000000) {
- len = n < 100000 ? 5 : n < 1000000 ? 6 : 7;
- } else {
- len = n < 100000000 ? 8 : n < 1000000000 ? 9 : 10;
- }
-
- char* str = fmtSpace(len);
- if (!str) return -1;
- fmtDec(n, str);
- return len;
- #endif
- }
- //------------------------------------------------------------------------------
- int StdioStream::printHex(uint32_t n) {
- #ifdef NEW_WAY
- char buf[8];
- char *ptr = fmtHex(n, buf + sizeof(buf));
- uint8_t len = buf + sizeof(buf) - ptr;
- return write(ptr, len);
- #else
- size_t len;
- if (n < 0X10000) {
- len = n < 0X10 ? 1 : n < 0X100 ? 2 : n < 0X1000 ? 3 : 4;
- } else {
- len = n < 0X100000 ? 5 : n < 0X1000000 ? 6 : n < 0X10000000 ? 7 : 8;
- }
- char* str = fmtSpace(len);
- if (!str) return -1;
-
- do {
- uint8_t h = n & 0XF;
- *str-- = h + (h < 10 ? '0' : 'A' - 10);
- n >>= 4;
- } while (n);
- return len;
- #endif
- }
- //------------------------------------------------------------------------------
- bool StdioStream::rewind() {
- if (m_flags & F_SWR) {
- if (!flushBuf()) return false;
- }
- SdBaseFile::seekSet(0);
- m_r = 0;
- return true;
- }
- //------------------------------------------------------------------------------
- int StdioStream::ungetc(int c) {
- // error if EOF.
- if (c == EOF) return EOF;
- // error if not reading.
- if ((m_flags & F_SRD) == 0) return EOF;
- // error if no space.
- if (m_p == m_buf) return EOF;
- m_r++;
- m_flags &= ~F_EOF;
- return *--m_p = (uint8_t)c;
- }
- //==============================================================================
- // private
- //------------------------------------------------------------------------------
- int StdioStream::fillGet() {
- if (!fillBuf()) {
- return EOF;
- }
- m_r--;
- return *m_p++;
- }
- //------------------------------------------------------------------------------
- // private
- bool StdioStream::fillBuf() {
- if (!(m_flags & F_SRD)) { /////////////check for F_ERR and F_EOF ??/////////////////
- if (!(m_flags & F_SRW)) {
- m_flags |= F_ERR;
- return false;
- }
- if (m_flags & F_SWR) {
- if (!flushBuf()) {
- return false;
- }
- m_flags &= ~F_SWR;
- m_flags |= F_SRD;
- m_w = 0;
- }
- }
- m_p = m_buf + UNGETC_BUF_SIZE;
- int nr = SdBaseFile::read(m_p, sizeof(m_buf) - UNGETC_BUF_SIZE);
- if (nr <= 0) {
- m_flags |= nr < 0 ? F_ERR : F_EOF;
- m_r = 0;
- return false;
- }
- m_r = nr;
- return true;
- }
- //------------------------------------------------------------------------------
- // private
- bool StdioStream::flushBuf() {
- if (!(m_flags & F_SWR)) { /////////////////check for F_ERR ??////////////////////////
- if (!(m_flags & F_SRW)) {
- m_flags |= F_ERR;
- return false;
- }
- m_flags &= ~F_SRD;
- m_flags |= F_SWR;
- m_r = 0;
- m_w = sizeof(m_buf);
- m_p = m_buf;
- return true;
- }
- uint8_t n = m_p - m_buf;
- m_p = m_buf;
- m_w = sizeof(m_buf);
- if (SdBaseFile::write(m_buf, n) == n) return true;
- m_flags |= F_ERR;
- return false;
- }
- //------------------------------------------------------------------------------
- int StdioStream::flushPut(uint8_t c) {
- if (!flushBuf()) return EOF;
- m_w--;
- return *m_p++ = c;
- }
- //------------------------------------------------------------------------------
- char* StdioStream::fmtSpace(uint8_t len) {
- if (m_w < len) {
- if (!flushBuf() || m_w < len) {
- return 0;
- }
- }
- if (len > m_w) return 0;
- m_p += len;
- m_w -= len;
- return reinterpret_cast<char*>(m_p);
- }
-
|