/// <summary> /// Encrypts the <see cref="Data"/> according to the <see cref="Type"/> and <see cref="SubType"/>. /// </summary> public void WriteBlock(BinaryWriter bw) { var xk = new SCXorShift32(Key); bw.Write(Key); bw.Write((byte)((byte)Type ^ xk.Next())); if (Type == SCTypeCode.Object) { bw.Write((uint)Data.Length ^ xk.Next32()); } else if (Type == SCTypeCode.Array) { var entries = (uint)(Data.Length / SubType.GetTypeSize()); bw.Write(entries ^ xk.Next32()); bw.Write((byte)((byte)SubType ^ xk.Next())); } foreach (var b in Data) { bw.Write((byte)(b ^ xk.Next())); } }
/// <summary> /// Reads a new <see cref="SCBlock"/> object from the <see cref="data"/>, determining the <see cref="Type"/> and <see cref="SubType"/> during read. /// </summary> /// <param name="data">Decrypted data</param> /// <param name="offset">Offset the block is to be read from (modified to offset by the amount of bytes consumed).</param> /// <returns>New object containing all info for the block.</returns> public static SCBlock ReadFromOffset(byte[] data, ref int offset) { // Create block, parse its key. var key = BitConverter.ToUInt32(data, offset); offset += 4; var xk = new SCXorShift32(key); // Parse the block's type //var block = var type = (SCTypeCode)(data[offset++] ^ xk.Next()); switch (type) { case SCTypeCode.Bool1: case SCTypeCode.Bool2: case SCTypeCode.Bool3: // Block types are empty, and have no extra data. Debug.Assert(type != SCTypeCode.Bool3); // invalid type, haven't seen it used yet return(new SCBlock(key, type)); case SCTypeCode.Object: // Cast raw bytes to Object { var num_bytes = BitConverter.ToUInt32(data, offset) ^ xk.Next32(); offset += 4; var arr = new byte[num_bytes]; for (int i = 0; i < arr.Length; i++) { arr[i] = (byte)(data[offset++] ^ xk.Next()); } return(new SCBlock(key, type, arr)); } case SCTypeCode.Array: // Cast raw bytes to SubType[] { var num_entries = BitConverter.ToUInt32(data, offset) ^ xk.Next32(); offset += 4; var sub = (SCTypeCode)(data[offset++] ^ xk.Next()); var num_bytes = num_entries * sub.GetTypeSize(); var arr = new byte[num_bytes]; for (int i = 0; i < arr.Length; i++) { arr[i] = (byte)(data[offset++] ^ xk.Next()); } #if DEBUG Debug.Assert(sub > SCTypeCode.Array || Array.TrueForAll(arr, z => z <= 1)); #endif return(new SCBlock(key, arr, sub)); } default: // Single Value Storage { var num_bytes = type.GetTypeSize(); var arr = new byte[num_bytes]; for (int i = 0; i < arr.Length; i++) { arr[i] = (byte)(data[offset++] ^ xk.Next()); } return(new SCBlock(key, type, arr)); } } }