Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  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* filename, 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(filename, 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. }