istream.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /**
  2. * Copyright (c) 20011-2017 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. // #include <ctype.h>
  26. #include <float.h>
  27. #include <ctype.h>
  28. #include "istream.h"
  29. //------------------------------------------------------------------------------
  30. int istream::get() {
  31. int c;
  32. m_gcount = 0;
  33. c = getch();
  34. if (c < 0) {
  35. setstate(failbit);
  36. } else {
  37. m_gcount = 1;
  38. }
  39. return c;
  40. }
  41. //------------------------------------------------------------------------------
  42. istream& istream::get(char& c) {
  43. int tmp = get();
  44. if (tmp >= 0) {
  45. c = tmp;
  46. }
  47. return *this;
  48. }
  49. //------------------------------------------------------------------------------
  50. istream& istream::get(char *str, streamsize n, char delim) {
  51. int c;
  52. FatPos_t pos;
  53. m_gcount = 0;
  54. while ((m_gcount + 1) < n) {
  55. c = getch(&pos);
  56. if (c < 0) {
  57. break;
  58. }
  59. if (c == delim) {
  60. setpos(&pos);
  61. break;
  62. }
  63. str[m_gcount++] = c;
  64. }
  65. if (n > 0) {
  66. str[m_gcount] = '\0';
  67. }
  68. if (m_gcount == 0) {
  69. setstate(failbit);
  70. }
  71. return *this;
  72. }
  73. //------------------------------------------------------------------------------
  74. void istream::getBool(bool *b) {
  75. if ((flags() & boolalpha) == 0) {
  76. getNumber(b);
  77. return;
  78. }
  79. #ifdef __AVR__
  80. PGM_P truePtr = PSTR("true");
  81. PGM_P falsePtr = PSTR("false");
  82. #else // __AVR__
  83. const char* truePtr = "true";
  84. const char* falsePtr = "false";
  85. #endif // __AVR
  86. const uint8_t true_len = 4;
  87. const uint8_t false_len = 5;
  88. bool trueOk = true;
  89. bool falseOk = true;
  90. uint8_t i = 0;
  91. int c = readSkip();
  92. while (1) {
  93. #ifdef __AVR__
  94. falseOk = falseOk && c == pgm_read_byte(falsePtr + i);
  95. trueOk = trueOk && c == pgm_read_byte(truePtr + i);
  96. #else // __AVR__
  97. falseOk = falseOk && c == falsePtr[i];
  98. trueOk = trueOk && c == truePtr[i];
  99. #endif // __AVR__
  100. if (trueOk == false && falseOk == false) {
  101. break;
  102. }
  103. i++;
  104. if (trueOk && i == true_len) {
  105. *b = true;
  106. return;
  107. }
  108. if (falseOk && i == false_len) {
  109. *b = false;
  110. return;
  111. }
  112. c = getch();
  113. }
  114. setstate(failbit);
  115. }
  116. //------------------------------------------------------------------------------
  117. void istream::getChar(char* ch) {
  118. int16_t c = readSkip();
  119. if (c < 0) {
  120. setstate(failbit);
  121. } else {
  122. *ch = c;
  123. }
  124. }
  125. //------------------------------------------------------------------------------
  126. //
  127. // http://www.exploringbinary.com/category/numbers-in-computers/
  128. //
  129. int16_t const EXP_LIMIT = 100;
  130. static const uint32_t uint32_max = (uint32_t)-1;
  131. bool istream::getDouble(double* value) {
  132. bool got_digit = false;
  133. bool got_dot = false;
  134. bool neg;
  135. int16_t c;
  136. bool expNeg = false;
  137. int16_t exp = 0;
  138. int16_t fracExp = 0;
  139. uint32_t frac = 0;
  140. FatPos_t endPos;
  141. double pow10;
  142. double v;
  143. getpos(&endPos);
  144. c = readSkip();
  145. neg = c == '-';
  146. if (c == '-' || c == '+') {
  147. c = getch();
  148. }
  149. while (1) {
  150. if (isdigit(c)) {
  151. got_digit = true;
  152. if (frac < uint32_max/10) {
  153. frac = frac * 10 + (c - '0');
  154. if (got_dot) {
  155. fracExp--;
  156. }
  157. } else {
  158. if (!got_dot) {
  159. fracExp++;
  160. }
  161. }
  162. } else if (!got_dot && c == '.') {
  163. got_dot = true;
  164. } else {
  165. break;
  166. }
  167. if (fracExp < -EXP_LIMIT || fracExp > EXP_LIMIT) {
  168. goto fail;
  169. }
  170. c = getch(&endPos);
  171. }
  172. if (!got_digit) {
  173. goto fail;
  174. }
  175. if (c == 'e' || c == 'E') {
  176. c = getch();
  177. expNeg = c == '-';
  178. if (c == '-' || c == '+') {
  179. c = getch();
  180. }
  181. while (isdigit(c)) {
  182. if (exp > EXP_LIMIT) {
  183. goto fail;
  184. }
  185. exp = exp * 10 + (c - '0');
  186. c = getch(&endPos);
  187. }
  188. }
  189. v = static_cast<double>(frac);
  190. exp = expNeg ? fracExp - exp : fracExp + exp;
  191. expNeg = exp < 0;
  192. if (expNeg) {
  193. exp = -exp;
  194. }
  195. pow10 = 10.0;
  196. while (exp) {
  197. if (exp & 1) {
  198. if (expNeg) {
  199. // check for underflow
  200. if (v < FLT_MIN * pow10 && frac != 0) {
  201. goto fail;
  202. }
  203. v /= pow10;
  204. } else {
  205. // check for overflow
  206. if (v > FLT_MAX / pow10) {
  207. goto fail;
  208. }
  209. v *= pow10;
  210. }
  211. }
  212. pow10 *= pow10;
  213. exp >>= 1;
  214. }
  215. setpos(&endPos);
  216. *value = neg ? -v : v;
  217. return true;
  218. fail:
  219. // error restore position to last good place
  220. setpos(&endPos);
  221. setstate(failbit);
  222. return false;
  223. }
  224. //------------------------------------------------------------------------------
  225. istream& istream::getline(char *str, streamsize n, char delim) {
  226. FatPos_t pos;
  227. int c;
  228. m_gcount = 0;
  229. if (n > 0) {
  230. str[0] = '\0';
  231. }
  232. while (1) {
  233. c = getch(&pos);
  234. if (c < 0) {
  235. break;
  236. }
  237. if (c == delim) {
  238. m_gcount++;
  239. break;
  240. }
  241. if ((m_gcount + 1) >= n) {
  242. setpos(&pos);
  243. setstate(failbit);
  244. break;
  245. }
  246. str[m_gcount++] = c;
  247. str[m_gcount] = '\0';
  248. }
  249. if (m_gcount == 0) {
  250. setstate(failbit);
  251. }
  252. return *this;
  253. }
  254. //------------------------------------------------------------------------------
  255. bool istream::getNumber(uint32_t posMax, uint32_t negMax, uint32_t* num) {
  256. int16_t c;
  257. int8_t any = 0;
  258. int8_t have_zero = 0;
  259. uint8_t neg;
  260. uint32_t val = 0;
  261. uint32_t cutoff;
  262. uint8_t cutlim;
  263. FatPos_t endPos;
  264. uint8_t f = flags() & basefield;
  265. uint8_t base = f == oct ? 8 : f != hex ? 10 : 16;
  266. getpos(&endPos);
  267. c = readSkip();
  268. neg = c == '-' ? 1 : 0;
  269. if (c == '-' || c == '+') {
  270. c = getch();
  271. }
  272. if (base == 16 && c == '0') { // TESTSUITE
  273. c = getch(&endPos);
  274. if (c == 'X' || c == 'x') {
  275. c = getch();
  276. // remember zero in case no hex digits follow x/X
  277. have_zero = 1;
  278. } else {
  279. any = 1;
  280. }
  281. }
  282. // set values for overflow test
  283. cutoff = neg ? negMax : posMax;
  284. cutlim = cutoff % base;
  285. cutoff /= base;
  286. while (1) {
  287. if (isdigit(c)) {
  288. c -= '0';
  289. } else if (isalpha(c)) {
  290. c -= isupper(c) ? 'A' - 10 : 'a' - 10;
  291. } else {
  292. break;
  293. }
  294. if (c >= base) {
  295. break;
  296. }
  297. if (val > cutoff || (val == cutoff && c > cutlim)) {
  298. // indicate overflow error
  299. any = -1;
  300. break;
  301. }
  302. val = val * base + c;
  303. c = getch(&endPos);
  304. any = 1;
  305. }
  306. setpos(&endPos);
  307. if (any > 0 || (have_zero && any >= 0)) {
  308. *num = neg ? -val : val;
  309. return true;
  310. }
  311. setstate(failbit);
  312. return false;
  313. }
  314. //------------------------------------------------------------------------------
  315. void istream::getStr(char *str) {
  316. FatPos_t pos;
  317. uint16_t i = 0;
  318. uint16_t m = width() ? width() - 1 : 0XFFFE;
  319. if (m != 0) {
  320. getpos(&pos);
  321. int c = readSkip();
  322. while (i < m) {
  323. if (c < 0) {
  324. break;
  325. }
  326. if (isspace(c)) {
  327. setpos(&pos);
  328. break;
  329. }
  330. str[i++] = c;
  331. c = getch(&pos);
  332. }
  333. }
  334. str[i] = '\0';
  335. if (i == 0) {
  336. setstate(failbit);
  337. }
  338. width(0);
  339. }
  340. //------------------------------------------------------------------------------
  341. istream& istream::ignore(streamsize n, int delim) {
  342. int c;
  343. m_gcount = 0;
  344. while (m_gcount < n) {
  345. c = getch();
  346. if (c < 0) {
  347. break;
  348. }
  349. m_gcount++;
  350. if (c == delim) {
  351. break;
  352. }
  353. }
  354. return *this;
  355. }
  356. //------------------------------------------------------------------------------
  357. int istream::peek() {
  358. int16_t c;
  359. FatPos_t pos;
  360. m_gcount = 0;
  361. getpos(&pos);
  362. c = getch();
  363. if (c < 0) {
  364. if (!bad()) {
  365. setstate(eofbit);
  366. }
  367. } else {
  368. setpos(&pos);
  369. }
  370. return c;
  371. }
  372. //------------------------------------------------------------------------------
  373. int16_t istream::readSkip() {
  374. int16_t c;
  375. do {
  376. c = getch();
  377. } while (isspace(c) && (flags() & skipws));
  378. return c;
  379. }
  380. //------------------------------------------------------------------------------
  381. /** used to implement ws() */
  382. void istream::skipWhite() {
  383. int c;
  384. FatPos_t pos;
  385. do {
  386. c = getch(&pos);
  387. } while (isspace(c));
  388. setpos(&pos);
  389. }