Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

270 linhas
8.1KB

  1. /**
  2. * Copyright (c) 2011-2019 Bill Greiman
  3. * This file is part of the SdFat library for SD memory cards.
  4. *
  5. * MIT License
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included
  15. * in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. */
  25. #ifndef BufferedPrint_h
  26. #define BufferedPrint_h
  27. /**
  28. * \file
  29. * \brief Fast buffered print.
  30. */
  31. #include "common/FmtNumber.h"
  32. /**
  33. * \class BufferedPrint
  34. * \brief Fast buffered print template.
  35. */
  36. template<typename WriteClass, uint8_t BUF_DIM>
  37. class BufferedPrint {
  38. public:
  39. BufferedPrint() : m_wr(nullptr), m_in(0) {}
  40. /** BufferedPrint constructor.
  41. * \param[in] wr Print destination.
  42. */
  43. explicit BufferedPrint(WriteClass* wr) : m_wr(wr), m_in(0) {}
  44. /** Initialize the BuffedPrint class.
  45. * \param[in] wr Print destination.
  46. */
  47. void begin(WriteClass* wr) {
  48. m_wr = wr;
  49. m_in = 0;
  50. }
  51. /** Flush the buffer - same as sync() with no status return. */
  52. void flush() {sync();}
  53. /** Print a character followed by a field terminator.
  54. * \param[in] c character to print.
  55. * \param[in] term The field terminator. Use '\\n' for CR LF.
  56. * \return true for success or false if an error occurs.
  57. */
  58. size_t printField(char c, char term) {
  59. char buf[3];
  60. char* str = buf + sizeof(buf);
  61. if (term) {
  62. *--str = term;
  63. if (term == '\n') {
  64. *--str = '\r';
  65. }
  66. }
  67. *--str = c;
  68. return write(str, buf + sizeof(buf) - str);
  69. }
  70. /** Print a string stored in AVR flash followed by a field terminator.
  71. * \param[in] fsh string to print.
  72. * \param[in] term The field terminator. Use '\\n' for CR LF.
  73. * \return true for success or false if an error occurs.
  74. */
  75. size_t printField(const __FlashStringHelper *fsh, char term) {
  76. #ifdef __AVR__
  77. size_t rtn = 0;
  78. PGM_P p = reinterpret_cast<PGM_P>(fsh);
  79. char c;
  80. while ((c = pgm_read_byte(p++))) {
  81. if (!write(&c, 1)) {
  82. return 0;
  83. }
  84. rtn++;
  85. }
  86. if (term) {
  87. char buf[2];
  88. char* str = buf + sizeof(buf);
  89. *--str = term;
  90. if (term == '\n') {
  91. *--str = '\r';
  92. }
  93. rtn += write(str, buf + sizeof(buf) - str);
  94. }
  95. return rtn;
  96. #else // __AVR__
  97. return printField(reinterpret_cast<const char *>(fsh), term);
  98. #endif // __AVR__
  99. }
  100. /** Print a string followed by a field terminator.
  101. * \param[in] str string to print.
  102. * \param[in] term The field terminator. Use '\\n' for CR LF.
  103. * \return true for success or false if an error occurs.
  104. */
  105. size_t printField(const char* str, char term) {
  106. size_t rtn = write(str, strlen(str));
  107. if (term) {
  108. char buf[2];
  109. char* ptr = buf + sizeof(buf);
  110. *--ptr = term;
  111. if (term == '\n') {
  112. *--ptr = '\r';
  113. }
  114. rtn += write(ptr, buf + sizeof(buf) - ptr);
  115. }
  116. return rtn;
  117. }
  118. /** Print a double followed by a field terminator.
  119. * \param[in] d The number to be printed.
  120. * \param[in] term The field terminator. Use '\\n' for CR LF.
  121. * \param[in] prec Number of digits after decimal point.
  122. * \return true for success or false if an error occurs.
  123. */
  124. size_t printField(double d, char term, uint8_t prec = 2) {
  125. char buf[24];
  126. char* str = buf + sizeof(buf);
  127. if (term) {
  128. *--str = term;
  129. if (term == '\n') {
  130. *--str = '\r';
  131. }
  132. }
  133. str = fmtDouble(str, d, prec, false);
  134. return write(str, buf + sizeof(buf) - str);
  135. }
  136. /** Print a float followed by a field terminator.
  137. * \param[in] f The number to be printed.
  138. * \param[in] term The field terminator. Use '\\n' for CR LF.
  139. * \param[in] prec Number of digits after decimal point.
  140. * \return true for success or false if an error occurs.
  141. */
  142. size_t printField(float f, char term, uint8_t prec = 2) {
  143. return printField(static_cast<double>(f), term, prec);
  144. }
  145. /** Print an integer value for 8, 16, and 32 bit signed and unsigned types.
  146. * \param[in] n The value to print.
  147. * \param[in] term The field terminator. Use '\\n' for CR LF.
  148. * \return true for success or false if an error occurs.
  149. */
  150. template<typename Type>
  151. size_t printField(Type n, char term) {
  152. const uint8_t DIM = sizeof(Type) <= 2 ? 8 : 13;
  153. char buf[DIM];
  154. char* str = buf + sizeof(buf);
  155. if (term) {
  156. *--str = term;
  157. if (term == '\n') {
  158. *--str = '\r';
  159. }
  160. }
  161. Type p = n < 0 ? -n : n;
  162. if (sizeof(Type) <= 2) {
  163. str = fmtBase10(str, (uint16_t)p);
  164. } else {
  165. str = fmtBase10(str, (uint32_t)p);
  166. }
  167. if (n < 0) {
  168. *--str = '-';
  169. }
  170. return write(str, buf + sizeof(buf) - str);
  171. }
  172. /** Print CR LF.
  173. * \return true for success or false if an error occurs.
  174. */
  175. size_t println() {
  176. char buf[2];
  177. buf[0] = '\r';
  178. buf[1] = '\n';
  179. return write(buf, 2);
  180. }
  181. /** Print a double.
  182. * \param[in] d The number to be printed.
  183. * \param[in] prec Number of digits after decimal point.
  184. * \return true for success or false if an error occurs.
  185. */
  186. size_t print(double d, uint8_t prec = 2) {
  187. return printField(d, 0, prec);
  188. }
  189. /** Print a double followed by CR LF.
  190. * \param[in] d The number to be printed.
  191. * \param[in] prec Number of digits after decimal point.
  192. * \return true for success or false if an error occurs.
  193. */
  194. size_t println(double d, uint8_t prec = 2) {
  195. return printField(d, '\n', prec);
  196. }
  197. /** Print a float.
  198. * \param[in] f The number to be printed.
  199. * \param[in] prec Number of digits after decimal point.
  200. * \return true for success or false if an error occurs.
  201. */
  202. size_t print(float f, uint8_t prec = 2) {
  203. return printField(static_cast<double>(f), 0, prec);
  204. }
  205. /** Print a float followed by CR LF.
  206. * \param[in] f The number to be printed.
  207. * \param[in] prec Number of digits after decimal point.
  208. * \return true for success or false if an error occurs.
  209. */
  210. size_t println(float f, uint8_t prec) {
  211. return printField(static_cast<double>(f), '\n', prec);
  212. }
  213. /** Print character, string, or number.
  214. * \param[in] v item to print.
  215. * \return true for success or false if an error occurs.
  216. */
  217. template<typename Type>
  218. size_t print(Type v) {
  219. return printField(v, 0);
  220. }
  221. /** Print character, string, or number followed by CR LF.
  222. * \param[in] v item to print.
  223. * \return true for success or false if an error occurs.
  224. */
  225. template<typename Type>
  226. size_t println(Type v) {
  227. return printField(v, '\n');
  228. }
  229. /** Flush the buffer.
  230. * \return true for success or false if an error occurs.
  231. */
  232. bool sync() {
  233. if (!m_wr || m_wr->write(m_buf, m_in) != m_in) {
  234. return false;
  235. }
  236. m_in = 0;
  237. return true;
  238. }
  239. /** Write data to an open file.
  240. * \param[in] src Pointer to the location of the data to be written.
  241. *
  242. * \param[in] n Number of bytes to write.
  243. *
  244. * \return For success write() returns the number of bytes written, always
  245. * \a n.
  246. */
  247. size_t write(const void* src, size_t n) {
  248. if ((m_in + n) > sizeof(m_buf)) {
  249. if (!sync()) {
  250. return 0;
  251. }
  252. if (n >= sizeof(m_buf)) {
  253. return n == m_wr->write((const uint8_t*)src, n) ? n : 0;
  254. }
  255. }
  256. memcpy(m_buf + m_in, src, n);
  257. m_in += n;
  258. return n;
  259. }
  260. private:
  261. WriteClass* m_wr;
  262. uint8_t m_in;
  263. // Insure room for double.
  264. uint8_t m_buf[BUF_DIM < 24 ? 24 : BUF_DIM]; // NOLINT
  265. };
  266. #endif // BufferedPrint_h