Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

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