Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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