You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

536 line
13KB

  1. /* Arduino RamDisk Library
  2. * Copyright (C) 2014 by William Greiman
  3. *
  4. * This file is part of the Arduino RamDisk Library
  5. *
  6. * This Library is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This Library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Arduino RamDisk Library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. /**
  21. * \file
  22. * StdioStream implementation
  23. */
  24. #include <Arduino.h>
  25. #include <StdioStream.h>
  26. #include <utility/FmtNumber.h>
  27. //------------------------------------------------------------------------------
  28. int StdioStream::fclose() {
  29. int rtn = 0;
  30. if (!m_flags) {
  31. return EOF;
  32. }
  33. if (m_flags & F_SWR) {
  34. if (!flushBuf()) rtn = EOF;
  35. }
  36. if (!SdBaseFile::close()) rtn = EOF;
  37. m_r = 0;
  38. m_w = 0;
  39. m_flags = 0;
  40. return rtn;
  41. }
  42. //------------------------------------------------------------------------------
  43. int StdioStream::fflush() {
  44. if ((m_flags & (F_SWR | F_SRW)) && !(m_flags & F_SRD)) {
  45. if (flushBuf() && SdBaseFile::sync()) return 0;
  46. }
  47. return EOF;
  48. }
  49. //------------------------------------------------------------------------------
  50. char* StdioStream::fgets(char* str, int num, size_t* len) {
  51. char* s = str;
  52. size_t n;
  53. if (num-- <= 0) return 0;
  54. while (num) {
  55. if ((n = m_r) == 0) {
  56. if (!fillBuf()) {
  57. if (s == str) return 0;
  58. break;
  59. }
  60. n = m_r;
  61. }
  62. if (n > num) n = num;
  63. uint8_t* end = reinterpret_cast<uint8_t*>(memchr(m_p, '\n', n));
  64. if (end != 0) {
  65. n = ++end - m_p;
  66. memcpy(s, m_p, n);
  67. m_r -= n;
  68. m_p = end;
  69. s += n;
  70. break;
  71. }
  72. memcpy(s, m_p, n);
  73. m_r -= n;
  74. m_p += n;
  75. s += n;
  76. num -= n;
  77. }
  78. *s = 0;
  79. if (len) *len = s - str;
  80. return str;
  81. }
  82. //------------------------------------------------------------------------------
  83. bool StdioStream::fopen(const char* filename, const char* mode) {
  84. uint8_t oflags;
  85. switch (*mode++) {
  86. case 'a':
  87. m_flags = F_SWR;
  88. oflags = O_WRITE | O_CREAT | O_APPEND | O_AT_END;
  89. break;
  90. case 'r':
  91. m_flags = F_SRD;
  92. oflags = O_READ;
  93. break;
  94. case 'w':
  95. m_flags = F_SWR;
  96. oflags = O_WRITE | O_CREAT | O_TRUNC;
  97. break;
  98. default:
  99. goto fail;
  100. }
  101. while (*mode) {
  102. switch (*mode++) {
  103. case '+':
  104. m_flags |= F_SRW;
  105. oflags |= O_RDWR;
  106. break;
  107. case 'b':
  108. break;
  109. case 'x':
  110. oflags |= O_EXCL;
  111. break;
  112. default:
  113. goto fail;
  114. }
  115. }
  116. if ((oflags & O_EXCL) && !(oflags & O_WRITE)) goto fail;
  117. if (!SdBaseFile::open(filename, oflags)) goto fail;
  118. m_r = 0;
  119. m_w = 0;
  120. m_p = m_buf;
  121. return true;
  122. fail:
  123. m_flags = 0;
  124. return false;
  125. }
  126. //------------------------------------------------------------------------------
  127. int StdioStream::fputs(const char* str) {
  128. size_t len = strlen(str);
  129. return fwrite(str, 1, len) == len ? len : EOF;
  130. }
  131. //------------------------------------------------------------------------------
  132. int StdioStream::fputs_P(PGM_P str) {
  133. PGM_P bgn = str;
  134. for (char c; (c = pgm_read_byte(str)); str++) {
  135. if (putc(c) < 0) return EOF;
  136. }
  137. return str - bgn;
  138. }
  139. //------------------------------------------------------------------------------
  140. size_t StdioStream::fread(void* ptr, size_t size, size_t count) {
  141. uint8_t* dst = reinterpret_cast<uint8_t*>(ptr);
  142. size_t total = size*count;
  143. if (total == 0) return 0;
  144. size_t need = total;
  145. while (need > m_r) {
  146. memcpy(dst, m_p, m_r);
  147. dst += m_r;
  148. m_p += m_r;
  149. need -= m_r;
  150. if (!fillBuf()) {
  151. return (total - need)/size;
  152. }
  153. }
  154. memcpy(dst, m_p, need);
  155. m_r -= need;
  156. m_p += need;
  157. return count;
  158. }
  159. //------------------------------------------------------------------------------
  160. int StdioStream::fseek(int32_t offset, int origin) {
  161. int32_t pos;
  162. if (m_flags & F_SWR) {
  163. if (!flushBuf()) {
  164. goto fail;
  165. }
  166. }
  167. switch (origin) {
  168. case SEEK_CUR:
  169. pos = ftell();
  170. if (pos < 0) {
  171. goto fail;
  172. }
  173. pos += offset;
  174. if (!SdBaseFile::seekCur(pos)) {
  175. goto fail;
  176. }
  177. break;
  178. case SEEK_SET:
  179. if (!SdBaseFile::seekSet(offset)) {
  180. goto fail;
  181. }
  182. break;
  183. case SEEK_END:
  184. if (!SdBaseFile::seekEnd(offset)) {
  185. goto fail;
  186. }
  187. break;
  188. default:
  189. goto fail;
  190. }
  191. m_r = 0;
  192. m_p = m_buf;
  193. return 0;
  194. fail:
  195. return EOF;
  196. }
  197. //------------------------------------------------------------------------------
  198. int32_t StdioStream::ftell() {
  199. uint32_t pos = SdBaseFile::curPosition();
  200. if (m_flags & F_SRD) {
  201. if (m_r > pos) return -1L;
  202. pos -= m_r;
  203. } else if (m_flags & F_SWR) {
  204. pos += m_p - m_buf;
  205. }
  206. return pos;
  207. }
  208. //------------------------------------------------------------------------------
  209. size_t StdioStream::fwrite(const void* ptr, size_t size, size_t count) {
  210. return write(ptr, count*size) < 0 ? EOF : count;
  211. #if 0 ////////////////////////////////////////////////////////////////////////////////////
  212. const uint8_t* src = static_cast<const uint8_t*>(ptr);
  213. size_t total = count*size;
  214. if (total == 0) return 0;
  215. size_t todo = total;
  216. while (todo > m_w) {
  217. memcpy(m_p, src, m_w);
  218. m_p += m_w;
  219. src += m_w;
  220. todo -= m_w;
  221. if (!flushBuf()) {
  222. return (total - todo)/size;
  223. }
  224. }
  225. memcpy(m_p, src, todo);
  226. m_p += todo;
  227. m_w -= todo;
  228. return count;
  229. #endif //////////////////////////////////////////////////////////////////////////////////
  230. }
  231. //------------------------------------------------------------------------------
  232. int StdioStream::write(const void* buf, size_t count) {
  233. const uint8_t* src = static_cast<const uint8_t*>(buf);
  234. size_t todo = count;
  235. while (todo > m_w) {
  236. memcpy(m_p, src, m_w);
  237. m_p += m_w;
  238. src += m_w;
  239. todo -= m_w;
  240. if (!flushBuf()) return EOF;
  241. }
  242. memcpy(m_p, src, todo);
  243. m_p += todo;
  244. m_w -= todo;
  245. return count;
  246. }
  247. //------------------------------------------------------------------------------
  248. size_t StdioStream::print(const __FlashStringHelper *str) {
  249. const char PROGMEM *p = (const char PROGMEM *)str;
  250. uint8_t c;
  251. while (c = pgm_read_byte(p)) {
  252. if (putc(c) < 0) return 0;
  253. p++;
  254. }
  255. return p - (const char PROGMEM *)str;
  256. }
  257. //------------------------------------------------------------------------------
  258. int StdioStream::printDec(float value, uint8_t prec) {
  259. #define FLOAT_NEW_WAY
  260. #ifdef FLOAT_NEW_WAY
  261. char buf[24];
  262. char *ptr = fmtFloat(value, buf + sizeof(buf), prec);
  263. // return fputs(ptr);
  264. // uint8_t len = buf + sizeof(buf) - ptr;
  265. return write(ptr, buf + sizeof(buf) - ptr);
  266. #else
  267. char* ptr;
  268. uint8_t rtn = 0;
  269. uint8_t sign = 0;
  270. if (value < 0) {
  271. value = -value;
  272. sign = '-';
  273. }
  274. // check for NaN INF OVF
  275. if (isnan(value)) {
  276. if (fputs_P(PSTR("nan")) < 0) return -1;
  277. rtn += 3;
  278. } else if (isinf(value)) {
  279. if (fputs_P(PSTR("inf")) < 0) return -1;
  280. rtn += 3;
  281. } else if (value > 4294967040.0) {
  282. if (fputs_P(PSTR("ovf")) < 0) return -1;;
  283. rtn += 3;
  284. } else {
  285. if (sign) {
  286. if (putc(sign) < 0) return -1;
  287. rtn++;
  288. }
  289. if (prec > 9) prec = 9;
  290. /*
  291. uint32_t s = 1;
  292. for (uint8_t i = 0; i < prec; i++) {
  293. // s *= 10;
  294. s = ((s << 2) + s) << 1;
  295. }
  296. // round value
  297. value += 0.5/s;
  298. */
  299. value += scale10(0.5, -prec);
  300. uint32_t whole = value;
  301. int np;
  302. if ((np = printDec(whole)) < 0) return -1;
  303. rtn += np;
  304. if (prec) {
  305. if (putc('.') < 0) return -1;
  306. char* str = fmtSpace(prec);
  307. if (!str) return -1;
  308. char* tmp = str - prec;
  309. // uint32_t fraction = s*(value - whole);
  310. uint32_t fraction = scale10(value - whole, prec);
  311. ptr = fmtDec(fraction, str);
  312. while (ptr > tmp) *--ptr = '0';
  313. rtn += prec + 1;
  314. }
  315. }
  316. return rtn;
  317. #endif
  318. }
  319. //------------------------------------------------------------------------------
  320. int StdioStream::printDec(signed char n) {
  321. uint8_t s = 0;
  322. if (n < 0) {
  323. if (fputc('-') < 0) return -1;
  324. n = -n;
  325. s = 1;
  326. }
  327. printDec((unsigned char)n);
  328. }
  329. //------------------------------------------------------------------------------
  330. int StdioStream::printDec(int16_t n) {
  331. int s;
  332. uint8_t rtn = 0;
  333. if (n < 0) {
  334. if (fputc('-') < 0) return -1;
  335. n = -n;
  336. rtn++;
  337. }
  338. if ((s = printDec((uint16_t)n)) < 0) return s;
  339. return rtn;
  340. }
  341. //------------------------------------------------------------------------------
  342. int StdioStream::printDec(uint16_t n) {
  343. #define NEW_WAY
  344. #ifdef NEW_WAY
  345. char buf[5];
  346. char *ptr = fmtDec(n, buf + sizeof(buf));
  347. uint8_t len = buf + sizeof(buf) - ptr;
  348. return write(ptr, len);
  349. #else
  350. uint8_t len;
  351. if (n < 100) {
  352. len = n < 10 ? 1 : 2;
  353. } else {
  354. len = n < 1000 ? 3 : n < 10000 ? 4 : 5;
  355. }
  356. char* str = fmtSpace(len);
  357. if (!str) return -1;
  358. fmtDec(n, str);
  359. return len;
  360. #endif
  361. }
  362. //------------------------------------------------------------------------------
  363. int StdioStream::printDec(int32_t n) {
  364. uint8_t s = 0;
  365. if (n < 0) {
  366. if (fputc('-') < 0) return -1;
  367. n = -n;
  368. s = 1;
  369. }
  370. int rtn = printDec((uint32_t)n);
  371. return rtn > 0 ? rtn + s : -1;
  372. }
  373. //------------------------------------------------------------------------------
  374. int StdioStream::printDec(uint32_t n) {
  375. #ifdef NEW_WAY
  376. char buf[10];
  377. char *ptr = fmtDec(n, buf + sizeof(buf));
  378. uint8_t len = buf + sizeof(buf) - ptr;
  379. return write(ptr, len);
  380. #else
  381. uint8_t len;
  382. if (n < 0X10000) {
  383. return printDec((uint16_t)n);
  384. }
  385. if (n < 10000000) {
  386. len = n < 100000 ? 5 : n < 1000000 ? 6 : 7;
  387. } else {
  388. len = n < 100000000 ? 8 : n < 1000000000 ? 9 : 10;
  389. }
  390. char* str = fmtSpace(len);
  391. if (!str) return -1;
  392. fmtDec(n, str);
  393. return len;
  394. #endif
  395. }
  396. //------------------------------------------------------------------------------
  397. int StdioStream::printHex(uint32_t n) {
  398. #ifdef NEW_WAY
  399. char buf[8];
  400. char *ptr = fmtHex(n, buf + sizeof(buf));
  401. uint8_t len = buf + sizeof(buf) - ptr;
  402. return write(ptr, len);
  403. #else
  404. size_t len;
  405. if (n < 0X10000) {
  406. len = n < 0X10 ? 1 : n < 0X100 ? 2 : n < 0X1000 ? 3 : 4;
  407. } else {
  408. len = n < 0X100000 ? 5 : n < 0X1000000 ? 6 : n < 0X10000000 ? 7 : 8;
  409. }
  410. char* str = fmtSpace(len);
  411. if (!str) return -1;
  412. do {
  413. uint8_t h = n & 0XF;
  414. *str-- = h + (h < 10 ? '0' : 'A' - 10);
  415. n >>= 4;
  416. } while (n);
  417. return len;
  418. #endif
  419. }
  420. //------------------------------------------------------------------------------
  421. bool StdioStream::rewind() {
  422. if (m_flags & F_SWR) {
  423. if (!flushBuf()) return false;
  424. }
  425. SdBaseFile::seekSet(0);
  426. m_r = 0;
  427. return true;
  428. }
  429. //------------------------------------------------------------------------------
  430. int StdioStream::ungetc(int c) {
  431. // error if EOF.
  432. if (c == EOF) return EOF;
  433. // error if not reading.
  434. if ((m_flags & F_SRD) == 0) return EOF;
  435. // error if no space.
  436. if (m_p == m_buf) return EOF;
  437. m_r++;
  438. m_flags &= ~F_EOF;
  439. return *--m_p = (uint8_t)c;
  440. }
  441. //==============================================================================
  442. // private
  443. //------------------------------------------------------------------------------
  444. int StdioStream::fillGet() {
  445. if (!fillBuf()) {
  446. return EOF;
  447. }
  448. m_r--;
  449. return *m_p++;
  450. }
  451. //------------------------------------------------------------------------------
  452. // private
  453. bool StdioStream::fillBuf() {
  454. if (!(m_flags & F_SRD)) { /////////////check for F_ERR and F_EOF ??/////////////////
  455. if (!(m_flags & F_SRW)) {
  456. m_flags |= F_ERR;
  457. return false;
  458. }
  459. if (m_flags & F_SWR) {
  460. if (!flushBuf()) {
  461. return false;
  462. }
  463. m_flags &= ~F_SWR;
  464. m_flags |= F_SRD;
  465. m_w = 0;
  466. }
  467. }
  468. m_p = m_buf + UNGETC_BUF_SIZE;
  469. int nr = SdBaseFile::read(m_p, sizeof(m_buf) - UNGETC_BUF_SIZE);
  470. if (nr <= 0) {
  471. m_flags |= nr < 0 ? F_ERR : F_EOF;
  472. m_r = 0;
  473. return false;
  474. }
  475. m_r = nr;
  476. return true;
  477. }
  478. //------------------------------------------------------------------------------
  479. // private
  480. bool StdioStream::flushBuf() {
  481. if (!(m_flags & F_SWR)) { /////////////////check for F_ERR ??////////////////////////
  482. if (!(m_flags & F_SRW)) {
  483. m_flags |= F_ERR;
  484. return false;
  485. }
  486. m_flags &= ~F_SRD;
  487. m_flags |= F_SWR;
  488. m_r = 0;
  489. m_w = sizeof(m_buf);
  490. m_p = m_buf;
  491. return true;
  492. }
  493. uint8_t n = m_p - m_buf;
  494. m_p = m_buf;
  495. m_w = sizeof(m_buf);
  496. if (SdBaseFile::write(m_buf, n) == n) return true;
  497. m_flags |= F_ERR;
  498. return false;
  499. }
  500. //------------------------------------------------------------------------------
  501. int StdioStream::flushPut(uint8_t c) {
  502. if (!flushBuf()) return EOF;
  503. m_w--;
  504. return *m_p++ = c;
  505. }
  506. //------------------------------------------------------------------------------
  507. char* StdioStream::fmtSpace(uint8_t len) {
  508. if (m_w < len) {
  509. if (!flushBuf() || m_w < len) {
  510. return 0;
  511. }
  512. }
  513. if (len > m_w) return 0;
  514. m_p += len;
  515. m_w -= len;
  516. return reinterpret_cast<char*>(m_p);
  517. }