io_utils.carbon 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. if (c == 0x31) {
  51. *p = *p + 1;
  52. } else if (c == 0x32) {
  53. *p = *p + 2;
  54. } else if (c == 0x33) {
  55. *p = *p + 3;
  56. } else if (c == 0x34) {
  57. *p = *p + 4;
  58. } else if (c == 0x35) {
  59. *p = *p + 5;
  60. } else if (c == 0x36) {
  61. *p = *p + 6;
  62. } else if (c == 0x37) {
  63. *p = *p + 7;
  64. } else if (c == 0x38) {
  65. *p = *p + 8;
  66. } else if (c == 0x39) {
  67. *p = *p + 9;
  68. }
  69. read_any_digits = true;
  70. }
  71. return read_any_digits;
  72. }
  73. fn PrintInt64NoNewline(n_val: i64) {
  74. var pow10: i64 = 1;
  75. var n: i64 = n_val;
  76. while (n / 10 >= pow10) {
  77. pow10 = pow10 * 10;
  78. }
  79. while (pow10 != 0) {
  80. let d: i64 = n / pow10;
  81. // TODO: Core.PrintChar(0x30 + (d as i32));
  82. if (d == 0) { Core.PrintChar(0x30); }
  83. else if (d == 1) { Core.PrintChar(0x31); }
  84. else if (d == 2) { Core.PrintChar(0x32); }
  85. else if (d == 3) { Core.PrintChar(0x33); }
  86. else if (d == 4) { Core.PrintChar(0x34); }
  87. else if (d == 5) { Core.PrintChar(0x35); }
  88. else if (d == 6) { Core.PrintChar(0x36); }
  89. else if (d == 7) { Core.PrintChar(0x37); }
  90. else if (d == 8) { Core.PrintChar(0x38); }
  91. else if (d == 9) { Core.PrintChar(0x39); }
  92. n = n % pow10;
  93. pow10 = pow10 / 10;
  94. }
  95. }
  96. fn PrintInt64(n_val: i64) {
  97. PrintInt64NoNewline(n_val);
  98. Core.PrintChar(0xA);
  99. }
  100. fn PeekChar() -> i32 {
  101. var next: i32 = ReadChar();
  102. UnreadChar(next);
  103. return next;
  104. }
  105. fn ConsumeChar(c: i32) -> bool {
  106. var next: i32 = ReadChar();
  107. if (next != c) {
  108. UnreadChar(next);
  109. return false;
  110. }
  111. return true;
  112. }
  113. fn SkipSpaces() -> bool {
  114. var skipped_any_spaces: bool = false;
  115. while (ConsumeChar(0x20)) {
  116. skipped_any_spaces = true;
  117. }
  118. return skipped_any_spaces;
  119. }
  120. fn SkipNewline() -> bool {
  121. // Optional carriage return.
  122. ConsumeChar(0x0D);
  123. // Newline.
  124. // TODO: Unread the CR if it was present?
  125. return ConsumeChar(0x0A);
  126. }
  127. fn SkipNChars(n: i32) -> bool {
  128. var i: i32 = 0;
  129. while (i < n) {
  130. if (ReadChar() == Core.EOF()) {
  131. return false;
  132. }
  133. ++i;
  134. }
  135. return true;
  136. }