/// <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> /// Finds the next record stored under the given key. /// </summary> /// <param name="key"> The key to search for. </param> /// <returns> The next record store under the given key, or /// <code>null</code> if no record with that key could be found. </returns> public byte[] FindNext(byte[] key) { lock (this) { /* There are no keys if we could not read the slot table. */ if (slotTable == null) { return(null); } /* Locate the hash entry if we have not yet done so. */ if (numberOfHashSlotsSearched == 0) { /* Get the hash value for the key. */ int u = CdbUtils.Hash(key); /* Unpack the information for this record. */ int slot = u & 255; numberOfHashSlots = slotTable[(slot << 1) + 1]; if (numberOfHashSlots == 0) { return(null); } currentKeyHashTablePos = slotTable[slot << 1]; /* Store the hash value. */ currentKeyHashValue = u; /* Locate the slot containing this key. */ u = (int)((uint)u >> 8); u %= numberOfHashSlots; u <<= 3; currentKeyPos = currentKeyHashTablePos + u; } /* Search all of the hash slots for this key. */ try { while (numberOfHashSlotsSearched < numberOfHashSlots) { /* Read the entry for this key from the hash slot. */ fileStream.Seek(currentKeyPos, SeekOrigin.Begin); int h = fileStream.ReadByte() | (fileStream.ReadByte() << 8) | (fileStream.ReadByte() << 16) | (fileStream.ReadByte() << 24); int pos = fileStream.ReadByte() | (fileStream.ReadByte() << 8) | (fileStream.ReadByte() << 16) | (fileStream.ReadByte() << 24); if (pos == 0) { return(null); } /* Advance the loop count and key position. Wrap the * key position around to the beginning of the hash slot * if we are at the end of the table. */ numberOfHashSlotsSearched += 1; currentKeyPos += 8; if (currentKeyPos == (currentKeyHashTablePos + (numberOfHashSlots << 3))) { currentKeyPos = currentKeyHashTablePos; } /* Ignore this entry if the hash values do not match. */ if (h != currentKeyHashValue) { continue; } /* Get the length of the key and data in this hash slot * entry. */ fileStream.Seek(pos, SeekOrigin.Begin); int klen = fileStream.ReadByte() | (fileStream.ReadByte() << 8) | (fileStream.ReadByte() << 16) | (fileStream.ReadByte() << 24); if (klen != key.Length) { continue; } int dlen = fileStream.ReadByte() | (fileStream.ReadByte() << 8) | (fileStream.ReadByte() << 16) | (fileStream.ReadByte() << 24); /* Read the key stored in this entry and compare it to * the key we were given. */ bool match = true; byte[] k = new byte[klen]; fileStream.Read(k, 0, k.Length); for (int i = 0; i < k.Length; i++) { if (k[i] != key[i]) { match = false; break; } } /* No match; check the next slot. */ if (!match) { continue; } /* The keys match, return the data. */ byte[] d = new byte[dlen]; fileStream.Read(d, 0, d.Length); return(d); } } catch (IOException) { return(null); } /* No more data values for this key. */ return(null); } }