/// <summary> /// Adds a key to the constant database. /// </summary> /// <param name="key">The key to add to the database.</param> /// <param name="data">The data associated with this key.</param> /// <exception cref="System.IO.IOException">If an error occurs adding the key /// to the database.</exception> public void Add(byte[] key, byte[] data) { /* Write out the key length. */ CdbUtils.WriteLittleEndianInt32(fileStream, key.Length); /* Write out the data length. */ CdbUtils.WriteLittleEndianInt32(fileStream, data.Length); /* Write out the key. */ fileStream.Write(key, 0, key.Length); /* Write out the data. */ fileStream.Write(data, 0, data.Length); /* Add the hash pointer to our list. */ int hash = CdbUtils.Hash(key); hashPointers.Add(new CdbHashPointer(hash, currentKeyPos)); /* Add this item to the count. */ tableCount[hash & 0xff]++; /* Update the file position pointer. */ PosPlus(8); PosPlus(key.Length); PosPlus(data.Length); }
/// <summary> /// Finalizes the constant database. /// </summary> /// <exception cref="System.IO.IOException">If an error occurs closing out the /// database.</exception> public void Finish() { if (fileStream == null) { return; } /* Find the start of each hash table. */ int curEntry = 0; for (int i = 0; i < 256; i++) { curEntry += tableCount[i]; tableStart[i] = curEntry; } /* Create a new hash pointer list in order by hash table. */ CdbHashPointer[] slotPointers = new CdbHashPointer[hashPointers.Count]; foreach (CdbHashPointer hp in hashPointers) { slotPointers[--tableStart[hp.HashValue & 0xff]] = hp; } /* Write out each of the hash tables, building the slot table in * the process. */ byte[] slotTable = new byte[2048]; for (int i = 0; i < 256; i++) { /* Get the length of the hashtable. */ int len = tableCount[i] * 2; /* Store the position of this table in the slot table. */ slotTable[(i * 8) + 0] = unchecked ((byte)(currentKeyPos & 0xff)); slotTable[(i * 8) + 1] = unchecked ((byte)(((int)((uint)currentKeyPos >> 8)) & 0xff)); slotTable[(i * 8) + 2] = unchecked ((byte)(((int)((uint)currentKeyPos >> 16)) & 0xff)); slotTable[(i * 8) + 3] = unchecked ((byte)(((int)((uint)currentKeyPos >> 24)) & 0xff)); slotTable[(i * 8) + 4 + 0] = unchecked ((byte)(len & 0xff)); slotTable[(i * 8) + 4 + 1] = unchecked ((byte)(((int)((uint)len >> 8)) & 0xff)); slotTable[(i * 8) + 4 + 2] = unchecked ((byte)(((int)((uint)len >> 16)) & 0xff)); slotTable[(i * 8) + 4 + 3] = unchecked ((byte)(((int)((uint)len >> 24)) & 0xff)); /* Build the hash table. */ int curSlotPointer = tableStart[i]; CdbHashPointer[] hashTable = new CdbHashPointer[len]; for (int u = 0; u < tableCount[i]; u++) { /* Get the hash pointer. */ CdbHashPointer hp = slotPointers[curSlotPointer++]; /* Locate a free space in the hash table. */ int @where = ((int)((uint)hp.HashValue >> 8)) % len; while (hashTable[@where] != null) { if (++@where == len) { @where = 0; } } /* Store the hash pointer. */ hashTable[@where] = hp; } /* Write out the hash table. */ for (int u = 0; u < len; u++) { CdbHashPointer hp = hashTable[u]; if (hp != null) { CdbUtils.WriteLittleEndianInt32(fileStream, hashTable[u].HashValue); CdbUtils.WriteLittleEndianInt32(fileStream, hashTable[u].EntryPos); } else { CdbUtils.WriteLittleEndianInt32(fileStream, 0); CdbUtils.WriteLittleEndianInt32(fileStream, 0); } PosPlus(8); } } /* Seek back to the beginning of the file and write out the * slot table. */ fileStream.Seek(0, SeekOrigin.Begin); fileStream.Write(slotTable, 0, slotTable.Length); /* Close the file. */ fileStream.Dispose(); fileStream = null; }