2
0

scanf.rs 15 KB

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