您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

381 行
8.1KB

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