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); }
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); }
private IEnumerable <object[]> ReadAllRows() { var rows = new List <object[]>(); var rowNumber = 0; while (_reader.PeekChar() != null) { rows.Add(_rowReader.ReadOneRowEnumerable(rowNumber++)); } return(rows.ToArray()); }
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 } }
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; }
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); }