ostream.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /**
  2. * Copyright (c) 2011-2022 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 ostream_h
  26. #define ostream_h
  27. /**
  28. * \file
  29. * \brief \ref ostream class
  30. */
  31. #include "ios.h"
  32. //==============================================================================
  33. /**
  34. * \class ostream
  35. * \brief Output Stream
  36. */
  37. class ostream : public virtual ios {
  38. public:
  39. ostream() {}
  40. /** call manipulator
  41. * \param[in] pf function to call
  42. * \return the stream
  43. */
  44. ostream& operator<< (ostream& (*pf)(ostream& str)) {
  45. return pf(*this);
  46. }
  47. /** call manipulator
  48. * \param[in] pf function to call
  49. * \return the stream
  50. */
  51. ostream& operator<< (ios_base& (*pf)(ios_base& str)) {
  52. pf(*this);
  53. return *this;
  54. }
  55. /** Output bool
  56. * \param[in] arg value to output
  57. * \return the stream
  58. */
  59. ostream &operator<< (bool arg) {
  60. putBool(arg);
  61. return *this;
  62. }
  63. /** Output string
  64. * \param[in] arg string to output
  65. * \return the stream
  66. */
  67. ostream &operator<< (const char *arg) {
  68. putStr(arg);
  69. return *this;
  70. }
  71. /** Output string
  72. * \param[in] arg string to output
  73. * \return the stream
  74. */
  75. ostream &operator<< (const signed char *arg) {
  76. putStr((const char*)arg);
  77. return *this;
  78. }
  79. /** Output string
  80. * \param[in] arg string to output
  81. * \return the stream
  82. */
  83. ostream &operator<< (const unsigned char *arg) {
  84. putStr((const char*)arg);
  85. return *this;
  86. }
  87. #if ENABLE_ARDUINO_STRING
  88. /** Output string
  89. * \param[in] arg string to output
  90. * \return the stream
  91. */
  92. ostream &operator<< (const String& arg) {
  93. putStr(arg.c_str());
  94. return *this;
  95. }
  96. #endif // ENABLE_ARDUINO_STRING
  97. /** Output character
  98. * \param[in] arg character to output
  99. * \return the stream
  100. */
  101. ostream &operator<< (char arg) {
  102. putChar(arg);
  103. return *this;
  104. }
  105. /** Output character
  106. * \param[in] arg character to output
  107. * \return the stream
  108. */
  109. ostream &operator<< (signed char arg) {
  110. putChar(static_cast<char>(arg));
  111. return *this;
  112. }
  113. /** Output character
  114. * \param[in] arg character to output
  115. * \return the stream
  116. */
  117. ostream &operator<< (unsigned char arg) {
  118. putChar(static_cast<char>(arg));
  119. return *this;
  120. }
  121. /** Output double
  122. * \param[in] arg value to output
  123. * \return the stream
  124. */
  125. ostream &operator<< (double arg) {
  126. putDouble(arg);
  127. return *this;
  128. }
  129. /** Output float
  130. * \param[in] arg value to output
  131. * \return the stream
  132. */
  133. ostream &operator<< (float arg) {
  134. putDouble(arg);
  135. return *this;
  136. }
  137. /** Output signed short
  138. * \param[in] arg value to output
  139. * \return the stream
  140. */
  141. ostream &operator<< (short arg) { // NOLINT
  142. putNum((int32_t)arg);
  143. return *this;
  144. }
  145. /** Output unsigned short
  146. * \param[in] arg value to output
  147. * \return the stream
  148. */
  149. ostream &operator<< (unsigned short arg) { // NOLINT
  150. putNum((uint32_t)arg);
  151. return *this;
  152. }
  153. /** Output signed int
  154. * \param[in] arg value to output
  155. * \return the stream
  156. */
  157. ostream &operator<< (int arg) {
  158. putNum((int32_t)arg);
  159. return *this;
  160. }
  161. /** Output unsigned int
  162. * \param[in] arg value to output
  163. * \return the stream
  164. */
  165. ostream &operator<< (unsigned int arg) {
  166. putNum((uint32_t)arg);
  167. return *this;
  168. }
  169. /** Output signed long
  170. * \param[in] arg value to output
  171. * \return the stream
  172. */
  173. ostream &operator<< (long arg) { // NOLINT
  174. putNum((int32_t)arg);
  175. return *this;
  176. }
  177. /** Output unsigned long
  178. * \param[in] arg value to output
  179. * \return the stream
  180. */
  181. ostream &operator<< (unsigned long arg) { // NOLINT
  182. putNum((uint32_t)arg);
  183. return *this;
  184. }
  185. /** Output signed long long
  186. * \param[in] arg value to output
  187. * \return the stream
  188. */
  189. ostream &operator<< (long long arg) { // NOLINT
  190. putNum((int64_t)arg);
  191. return *this;
  192. }
  193. /** Output unsigned long long
  194. * \param[in] arg value to output
  195. * \return the stream
  196. */
  197. ostream &operator<< (unsigned long long arg) { // NOLINT
  198. putNum((uint64_t)arg);
  199. return *this;
  200. }
  201. /** Output pointer
  202. * \param[in] arg value to output
  203. * \return the stream
  204. */
  205. ostream& operator<< (const void* arg) {
  206. putNum(reinterpret_cast<uint32_t>(arg));
  207. return *this;
  208. }
  209. /** Output a string from flash using the Arduino F() macro.
  210. * \param[in] arg pointing to flash string
  211. * \return the stream
  212. */
  213. ostream &operator<< (const __FlashStringHelper *arg) {
  214. putPgm(reinterpret_cast<const char*>(arg));
  215. return *this;
  216. }
  217. /**
  218. * Puts a character in a stream.
  219. *
  220. * The unformatted output function inserts the element \a ch.
  221. * It returns *this.
  222. *
  223. * \param[in] ch The character
  224. * \return A reference to the ostream object.
  225. */
  226. ostream& put(char ch) {
  227. putch(ch);
  228. return *this;
  229. }
  230. // ostream& write(char *str, streamsize count);
  231. /**
  232. * Flushes the buffer associated with this stream. The flush function
  233. * calls the sync function of the associated file.
  234. * \return A reference to the ostream object.
  235. */
  236. ostream& flush() {
  237. if (!sync()) {
  238. setstate(badbit);
  239. }
  240. return *this;
  241. }
  242. /**
  243. * \return the stream position
  244. */
  245. pos_type tellp() {
  246. return tellpos();
  247. }
  248. /**
  249. * Set the stream position
  250. * \param[in] pos The absolute position in which to move the write pointer.
  251. * \return Is always *this. Failure is indicated by the state of *this.
  252. */
  253. ostream& seekp(pos_type pos) {
  254. if (!seekpos(pos)) {
  255. setstate(failbit);
  256. }
  257. return *this;
  258. }
  259. /**
  260. * Set the stream position.
  261. *
  262. * \param[in] off An offset to move the write pointer relative to way.
  263. * \a off is a signed 32-bit int so the offset is limited to +- 2GB.
  264. * \param[in] way One of ios::beg, ios::cur, or ios::end.
  265. * \return Is always *this. Failure is indicated by the state of *this.
  266. */
  267. ostream& seekp(off_type off, seekdir way) {
  268. if (!seekoff(off, way)) {
  269. setstate(failbit);
  270. }
  271. return *this;
  272. }
  273. protected:
  274. /// @cond SHOW_PROTECTED
  275. /** Put character with binary/text conversion
  276. * \param[in] ch character to write
  277. */
  278. virtual void putch(char ch) = 0;
  279. virtual void putstr(const char *str) = 0;
  280. virtual bool seekoff(off_type pos, seekdir way) = 0;
  281. virtual bool seekpos(pos_type pos) = 0;
  282. virtual bool sync() = 0;
  283. virtual pos_type tellpos() = 0;
  284. /// @endcond
  285. private:
  286. void do_fill(unsigned len);
  287. void fill_not_left(unsigned len);
  288. void putBool(bool b);
  289. void putChar(char c);
  290. void putDouble(double n);
  291. void putNum(int32_t n);
  292. void putNum(int64_t n);
  293. void putNum(uint32_t n) {putNum(n, false);}
  294. void putNum(uint64_t n) {putNum(n, false);}
  295. void putPgm(const char* str);
  296. void putStr(const char* str);
  297. template<typename T>
  298. char* fmtNum(T n, char *ptr, uint8_t base) {
  299. char a = flags() & uppercase ? 'A' - 10 : 'a' - 10;
  300. do {
  301. T m = n;
  302. n /= base;
  303. char c = m - base * n;
  304. *--ptr = c < 10 ? c + '0' : c + a;
  305. } while (n);
  306. return ptr;
  307. }
  308. template<typename T>
  309. void putNum(T n, bool neg) {
  310. char buf[(8*sizeof(T) + 2)/3 + 2];
  311. char* ptr = buf + sizeof(buf) - 1;
  312. char* num;
  313. char* str;
  314. uint8_t base = flagsToBase();
  315. *ptr = '\0';
  316. str = num = fmtNum(n, ptr, base);
  317. if (base == 10) {
  318. if (neg) {
  319. *--str = '-';
  320. } else if (flags() & showpos) {
  321. *--str = '+';
  322. }
  323. } else if (flags() & showbase) {
  324. if (flags() & hex) {
  325. *--str = flags() & uppercase ? 'X' : 'x';
  326. }
  327. *--str = '0';
  328. }
  329. uint8_t len = ptr - str;
  330. fmtflags adj = flags() & adjustfield;
  331. if (adj == internal) {
  332. while (str < num) {
  333. putch(*str++);
  334. }
  335. do_fill(len);
  336. } else {
  337. // do fill for right
  338. fill_not_left(len);
  339. }
  340. putstr(str);
  341. do_fill(len);
  342. }
  343. };
  344. #endif // ostream_h