public BaseSnapObject MakeCopy() { var item = SnapObjectsInfo.GetInstanceByType(Type); item.Deserialize(Serialize(), 0); return(item); }
public static Snapshot UnpackDelta(Snapshot from, int[] inputData, int inputOffset, int inputSize) { var snapshotBuilder = new SnapshotBuilder(); var endIndex = inputOffset + inputSize; var numDeletedItems = inputData[inputOffset++]; var numUpdatedItems = inputData[inputOffset++]; var numTempItems = inputData[inputOffset++]; var deletedOffset = inputOffset; inputOffset += numDeletedItems; if (inputOffset > endIndex) { return(null); } snapshotBuilder.StartBuild(); for (var i = 0; i < from.ItemsCount; i++) { var item = from[i]; var keep = true; for (var d = 0; d < numDeletedItems; d++) { if (inputData[deletedOffset + d] == item.Key) { keep = false; break; } } if (keep) { snapshotBuilder.AddItem(item.Object.MakeCopy(), item.Id); } } for (var i = 0; i < numUpdatedItems; i++) { if (inputOffset + 2 > endIndex) { return(null); } var type = (SnapObject)inputData[inputOffset++]; var id = inputData[inputOffset++]; int itemSize; // in bytes if (SnapObjectsInfo.GetSizeByType(type) != 0) { itemSize = SnapObjectsInfo.GetSizeByType(type); } else { if (inputOffset + 1 > endIndex) { return(null); } itemSize = inputData[inputOffset++] * sizeof(int); } if (itemSize < 0 || !RangeCheck(endIndex, inputOffset, itemSize / sizeof(int))) { return(null); } var key = ((int)type << 16) | id; var newItem = snapshotBuilder.FindItem(key)?.Object; if (newItem == null) { var item = SnapObjectsInfo.GetInstanceByType(type); if (snapshotBuilder.AddItem(item, id)) { newItem = item; } } if (newItem == null) { return(null); } var fromItem = from.FindItem(key); if (fromItem != null) { UndiffItem(fromItem.Object, inputData, inputOffset, newItem); } else { newItem.Deserialize(inputData, inputOffset); } inputOffset += itemSize / sizeof(int); } return(snapshotBuilder.EndBuild()); }
public static int CreateDelta(Snapshot from, Snapshot to, int[] outputData) { var numDeletedItems = 0; var numUpdatedItems = 0; var numTempItems = 0; var outputOffset = 3; var hashItems = new HashItem[HASHLIST_SIZE]; for (var i = 0; i < hashItems.Length; i++) { hashItems[i] = new HashItem(); } GenerateHash(hashItems, to); // pack deleted stuff for (var i = 0; i < from.ItemsCount; i++) { var fromItem = from[i]; if (GetItemIndexHashed(fromItem.Key, hashItems) == -1) { // deleted numDeletedItems++; outputData[outputOffset++] = fromItem.Key; } } GenerateHash(hashItems, from); var pastIndecies = new int[SnapshotBuilder.MAX_SNAPSHOT_ITEMS]; // fetch previous indices // we do this as a separate pass because it helps the cache for (var i = 0; i < to.ItemsCount; i++) { pastIndecies[i] = GetItemIndexHashed(to[i].Key, hashItems); } for (var i = 0; i < to.ItemsCount; i++) { var currentItem = to[i]; var pastIndex = pastIndecies[i]; if (pastIndex != -1) { var pastItem = from[pastIndex]; var offset = outputOffset + 3; if (SnapObjectsInfo.GetSizeByType(currentItem.Type) != 0) { offset = outputOffset + 2; } if (DiffItem(pastItem.Object, currentItem.Object, outputData, offset) != 0) { outputData[outputOffset++] = (int)currentItem.Type; outputData[outputOffset++] = currentItem.Id; if (SnapObjectsInfo.GetSizeByType(currentItem.Type) == 0) { outputData[outputOffset++] = currentItem.Object.SerializeLength; } outputOffset += currentItem.Object.SerializeLength; // count item int fields numUpdatedItems++; } } else { outputData[outputOffset++] = (int)currentItem.Type; outputData[outputOffset++] = currentItem.Id; if (SnapObjectsInfo.GetSizeByType(currentItem.Type) == 0) { outputData[outputOffset++] = currentItem.Object.SerializeLength; } var data = currentItem.Object.Serialize(); Array.Copy(data, 0, outputData, outputOffset, data.Length); outputOffset += data.Length; numUpdatedItems++; } } if (numDeletedItems == 0 && numUpdatedItems == 0 && numTempItems == 0) { return(0); } outputData[0] = numDeletedItems; outputData[1] = numUpdatedItems; outputData[2] = numTempItems; return(outputOffset); }