/// <summary> /// Destructively Copies the whole MarkupString Structure into the given MarkupString Object. /// </summary> /// <param name="newMarkupString">The MarkupString object to copy into.</param> /// <returns>The newMarkupString, now filled with this MarkupString's information.</returns> public MarkupString CopyInto(MarkupString newMarkupString) { if (this.IsString()) { newMarkupString.beneathList = null; newMarkupString.stringWeight = null; newMarkupString.MyMarkup = null; newMarkupString.bareString = new StringBuilder(); newMarkupString.bareString.Append(this.bareString); return(newMarkupString); } // Implied else. newMarkupString.beneathList = new List <MarkupString>(); newMarkupString.stringWeight = new List <int>(); newMarkupString.MyMarkup = new Markup(this.MyMarkup); foreach (MarkupString mySubMarkupString in this.beneathList) { newMarkupString.bareString = null; var thisOne = new MarkupString(); newMarkupString.beneathList.Add(mySubMarkupString.CopyInto(thisOne)); newMarkupString.stringWeight.Add(thisOne.Weight()); } return(newMarkupString); }
/// <summary> /// An edit function that replaces the position->range with a copy of the new MarkupString. /// </summary> /// <param name="newMarkupString">The new MarkupString to copy and insert into this structure.</param> /// <param name="position">The position where the edit begins, based on an insert position.</param> /// <param name="length">The length of string to 'replace' with this edit.</param> /// <returns>The MarkupString itself.</returns> public MarkupString Replace(MarkupString newMarkupString, int position, int length) { var replacement = new MarkupString(newMarkupString); Insert(replacement, position); Remove(position + replacement.Weight(), length); return(this); }
/// <summary> /// Initializes a new instance of the <see cref="FunctionResult" /> class, along with a copy of the MarkupString given. /// </summary> /// <param name="markupString">The MarkupString to insert into the Result.</param> public FunctionResult(MarkupString markupString = null) { if (markupString == null) { this.results.Add(new MarkupString(string.Empty)); return; } this.results.Add(new MarkupString(markupString)); }
/// <summary> /// This function returns the position of the MarkupString after concatenating two existing ones. /// <remarks>It is up to another function to link this result in properly.</remarks> /// </summary> /// <param name="left">MarkupString on the left.</param> /// <param name="right">MarkupString on the right.</param> /// <returns>A MarkupString that simply has concatenated the two MarkupStrings.</returns> public MarkupString Concat(MarkupString left, MarkupString right) { var newMarkupString = new MarkupString(); newMarkupString.beneathList.Add(left); newMarkupString.stringWeight.Add(left.Weight()); newMarkupString.beneathList.Add(right); newMarkupString.stringWeight.Add(right.Weight()); return(newMarkupString); }
/// <summary> /// Implementation of flattening the MarkupString. This assumes the wrapper has given us a mixed markup for the first /// step. /// </summary> /// <param name="markupStringList">A reference to a markupStringList to put the generated MarkupString instances into.</param> /// <param name="mup">The Markup of our parent to Markup.Mix()</param> private void FlattenInto(ref List <MarkupString> markupStringList, Markup mup) { if (!this.IsString()) { foreach (MarkupString each in this.beneathList) { each.FlattenInto(ref markupStringList, this.MyMarkup.Mix(mup)); } } else { var myMarkupParent = new MarkupString(mup); myMarkupParent.Insert(this.bareString.ToString(), 0); markupStringList.Add(myMarkupParent); } }
/// <summary> /// The work-horse for destructively copying a substring set of a MarkupString into the given MarkupString object. /// </summary> /// <param name="newMarkupString">The MarkupString object to copy into.</param> /// <param name="position">The zero-based starting character position in this instance.</param> /// <param name="length">The number of characters in the substring.</param> private void CopySubstringInto(MarkupString newMarkupString, int position, int length) { if (this.IsString()) { newMarkupString.MyMarkup = null; newMarkupString.beneathList = null; newMarkupString.stringWeight = null; newMarkupString.bareString = new StringBuilder(this.bareString.ToString().Substring(position, length)); } else { newMarkupString.MyMarkup = new Markup(this.MyMarkup); newMarkupString.beneathList = new List <MarkupString>(); newMarkupString.stringWeight = new List <int>(); newMarkupString.bareString = null; // We can't do this in parallel. Must be done in-order. foreach (MarkupString markupStringItem in this.beneathList) { // We're done if we have nothing else to add to the substring node. if (length <= 0) { break; } // If the weight is less than the position, or equal to, this is not where we want to copy from. // So reduce the relative-position and try again. if (markupStringItem.Weight() <= position) { position -= markupStringItem.Weight(); continue; } int maxCut = markupStringItem.Weight() - position; int curCut = maxCut < length ? maxCut : length; var thisOne = new MarkupString(); markupStringItem.CopySubstringInto(thisOne, position, curCut); newMarkupString.beneathList.Add(thisOne); newMarkupString.stringWeight.Add(thisOne.Weight()); length -= curCut; position = 0; } } }
/// <summary> /// Initializes a new instance of the <see cref="MarkupString" /> class, copied from the object given, based on /// position and length. This is also known as the Substring copy constructor. /// </summary> /// <param name="copyFrom">The MarkupString node to assumed to be root - and copy from.</param> /// <param name="position">What character position (0 based) to start the copy from.</param> /// <param name="length">How many characters to copy.</param> public MarkupString(MarkupString copyFrom, int position, int length) { copyFrom.CopySubstringInto(this, position, length); }
/// <summary> /// Initializes a new instance of the <see cref="MarkupString" /> class, copied from the object given. /// </summary> /// <param name="copyFrom">The MarkupString node to assumed to be root - and copy from.</param> public MarkupString(MarkupString copyFrom) { copyFrom.CopyInto(this); }
/// <summary> /// StringTest tests strings. To be converted into a UnitTest later. /// </summary> public static void StringTest() { Console.Read(); const MarkupRule hiLite = MarkupRule.HiLight; var hiLiteAsList = new HashSet <MarkupRule> { hiLite }; var testString1 = new MarkupString(new Markup(hiLiteAsList)); var testString2 = new MarkupString(); /* ---------------------------------- * Testing Ansi Insert and Remove * ---------------------------------- */ Console.WriteLine("Inserting DOOD into HiLite markup string 1 at position 0."); testString1.Insert("DOOD", 0); Console.WriteLine("Inserting Omnomnom into markup string 2 at position 0."); testString2.Insert("Omnomnom", 0); Console.WriteLine("Inserting markup string 1 into markup string 2 at position 4."); testString2.Insert(testString1, 4); Console.WriteLine("Printing markup string 2: "); Console.WriteLine(testString2.ToString()); Console.WriteLine("Removing 4 characters starting at position 3 from markup string 2."); testString2.Remove(3, 4); Console.WriteLine("Printing markup string 2: "); Console.WriteLine(testString2.ToString()); /* ---------------------------------- * Testing Ansi Flattening * ---------------------------------- */ Console.WriteLine("Ansi Flattening Tests"); var testString3 = new List <MarkupString>(); testString2.FlattenInto(ref testString3); Console.WriteLine("Flattening string 2 into string 3, and printing."); Console.WriteLine(testString2.ToString()); var sb2 = new StringBuilder(); foreach (MarkupString each in testString3) { sb2.Append(each.ToTestString()); } Console.WriteLine(sb2.ToString()); Console.WriteLine("\n\n\n"); Console.ReadLine(); Console.WriteLine("Creating string 4 from string 2 (" + testString2 + "), starting at position 2, length 4."); var testString4 = new MarkupString(testString2, 2, 4); Console.WriteLine(testString4.ToString()); Console.WriteLine("\nInserting 'Graaaa' into string 4 at position 2."); testString4.Insert("Graaaa", 2); Console.WriteLine("Printing test string 4"); Console.WriteLine(testString4); Console.WriteLine("Replacing string 4 at position 3 for length 4 with 'IttyBittyKittyCommitty'"); testString4.Replace(new MarkupString("IttyBittyKittyCommitty"), 3, 4); Console.WriteLine("Printing test string 4"); Console.WriteLine(testString4); Console.WriteLine("Replacing string 4 at position 4 for length 2 with string 2 (" + testString2 + ")"); testString4.Replace(testString2, 4, 2); Console.WriteLine("Printing test string 4"); Console.WriteLine(testString4); Console.ReadLine(); }
/// <summary> /// Appends a MarkupString to the end of this instance of MarkupString. /// </summary> /// <param name="markupStringArg">The MarkupString being added to this instance.</param> /// <returns>The MarkupString itself.</returns> public MarkupString Append(MarkupString markupStringArg) { beneathList.Add(markupStringArg); stringWeight.Add(markupStringArg.Weight()); return(this); }
/// <summary> /// The InsertString will put markupStringArg into the position in the MarkupString structure. /// To do this, it may split up a string beneath it. After all, the node is expected to be Marked Up. /// </summary> /// <param name="markupStringArg">The MarkupString to insert. Please make sure to give it a Copy!</param> /// <param name="position">The position into which to insert. See remarks for insertion logic.</param> /// <returns>The MarkupString itself.</returns> public MarkupString Insert(MarkupString markupStringArg, int position) { if (IsString()) { beneathList = new List <MarkupString>(); stringWeight = new List <int>(); MyMarkup = new Markup(); // Blank Markup Transition var rightside = bareString.ToString().Substring(position); var leftside = bareString.ToString().Substring(0, bareString.Length - rightside.Length); beneathList.Add(new MarkupString(leftside)); beneathList.Add(new MarkupString(markupStringArg)); beneathList.Add(new MarkupString(rightside)); bareString = null; stringWeight.Add(beneathList[0].Weight()); stringWeight.Add(beneathList[1].Weight()); stringWeight.Add(beneathList[2].Weight()); } else { var targetPosition = position; // We need to find the way this string is now 'split', and leave the 'remainder' up to another call of InsertString. var passedWeights = stringWeight.TakeWhile(val => (targetPosition -= val) >= 0).Count(); /* Warning: here, a position of 3 generates a targetPosition of -5 after noticing a weight 8. The position it needs to * go into is 3. But had it passed over a weight of 2, the targetposition would be '1' for the /next/ unit. Which is correct. * * But if that had a weight of 4, it'd end up being 1-4 = -3. We need to re-add the last step, on which the evaluation failed. */ if (targetPosition == 0) { // We must place it 'between', at the beginning, or at the 'end' of a beneathList. // We know how many elements in we should be... so: // If count is at 0, it's an insert. // If count is equal to stringWeight.Count, append at end. // Otherwise, pass the new targetPosition to insert into the String. beneathList.Insert(passedWeights, markupStringArg); stringWeight.Insert(passedWeights, markupStringArg.Weight()); } else { // This is the adjustment for the 'last step reduction' error. targetPosition += stringWeight[passedWeights]; beneathList[passedWeights].Insert(markupStringArg, targetPosition); stringWeight[passedWeights] += markupStringArg.Weight(); if (!beneathList[passedWeights].MyMarkup.IsOnlyInherit()) { return(this); } // If the below is now an empty (OnlyInherit) Markup, we can 'pull it up'. // That is to say, we can put its individual beneathLists in the position where we had our old one. // If the item below is not an empty (OnlyInherit) Markup, then it wasn't the item below that we did // the final insert into. var reference = beneathList[passedWeights]; beneathList.RemoveAt(passedWeights); stringWeight.RemoveAt(passedWeights); beneathList.InsertRange(passedWeights, reference.beneathList); stringWeight.InsertRange(passedWeights, reference.stringWeight); } } return(this); }