istream.cpp 8.8 KB

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