public static IEnumerable <MYDRecord> Records(MYDBinaryReader br) { foreach (byte[] record_data in MYDBlockReader.Blocks(br)) { yield return(ProcessRecord(record_data)); } }
private static MYDRecord ProcessRecord(byte[] record_data) { //DumpRecord(record_data); //return; using (MemoryStream ms = new MemoryStream(record_data)) { MYDBinaryReader br = new MYDBinaryReader(ms); { int NULLIES = 7; // Read the nullyinfo bits byte[] nulls_bytes = br.ReadBytes(NULLIES); string nulls = ""; for (int i = 0; i < NULLIES; ++i) { nulls = Convert.ToString(nulls_bytes[i], 2).PadLeft(8, '0') + nulls; } nulls = StringTools.Reverse(nulls); // Read the id int id = -1; if ((nulls_bytes[0] & 0x01) == 0x00) { byte[] id_bytes = br.ReadBytes(4); id = 1 * id_bytes[0] + 256 * id_bytes[1] + 256 * 256 * id_bytes[2] + 256 * 256 * 256 * id_bytes[3]; } // Read the reference type int reference_type = -1; if ((nulls_bytes[0] & 0x02) == 0x00) { byte[] reference_type_bytes = br.ReadBytes(2); reference_type = 1 * reference_type_bytes[0] + 256 * reference_type_bytes[1]; } // Read the varfields Dictionary <string, string> datas = new Dictionary <string, string>(); for (int field = 2; field < 54; ++field) { if (nulls[field] == '0') { byte[] data_length_bytes = br.ReadBytes(3); int data_length = 1 * data_length_bytes[0] + 256 * data_length_bytes[1] + 256 * 256 * data_length_bytes[2]; byte[] data_bytes = br.ReadBytes(data_length); string data = Encoding.ASCII.GetString(data_bytes); datas[EndnoteConstants.FIELD_NAMES[field]] = data; } } MYDRecord myd_record = new MYDRecord(); myd_record.id = id; myd_record.reference_type = reference_type; myd_record.fields = datas; return(myd_record); } } }
public static IEnumerable <byte[]> Blocks(MYDBinaryReader br) { while (br.Position < br.Length) { MYDBlock root_block = MYDBlock.Read(br); //root_block.DumpStats(); long post_block_processing_return_offset = br.Position; // Only follow blocks that are a 'starting block' if (!root_block.is_block_first) { continue; } // Concatenate all blocks byte[] record_data = new byte[root_block.rec_len]; { MYDBlock block = root_block; int record_data_i = 0; while (true) { Array.Copy(block.data, 0, record_data, record_data_i, block.data_len); record_data_i += block.data_len; if (block.is_block_last) { break; } if (0 == block.next_filepos) { throw new GenericException("Expecting a file offset if we have more blocks!"); } br.Seek(block.next_filepos); //Logging.Info("Appending additional data from block at {0}", block.next_filepos); block = MYDBlock.Read(br); //block.DumpStats("\t"); } if (record_data_i != root_block.rec_len) { throw new GenericException("Block building length {0} is different to expected length of {1}!", record_data_i, root_block.rec_len); } } br.Seek(post_block_processing_return_offset); yield return(record_data); } }
private static void DumpRecord(byte[] record_data) { using (MemoryStream ms = new MemoryStream(record_data)) { MYDBinaryReader br = new MYDBinaryReader(ms); { int NULLIES = 20; // Read the nullyinfo bits byte[] nulls_bytes = br.ReadBytes(NULLIES); string binary = ""; string hex = ""; string ascii = ""; for (int i = 0; i < NULLIES; ++i) { binary = binary + Convert.ToString(nulls_bytes[i], 2).PadLeft(8, '0') + " "; hex = hex + String.Format("{0:X2}", nulls_bytes[i]); ascii = ascii + ((nulls_bytes[i] < 32) ? "." : ASCIIEncoding.ASCII.GetString(nulls_bytes, i, 1)); } Logging.Info("{0} {1} {2}", ascii, hex, binary); } } }
internal static MYDBlock Read(MYDBinaryReader br) { MYDBlock block = new MYDBlock(); // Debugging purposes block.start_position = br.Position; // Start of header block.header = br.ReadByte(); block.rec_len = 0; block.data_len = 0; block.block_len = 0; block.next_filepos = 0; // See http://dev.mysql.com/doc/internals/en/layout-record-storage-frame.html // Or bottom of this code switch (block.header) { case 0: block.block_len = br.Read3(); block.block_len -= 4; // Deleted blocks include the header in their total length...sigh. block.is_block_deleted = true; break; case 1: block.rec_len = block.data_len = block.block_len = br.Read2(); block.is_block_first = block.is_block_last = true; break; case 2: block.rec_len = block.data_len = block.block_len = br.Read3(); block.is_block_first = block.is_block_last = true; break; case 13: block.rec_len = br.Read4(); block.data_len = block.block_len = br.Read3(); block.next_filepos = br.Read8(); block.is_block_first = true; break; case 3: block.rec_len = block.data_len = br.Read2(); block.block_len = block.rec_len + br.Read1(); block.is_block_first = block.is_block_last = true; break; case 4: block.rec_len = block.data_len = br.Read3(); block.block_len = block.rec_len + br.Read1(); block.is_block_first = block.is_block_last = true; break; case 5: block.rec_len = br.Read2(); block.data_len = block.block_len = br.Read2(); block.next_filepos = br.Read8(); block.is_block_first = true; break; case 6: block.rec_len = br.Read3(); block.data_len = block.block_len = br.Read3(); block.next_filepos = br.Read8(); block.is_block_first = true; break; case 7: block.data_len = block.block_len = br.Read2(); block.is_block_last = true; break; case 8: block.data_len = block.block_len = br.Read3(); block.is_block_last = true; break; case 9: block.data_len = br.Read2(); block.block_len = block.data_len + br.Read1(); block.is_block_last = true; break; case 10: block.data_len = br.Read3(); block.block_len = block.rec_len + br.Read1(); block.is_block_last = true; break; case 11: block.data_len = block.block_len = br.Read2(); block.next_filepos = br.Read8(); break; case 12: block.data_len = block.block_len = br.Read3(); block.next_filepos = br.Read8(); break; default: break; } block.data = br.ReadBytes(block.block_len); return(block); }