您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

607 行
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. if (n < 0) {
  365. if (fputc('-') < 0) {
  366. return -1;
  367. }
  368. n = -n;
  369. }
  370. return printDec((unsigned char)n);
  371. }
  372. //------------------------------------------------------------------------------
  373. int StdioStream::printDec(int16_t n) {
  374. int s;
  375. uint8_t rtn = 0;
  376. if (n < 0) {
  377. if (fputc('-') < 0) {
  378. return -1;
  379. }
  380. n = -n;
  381. rtn++;
  382. }
  383. if ((s = printDec((uint16_t)n)) < 0) {
  384. return s;
  385. }
  386. return rtn;
  387. }
  388. //------------------------------------------------------------------------------
  389. int StdioStream::printDec(uint16_t n) {
  390. #define NEW_WAY
  391. #ifdef NEW_WAY
  392. char buf[5];
  393. char *ptr = fmtDec(n, buf + sizeof(buf));
  394. uint8_t len = buf + sizeof(buf) - ptr;
  395. return write(ptr, len);
  396. #else
  397. uint8_t len;
  398. if (n < 100) {
  399. len = n < 10 ? 1 : 2;
  400. } else {
  401. len = n < 1000 ? 3 : n < 10000 ? 4 : 5;
  402. }
  403. char* str = fmtSpace(len);
  404. if (!str) {
  405. return -1;
  406. }
  407. fmtDec(n, str);
  408. return len;
  409. #endif
  410. }
  411. //------------------------------------------------------------------------------
  412. int StdioStream::printDec(int32_t n) {
  413. uint8_t s = 0;
  414. if (n < 0) {
  415. if (fputc('-') < 0) {
  416. return -1;
  417. }
  418. n = -n;
  419. s = 1;
  420. }
  421. int rtn = printDec((uint32_t)n);
  422. return rtn > 0 ? rtn + s : -1;
  423. }
  424. //------------------------------------------------------------------------------
  425. int StdioStream::printDec(uint32_t n) {
  426. #ifdef NEW_WAY
  427. char buf[10];
  428. char *ptr = fmtDec(n, buf + sizeof(buf));
  429. uint8_t len = buf + sizeof(buf) - ptr;
  430. return write(ptr, len);
  431. #else
  432. uint8_t len;
  433. if (n < 0X10000) {
  434. return printDec((uint16_t)n);
  435. }
  436. if (n < 10000000) {
  437. len = n < 100000 ? 5 : n < 1000000 ? 6 : 7;
  438. } else {
  439. len = n < 100000000 ? 8 : n < 1000000000 ? 9 : 10;
  440. }
  441. char* str = fmtSpace(len);
  442. if (!str) {
  443. return -1;
  444. }
  445. fmtDec(n, str);
  446. return len;
  447. #endif
  448. }
  449. //------------------------------------------------------------------------------
  450. int StdioStream::printHex(uint32_t n) {
  451. #ifdef NEW_WAY
  452. char buf[8];
  453. char *ptr = fmtHex(n, buf + sizeof(buf));
  454. uint8_t len = buf + sizeof(buf) - ptr;
  455. return write(ptr, len);
  456. #else
  457. size_t len;
  458. if (n < 0X10000) {
  459. len = n < 0X10 ? 1 : n < 0X100 ? 2 : n < 0X1000 ? 3 : 4;
  460. } else {
  461. len = n < 0X100000 ? 5 : n < 0X1000000 ? 6 : n < 0X10000000 ? 7 : 8;
  462. }
  463. char* str = fmtSpace(len);
  464. if (!str) {
  465. return -1;
  466. }
  467. do {
  468. uint8_t h = n & 0XF;
  469. *str-- = h + (h < 10 ? '0' : 'A' - 10);
  470. n >>= 4;
  471. } while (n);
  472. return len;
  473. #endif
  474. }
  475. //------------------------------------------------------------------------------
  476. bool StdioStream::rewind() {
  477. if (m_flags & F_SWR) {
  478. if (!flushBuf()) {
  479. return false;
  480. }
  481. }
  482. FatFile::seekSet(0);
  483. m_r = 0;
  484. return true;
  485. }
  486. //------------------------------------------------------------------------------
  487. int StdioStream::ungetc(int c) {
  488. // error if EOF.
  489. if (c == EOF) {
  490. return EOF;
  491. }
  492. // error if not reading.
  493. if ((m_flags & F_SRD) == 0) {
  494. return EOF;
  495. }
  496. // error if no space.
  497. if (m_p == m_buf) {
  498. return EOF;
  499. }
  500. m_r++;
  501. m_flags &= ~F_EOF;
  502. return *--m_p = (uint8_t)c;
  503. }
  504. //==============================================================================
  505. // private
  506. //------------------------------------------------------------------------------
  507. int StdioStream::fillGet() {
  508. if (!fillBuf()) {
  509. return EOF;
  510. }
  511. m_r--;
  512. return *m_p++;
  513. }
  514. //------------------------------------------------------------------------------
  515. // private
  516. bool StdioStream::fillBuf() {
  517. if (!(m_flags &
  518. F_SRD)) { /////////////check for F_ERR and F_EOF ??/////////////////
  519. if (!(m_flags & F_SRW)) {
  520. m_flags |= F_ERR;
  521. return false;
  522. }
  523. if (m_flags & F_SWR) {
  524. if (!flushBuf()) {
  525. return false;
  526. }
  527. m_flags &= ~F_SWR;
  528. m_flags |= F_SRD;
  529. m_w = 0;
  530. }
  531. }
  532. m_p = m_buf + UNGETC_BUF_SIZE;
  533. int nr = FatFile::read(m_p, sizeof(m_buf) - UNGETC_BUF_SIZE);
  534. if (nr <= 0) {
  535. m_flags |= nr < 0 ? F_ERR : F_EOF;
  536. m_r = 0;
  537. return false;
  538. }
  539. m_r = nr;
  540. return true;
  541. }
  542. //------------------------------------------------------------------------------
  543. // private
  544. bool StdioStream::flushBuf() {
  545. if (!(m_flags &
  546. F_SWR)) { /////////////////check for F_ERR ??////////////////////////
  547. if (!(m_flags & F_SRW)) {
  548. m_flags |= F_ERR;
  549. return false;
  550. }
  551. m_flags &= ~F_SRD;
  552. m_flags |= F_SWR;
  553. m_r = 0;
  554. m_w = sizeof(m_buf);
  555. m_p = m_buf;
  556. return true;
  557. }
  558. uint8_t n = m_p - m_buf;
  559. m_p = m_buf;
  560. m_w = sizeof(m_buf);
  561. if (FatFile::write(m_buf, n) == n) {
  562. return true;
  563. }
  564. m_flags |= F_ERR;
  565. return false;
  566. }
  567. //------------------------------------------------------------------------------
  568. int StdioStream::flushPut(uint8_t c) {
  569. if (!flushBuf()) {
  570. return EOF;
  571. }
  572. m_w--;
  573. return *m_p++ = c;
  574. }
  575. //------------------------------------------------------------------------------
  576. char* StdioStream::fmtSpace(uint8_t len) {
  577. if (m_w < len) {
  578. if (!flushBuf() || m_w < len) {
  579. return 0;
  580. }
  581. }
  582. if (len > m_w) {
  583. return 0;
  584. }
  585. m_p += len;
  586. m_w -= len;
  587. return reinterpret_cast<char*>(m_p);
  588. }