io_utils.carbon 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. library "io_utils";
  5. import Core library "io";
  6. import Core library "range";
  7. // If non-zero, this is the most recently read character plus 2.
  8. // The +2 is necessary to distinguish the case of no unread character
  9. // from the case of unreading an EOF.
  10. var unread_char: i32 = 0;
  11. fn ReadChar() -> i32 {
  12. if (unread_char != 0) {
  13. var result: i32 = unread_char - 2;
  14. unread_char = 0;
  15. return result;
  16. }
  17. return Core.ReadChar();
  18. }
  19. fn UnreadChar(c: i32) {
  20. // TODO: assert(unread_char == 0);
  21. unread_char = c + 2;
  22. }
  23. // TODO: Make generic.
  24. fn ReadInt(p: i32*) -> bool {
  25. var read_any_digits: bool = false;
  26. *p = 0;
  27. while (true) {
  28. var c: i32 = ReadChar();
  29. if (c < 0x30 or c > 0x39) {
  30. UnreadChar(c);
  31. break;
  32. }
  33. // TODO: Check for overflow.
  34. *p *= 10;
  35. *p += c - 0x30;
  36. read_any_digits = true;
  37. }
  38. return read_any_digits;
  39. }
  40. fn ReadInt64(p: i64*) -> bool {
  41. var read_any_digits: bool = false;
  42. *p = 0;
  43. while (true) {
  44. var c: i32 = ReadChar();
  45. if (c < 0x30 or c > 0x39) {
  46. UnreadChar(c);
  47. break;
  48. }
  49. // TODO: Check for overflow.
  50. *p = *p * 10;
  51. *p = *p + ((c - 0x30) as i64);
  52. read_any_digits = true;
  53. }
  54. return read_any_digits;
  55. }
  56. fn PrintInt64NoNewline(n_val: i64) {
  57. var pow10: i64 = 1;
  58. var n: i64 = n_val;
  59. while (n / 10 >= pow10) {
  60. pow10 = pow10 * 10;
  61. }
  62. while (pow10 != 0) {
  63. let d: i64 = n / pow10;
  64. Core.PrintChar(((d + 0x30) as u8) as char);
  65. n = n % pow10;
  66. pow10 = pow10 / 10;
  67. }
  68. }
  69. fn PrintInt64(n_val: i64) {
  70. PrintInt64NoNewline(n_val);
  71. Core.PrintChar('\n');
  72. }
  73. fn PeekChar() -> i32 {
  74. var next: i32 = ReadChar();
  75. UnreadChar(next);
  76. return next;
  77. }
  78. fn ConsumeChar(c: i32) -> bool {
  79. var next: i32 = ReadChar();
  80. if (next != c) {
  81. UnreadChar(next);
  82. return false;
  83. }
  84. return true;
  85. }
  86. fn SkipSpaces() -> bool {
  87. var skipped_any_spaces: bool = false;
  88. while (ConsumeChar(0x20)) {
  89. skipped_any_spaces = true;
  90. }
  91. return skipped_any_spaces;
  92. }
  93. fn SkipNewline() -> bool {
  94. // Optional carriage return.
  95. ConsumeChar(0x0D);
  96. // Newline.
  97. // TODO: Unread the CR if it was present?
  98. return ConsumeChar(0x0A);
  99. }
  100. fn SkipNChars(n: i32) -> bool {
  101. for (_: i32 in Core.Range(n)) {
  102. if (ReadChar() == Core.EOF()) {
  103. return false;
  104. }
  105. }
  106. return true;
  107. }