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

657 lines
23KB

  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. #ifndef StdioStream_h
  21. #define StdioStream_h
  22. /**
  23. * \file
  24. * StdioStream class
  25. */
  26. #include <limits.h>
  27. #include <Arduino.h>
  28. #include <SdFat.h>
  29. #include <SdBaseFile.h>
  30. //------------------------------------------------------------------------------
  31. /** Total size of stream buffer. The entire buffer is used for output.
  32. * During input UNGETC_BUF_SIZE of this space is reserved for ungetc.
  33. */
  34. const uint8_t STREAM_BUF_SIZE = 64;
  35. /** Amount of buffer allocated for ungetc during input. */
  36. const uint8_t UNGETC_BUF_SIZE = 2;
  37. //------------------------------------------------------------------------------
  38. // Get rid of any macros defined in <stdio.h>.
  39. #include <stdio.h>
  40. #undef clearerr
  41. #undef fclose
  42. #undef feof
  43. #undef ferror
  44. #undef fflush
  45. #undef fgetc
  46. #undef fgetpos
  47. #undef fgets
  48. #undef fopen
  49. #undef fprintf
  50. #undef fputc
  51. #undef fputs
  52. #undef fread
  53. #undef freopen
  54. #undef fscanf
  55. #undef fseek
  56. #undef fsetpos
  57. #undef ftell
  58. #undef fwrite
  59. #undef getc
  60. #undef getchar
  61. #undef gets
  62. #undef perror
  63. #undef printf
  64. #undef putc
  65. #undef putchar
  66. #undef puts
  67. #undef remove
  68. #undef rename
  69. #undef rewind
  70. #undef scanf
  71. #undef setbuf
  72. #undef setvbuf
  73. #undef sprintf // NOLINT
  74. #undef sscanf
  75. #undef tmpfile
  76. #undef tmpnam
  77. #undef ungetc
  78. #undef vfprintf
  79. #undef vprintf
  80. #undef vsprintf
  81. // make sure needed macros are defined
  82. #ifndef EOF
  83. /** End-of-file return value. */
  84. #define EOF (-1)
  85. #endif // EOF
  86. #ifndef NULL
  87. /** Null pointer */
  88. #define NULL 0
  89. #endif // NULL
  90. #ifndef SEEK_CUR
  91. /** Seek relative to current position. */
  92. #define SEEK_CUR 1
  93. #endif // SEEK_CUR
  94. #ifndef SEEK_END
  95. /** Seek relative to end-of-file. */
  96. #define SEEK_END 2
  97. #endif // SEEK_END
  98. #ifndef SEEK_SET
  99. /** Seek relative to start-of-file. */
  100. #define SEEK_SET 0
  101. #endif // SEEK_SET
  102. //------------------------------------------------------------------------------
  103. /** \class StdioStream
  104. * \brief StdioStream implements a minimal stdio stream.
  105. *
  106. * StdioStream does not support subdirectories or long file names.
  107. */
  108. class StdioStream : private SdBaseFile {
  109. public:
  110. /** Constructor
  111. *
  112. */
  113. StdioStream() {
  114. m_w = m_r = 0;
  115. m_p = m_buf;
  116. m_flags = 0;
  117. }
  118. //----------------------------------------------------------------------------
  119. /** Clear the stream's end-of-file and error indicators. */
  120. void clearerr() {m_flags &= ~(F_ERR | F_EOF);}
  121. //----------------------------------------------------------------------------
  122. /** Close a stream.
  123. *
  124. * A successful call to the fclose function causes the stream to be
  125. * flushed and the associated file to be closed. Any unwritten buffered
  126. * data is written to the file; any unread buffered data is discarded.
  127. * Whether or not the call succeeds, the stream is disassociated from
  128. * the file.
  129. *
  130. * \return zero if the stream was successfully closed, or EOF if any any
  131. * errors are detected.
  132. */
  133. int fclose();
  134. //----------------------------------------------------------------------------
  135. /** Test the stream's end-of-file indicator.
  136. * \return non-zero if and only if the end-of-file indicator is set.
  137. */
  138. int feof() {return (m_flags & F_EOF) != 0;}
  139. //----------------------------------------------------------------------------
  140. /** Test the stream's error indicator.
  141. * \return return non-zero if and only if the error indicator is set.
  142. */
  143. int ferror() {return (m_flags & F_ERR) != 0;}
  144. //----------------------------------------------------------------------------
  145. /** Flush the stream.
  146. *
  147. * If stream is an output stream or an update stream in which the most
  148. * recent operation was not input, any unwritten data is written to the
  149. * file; otherwise the call is an error since any buffered input data
  150. * would be lost.
  151. *
  152. * \return sets the error indicator for the stream and returns EOF if an
  153. * error occurs, otherwise it returns zero.
  154. */
  155. int fflush();
  156. //----------------------------------------------------------------------------
  157. /** Get a byte from the stream.
  158. *
  159. * \return If the end-of-file indicator for the stream is set, or if the
  160. * stream is at end-of-file, the end-of-file indicator for the stream is
  161. * set and the fgetc function returns EOF. Otherwise, the fgetc function
  162. * returns the next character from the input stream.
  163. */
  164. int fgetc() {return m_r-- == 0 ? fillGet() : *m_p++;}
  165. //----------------------------------------------------------------------------
  166. /** Get a string from a stream.
  167. *
  168. * The fgets function reads at most one less than the number of
  169. * characters specified by num from the stream into the array pointed
  170. * to by str. No additional characters are read after a new-line
  171. * character (which is retained) or after end-of-file. A null character
  172. * is written immediately after the last character read into the array.
  173. *
  174. * \param[out] str Pointer to an array of where the string is copied.
  175. *
  176. * \param[in] num Maximum number of characters including the null
  177. * character.
  178. *
  179. * \param[out] len If len is not null and fgets is successful, the
  180. * length of the string is returned.
  181. *
  182. * \return str if successful. If end-of-file is encountered and no
  183. * characters have been read into the array, the contents of the array
  184. * remain unchanged and a null pointer is returned. If a read error
  185. * occurs during the operation, the array contents are indeterminate
  186. * and a null pointer is returned.
  187. */
  188. char* fgets(char* str, int num, size_t* len = 0);
  189. //----------------------------------------------------------------------------
  190. /** Open a stream.
  191. *
  192. * Open a file and associates the stream with it.
  193. *
  194. * \param[in] filename name of the file to be opened.
  195. *
  196. * \param[in] mode a string that indicates the open mode.
  197. *
  198. * <table>
  199. * <tr>
  200. * <td>"r" or "rb"</td>
  201. * <td>Open a file for reading. The file must exist.</td>
  202. * </tr>
  203. * <tr>
  204. * <td>"w" or "wb"</td>
  205. * <td>Truncate an existing to zero length or create an empty file
  206. * for writing.</td>
  207. * </tr>
  208. * <tr>
  209. * <td>"wx" or "wbx"</td>
  210. * <td>Create a file for writing. Fails if the file already exists.</td>
  211. * </tr>
  212. * <tr>
  213. * <td>"a" or "ab"</td>
  214. * <td>Append; open or create file for writing at end-of-file.</td>
  215. * </tr>
  216. * <tr>
  217. * <td>"r+" or "rb+" or "r+b"</td>
  218. * <td>Open a file for update (reading and writing).</td>
  219. * </tr>
  220. * <tr>
  221. * <td>"w+" or "w+b" or "wb+"</td>
  222. * <td>Truncate an existing to zero length or create a file for update.</td>
  223. * </tr>
  224. * <tr>
  225. * <td>"w+x" or "w+bx" or "wb+x"</td>
  226. * <td>Create a file for update. Fails if the file already exists.</td>
  227. * </tr>
  228. * <tr>
  229. * <td>"a+" or "a+b" or "ab+"</td>
  230. * <td>Append; open or create a file for update, writing at end-of-file.</td>
  231. * </tr>
  232. * </table>
  233. * The character 'b' shall have no effect, but is allowed for ISO C
  234. * standard conformance.
  235. *
  236. * Opening a file with append mode causes all subsequent writes to the
  237. * file to be forced to the then current end-of-file, regardless of
  238. * intervening calls to the fseek function.
  239. *
  240. * When a file is opened with update mode, both input and output may be
  241. * performed on the associated stream. However, output shall not be
  242. * directly followed by input without an intervening call to the fflush
  243. * function or to a file positioning function (fseek, or rewind), and
  244. * input shall not be directly followed by output without an intervening
  245. * call to a file positioning function, unless the input operation
  246. * encounters endof-file.
  247. *
  248. * \return true for success or false for failure.
  249. */
  250. bool fopen(const char* filename, const char * mode);
  251. //----------------------------------------------------------------------------
  252. /** Write a byte to a stream.
  253. *
  254. * \param[in] c the byte to be written (converted to an unsigned char).
  255. *
  256. * \return Upon successful completion, fputc() returns the value it
  257. * has written. Otherwise, it returns EOF and sets the error indicator for
  258. * the stream.
  259. */
  260. int fputc(int c) {return m_w-- == 0 ? flushPut(c) : *m_p++ = c;}
  261. //----------------------------------------------------------------------------
  262. /** Write a string to a stream.
  263. *
  264. * \param[in] str a pointer to the string to be written.
  265. *
  266. * \return for success, fputs() returns a non-negative
  267. * number. Otherwise, it returns EOF and sets the error indicator for
  268. * the stream.
  269. */
  270. int fputs(const char* str);
  271. //----------------------------------------------------------------------------
  272. /** Write a string stored in flash.
  273. *
  274. * \param[in] str string to be written.
  275. *
  276. * \return for success, fputs() returns a non-negative
  277. * number. Otherwise, it returns EOF and sets the error indicator for
  278. * the stream.
  279. */
  280. int fputs_P(PGM_P str);
  281. //----------------------------------------------------------------------------
  282. /** Binary input.
  283. *
  284. * Reads an array of up to count elements, each one with a size of size
  285. * bytes.
  286. * \param[out] ptr pointer to area of at least (size*count) bytes where
  287. * the data will be stored.
  288. *
  289. * \param[in] size the size, in bytes, of each element to be read.
  290. *
  291. * \param[in] count the number of elements to be read.
  292. *
  293. * \return number of elements successfully read, which may be less than
  294. * count if a read error or end-of-file is encountered. If size or count
  295. * is zero, fread returns zero and the contents of the array and the
  296. * state of the stream remain unchanged.
  297. */
  298. size_t fread(void* ptr, size_t size, size_t count);
  299. //----------------------------------------------------------------------------
  300. /** Set the file position for the stream.
  301. *
  302. * \param[in] offset number of offset from the origin.
  303. *
  304. * \param[in] origin position used as reference for the offset. It is
  305. * specified by one of the following constants.
  306. *
  307. * SEEK_SET - Beginning of file.
  308. *
  309. * SEEK_CUR - Current position of the file pointer.
  310. *
  311. * SEEK_END - End of file.
  312. *
  313. * \return zero for success. Otherwise, it returns non-zero and sets the
  314. * error indicator for the stream.
  315. */
  316. int fseek(int32_t offset, int origin);
  317. //----------------------------------------------------------------------------
  318. /** Get the current position in a stream.
  319. *
  320. * \return If successful, ftell return the current value of the position
  321. * indicator. On failure, ftell returns −1L.
  322. */
  323. int32_t ftell();
  324. //----------------------------------------------------------------------------
  325. /** Binary output.
  326. *
  327. * Writes an array of up to count elements, each one with a size of size
  328. * bytes.
  329. * \param[in] ptr pointer to (size*count) bytes of data to be written.
  330. *
  331. * \param[in] size the size, in bytes, of each element to be written.
  332. *
  333. * \param[in] count the number of elements to be written.
  334. *
  335. * \return number of elements successfully written. if this number is
  336. * less than count, an error has occured. If size or count is zero,
  337. * fwrite returns zero.
  338. */
  339. size_t fwrite(const void * ptr, size_t size, size_t count);
  340. //----------------------------------------------------------------------------
  341. /** Get a byte from the stream.
  342. *
  343. * getc and fgetc are equivalent but getc is inline so it is faster but
  344. * require more flash memory.
  345. *
  346. * \return If the end-of-file indicator for the stream is set, or if the
  347. * stream is at end-of-file, the end-of-file indicator for the stream is
  348. * set and the fgetc function returns EOF. Otherwise, the fgetc function
  349. * returns the next character from the input stream.
  350. */
  351. inline __attribute__((always_inline))
  352. int getc() {return m_r-- == 0 ? fillGet() : *m_p++;}
  353. //----------------------------------------------------------------------------
  354. /** Write a byte to a stream.
  355. *
  356. * putc and fputc are equivalent but putc is inline so it is faster but
  357. * require more flash memory.
  358. *
  359. * \param[in] c the byte to be written (converted to an unsigned char).
  360. *
  361. * \return Upon successful completion, fputc() returns the value it
  362. * has written. Otherwise, it returns EOF and sets the error indicator for
  363. * the stream.
  364. */
  365. inline __attribute__((always_inline))
  366. int putc(int c) {return m_w-- == 0 ? flushPut(c) : *m_p++ = c;}
  367. //----------------------------------------------------------------------------
  368. /** Write a CR/LF.
  369. *
  370. * \return two, the number of bytes written, for success or -1 for failure.
  371. */
  372. inline __attribute__((always_inline))
  373. int putCRLF() {
  374. if (m_w < 2) {
  375. if (!flushBuf()) return -1;
  376. }
  377. *m_p++ = '\r';
  378. *m_p++ = '\n';
  379. m_w -= 2;
  380. return 2;
  381. }
  382. //----------------------------------------------------------------------------
  383. /** Write a character.
  384. * \param[in] c the character to write.
  385. * \return the number of bytes written.
  386. */
  387. size_t print(char c) {
  388. return putc(c) < 0 ? 0 : 1;
  389. }
  390. //----------------------------------------------------------------------------
  391. /** Write a string.
  392. *
  393. * \param[in] str the string to be written.
  394. *
  395. * \return the number of bytes written.
  396. */
  397. size_t print(const char* str) {
  398. int n = fputs(str);
  399. return n < 0 ? 0 : n;
  400. }
  401. //----------------------------------------------------------------------------
  402. /** Print a string stored in flash memory.
  403. *
  404. * \param[in] str the string to print.
  405. *
  406. * \return the number of bytes written.
  407. */
  408. size_t print(const __FlashStringHelper *str);
  409. //----------------------------------------------------------------------------
  410. /** Print a floating point number.
  411. *
  412. * \param[in] prec Number of digits after decimal point.
  413. *
  414. * \param[in] val the number to be printed.
  415. *
  416. * \return the number of bytes written.
  417. */
  418. size_t print(double val, uint8_t prec = 2) {
  419. return print(static_cast<float>(val), prec);
  420. }
  421. //----------------------------------------------------------------------------
  422. /** Print a floating point number.
  423. *
  424. * \param[in] prec Number of digits after decimal point.
  425. *
  426. * \param[in] val the number to be printed.
  427. *
  428. * \return the number of bytes written.
  429. */
  430. size_t print(float val, uint8_t prec = 2) {
  431. int n = printDec(val, prec);
  432. return n > 0 ? n : 0;
  433. }
  434. //----------------------------------------------------------------------------
  435. /** Print a number.
  436. *
  437. * \param[in] val the number to be printed.
  438. *
  439. * \return the number of bytes written.
  440. */
  441. template <typename T>
  442. size_t print(T val) {
  443. int n = printDec(val);
  444. return n > 0 ? n : 0;
  445. }
  446. //----------------------------------------------------------------------------
  447. /** Write a CR/LF.
  448. *
  449. * \return two, the number of bytes written, for success or zero for failure.
  450. */
  451. size_t println() {
  452. return putCRLF() > 0 ? 2 : 0;
  453. }
  454. //----------------------------------------------------------------------------
  455. /** Print a floating point number followed by CR/LF.
  456. *
  457. * \param[in] val the number to be printed.
  458. *
  459. * \param[in] prec Number of digits after decimal point.
  460. *
  461. * \return the number of bytes written.
  462. */
  463. size_t println(double val, uint8_t prec = 2) {
  464. return println(static_cast<float>(val), prec);
  465. }
  466. //----------------------------------------------------------------------------
  467. /** Print a floating point number followed by CR/LF.
  468. *
  469. * \param[in] val the number to be printed.
  470. *
  471. * \param[in] prec Number of digits after decimal point.
  472. *
  473. * \return the number of bytes written.
  474. */
  475. size_t println(float val, uint8_t prec = 2) {
  476. int n = printDec(val, prec);
  477. return n > 0 && putCRLF() > 0 ? n + 2 : 0;
  478. }
  479. //----------------------------------------------------------------------------
  480. /** Print an item followed by CR/LF
  481. *
  482. * \param[in] val the item to be printed.
  483. *
  484. * \return the number of bytes written.
  485. */
  486. template <typename T>
  487. size_t println(T val) {
  488. int n = print(val);
  489. return putCRLF() > 0 ? n + 2 : 0;
  490. }
  491. //----------------------------------------------------------------------------
  492. /** Print a char as a number.
  493. * \param[in] n number to be printed.
  494. * \return The number of bytes written or -1 if an error occurs.
  495. */
  496. int printDec(char n) {
  497. if (CHAR_MIN == 0) {
  498. return printDec((unsigned char)n);
  499. } else {
  500. return printDec((signed char)n);
  501. }
  502. }
  503. //----------------------------------------------------------------------------
  504. /** print a signed 8-bit integer
  505. * \param[in] n number to be printed.
  506. * \return The number of bytes written or -1 if an error occurs.
  507. */
  508. int printDec(signed char n);
  509. //----------------------------------------------------------------------------
  510. /** Print an unsigned 8-bit number.
  511. * \param[in] n number to be print.
  512. * \return The number of bytes written or -1 if an error occurs.
  513. */
  514. int printDec(unsigned char n) {
  515. return printDec((uint16_t)n);
  516. }
  517. //----------------------------------------------------------------------------
  518. /** Print a int16_t
  519. * \param[in] n number to be printed.
  520. * \return The number of bytes written or -1 if an error occurs.
  521. */
  522. int printDec(int16_t n);
  523. //----------------------------------------------------------------------------
  524. /** print a uint16_t.
  525. * \param[in] n number to be printed.
  526. * \return The number of bytes written or -1 if an error occurs.
  527. */
  528. int printDec(uint16_t n);
  529. //----------------------------------------------------------------------------
  530. /** Print a signed 32-bit integer.
  531. * \param[in] n number to be printed.
  532. * \return The number of bytes written or -1 if an error occurs.
  533. */
  534. int printDec(int32_t n);
  535. //----------------------------------------------------------------------------
  536. /** Write an unsigned 32-bit number.
  537. * \param[in] n number to be printed.
  538. * \return The number of bytes written or -1 if an error occurs.
  539. */
  540. int printDec(uint32_t n);
  541. //----------------------------------------------------------------------------
  542. /** Print a double.
  543. * \param[in] value The number to be printed.
  544. * \param[in] prec Number of digits after decimal point.
  545. * \return The number of bytes written or -1 if an error occurs.
  546. */
  547. int printDec(double value, uint8_t prec) {
  548. return printDec(static_cast<float>(value), prec);
  549. }
  550. //----------------------------------------------------------------------------
  551. /** Print a float.
  552. * \param[in] value The number to be printed.
  553. * \param[in] prec Number of digits after decimal point.
  554. * \return The number of bytes written or -1 if an error occurs.
  555. */
  556. int printDec(float value, uint8_t prec);
  557. //----------------------------------------------------------------------------
  558. /** Print a number followed by a field terminator.
  559. * \param[in] value The number to be printed.
  560. * \param[in] term The field terminator.
  561. * \param[in] prec Number of digits after decimal point.
  562. * \return The number of bytes written or -1 if an error occurs.
  563. */
  564. int printField(double value, char term, uint8_t prec = 2) {
  565. return printField(static_cast<float>(value), term, prec) > 0;
  566. }
  567. //----------------------------------------------------------------------------
  568. /** Print a number followed by a field terminator.
  569. * \param[in] value The number to be printed.
  570. * \param[in] term The field terminator.
  571. * \param[in] prec Number of digits after decimal point.
  572. * \return The number of bytes written or -1 if an error occurs.
  573. */
  574. int printField(float value, char term, uint8_t prec = 2) {
  575. int rtn = printDec(value, prec);
  576. return rtn < 0 || putc(term) < 0 ? -1 : rtn + 1;
  577. }
  578. //----------------------------------------------------------------------------
  579. /** Print a number followed by a field terminator.
  580. * \param[in] value The number to be printed.
  581. * \param[in] term The field terminator.
  582. * \return The number of bytes written or -1 if an error occurs.
  583. */
  584. template <typename T>
  585. int printField(T value, char term) {
  586. int rtn = printDec(value);
  587. return rtn < 0 || putc(term) < 0 ? -1 : rtn + 1;
  588. }
  589. //----------------------------------------------------------------------------
  590. /** Print HEX
  591. * \param[in] n number to be printed as HEX.
  592. *
  593. * \return The number of bytes written or -1 if an error occurs.
  594. */
  595. int printHex(uint32_t n);
  596. //----------------------------------------------------------------------------
  597. /** Print HEX with CRLF
  598. * \param[in] n number to be printed as HEX.
  599. *
  600. * \return The number of bytes written or -1 if an error occurs.
  601. */
  602. int printHexln(uint32_t n) {
  603. int rtn = printHex(n);
  604. return rtn < 0 || putCRLF() != 2 ? -1 : rtn + 2;
  605. }
  606. //----------------------------------------------------------------------------
  607. /** Set position of a stream to the beginning.
  608. *
  609. * The rewind function sets the file position to the beginning of the
  610. * file. It is equivalent to fseek(0L, SEEK_SET) except that the error
  611. * indicator for the stream is also cleared.
  612. *
  613. * \return true for success or false for failure.
  614. */
  615. bool rewind();
  616. //----------------------------------------------------------------------------
  617. /** Push a byte back into an input stream.
  618. *
  619. * \param[in] c the byte (converted to an unsigned char) to be pushed back.
  620. *
  621. * One character of pushback is guaranteed. If the ungetc function is
  622. * called too many times without an intervening read or file positioning
  623. * operation on that stream, the operation may fail.
  624. *
  625. * A successful intervening call to a file positioning function (fseek,
  626. * fsetpos, or rewind) discards any pushed-back characters for the stream.
  627. *
  628. * \return Upon successful completion, ungetc() returns the byte pushed
  629. * back after conversion. Otherwise it returns EOF.
  630. */
  631. int ungetc(int c);
  632. //============================================================================
  633. private:
  634. bool fillBuf();
  635. int fillGet();
  636. bool flushBuf();
  637. int flushPut(uint8_t c);
  638. char* fmtSpace(uint8_t len);
  639. int write(const void* buf, size_t count);
  640. //----------------------------------------------------------------------------
  641. // F_SRD and F_WR are never simultaneously asserted
  642. static const uint8_t F_SRD = 0x01; // OK to read
  643. static const uint8_t F_SWR = 0x02; // OK to write
  644. static const uint8_t F_SRW = 0x04; // open for reading & writing
  645. static const uint8_t F_EOF = 0x10; // found EOF
  646. static const uint8_t F_ERR = 0x20; // found error
  647. //----------------------------------------------------------------------------
  648. uint8_t m_flags;
  649. uint8_t* m_p;
  650. uint8_t m_r;
  651. uint8_t m_w;
  652. uint8_t m_buf[STREAM_BUF_SIZE];
  653. };
  654. //------------------------------------------------------------------------------
  655. #endif // StdioStream_h