You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
4.7KB

  1. /* Arduino SdFat Library
  2. * Copyright (C) 2012 by William Greiman
  3. *
  4. * This file is part of the Arduino SdFat 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 SdFat Library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #include <ostream.h>
  21. #ifndef PSTR
  22. #define PSTR(x) x
  23. #endif
  24. //------------------------------------------------------------------------------
  25. void ostream::do_fill(unsigned len) {
  26. for (; len < width(); len++) putch(fill());
  27. width(0);
  28. }
  29. //------------------------------------------------------------------------------
  30. void ostream::fill_not_left(unsigned len) {
  31. if ((flags() & adjustfield) != left) {
  32. do_fill(len);
  33. }
  34. }
  35. //------------------------------------------------------------------------------
  36. char* ostream::fmtNum(uint32_t n, char *ptr, uint8_t base) {
  37. char a = flags() & uppercase ? 'A' - 10 : 'a' - 10;
  38. do {
  39. uint32_t m = n;
  40. n /= base;
  41. char c = m - base * n;
  42. *--ptr = c < 10 ? c + '0' : c + a;
  43. } while (n);
  44. return ptr;
  45. }
  46. //------------------------------------------------------------------------------
  47. void ostream::putBool(bool b) {
  48. if (flags() & boolalpha) {
  49. if (b) {
  50. putPgm(PSTR("true"));
  51. } else {
  52. putPgm(PSTR("false"));
  53. }
  54. } else {
  55. putChar(b ? '1' : '0');
  56. }
  57. }
  58. //------------------------------------------------------------------------------
  59. void ostream::putChar(char c) {
  60. fill_not_left(1);
  61. putch(c);
  62. do_fill(1);
  63. }
  64. //------------------------------------------------------------------------------
  65. void ostream::putDouble(double n) {
  66. uint8_t nd = precision();
  67. double round = 0.5;
  68. char sign;
  69. char buf[13]; // room for sign, 10 digits, '.', and zero byte
  70. char *end = buf + sizeof(buf) - 1;
  71. char *str = end;
  72. // terminate string
  73. *end = '\0';
  74. // get sign and make nonnegative
  75. if (n < 0.0) {
  76. sign = '-';
  77. n = -n;
  78. } else {
  79. sign = flags() & showpos ? '+' : '\0';
  80. }
  81. // check for larger than uint32_t
  82. if (n > 4.0E9) {
  83. putPgm(PSTR("BIG FLT"));
  84. return;
  85. }
  86. // round up and separate in and fraction parts
  87. for (uint8_t i = 0; i < nd; ++i) round *= 0.1;
  88. n += round;
  89. uint32_t intPart = n;
  90. double fractionPart = n - intPart;
  91. // format intPart and decimal point
  92. if (nd || (flags() & showpoint)) *--str = '.';
  93. str = fmtNum(intPart, str, 10);
  94. // calculate length for fill
  95. uint8_t len = sign ? 1 : 0;
  96. len += nd + end - str;
  97. // extract adjust field
  98. fmtflags adj = flags() & adjustfield;
  99. if (adj == internal) {
  100. if (sign) putch(sign);
  101. do_fill(len);
  102. } else {
  103. // do fill for internal or right
  104. fill_not_left(len);
  105. if (sign) *--str = sign;
  106. }
  107. putstr(str);
  108. // output fraction
  109. while (nd-- > 0) {
  110. fractionPart *= 10.0;
  111. int digit = static_cast<int>(fractionPart);
  112. putch(digit + '0');
  113. fractionPart -= digit;
  114. }
  115. // do fill if not done above
  116. do_fill(len);
  117. }
  118. //------------------------------------------------------------------------------
  119. void ostream::putNum(int32_t n) {
  120. bool neg = n < 0 && flagsToBase() == 10;
  121. if (neg) n = -n;
  122. putNum(n, neg);
  123. }
  124. //------------------------------------------------------------------------------
  125. void ostream::putNum(uint32_t n, bool neg) {
  126. char buf[13];
  127. char* end = buf + sizeof(buf) - 1;
  128. char* num;
  129. char* str;
  130. uint8_t base = flagsToBase();
  131. *end = '\0';
  132. str = num = fmtNum(n, end, base);
  133. if (base == 10) {
  134. if (neg) {
  135. *--str = '-';
  136. } else if (flags() & showpos) {
  137. *--str = '+';
  138. }
  139. } else if (flags() & showbase) {
  140. if (flags() & hex) {
  141. *--str = flags() & uppercase ? 'X' : 'x';
  142. }
  143. *--str = '0';
  144. }
  145. uint8_t len = end - str;
  146. fmtflags adj = flags() & adjustfield;
  147. if (adj == internal) {
  148. while (str < num) putch(*str++);
  149. }
  150. if (adj != left) {
  151. do_fill(len);
  152. }
  153. putstr(str);
  154. do_fill(len);
  155. }
  156. //------------------------------------------------------------------------------
  157. void ostream::putPgm(const char* str) {
  158. int n;
  159. for (n = 0; pgm_read_byte(&str[n]); n++) {}
  160. fill_not_left(n);
  161. for (uint8_t c; (c = pgm_read_byte(str)); str++) {
  162. putch(c);
  163. }
  164. do_fill(n);
  165. }
  166. //------------------------------------------------------------------------------
  167. void ostream::putStr(const char *str) {
  168. unsigned n = strlen(str);
  169. fill_not_left(n);
  170. putstr(str);
  171. do_fill(n);
  172. }