Exemplo n.º 1
0
        private HashTableEntry BinarySearch(int key)
        {
            int            start        = 0;
            int            end          = _count - 1;
            HashTableEntry currentEntry = null;

            while (start != end)
            {
                int middle = (start + end) / 2;
                currentEntry = _entries[middle];
                var testKey = currentEntry.key;
                if (testKey == key)
                {
                    return(currentEntry);
                }
                if (testKey > key)
                {
                    // search in interval [start;middle-1]
                    end = middle - 1;
                }
                else
                {
                    // search in interval [middle+1,_count-1)
                    start = middle + 1;
                }
            }
            currentEntry = _entries[start];
            return(currentEntry.key == key ? currentEntry : null);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Gets the file info of the provided path.
        /// </summary>
        /// <returns>The file info, or null if the file doesn't exist in the archive.</returns>
        /// <param name="filePath">File path.</param>
        public MPQFileInfo GetFileInfo(string filePath)
        {
            if (this.IsDisposed)
            {
                throw new ObjectDisposedException(ToString(), "Cannot use a disposed archive.");
            }

            if (ContainsFile(filePath))
            {
                HashTableEntry  hashEntry  = this.ArchiveHashTable.FindEntry(filePath);
                BlockTableEntry blockEntry = this.ArchiveBlockTable.GetEntry((int)hashEntry.GetBlockEntryIndex());

                if (HasFileAttributes())
                {
                    return(new MPQFileInfo(filePath, hashEntry, blockEntry));
                }
                else
                {
                    return(new MPQFileInfo(filePath, hashEntry, blockEntry, this.FileAttributes.FileAttributes[(int)hashEntry.GetBlockEntryIndex()]));
                }
            }
            else
            {
                return(null);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Adds value for the provided key; if key already exists, updates value.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Add(K key, T value)
        {
            var index     = GetIndex(key);
            var entryList = table[index];
            var entry     = new HashTableEntry <K, T>
            {
                Key   = key,
                Value = value
            };

            if (entryList == null || entryList.IsEmpty)
            {
                var list = new LinkedList <HashTableEntry <K, T> >();
                list.PushFront(entry);
                table[index] = list;
            }
            else
            {
                var list = table[index];
                for (int i = 0; i < list.Length; i++)
                {
                    var element = list.ElementAt(i);
                    if (element.Key.Equals(key))
                    {
                        list.Set(i, entry);
                        return;
                    }
                }

                list.PushFront(entry);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Expands the capacity of the keys and values arrays.
        /// </summary>
        private void _expandCapacity(int minCapacity)
        {
            if (_hashTableStore.Length < minCapacity)
            {
                int newCapacity = (_hashTableStore.Length == 0 ? _defaultCapacity : _getExpandPrime(_hashTableStore.Length * 2));

                if (newCapacity >= MAX_PRIME_ARRAY_LENGTH)
                {
                    newCapacity = MAX_PRIME_ARRAY_LENGTH;
                }

                // Try to expand the size
                try
                {
                    HashTableEntry <TKey, TValue>[] newKeysMap = new HashTableEntry <TKey, TValue> [newCapacity];

                    if (_size > 0)
                    {
                        // REHASH
                    }

                    _hashTableStore = newKeysMap;
                }
                catch (OutOfMemoryException)
                {
                    throw;
                }
            }
        }
Exemplo n.º 5
0
        public void RemoveHandler(int key, Delegate handler)
        {
            HashTableEntry e = null;

            e = BinarySearch(key);
            if (e != null)
            {
                e.handler = Delegate.Remove(e.handler, handler);
            }
        }
Exemplo n.º 6
0
 public MPQFileInfo
 (
     [NotNull] string inPath,
     [NotNull] HashTableEntry inHashEntry,
     [NotNull] BlockTableEntry inBlockEntry
 )
 {
     Path       = inPath;
     HashEntry  = inHashEntry;
     BlockEntry = inBlockEntry;
 }
Exemplo n.º 7
0
 public MPQFileInfo
 (
     [NotNull] string inPath,
     [NotNull] HashTableEntry inHashEntry,
     [NotNull] BlockTableEntry inBlockEntry,
     [NotNull] FileAttributes inAttributes
 )
     : this(inPath, inHashEntry, inBlockEntry)
 {
     Attributes = inAttributes;
 }
Exemplo n.º 8
0
        /// <summary>
        /// Checks if the specified file path exists in the archive.
        /// </summary>
        /// <returns><c>true</c>, if the file exists, <c>false</c> otherwise.</returns>
        /// <param name="filePath">File path.</param>
        public bool ContainsFile(string filePath)
        {
            if (this.IsDisposed)
            {
                throw new ObjectDisposedException(ToString(), "Cannot use a disposed archive.");
            }

            HashTableEntry fileHashEntry = this.ArchiveHashTable.FindEntry(filePath.ToUpperInvariant());

            return(fileHashEntry != null);
        }
Exemplo n.º 9
0
 private void InsertDelegate(int key, int afterPosition, Delegate handler)
 {
     if ((_count + 1) == _entries.Length)
     {
         Array.Resize(ref _entries, _entries.Length * 2);
     }
     for (int i = _count - 1; i > afterPosition; i--)
     {
         _entries[i + 1] = _entries[i];
     }
     _entries[afterPosition + 1] = new HashTableEntry(key, handler);
 }
Exemplo n.º 10
0
        /// <summary>
        /// Fast initialize
        /// </summary>
        /// <param name="keys"></param>
        /// <param name="handlers"></param>
        internal void Initialize(int[] keys, Delegate[] handlers)
        {
            HashTableEntry[] table = new HashTableEntry[keys.Length];
            for (int i = 0; i < keys.Length; i++)
            {
                table[i] = new HashTableEntry(keys[i], handlers[i]);
            }
            Array.Sort(table, (x, y) => x.key.CompareTo(y.key));

            _entries = table;
            _count   = _entries.Length;
        }
Exemplo n.º 11
0
        /// <summary>
        /// Removes the given key from the hash table.
        /// </summary>
        /// <param name="key"></param>
        public void Remove(K key)
        {
            var index = GetIndex(key);
            var list  = table[index];
            var entry = new HashTableEntry <K, T> {
                Key = key
            };

            if (list == null || list.IsEmpty)
            {
                return;
            }

            list.Remove(entry);
        }
Exemplo n.º 12
0
        public void AddHandler(int key, Delegate handler)
        {
            HashTableEntry e = null;
            int            nearest;

            e = BinarySearch(key, out nearest);
            if (e != null)
            {
                e.handler = Delegate.Combine(e.handler, handler);
            }
            else
            {
                InsertDelegate(key, nearest, handler);
            }
        }
Exemplo n.º 13
0
        public void Add(object key, object value)
        {
            HashTableEntry hashTableEntry = new HashTableEntry();

            int index = Index(key);

            if (Contains(key))
            {
                throw new Exception("Key already exists in the hash table");
            }

            hashTableEntry.Key   = key;
            hashTableEntry.Value = value;

            _tableEntries[index] = hashTableEntry;

            _size++;
        }
Exemplo n.º 14
0
        /// <inheritdoc />
        /// <exception cref="ObjectDisposedException">Thrown if the archive has been disposed.</exception>
        /// <exception cref="FileNotFoundException">Thrown if the archive does not contain a file at the given path.</exception>
        public MPQFileInfo GetFileInfo(string filePath)
        {
            ThrowIfDisposed();

            if (!ContainsFile(filePath))
            {
                throw new FileNotFoundException("The given file was not present in the archive.", filePath);
            }

            HashTableEntry  hashEntry  = ArchiveHashTable.FindEntry(filePath);
            BlockTableEntry blockEntry = ArchiveBlockTable.GetEntry((int)hashEntry.GetBlockEntryIndex());

            if (HasFileAttributes())
            {
                return(new MPQFileInfo(filePath, hashEntry, blockEntry));
            }

            return(new MPQFileInfo(filePath, hashEntry, blockEntry, FileAttributes.FileAttributes[(int)hashEntry.GetBlockEntryIndex()]));
        }
Exemplo n.º 15
0
        /// <summary>
        /// Add an item into the hash table
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Add(K key, V value)
        {
            if (key == null)
            {
                throw new ArgumentNullException("Null key");
            }

            //Next pointer is null by default. No need to set
            var newEntry = new HashTableEntry(key, value);
            var hash     = key.GetHashCode();

            //Resize making the max this current hash
            if (hash >= currentBucketSize)
            {
                currentBucketSize = hash + 1;
                Array.Resize <HashTableEntry>(ref bucketsArray, currentBucketSize);
            }


            var firstItem = bucketsArray[hash];

            //First check if this bucket is empty
            if (firstItem == null)
            {
                //Make it the first item in the chain
                bucketsArray[hash] = newEntry;
            }
            //There are other items in the chain. Add it to the end
            else
            {
                var curr = firstItem;

                //Keep going until we hit the end of the list
                while (curr.nextEntry != null)
                {
                    curr = curr.nextEntry;
                }

                //Make the current guy point to the new entry we are adding
                curr.nextEntry = newEntry;
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Contracts the capacity of the keys and values arrays.
        /// </summary>
        private void _contractCapacity()
        {
            // Only contract the array if the number of elements is less than 1/3 of the total array size.
            int oneThird = (_hashTableStore.Length / 3);

            if (_size <= oneThird)
            {
                int newCapacity = (_hashTableStore.Length == 0 ? _defaultCapacity : _getContractPrime(_hashTableStore.Length));

                // Try to expand the size
                HashTableEntry <TKey, TValue>[] newKeysMap = new HashTableEntry <TKey, TValue> [newCapacity];

                if (_size > 0)
                {
                    // REHASH
                }

                _hashTableStore = newKeysMap;
            }
        }
        private void Resize(int newSize, bool ForceNewHashCodes)
        {
            if (newSize < this.entries.Length)
            {
                throw new ArgumentOutOfRangeException();
            }

            int[] newBuckets = new int[newSize];
            for (int i = 0; i < newBuckets.Length; i++)
            {
                newBuckets[i] = -1;
            }

            HashTableEntry[] newEntries = new HashTableEntry[newSize];
            Array.Copy(this.entries, 0, newEntries, 0, this.count);
            if (ForceNewHashCodes)
            {
                for (int i = 0; i < this.count; i++)
                {
                    if (newEntries[i].HashCode != -1)
                    {
                        newEntries[i].HashCode = ReHash(newEntries[i].Key.GetHashCode()) & 0x7FFFFFFF;
                    }
                }
            }

            for (int i = 0; i < this.count; i++)
            {
                if (newEntries[i].HashCode >= 0)
                {
                    int bucket = newEntries[i].HashCode % newSize;
                    newEntries[i].Next = newBuckets[bucket];
                    newBuckets[bucket] = i;
                }
            }

            this.buckets = newBuckets;
            this.entries = newEntries;
        }
Exemplo n.º 18
0
 public Delegate this[int key]
 {
     get
     {
         HashTableEntry e = null;
         e = BinarySearch(key);
         return(e != null ? e.handler : null);
     }
     set
     {
         HashTableEntry e = null;
         int            nearest;
         e = BinarySearch(key, out nearest);
         if (e != null)
         {
             e.handler = value;
         }
         else
         {
             InsertDelegate(key, nearest, value);
         }
     }
 }
Exemplo n.º 19
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Warcraft.MPQ.FileInfo.MPQFileInfo"/> class.
 /// </summary>
 /// <param name="InPath">In path.</param>
 /// <param name="InHashEntry">In hash entry.</param>
 /// <param name="InBlockEntry">In block entry.</param>
 public MPQFileInfo(string InPath, HashTableEntry InHashEntry, BlockTableEntry InBlockEntry)
 {
     this.Path       = InPath;
     this.HashEntry  = InHashEntry;
     this.BlockEntry = InBlockEntry;
 }
Exemplo n.º 20
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Warcraft.MPQ.FileInfo.MPQFileInfo"/> class.
 /// </summary>
 /// <param name="InPath">In path.</param>
 /// <param name="InHashEntry">In hash entry.</param>
 /// <param name="InBlockEntry">In block entry.</param>
 /// <param name="InAttributes">In attributes.</param>
 public MPQFileInfo(string InPath, HashTableEntry InHashEntry, BlockTableEntry InBlockEntry, FileAttributes InAttributes)
     : this(InPath, InHashEntry, InBlockEntry)
 {
     this.Attributes = InAttributes;
 }
Exemplo n.º 21
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Warcraft.MPQ.FileInfo.MPQFileInfo"/> class.
 /// </summary>
 /// <param name="inPath">In path.</param>
 /// <param name="inHashEntry">In hash entry.</param>
 /// <param name="inBlockEntry">In block entry.</param>
 /// <param name="inAttributes">In attributes.</param>
 public MPQFileInfo(string inPath, HashTableEntry inHashEntry, BlockTableEntry inBlockEntry, FileAttributes inAttributes)
     : this(inPath, inHashEntry, inBlockEntry)
 {
     this.Attributes = inAttributes;
 }
Exemplo n.º 22
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Warcraft.MPQ.FileInfo.MPQFileInfo"/> class.
 /// </summary>
 /// <param name="inPath">In path.</param>
 /// <param name="inHashEntry">In hash entry.</param>
 /// <param name="inBlockEntry">In block entry.</param>
 public MPQFileInfo(string inPath, HashTableEntry inHashEntry, BlockTableEntry inBlockEntry)
 {
     this.Path       = inPath;
     this.HashEntry  = inHashEntry;
     this.BlockEntry = inBlockEntry;
 }
Exemplo n.º 23
0
 private void InsertDelegate( int key, int afterPosition, Delegate handler )
 {
     if ( ( _count + 1 ) == _entries.Length )
     {
         Array.Resize( ref _entries, _entries.Length*2 );
     }
     for ( int i = _count - 1; i > afterPosition; i-- )
     {
         _entries[ i + 1 ] = _entries[ i ];
     }
     _entries[afterPosition + 1] = new HashTableEntry(key, handler);
 }
Exemplo n.º 24
0
        /// <summary>
        /// Fast initialize
        /// </summary>
        /// <param name="keys"></param>
        /// <param name="handlers"></param>
        internal void Initialize( int[] keys, Delegate[] handlers )
        {
            HashTableEntry[] table = new HashTableEntry[keys.Length];
            for ( int i = 0; i < keys.Length; i++ )
            {
                table[ i ] = new HashTableEntry( keys[ i ], handlers[ i ] );
            }
            Array.Sort( table, ( x, y ) => x.key.CompareTo( y.key ) );

            _entries = table;
            _count = _entries.Length;
        }
Exemplo n.º 25
0
 /// <summary>
 /// Gets the size of the full hash table.
 /// </summary>
 /// <returns>The hash table size.</returns>
 public ulong GetHashTableSize()
 {
     return((ulong)(HashTableEntryCount * HashTableEntry.GetSize()));
 }
Exemplo n.º 26
0
        // TODO: Filter files based on language and platform
        /// <summary>
        /// Extract the file at <paramref name="filePath"/> from the archive.
        /// </summary>
        /// <returns>The file as a byte array, or null if the file could not be found.</returns>
        /// <param name="filePath">Path to the file in the archive.</param>
        public byte[] ExtractFile(string filePath)
        {
            if (this.IsDisposed)
            {
                throw new ObjectDisposedException(ToString(), "Cannot use a disposed archive.");
            }

            // Reset all positions to be safe
            this.ArchiveReader.BaseStream.Position = 0;

            HashTableEntry fileHashEntry = this.ArchiveHashTable.FindEntry(filePath);

            if (fileHashEntry == null)
            {
                return(null);
            }

            BlockTableEntry fileBlockEntry = this.ArchiveBlockTable.GetEntry((int)fileHashEntry.GetBlockEntryIndex());

            // Drop out if the file is not actually a file
            if (!fileBlockEntry.HasData())
            {
                return(null);
            }

            // Seek to the beginning of the file's sectors
            long adjustedBlockOffset;

            if (this.Header.GetFormat() >= MPQFormat.ExtendedV1 && RequiresExtendedFormat())
            {
                ushort upperOffsetBits = this.ExtendedBlockTable[(int)fileHashEntry.GetBlockEntryIndex()];
                adjustedBlockOffset = (long)fileBlockEntry.GetExtendedBlockOffset(upperOffsetBits);
            }
            else
            {
                adjustedBlockOffset = fileBlockEntry.GetBlockOffset();
            }
            this.ArchiveReader.BaseStream.Position = adjustedBlockOffset;

            // Calculate the decryption key if neccesary
            uint fileKey = MPQCrypt.CreateFileEncryptionKey
                           (
                filePath,
                fileBlockEntry.ShouldEncryptionKeyBeAdjusted(),
                adjustedBlockOffset,
                fileBlockEntry.GetFileSize()
                           );

            // Examine the file storage types and extract as neccesary
            if (fileBlockEntry.IsSingleUnit())
            {
                return(ExtractSingleUnitFile(fileBlockEntry, fileKey));
            }

            if (fileBlockEntry.IsCompressed())
            {
                return(ExtractCompressedSectoredFile(fileBlockEntry, fileKey, adjustedBlockOffset));
            }

            return(ExtractUncompressedSectoredFile(fileBlockEntry, fileKey));
        }
Exemplo n.º 27
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Warcraft.MPQ.FileInfo.MPQFileInfo"/> class.
 /// </summary>
 /// <param name="inPath">In path.</param>
 /// <param name="inHashEntry">In hash entry.</param>
 /// <param name="inBlockEntry">In block entry.</param>
 public MPQFileInfo(string inPath, HashTableEntry inHashEntry, BlockTableEntry inBlockEntry)
 {
     Path       = inPath;
     HashEntry  = inHashEntry;
     BlockEntry = inBlockEntry;
 }