scanf.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. use alloc::string::String;
  2. use alloc::vec::Vec;
  3. use io::Read;
  4. use platform::types::*;
  5. use va_list::VaList;
  6. #[derive(PartialEq, Eq)]
  7. enum IntKind {
  8. Byte,
  9. Short,
  10. Int,
  11. Long,
  12. LongLong,
  13. IntMax,
  14. PtrDiff,
  15. Size,
  16. }
  17. /// Helper function for progressing a C string
  18. unsafe fn next_byte(string: &mut *const c_char) -> Result<u8, c_int> {
  19. let c = **string as u8;
  20. *string = string.offset(1);
  21. if c == 0 {
  22. Err(-1)
  23. } else {
  24. Ok(c)
  25. }
  26. }
  27. unsafe fn inner_scanf<R: Read>(
  28. mut r: R,
  29. mut format: *const c_char,
  30. mut ap: VaList,
  31. ) -> Result<c_int, c_int> {
  32. let mut matched = 0;
  33. let mut byte = 0;
  34. let mut skip_read = false;
  35. let mut count = 0;
  36. macro_rules! read {
  37. () => {{
  38. let buf = &mut [byte];
  39. match r.read(buf) {
  40. Ok(0) => false,
  41. Ok(_) => {
  42. byte = buf[0];
  43. count += 1;
  44. true
  45. }
  46. Err(_) => return Err(-1),
  47. }
  48. }};
  49. }
  50. macro_rules! maybe_read {
  51. () => {
  52. maybe_read!(inner false);
  53. };
  54. (noreset) => {
  55. maybe_read!(inner);
  56. };
  57. (inner $($placeholder:expr)*) => {
  58. if !skip_read && !read!() {
  59. return Ok(matched);
  60. }
  61. $(else {
  62. // Hacky way of having this optional
  63. skip_read = $placeholder;
  64. })*
  65. }
  66. }
  67. while *format != 0 {
  68. let mut c = *format as u8;
  69. format = format.offset(1);
  70. if c == b' ' {
  71. maybe_read!(noreset);
  72. while (byte as char).is_whitespace() {
  73. if !read!() {
  74. return Ok(matched);
  75. }
  76. }
  77. skip_read = true;
  78. } else if c != b'%' {
  79. maybe_read!();
  80. if c != byte {
  81. return Ok(matched);
  82. }
  83. } else {
  84. c = next_byte(&mut format)?;
  85. let mut ignore = false;
  86. if c == b'*' {
  87. ignore = true;
  88. c = next_byte(&mut format)?;
  89. }
  90. let mut width = String::new();
  91. while c >= b'0' && c <= b'9' {
  92. width.push(c as char);
  93. c = next_byte(&mut format)?;
  94. }
  95. let mut width = if width.is_empty() {
  96. None
  97. } else {
  98. match width.parse::<usize>() {
  99. Ok(n) => Some(n),
  100. Err(_) => return Err(-1),
  101. }
  102. };
  103. let mut kind = IntKind::Int;
  104. loop {
  105. kind = match c {
  106. b'h' => {
  107. if kind == IntKind::Short || kind == IntKind::Byte {
  108. IntKind::Byte
  109. } else {
  110. IntKind::Short
  111. }
  112. }
  113. b'j' => IntKind::IntMax,
  114. b'l' => {
  115. if kind == IntKind::Long || kind == IntKind::LongLong {
  116. IntKind::LongLong
  117. } else {
  118. IntKind::Long
  119. }
  120. }
  121. b'q' | b'L' => IntKind::LongLong,
  122. b't' => IntKind::PtrDiff,
  123. b'z' => IntKind::Size,
  124. _ => break,
  125. };
  126. c = next_byte(&mut format)?;
  127. }
  128. if c != b'n' {
  129. maybe_read!(noreset);
  130. }
  131. match c {
  132. b'%' => {
  133. while (byte as char).is_whitespace() {
  134. if !read!() {
  135. return Ok(matched);
  136. }
  137. }
  138. if byte != b'%' {
  139. return Err(matched);
  140. } else if !read!() {
  141. return Ok(matched);
  142. }
  143. }
  144. b'd' | b'i' | b'o' | b'u' | b'x' | b'X' | b'f' | b'e' | b'g' | b'E' | b'a'
  145. | b'p' => {
  146. while (byte as char).is_whitespace() {
  147. if !read!() {
  148. return Ok(matched);
  149. }
  150. }
  151. let pointer = c == b'p';
  152. // Pointers aren't automatic, but we do want to parse "0x"
  153. let auto = c == b'i' || pointer;
  154. let float = c == b'f' || c == b'e' || c == b'g' || c == b'E' || c == b'a';
  155. let mut radix = match c {
  156. b'o' => 8,
  157. b'x' | b'X' | b'p' => 16,
  158. _ => 10,
  159. };
  160. let mut n = String::new();
  161. let mut dot = false;
  162. while width.map(|w| w > 0).unwrap_or(true)
  163. && ((byte >= b'0' && byte <= b'7')
  164. || (radix >= 10 && (byte >= b'8' && byte <= b'9'))
  165. || (float && !dot && byte == b'.')
  166. || (radix == 16
  167. && ((byte >= b'a' && byte <= b'f')
  168. || (byte >= b'A' && byte <= b'F'))))
  169. {
  170. if auto
  171. && n.is_empty()
  172. && byte == b'0'
  173. && width.map(|w| w > 0).unwrap_or(true)
  174. {
  175. if !pointer {
  176. radix = 8;
  177. }
  178. width = width.map(|w| w - 1);
  179. if !read!() {
  180. break;
  181. }
  182. if width.map(|w| w > 0).unwrap_or(true)
  183. && (byte == b'x' || byte == b'X')
  184. {
  185. radix = 16;
  186. width = width.map(|w| w - 1);
  187. if width.map(|w| w > 0).unwrap_or(true) && !read!() {
  188. break;
  189. }
  190. }
  191. continue;
  192. }
  193. if byte == b'.' {
  194. // Don't allow another dot
  195. dot = true;
  196. }
  197. n.push(byte as char);
  198. width = width.map(|w| w - 1);
  199. if width.map(|w| w > 0).unwrap_or(true) && !read!() {
  200. break;
  201. }
  202. }
  203. macro_rules! parse_type {
  204. (noformat $type:ident) => {{
  205. let n = if n.is_empty() {
  206. 0 as $type
  207. } else {
  208. n.parse::<$type>().map_err(|_| 0)?
  209. };
  210. if !ignore {
  211. *ap.get::<*mut $type>() = n;
  212. matched += 1;
  213. }
  214. }};
  215. (c_double) => {
  216. parse_type!(noformat c_double);
  217. };
  218. (c_float) => {
  219. parse_type!(noformat c_float);
  220. };
  221. ($type:ident) => {
  222. parse_type!($type, $type);
  223. };
  224. ($type:ident, $final:ty) => {{
  225. let n = if n.is_empty() {
  226. 0 as $type
  227. } else {
  228. $type::from_str_radix(&n, radix).map_err(|_| 0)?
  229. };
  230. if !ignore {
  231. *ap.get::<*mut $final>() = n as $final;
  232. matched += 1;
  233. }
  234. }};
  235. }
  236. if float {
  237. if kind == IntKind::Long || kind == IntKind::LongLong {
  238. parse_type!(c_double);
  239. } else {
  240. parse_type!(c_float);
  241. }
  242. } else if c == b'p' {
  243. parse_type!(size_t, *mut c_void);
  244. } else {
  245. let unsigned = c == b'o' || c == b'u' || c == b'x' || c == b'X';
  246. match kind {
  247. IntKind::Byte => {
  248. if unsigned {
  249. parse_type!(c_uchar);
  250. } else {
  251. parse_type!(c_char);
  252. }
  253. }
  254. IntKind::Short => {
  255. if unsigned {
  256. parse_type!(c_ushort)
  257. } else {
  258. parse_type!(c_short)
  259. }
  260. }
  261. IntKind::Int => {
  262. if unsigned {
  263. parse_type!(c_uint)
  264. } else {
  265. parse_type!(c_int)
  266. }
  267. }
  268. IntKind::Long => {
  269. if unsigned {
  270. parse_type!(c_ulong)
  271. } else {
  272. parse_type!(c_long)
  273. }
  274. }
  275. IntKind::LongLong => {
  276. if unsigned {
  277. parse_type!(c_ulonglong)
  278. } else {
  279. parse_type!(c_longlong)
  280. }
  281. }
  282. IntKind::IntMax => {
  283. if unsigned {
  284. parse_type!(uintmax_t)
  285. } else {
  286. parse_type!(intmax_t)
  287. }
  288. }
  289. IntKind::PtrDiff => parse_type!(ptrdiff_t),
  290. IntKind::Size => {
  291. if unsigned {
  292. parse_type!(size_t)
  293. } else {
  294. parse_type!(ssize_t)
  295. }
  296. }
  297. }
  298. }
  299. }
  300. b's' => {
  301. while (byte as char).is_whitespace() {
  302. if !read!() {
  303. return Ok(matched);
  304. }
  305. }
  306. let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.get()) };
  307. while width.map(|w| w > 0).unwrap_or(true) && !(byte as char).is_whitespace() {
  308. if let Some(ref mut ptr) = ptr {
  309. **ptr = byte as c_char;
  310. *ptr = ptr.offset(1);
  311. }
  312. width = width.map(|w| w - 1);
  313. if width.map(|w| w > 0).unwrap_or(true) && !read!() {
  314. break;
  315. }
  316. }
  317. if let Some(ptr) = ptr {
  318. *ptr = 0;
  319. matched += 1;
  320. }
  321. }
  322. b'c' => {
  323. let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.get()) };
  324. for i in 0..width.unwrap_or(1) {
  325. if let Some(ptr) = ptr {
  326. *ptr.add(i) = byte as c_char;
  327. }
  328. width = width.map(|w| w - 1);
  329. if width.map(|w| w > 0).unwrap_or(true) && !read!() {
  330. break;
  331. }
  332. }
  333. if ptr.is_some() {
  334. matched += 1;
  335. }
  336. }
  337. b'[' => {
  338. c = next_byte(&mut format)?;
  339. let mut matches = Vec::new();
  340. let mut invert = false;
  341. if c == b'^' {
  342. c = next_byte(&mut format)?;
  343. invert = true;
  344. }
  345. let mut prev;
  346. loop {
  347. matches.push(c);
  348. prev = c;
  349. c = next_byte(&mut format)?;
  350. if c == b'-' {
  351. if prev == b']' {
  352. continue;
  353. }
  354. c = next_byte(&mut format)?;
  355. if c == b']' {
  356. matches.push(b'-');
  357. break;
  358. }
  359. prev += 1;
  360. while prev < c {
  361. matches.push(prev);
  362. prev += 1;
  363. }
  364. } else if c == b']' {
  365. break;
  366. }
  367. }
  368. let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.get()) };
  369. while width.map(|w| w > 0).unwrap_or(true) && !invert == matches.contains(&byte)
  370. {
  371. if let Some(ref mut ptr) = ptr {
  372. **ptr = byte as c_char;
  373. *ptr = ptr.offset(1);
  374. }
  375. width = width.map(|w| w - 1);
  376. if width.map(|w| w > 0).unwrap_or(true) && !read!() {
  377. break;
  378. }
  379. }
  380. if let Some(ptr) = ptr {
  381. *ptr = 0;
  382. matched += 1;
  383. }
  384. }
  385. b'n' => {
  386. if !ignore {
  387. *ap.get::<*mut c_int>() = count as c_int;
  388. }
  389. }
  390. _ => return Err(-1),
  391. }
  392. if width != Some(0) && c != b'n' {
  393. // It didn't hit the width, so an extra character was read and matched.
  394. // But this character did not match so let's reuse it.
  395. skip_read = true;
  396. }
  397. }
  398. }
  399. Ok(matched)
  400. }
  401. pub unsafe fn scanf<R: Read>(r: R, format: *const c_char, ap: VaList) -> c_int {
  402. match inner_scanf(r, format, ap) {
  403. Ok(n) => n,
  404. Err(n) => n,
  405. }
  406. }