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

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