io_utils.carbon 2.4 KB

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