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);
                }
            }
        }
Exemple #3
0
        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);
        }