CharacterReader.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. using System;
  2. namespace Avalonia.Utilities
  3. {
  4. // TODO12: This should not be public
  5. #if !BUILDTASK
  6. public
  7. #endif
  8. ref struct CharacterReader
  9. {
  10. private ReadOnlySpan<char> _s;
  11. public CharacterReader(ReadOnlySpan<char> s)
  12. :this()
  13. {
  14. _s = s;
  15. }
  16. public bool End => _s.IsEmpty;
  17. public char Peek => _s[0];
  18. public int Position { get; private set; }
  19. public char Take()
  20. {
  21. Position++;
  22. char taken = _s[0];
  23. _s = _s.Slice(1);
  24. return taken;
  25. }
  26. public void SkipWhitespace()
  27. {
  28. var trimmed = _s.TrimStart();
  29. Position += _s.Length - trimmed.Length;
  30. _s = trimmed;
  31. }
  32. public bool TakeIf(char c)
  33. {
  34. if (Peek == c)
  35. {
  36. Take();
  37. return true;
  38. }
  39. else
  40. {
  41. return false;
  42. }
  43. }
  44. internal bool TakeIf(string s)
  45. {
  46. var p = TryPeek(s.Length);
  47. if (p.SequenceEqual(s.AsSpan()))
  48. {
  49. _s = _s.Slice(s.Length);
  50. Position += s.Length;
  51. return true;
  52. }
  53. return false;
  54. }
  55. public bool TakeIf(Func<char, bool> condition)
  56. {
  57. if (condition(Peek))
  58. {
  59. Take();
  60. return true;
  61. }
  62. return false;
  63. }
  64. public ReadOnlySpan<char> TakeUntil(char c)
  65. {
  66. int len;
  67. for (len = 0; len < _s.Length && _s[len] != c; len++)
  68. {
  69. }
  70. var span = _s.Slice(0, len);
  71. _s = _s.Slice(len);
  72. Position += len;
  73. return span;
  74. }
  75. public ReadOnlySpan<char> TakeWhile(Func<char, bool> condition)
  76. {
  77. int len;
  78. for (len = 0; len < _s.Length && condition(_s[len]); len++)
  79. {
  80. }
  81. var span = _s.Slice(0, len);
  82. _s = _s.Slice(len);
  83. Position += len;
  84. return span;
  85. }
  86. public ReadOnlySpan<char> TryPeek(int count)
  87. {
  88. if (_s.Length < count)
  89. return ReadOnlySpan<char>.Empty;
  90. return _s.Slice(0, count);
  91. }
  92. public ReadOnlySpan<char> PeekWhitespace()
  93. {
  94. var trimmed = _s.TrimStart();
  95. return _s.Slice(0, _s.Length - trimmed.Length);
  96. }
  97. public void Skip(int count)
  98. {
  99. if (_s.Length < count)
  100. throw new IndexOutOfRangeException();
  101. _s = _s.Slice(count);
  102. }
  103. }
  104. }