Esempio n. 1
0
        public void CanReadSimpleString()
        {
            using var textReader = new StringReader("test");
            using var charReader = new CharReader(textReader);

            Assert.That(charReader.PeekChar(), Is.EqualTo('t'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('t'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('e'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('e'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('s'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('s'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('t'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('t'));
            Assert.That(charReader.PeekChar(), Is.Null);
            Assert.That(charReader.ReadChar(), Is.Null);
        }
Esempio n. 2
0
        public void CanReadSimpleContent(string testString)
        {
            using var textReader = new StringReader(testString);
            using var charReader = new CharReader(textReader);


            foreach (var ch in testString)
            {
                var peekedChar = charReader.PeekChar();
                Assert.That(peekedChar, Is.EqualTo(ch));
                var readChar = charReader.ReadChar();
                Assert.That(readChar, Is.EqualTo(ch));
            }

            Assert.That(charReader.PeekChar(), Is.Null);
            Assert.That(charReader.ReadChar(), Is.Null);
        }
Esempio n. 3
0
        private IEnumerable <object[]> ReadAllRows()
        {
            var rows      = new List <object[]>();
            var rowNumber = 0;

            while (_reader.PeekChar() != null)
            {
                rows.Add(_rowReader.ReadOneRowEnumerable(rowNumber++));
            }

            return(rows.ToArray());
        }
Esempio n. 4
0
        private void GenerateFromPattern(StringBuilder stream, string rawPattern)
        {
            CharReader reader = new CharReader(TranslateDefs(rawPattern, "", ""), 0);

            // Output stuff
            WordFormat currentFormat = WordFormat.None;
            string buffer = "";

            // Input stuff
            char c = ' ';
            char prev = ' '; // This is only used by the Proper format mode to determine the start of a word

            // A/An conversion stuff
            int anIndex = -1;
            WordFormat anFormat = WordFormat.None;

            // Selector stuff
            int uniformSeedSalt = rand.Next(0, 1000000);
            List<int> activeSelectors = new List<int>();
            List<int> selectorUniformIDs = new List<int>();
            int currentUniformID = -1;

            // Word lock stuff
            Dictionary<string, Dictionary<string, int>> locks = new Dictionary<string, Dictionary<string, int>>();

            // Repeater stuff
            List<RepeaterInstance> repeaters = new List<RepeaterInstance>();

            // Volatile flags
            List<string> vflags = new List<string>();

            while (!reader.EndOfString) // Read through pattern until we reach the end
            {
                prev = c;
                c = reader.ReadChar();
                string className = "";
                string subType = "";

                #region Frequency indicators
                if (Char.IsNumber(c)) // Check if frequency indicator is here. Example: 40%{ +n[plural] are +A. }
                {
                    int oldPos = reader.Position;
                    int percentIndex = reader.Source.IndexOf('%', reader.Position);
                    int nextSpace = reader.Source.IndexOf(' ', reader.Position);
                    if (percentIndex > -1 && (percentIndex < nextSpace || nextSpace == -1))
                    {
                        reader.Position--; // Revert reading of first digit
                        string percentStr = reader.ReadString(percentIndex - reader.Position);
                        int percent;
                        if (!int.TryParse(percentStr, out percent))
                        {
                            Error("Frequency indicator percent value was not a number.", reader);
                            return;
                        }

                        if (percent > 100)
                        {
                            percent = 100;
                        }
                        else if (percent <= 0)
                        {
                            Error("0% frequency indicator detected. Why is this here?", reader);
                            return;
                        }

                        reader.Position++; // Skip past '%'

                        if ((char)reader.PeekChar() == '[') // Make sure this bitch is tight
                        {
                            reader.Position++; // Skip past '['
                            int closure = reader.Source.FindClosingSquareBracket(reader.Position);

                            if (closure < 0)
                            {
                                Error("Missing closing bracket in frequency indicator.", reader);
                                return;
                            }

                            if (rand.Next(0, 101) > percent)
                            {
                                reader.Position = closure;
                            }

                            continue;
                        }
                        else
                        {
                            reader.Position = oldPos; // Fall back to beginning of number if there is a false positive and it's just a number
                        }
                    }
                }
                #endregion

                #region Selectors
                if (c == '{') // Selector. Picks random item inside brackets. Example: {First/second/third/fourth/...}
                {
                    int end = reader.Source.FindClosingCurlyBracket(reader.Position);
                    if (end == -1)
                    {
                        Error("Incomplete curly brackets. Did you forget to close a selector?", reader);
                        return;
                    }
                    int[] startIndices = reader.Source.GetSelectorSubs(reader.Position);
                    if (startIndices.Length < 2)
                    {
                        Error("Selector is empty or only has one option.", reader);
                        return;
                    }
                    activeSelectors.Add(end + 1);
                    selectorUniformIDs.Add(currentUniformID);
                    if (currentUniformID > -1)
                    {
                        LongRandom uniRand = new LongRandom(uniformSeedSalt + currentUniformID);
                        reader.Position = startIndices[uniRand.Next(0, startIndices.Length)];
                    }
                    else
                    {
                        reader.Position = startIndices[rand.Next(0, startIndices.Length)];
                    }
                    currentUniformID = -1;
                }
                else if (c == '}')
                {
                    if (activeSelectors.Count == 0)
                    {
                        Error("Unexpected '}' found in pattern.", reader);
                        return;
                    }

                    activeSelectors.RemoveAt(activeSelectors.Count - 1);
                    selectorUniformIDs.RemoveAt(selectorUniformIDs.Count - 1);
                    continue;
                }
                else if (c == '/')
                {
                    if (activeSelectors.Count == 0)
                    {
                        Error("Unexpected '/' found in pattern.", reader);
                        return;
                    }
                    reader.Position = activeSelectors[activeSelectors.Count - 1];
                    activeSelectors.RemoveAt(activeSelectors.Count - 1);
                    selectorUniformIDs.RemoveAt(selectorUniformIDs.Count - 1);
                    continue;
                }
                else if (c == '*')
                {
                    int bracketIndex = reader.Source.IndexOf("{", reader.Position);
                    if (bracketIndex <= reader.Position)
                    {
                        Error("Uniform operator could not find a selector to associate with.", reader);
                        return;
                    }
                    string strUID = reader.ReadString(bracketIndex - reader.Position);
                    int uid;
                    if (!int.TryParse(strUID, out uid))
                    {
                        Error("Uniform ID was not a number.", reader);
                        return;
                    }
                    else if (uid < 0)
                    {
                        Error("Uniform ID's cannot be negative.", reader);
                        return;
                    }
                    currentUniformID = uid;
                    continue;
                }
                #endregion

                #region Repeaters
                if (c == '^')
                {
                    // iteration range
                    if (reader.PeekChar() != '[')
                    {
                        Error("Repeater iterations parameter did not have an opening bracket.", reader);
                        return;
                    }
                    reader.ReadChar(); // skip [
                    int rightRangeBracketIndex = reader.Source.FindClosingSquareBracket(reader.Position);
                    if (rightRangeBracketIndex < 0)
                    {
                        Error("Repeater iterations parameter did not have a closing bracket.", reader);
                        return;
                    }
                    string strRangeParameter = reader.ReadString(rightRangeBracketIndex - reader.Position).Trim();
                    reader.ReadChar(); // skip ]
                    int constantParam = 0;
                    int min = 0;
                    int max = 0;
                    if (!int.TryParse(strRangeParameter, out constantParam))
                    {
                        string[] parts = strRangeParameter.Split(new char[] { '-' });
                        if (parts.Length != 2)
                        {
                            Error("Repeater range parameter must be a pair of two numbers.", reader);
                            return;
                        }
                        if (!int.TryParse(parts[0], out min) || !int.TryParse(parts[1], out max))
                        {
                            Error("Repeater range parameter did not contain valid numbers.", reader);
                            return;
                        }
                        if (min > max || min == 0 || max == 0)
                        {
                            Error("Repeater range must be greater than zero, and max > min.", reader);
                            return;
                        }
                        constantParam = rand.Next(min, max);
                    }
                    // separator
                    if (reader.ReadChar() != '[')
                    {
                        Error("Repeater separator parameter did not have an opening bracket.", reader);
                        return;
                    }
                    int sepIndex = reader.Position;
                    int rightSepBracketIndex = reader.Source.FindClosingSquareBracket(reader.Position);
                    if (rightSepBracketIndex < 0)
                    {
                        Error("Repeater separator parameter did not have a closing bracket.", reader);
                    }
                    string strSepParameter = reader.ReadString(rightSepBracketIndex - reader.Position);
                    int sepEnd = reader.Position;
                    reader.ReadChar(); // skip ]

                    // content
                    if (reader.ReadChar() != '[')
                    {
                        Error("Repeater content parameter did not have an opening bracket.", reader);
                        return;
                    }
                    int rightContentBracketIndex = reader.Source.FindClosingSquareBracket(reader.Position);
                    if (rightSepBracketIndex < 0)
                    {
                        Error("Repeater content parameter did not have a closing bracket.", reader);
                    }
                    int pStart = reader.Position;

                    reader.ReadString(rightContentBracketIndex - reader.Position);

                    int pEnd = reader.Position;

                    repeaters.Add(new RepeaterInstance(pStart, pEnd, sepIndex, sepEnd, strSepParameter, constantParam));

                    reader.Position = pStart;
                }
                else if (c == ']' && repeaters.Count > 0) // End of repeater iteration?
                {
                    int last = repeaters.Count - 1;
                    RepeaterInstance rep = repeaters[last];
                    if (reader.Position - 1 != rep.ContentEndIndex && reader.Position - 1 != rep.SeparatorEndIndex)
                    {
                        continue;
                    }

                    if (rep.OnSeparator) // Currently writing separator?
                    {
                        rep.OnSeparator = false;
                        reader.Position = rep.ContentStartIndex;
                    }
                    else // Currently writing content?
                    {
                        if (repeaters[last].Elapse())
                        {
                            repeaters.RemoveAt(last); // Remove the last repeater if it's finished
                            continue;
                        }
                        else
                        {
                            rep.OnSeparator = true;
                            reader.Position = rep.SeparatorStartIndex; // Add separator if not
                        }
                    }
                }
                #endregion

                #region Flags
                else if (c == '$')
                {
                    int leftBracket = reader.Source.IndexOf("[", reader.Position);
                    if (leftBracket < 0)
                    {
                        Error("Missing '[' on flag call.", reader);
                        return;
                    }
                    string func = reader.ReadString(leftBracket - reader.Position).ToLower();
                    reader.ReadChar(); // skip [
                    if (func.Contains(' '))
                    {
                        Error("Invalid flag function.", reader);
                        return;
                    }
                    int rightBracket = reader.Source.FindClosingSquareBracket(reader.Position);
                    if (rightBracket < leftBracket)
                    {
                        Error("Missing ']' on flag call.", reader);
                        return;
                    }
                    string firstParam = reader.ReadString(rightBracket - reader.Position);
                    reader.ReadChar(); // skip ]
                    if (func == "set")
                    {
                        if (!vflags.Contains(firstParam))
                        {
                            vflags.Add(firstParam);
                        }
                        continue;
                    }
                    else if (func == "unset")
                    {
                        if (vflags.Contains(firstParam))
                        {
                            vflags.Remove(firstParam);
                        }
                        continue;
                    }
                    else if (func == "if")
                    {
                        if (reader.ReadChar() != '[')
                        {
                            Error("Missing '[' in IF body.", reader);
                            return;
                        }
                        int rightBodyBracket = reader.Source.FindClosingSquareBracket(reader.Position);
                        if (rightBodyBracket < 0)
                        {
                            Error("Missing ']' in IF body.", reader);
                            return;
                        }
                        if (!vflags.Contains(firstParam))
                        {
                            reader.Position = rightBodyBracket;
                        }
                        continue;
                    }
                    else if (func == "ifnot")
                    {
                        if (reader.ReadChar() != '[')
                        {
                            Error("Missing '[' in IF body.", reader);
                            return;
                        }
                        int rightBodyBracket = reader.Source.FindClosingSquareBracket(reader.Position);
                        if (rightBodyBracket < 0)
                        {
                            Error("Missing ']' in IF body.", reader);
                            return;
                        }
                        if (vflags.Contains(firstParam))
                        {
                            reader.Position = rightBodyBracket;
                        }
                        continue;
                    }
                    else if (func == "g_set")
                    {
                        if (!flags.Contains(firstParam))
                        {
                            flags.Add(firstParam);
                        }
                        continue;
                    }
                    else if (func == "g_unset")
                    {
                        if (flags.Contains(firstParam))
                        {
                            flags.Remove(firstParam);
                        }
                        continue;
                    }
                    else if (func == "g_if")
                    {
                        if (reader.ReadChar() != '[')
                        {
                            Error("Missing '[' in IF body.", reader);
                            return;
                        }
                        int rightBodyBracket = reader.Source.IndexOf("]", reader.Position);
                        if (rightBodyBracket < 0)
                        {
                            Error("Missing ']' in IF body.", reader);
                            return;
                        }
                        if (!flags.Contains(firstParam))
                        {
                            reader.Position = rightBodyBracket;
                        }
                        continue;
                    }
                    else if (func == "g_ifnot")
                    {
                        if (reader.ReadChar() != '[')
                        {
                            Error("Missing '[' in IF body.", reader);
                            return;
                        }
                        int rightBodyBracket = reader.Source.IndexOf("]", reader.Position);
                        if (rightBodyBracket < 0)
                        {
                            Error("Missing ']' in IF body.", reader);
                            return;
                        }
                        if (flags.Contains(firstParam))
                        {
                            reader.Position = rightBodyBracket;
                        }
                        continue;
                    }
                    else
                    {
                        Error("Unrecognized flag function.", reader);
                        return;
                    }
                }
                #endregion
                else if (c == '+') // Random word
                {
                    string lockID = "";
                    char symbol = reader.ReadChar();
                    if (symbol == ' ' || symbol == '+' || symbol == '#' || symbol == '*' || symbol == '~' || symbol == '|')
                    {
                        Warning("Enountered illegal symbol: '" + symbol.ToString() + "'", reader);
                        continue;
                    }
                    else if (symbol == '[') // Check if there is a class accessor. (For example: +[class]n)
                    {
                        int closure = reader.Source.IndexOf(']', reader.Position);
                        if (closure < 0)
                        {
                            Error("Incomplete brackets in class accessor.", reader);
                            return;
                        }
                        className = reader.ReadString(closure - reader.Position);
                        reader.Position++; // Skip past ']'
                        symbol = reader.ReadChar();
                    }
                    if (reader.PeekChar() == '[') // Check if there is a subtype accessor. (For example: +n[subtype] or +[class]n[subtype])
                    {
                        reader.Position++;
                        int closure = reader.Source.IndexOf(']', reader.Position);
                        if (closure < 0)
                        {
                            Error("Incomplete brackets in subtype accessor.", reader);
                            return;
                        }
                        subType = reader.ReadString(closure - reader.Position);
                        reader.Position++; // Skip past ']'
                    }
                    if (reader.PeekChar() == '<') // Check if there is a word lock accessor. (For example: +n<#> or +[class]n[subtype]<#>)
                    {
                        string lockKey = className + ":" + symbol.ToString();
                        if (!locks.ContainsKey(lockKey))
                        {
                            locks.Add(lockKey, new Dictionary<string, int>());
                        }
                        reader.Position++;
                        int closure = reader.Source.IndexOf('>', reader.Position);
                        if (closure < 0)
                        {
                            Error("Incomplete brackets in word lock accessor.", reader);
                            return;
                        }
                        lockID = reader.ReadString(closure - reader.Position);
                        if (lockID == "")
                        {
                            Error("Empty word lock ID.", reader);
                            return;
                        }
                        if (!locks[lockKey].ContainsKey(lockID) && wordBank.ContainsKey(symbol)) // add a new word lock if a new ID is found --- this allows reuse of the word!
                        {
                            locks[lockKey].Add(lockID, wordBank[symbol].GetRandomIndex(rand, className));
                        }
                        reader.Position++; // Skip past '>'
                    }

                    if (!wordBank.ContainsKey(symbol)) // Make sure the symbol is registered
                    {
                        Warning("Word symbol not found: '" + symbol.ToString() + "'", reader);
                    }
                    else if (lockID != "")
                    {
                        buffer = wordBank[symbol].GetWordByIndex(locks[className + ":" + symbol.ToString()][lockID], subType, currentFormat);
                    }
                    else
                    {
                        if (className.Contains(","))
                        {
                            string[] mcNames = className.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                            if (mcNames.Length < 2)
                            {
                                Error("A multi-class expression must include more than one class name in its parameters.", reader);
                                return;
                            }
                            for (int i = 0; i < mcNames.Length; i++)
                            {
                                mcNames[i] = mcNames[i].Trim(); // this is to get rid of spaces between the class names
                            }
                            for (int i = 0; i < mcNames.Length; i++)
                            {
                                if (!ClassExists(symbol, mcNames[i]))
                                {
                                    Error("Bad multiclass", reader);
                                    return;
                                }
                            }
                            buffer = wordBank[symbol].GetRandomWordMultiClass(rand, subType, currentFormat, mcNames);
                        }
                        else if (!ClassExists(symbol, className))
                        {
                            Warning("Class not found: " + symbol.ToString() + " -> " + className, reader);
                        }
                        else
                        {
                            int index = wordBank[symbol].GetRandomIndex(rand, className);
                            buffer = wordBank[symbol].GetWordByIndex(index, subType, currentFormat);
                            if (graph != null && symbol == 'n')
                            {
                                graph.Add(wordBank[symbol].GetWordByIndex(index, "", WordFormat.None));
                            }
                        }
                    }
                    buffer = buffer.Capitalize(currentFormat);
                    if (anIndex > -1 && buffer.StartsWithVowel())
                    {
                        if (anFormat == WordFormat.AllCaps)
                        {
                            stream.Insert(anIndex, "N");
                        }
                        else
                        {
                            stream.Insert(anIndex, "n");
                        }
                    }

                    anIndex = -1;
                    anFormat = WordFormat.None;
                }
                else if (c == '|' || c == '\n') // Line break
                {
                    buffer = "\r\n";
                }
                else if (c == '~') // Capitalize
                {
                    if (reader.PeekChar() == '~')
                    {
                        reader.ReadChar();
                        currentFormat = WordFormat.Capitalized;
                    }
                    else if (currentFormat == WordFormat.Proper)
                    {
                        currentFormat = WordFormat.None;
                    }
                    else
                    {
                        currentFormat = WordFormat.Proper;
                    }
                }
                else if (c == '@') // Capslock
                {
                    if (currentFormat == WordFormat.AllCaps)
                    {
                        currentFormat = WordFormat.None;
                    }
                    else
                    {
                        currentFormat = WordFormat.AllCaps;
                    }
                }
                else if (c == '#') // Random number
                {
                    if (reader.PeekChar() == '[')
                    {
                        reader.Position++;

                        int closure = reader.Source.IndexOf(']', reader.Position);
                        if (closure < 0)
                        {
                            Error("Incomplete parenthases in random number range.", reader);
                            return;
                        }

                        string rangeStr = reader.ReadString(closure - reader.Position);
                        reader.Position++; // Skip past ']'

                        string[] rangeParts = rangeStr.Split('-');

                        if (rangeParts.Length != 2)
                        {
                            Error("Invalid number of range elements for random number. Got " + rangeParts.Length + ", need 2.", reader);
                            return;
                        }

                        int min;
                        int max;

                        if (!int.TryParse(rangeParts[0], out min))
                        {
                            Error("Invalid minimum value for random number.", reader);
                            return;
                        }

                        if (!int.TryParse(rangeParts[1], out max))
                        {
                            Error("Invalid maximum value for random number.", reader);
                            return;
                        }

                        buffer = rand.Next(min, max).ToString();
                    }
                }
                else if (c != '{' && c != '}' && c != '[' && c != ']' && c != '<' && c != '>') // Covers all other characters except brackets
                {
                    if (prev == ' ' && c == 'a' && !char.IsLetterOrDigit((char)reader.PeekChar())) // YES! YES!
                    {
                        anIndex = stream.Length + 1;
                        anFormat = currentFormat;
                    }
                    if (currentFormat == WordFormat.AllCaps || (currentFormat == WordFormat.Proper && !Char.IsLetterOrDigit(prev) && prev.PermitsCap()))
                    {
                        buffer = c.ToString().ToUpper();
                    }
                    else if (currentFormat == WordFormat.Capitalized)
                    {
                        buffer = c.ToString().ToUpper();
                        currentFormat = WordFormat.None;
                    }
                    else
                    {
                        buffer = c.ToString();
                    }
                }
                stream.Append(buffer);
                buffer = ""; // Fixes the word repitition bug when terminating Proper formatting in a pattern
            }
        }
Esempio n. 5
0
        private string TranslateDefs(string rawPattern, string lastMacro, string lastGlobal)
        {
            CharReader pp = new CharReader(rawPattern, 0);
            string pattern = "";
            if (rawPattern.Contains("=") || rawPattern.Contains("&"))
            {
                while (!pp.EndOfString)
                {
                    char d = pp.ReadChar();
                    if (d == '=')
                    {
                        if (pp.PeekChar() != '[')
                        {
                            Error("Missing '[' in macro call", pp);
                            return "";
                        }

                        pp.Position++; // Skip [
                        int endIndex = rawPattern.IndexOf(']', pp.Position);

                        if (endIndex == -1)
                        {
                            Error("Missing ']' in macro call", pp);
                            return "";
                        }

                        string macroName = pp.ReadString(endIndex - pp.Position);

                        if (macroName == "")
                        {
                            Error("Empty macro.", pp);
                            return "";
                        }
                        if (macroName.Contains("+"))
                        {
                            string[] macroParts = macroName.Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries);
                            if (macroParts.Length == 0)
                            {
                                Error("Empty macro.", pp);
                                return "";
                            }
                            for (int i = 0; i < macroParts.Length; i++)
                            {
                                string macroPart = macroParts[i].Trim();
                                if (!macroBank.ContainsKey(macroPart))
                                {
                                    Error("Macro \"" + macroPart + "\" doesn't exist.", pp);
                                    return "";
                                }
                                pattern += TranslateDefs(macroBank[macroPart], lastMacro, lastGlobal);
                            }
                        }
                        else
                        {
                            if (macroName == lastMacro)
                            {
                                Error("Macro error: Cannot create a macro that references itself. (" + macroName + ")", pp);
                                return "";
                            }
                            if (!macroBank.ContainsKey(macroName))
                            {
                                Error("Macro \"" + macroName + "\" doesn't exist.", pp);
                                return "";
                            }
                            pattern += TranslateDefs(macroBank[macroName], macroName, lastGlobal);
                        }
                        pp.Position++; // Skip ]
                    }
                    else if (d == '&') // Bracket check in case we hit a flag
                    {
                        if (pp.PeekChar() != '[')
                        {
                            Error("Missing '[' in global call", pp);
                            return "";
                        }
                        pp.Position++; // Skip [
                        int endIndex = rawPattern.IndexOf(']', pp.Position);

                        if (endIndex == -1)
                        {
                            Error("Missing ']' in global call", pp);
                            return "";
                        }

                        string globalName = pp.ReadString(endIndex - pp.Position);
                        if (globalName == lastGlobal)
                        {
                            Error("Global error: Cannot create a global that references itself. (" + globalName + ")", pp);
                            return "";
                        }
                        pp.Position++; // Skip ]
                        if (!globalValues.ContainsKey(globalName))
                        {
                            Error("Global \"" + globalName + "\" doesn't exist.", pp);
                            return "";
                        }
                        pattern += TranslateDefs(globalValues[globalName], lastMacro, globalName);
                    }
                    else
                    {
                        pattern += d;
                    }
                }
            }
            else
            {
                pattern = rawPattern;
            }
            return pattern;
        }
Esempio n. 6
0
        public void CanReadSimpleContentWhileCaching(int readAhead)
        {
            const string testString = "Hello world!";

            using var textReader = new StringReader(testString);
            using var charReader = new CharReader(textReader);


            Assert.That(charReader.PeekString(readAhead),
                        Is.EqualTo(testString.Substring(0, Math.Min(testString.Length, readAhead))));
            Assert.That(charReader.PeekChar(), Is.EqualTo('H'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('H'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('e'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('e'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('l'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('l'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('l'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('l'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('o'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('o'));
            Assert.That(charReader.PeekChar(), Is.EqualTo(' '));
            Assert.That(charReader.ReadChar(), Is.EqualTo(' '));
            Assert.That(charReader.PeekString(6), Is.EqualTo("world!"));
            Assert.That(charReader.PeekChar(), Is.EqualTo('w'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('w'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('o'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('o'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('r'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('r'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('l'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('l'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('d'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('d'));
            Assert.That(charReader.PeekChar(), Is.EqualTo('!'));
            Assert.That(charReader.ReadChar(), Is.EqualTo('!'));

            Assert.That(charReader.PeekChar(), Is.Null);
            Assert.That(charReader.ReadChar(), Is.Null);
        }