private int MergeWithRight(int index, T value) { // E.g. [1 1][2 2 2][1] into [1 1][2 2][9][1] if (index + 1 >= List.Count || List[index + 1].Value.CompareTo(value) != 0) { List[index] = new RLEDataPair <T>(List[index].Key - 1, List[index].Value); // --List[index].Key; List.Insert(index + 1, new RLEDataPair <T>(1, value)); return(index + 1); } else // E.g. [1 1][2 2 2][1] into [1 1][2 2][1 1] { List[index] = new RLEDataPair <T>(List[index].Key - 1, List[index].Value); // --List[index].Key; if (List[index].Key == 0) { // [1 1][2][3 3] into [1 1][3 3 3] List.RemoveAt(index); --index; } // This following can happen if run has a length of one // and merge with left and right needs to be done else if (List[index].Value.CompareTo(List[index + 1].Value) == 0) { // [2 2][1][1 1] into [2 2][1 1 1] List[index + 1] = new RLEDataPair <T>(List[index + 1].Key + List[index].Key + 1, List[index + 1].Value); // List[index + 1].Key += List[index].Key + 1; List.RemoveAt(index); return(index); } List[index] = new RLEDataPair <T>(List[index].Key + 1, List[index].Value); // ++List[index].Key; return(index + 1); } }
public void Assign(List <RLEDataPair <T> > arr) { m_decompressedLength = 0; for (int i = 0; i < arr.Count; i++) { RLEDataPair <T> t = arr[i]; m_decompressedLength += t.Key; } List = arr; }
public void Assign(RLEDataPair <T>[] arr) { m_decompressedLength = 0; for (int i = 0; i < arr.Length; i++) { RLEDataPair <T> t = arr[i]; m_decompressedLength += t.Key; } List = new List <RLEDataPair <T> >(arr); }
public void SetDataOnIndex(int index, T value) { int sum = 0; for (int i = 0; i < List.Count; i++) { sum += List[i].Key; if (sum <= index) { continue; } // Do nothing if we are trying to set the same value // This further simplifies logic behind merging adjacent runs // because we now know that the position on index is going to // contain different data if (List[i].Value.CompareTo(value) == 0) { return; } var maxPosWithinRun = List[i].Key - 1; var posWithinRun = index - (sum - List[i].Key); // If we are at run's edge let's merge adjacent runs if possible if (List[i].Key == 1) { var newIndex = MergeWithLeft(i, value); MergeWithRight(newIndex, value); } else if (posWithinRun == 0) { MergeWithLeft(i, value); } else if (posWithinRun == maxPosWithinRun) { MergeWithRight(i, value); } else // Nothing to merge. Split the old run and place a new one in the middle { var tmpCnt = List[i].Key; List[i] = new RLEDataPair <T>(posWithinRun, List[i].Value); List.Insert(i + 1, new RLEDataPair <T>(1, value)); List.Insert(i + 2, new RLEDataPair <T>(tmpCnt - List[i].Key - 1, List[i].Value)); } return; } }
public void Decompress(ref T[] outData) { int offset = 0; for (int i = 0; i < List.Count; i++) { RLEDataPair <T> pair = List[i]; for (int j = 0; j < pair.Key; j++) { outData[offset + j] = pair.Value; } offset += pair.Key; } }
public T[] Decompress() { T[] data = new T[m_decompressedLength]; // 2nd pass - decompress data int offset = 0; for (int i = 0; i < List.Count; i++) { RLEDataPair <T> pair = List[i]; for (int j = 0; j < pair.Key; j++) { data[offset + j] = pair.Value; } offset += pair.Key; } return(data); }