public static short AddVariableSizeItem(IPage page, byte[] itemContent) { ushort freeSpace = GetFreeSpace(page); var itemLength = itemContent.Length; if (freeSpace < itemLength) { return(-1); } short headerLength = BitConverter.ToInt16(page.Content, OnPageOffsets.HeaderLength); var lengthMarkers = ReadMarkers(page, headerLength); int offset = 0; for (short i = 0; i < lengthMarkers.Length; i++) { offset += Math.Abs(lengthMarkers[i]); if (lengthMarkers[i] <= 0) { // we have an empty slot if (itemLength == -lengthMarkers[i]) { // simple case: a new item has exactly the same size as deleted one, rewrite it RewriteVariableSizeItem(page, itemContent, headerLength, i, offset, freeSpace); } else { PlaceItemToSlot(page, headerLength, itemContent, lengthMarkers, i); } return(i); } } // here we need two extra bytes if (freeSpace < itemLength + OnPagePointerSize) { return(-1); } // write length of the marker array var markersLengthBytes = BitConverter.GetBytes((short)(lengthMarkers.Length + 1)); markersLengthBytes.CopyTo(page.Content, headerLength); // write new length marker var newMarkerBytes = BitConverter.GetBytes((short)itemContent.Length); newMarkerBytes.CopyTo(page.Content, headerLength + OnPagePointerSize * (lengthMarkers.Length + 1)); // write item itself Buffer.BlockCopy(itemContent, 0, page.Content, page.Content.Length - offset - itemLength, itemLength); // write free space RadixTreeNodesPageHeader.WriteFreeSpace(page, (ushort)(freeSpace - itemLength - OnPagePointerSize)); return((short)lengthMarkers.Length); }
private static void WriteFreeSpace(IPage page, ushort freeSpace) { RadixTreeNodesPageHeader.WriteFreeSpace(page, freeSpace); }