private void AppendToBack(RopeString ropeString, int fromIndex, int length) { if (length == 0) return; // First we search sector with lesser or equals first index to fromIndex int anotherStringSectorIndex = SearchSectorByGlobalIndex(ropeString, fromIndex); if (anotherStringSectorIndex == -1) throw new InvalidOperationException("fromIndex ouside of bounds"); // Cope from found sector from fromIndex to end to another new sector. var firstNewSector = new RopeSector(); var firstOldSector = ropeString._descriptors[anotherStringSectorIndex].Sector; var indexInsideFirstSector = fromIndex - ropeString._descriptors[anotherStringSectorIndex].FirstIndexInGlobal; // If index inside sector is zero --- just copy full sector. if (indexInsideFirstSector > 0) { while (indexInsideFirstSector < firstOldSector.Length && firstNewSector.Length < length) { firstNewSector.AppendToBack(firstOldSector[indexInsideFirstSector++]); } // Add new first sector to back of current string. _descriptors.Add( new RopeSectorDescriptor { FirstIndexInGlobal = Length, Sector = firstNewSector }); Length += firstNewSector.Length; ++anotherStringSectorIndex; } int lastIndex = fromIndex + length - 1; // First we search sector with lesser or equals first index to fromIndex int anotherStringSectorFinishIndex = SearchSectorByGlobalIndex(ropeString, lastIndex); if (anotherStringSectorFinishIndex == -1) throw new InvalidOperationException("fromIndex + length ouside of bounds"); // Batch add all next sectors to back of currect string. while (anotherStringSectorIndex < anotherStringSectorFinishIndex) { RopeSector sector = ropeString._descriptors[anotherStringSectorIndex++].Sector; _descriptors.Add( new RopeSectorDescriptor { FirstIndexInGlobal = Length, Sector = sector }); Length += sector.Length; } // Add last sector if needed. if (anotherStringSectorFinishIndex >= anotherStringSectorIndex && anotherStringSectorFinishIndex < ropeString._descriptors.Count && ropeString._descriptors[anotherStringSectorFinishIndex].FirstIndexInGlobal <= lastIndex) { var lastSector = ropeString._descriptors[anotherStringSectorFinishIndex].Sector; int countOfCopiedChars = lastIndex - ropeString._descriptors[anotherStringSectorFinishIndex].FirstIndexInGlobal + 1; var newSector = new RopeSector(); for (int indexInsideSector = 0; indexInsideSector < countOfCopiedChars; ++indexInsideSector) newSector.AppendToBack(lastSector[indexInsideSector]); _descriptors.Add(new RopeSectorDescriptor { FirstIndexInGlobal = Length, Sector = newSector }); Length += newSector.Length; } }
private static RopeString ConvertFromRegularString(string regularString) { var ropeString = new RopeString(); int currentIndex = 0; while (currentIndex < regularString.Length) { var sector = new RopeSector(); while (sector.Length < RopeSector.SectorSize && currentIndex < regularString.Length) { sector.AppendToBack(regularString[currentIndex++]); } ropeString.PushSectorToBack(sector); } return ropeString; }