// Take the concatenated set of redirect URL data, parse them, and populate the master list
            private static bool MergeRawDataIntoMasterList(byte[] rawChunkData, ref MasterList[] masterLists, int masterListsOffset)
            {
                uint index = 0;

                while (rawChunkData.Length > index)
                {
                    bool fIsAddChunk = false;
                    // Read chunk type (add or sub)
                    if ((('a' != rawChunkData[index]) && ('s' != rawChunkData[index])) ||
                        (':' != rawChunkData[index + 1]))
                    {
                        // Invalid file format
                        return false;
                    }

                    if ('a' == rawChunkData[index])
                    {
                        fIsAddChunk = true;
                    }

                    // Move the position marker past the "?:"
                    index += 2;

                    // Read chunk number
                    uint chunkNumber = 0;
                    if (false == GetUintFromString(rawChunkData, ref index, (byte)':', out chunkNumber))
                    {
                        // Invalid file format
                        return false;
                    }

                    // Pick the appropriate master list to put this data into (based on whether it's an add or sub chunk)
                    int masterListsIndex = masterListsOffset + ((true == fIsAddChunk) ? 0 : 1);

                    // Read size of hash prefix (not size of hash key)
                    uint cbHashPrefix = 0;
                    if (false == GetUintFromString(rawChunkData, ref index, (byte)':', out cbHashPrefix))
                    {
                        // Invalid file format
                        return false;
                    }

                    // Read size of chunk
                    uint cbChunk = 0;
                    if (false == GetUintFromString(rawChunkData, ref index, 0x0A, out cbChunk))
                    {
                        // Invalid file format
                        return false;
                    }

                    Chunk chunk = new Chunk();

                    // Iterate through chunk binary blob and read all hash keys
                    // Add hash keys to dictionary
                    uint endIndex = index + cbChunk;
                    for (; endIndex > index; )
                    {
                        // Read the host key
                        byte[] hostKey = new byte[4];
                        Buffer.BlockCopy(rawChunkData, (int)index, hostKey, 0, hostKey.Length);
                        index += (uint)hostKey.Length;

                        HostKeyData hostKeyData = new HostKeyData();
                        uint prefixCount = rawChunkData[index++];

                        // If it's a sub chunk and there are no prefixes, then get the add chunk reference
                        if ((false == fIsAddChunk) && (0 == prefixCount))
                        {
                            hostKeyData.addChunkReference = GetBigEndianUintFromByteArray(ref rawChunkData, ref index);
                        }
                        else
                        {
                            hostKeyData.addChunkReference = 0;
                            // Iterate through the count of hash key prefixes (and add chunk references, if this is a sub chunk)
                            for (int prefixIndex = 0; prefixCount > prefixIndex; prefixIndex++)
                            {
                                uint hashPrefixAddChunkReference = 0;
                                if (false == fIsAddChunk)
                                {
                                    hashPrefixAddChunkReference = GetBigEndianUintFromByteArray(ref rawChunkData, ref index);
                                }
                                // Read the hash prefix
                                byte[] hashPrefix = new byte[cbHashPrefix];
                                Buffer.BlockCopy(rawChunkData, (int)index, hashPrefix, 0, hashPrefix.Length);
                                index += (uint)hashPrefix.Length;

                                // Add/replace hash prefix entry to HostKeyData object
                                if (hostKeyData.e.ContainsKey(hashPrefix))
                                {
                                    hostKeyData.e.Remove(hashPrefix);
                                }
                                hostKeyData.e.Add(hashPrefix, hashPrefixAddChunkReference);
                            }
                        }

                        uint hostKeyNumber = GetLittleEndianUintFromByteArray(ref hostKey);

                        // Add/replace chunk entry to chunk object
                        if (chunk.e.ContainsKey(hostKeyNumber))
                        {
                            chunk.e.Remove(hostKeyNumber);
                        }
                        chunk.e.Add(hostKeyNumber, hostKeyData);
                    }

                    // Add/replace chunk dictionary to master chunk list
                    if (masterLists[masterListsIndex].e.ContainsKey(chunkNumber))
                    {
                        masterLists[masterListsIndex].e.Remove(chunkNumber);
                    }
                    masterLists[masterListsIndex].e.Add(chunkNumber, chunk);
                }

                return true;
            }
 // Reads the contents of this object to disk
 public void ReadFromDisk(BinaryReader br)
 {
     e.Clear();
     int count = br.ReadInt32();
     for (int index = 0; count > index; index++)
     {
         uint key = br.ReadUInt32();
         HostKeyData value = new HostKeyData();
         value.ReadFromDisk(br);
         e.Add(key, value);
     }
 }