CharacterReader.cs 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. namespace Avalonia.Utilities
  5. {
  6. public ref struct CharacterReader
  7. {
  8. private ReadOnlySpan<char> _s;
  9. public CharacterReader(ReadOnlySpan<char> s)
  10. :this()
  11. {
  12. _s = s;
  13. }
  14. public bool End => _s.IsEmpty;
  15. public char Peek => _s[0];
  16. public int Position { get; private set; }
  17. public char Take()
  18. {
  19. Position++;
  20. char taken = _s[0];
  21. _s = _s.Slice(1);
  22. return taken;
  23. }
  24. public void SkipWhitespace()
  25. {
  26. var trimmed = _s.TrimStart();
  27. Position += _s.Length - trimmed.Length;
  28. _s = trimmed;
  29. }
  30. public bool TakeIf(char c)
  31. {
  32. if (Peek == c)
  33. {
  34. Take();
  35. return true;
  36. }
  37. else
  38. {
  39. return false;
  40. }
  41. }
  42. public bool TakeIf(Func<char, bool> condition)
  43. {
  44. if (condition(Peek))
  45. {
  46. Take();
  47. return true;
  48. }
  49. return false;
  50. }
  51. public ReadOnlySpan<char> TakeUntil(char c)
  52. {
  53. int len;
  54. for (len = 0; len < _s.Length && _s[len] != c; len++)
  55. {
  56. }
  57. var span = _s.Slice(0, len);
  58. _s = _s.Slice(len);
  59. Position += len;
  60. return span;
  61. }
  62. public ReadOnlySpan<char> TakeWhile(Func<char, bool> condition)
  63. {
  64. int len;
  65. for (len = 0; len < _s.Length && condition(_s[len]); len++)
  66. {
  67. }
  68. var span = _s.Slice(0, len);
  69. _s = _s.Slice(len);
  70. Position += len;
  71. return span;
  72. }
  73. }
  74. }