// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.IO; using System.Linq; using System.Text; namespace Microsoft.AspNetCore.Razor.Parser { internal static class TextReaderExtensions { public static string ReadUntil(this TextReader reader, char terminator) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } return ReadUntil(reader, terminator, inclusive: false); } public static string ReadUntil(this TextReader reader, char terminator, bool inclusive) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } // Rather not allocate an array to use ReadUntil(TextReader, params char[]) so we'll just call the predicate version directly return ReadUntil(reader, c => c == terminator, inclusive); } public static string ReadUntil(this TextReader reader, params char[] terminators) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (terminators == null) { throw new ArgumentNullException(nameof(terminators)); } // NOTE: Using named parameters would be difficult here, hence the inline comment return ReadUntil(reader, inclusive: false, terminators: terminators); } public static string ReadUntil( this TextReader reader, bool inclusive, params char[] terminators) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (terminators == null) { throw new ArgumentNullException(nameof(terminators)); } return ReadUntil(reader, c => terminators.Any(tc => tc == c), inclusive: inclusive); } public static string ReadUntil(this TextReader reader, Predicate condition) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (condition == null) { throw new ArgumentNullException(nameof(condition)); } return ReadUntil(reader, condition, inclusive: false); } public static string ReadUntil( this TextReader reader, Predicate condition, bool inclusive) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (condition == null) { throw new ArgumentNullException(nameof(condition)); } var builder = new StringBuilder(); var ch = -1; while ((ch = reader.Peek()) != -1 && !condition((char)ch)) { reader.Read(); // Advance the reader builder.Append((char)ch); } if (inclusive && reader.Peek() != -1) { builder.Append((char)reader.Read()); } return builder.ToString(); } public static string ReadWhile(this TextReader reader, Predicate condition) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (condition == null) { throw new ArgumentNullException(nameof(condition)); } return ReadWhile(reader, condition, inclusive: false); } public static string ReadWhile( this TextReader reader, Predicate condition, bool inclusive) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (condition == null) { throw new ArgumentNullException(nameof(condition)); } return ReadUntil(reader, ch => !condition(ch), inclusive); } public static string ReadWhiteSpace(this TextReader reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } return ReadWhile(reader, c => Char.IsWhiteSpace(c)); } public static string ReadUntilWhiteSpace(this TextReader reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } return ReadUntil(reader, c => Char.IsWhiteSpace(c)); } } }