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.

преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  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. }