Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

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