scanf.rs 15 KB

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