Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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