jvm/c/hash_table.c
2024-12-23 14:41:20 -06:00

269 lines
8.5 KiB
C

#include <stdint.h>
static uint32_t fnv_1(const uint8_t * buf, int length)
{
const uint32_t fnv_offset_basis = 0x811c9dc5;
const uint32_t fnv_prime = 0x01000193;
uint32_t hash = fnv_offset_basis;
for (int i = 0; i < length; i++) {
hash = hash * fnv_prime;
hash = hash ^ buf[i];
}
return hash;
}
struct hash_table_entry {
const uint8_t * key;
int key_length;
void * value;
struct hash_table_entry * next;
};
void hash_table_init(int hash_table_length,
struct hash_table_entry * entry,
struct hash_table_entry * overflow)
{
for (int i = 0; i < hash_table_length; i++) {
entry[i].key = nullptr;
entry[i].next = nullptr;
overflow[i].key = nullptr;
overflow[i].next = nullptr;
}
}
static int max = 0;
void hash_table_add(int hash_table_length,
struct hash_table_entry * entry,
struct hash_table_entry * overflow,
int * overflow_length,
const uint8_t * key,
int key_length,
void * value)
{
uint32_t hash = fnv_1(key, key_length) & (hash_table_length - 1);
struct hash_table_entry * e = &entry[hash];
while (e->next != nullptr) {
e = e->next;
}
int i = 0;
if (e->key != nullptr) {
if ((++i) > max) max = i;
// allocate e from overflow
e->next = &overflow[(*overflow_length)++];
e = e->next;
}
e->key = key;
e->key_length = key_length;
e->value = value;
}
static inline bool key_equal(const uint8_t * a, const uint8_t * b, int length)
{
for (int i = 0; i < length; i++) {
if (a[i] != b[i])
return false;
}
return true;
}
#include <stdio.h>
struct hash_table_entry * hash_table_find(int hash_table_length,
struct hash_table_entry * entry,
struct hash_table_entry * overflow,
const uint8_t * key,
int key_length)
{
uint32_t hash = fnv_1(key, key_length) & (hash_table_length - 1);
struct hash_table_entry * e = &entry[hash];
while (e->key != nullptr) {
if (e->key_length == key_length && key_equal(e->key, key, key_length)) {
return e;
}
printf("collision %s %s\n", (char *)e->key, (char *)key);
e = e->next;
}
return nullptr;
}
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <assert.h>
static const char * names[] = {
"java/beans/Introspector.java",
"java/beans/PropertyDescriptor.java",
"java/beans/PropertyVetoException.java",
"java/beans/BeanInfo.java",
"java/beans/Customizer.java",
"java/beans/FeatureDescriptor.java",
"java/beans/BeanDescriptor.java",
"java/beans/Beans.java",
"java/beans/AppletInitializer.java",
"java/beans/Expression.java",
"java/beans/MethodDescriptor.java",
"java/beans/PropertyChangeSupport.java",
"java/beans/PropertyChangeEvent.java",
"java/beans/DesignMode.java",
"java/beans/EventSetDescriptor.java",
"java/beans/IndexedPropertyDescriptor.java",
"java/beans/VetoableChangeListener.java",
"java/beans/ConstructorProperties.java",
"java/beans/IndexedPropertyChangeEvent.java",
"java/beans/PropertyEditorManager.java",
"java/beans/IntrospectionException.java",
"java/beans/PropertyChangeListener.java",
"java/beans/XMLEncoder.java",
"java/beans/Visibility.java",
"java/beans/VetoableChangeSupport.java",
"java/beans/ParameterDescriptor.java",
"java/beans/XMLDecoder.java",
"java/beans/PropertyChangeListenerProxy.java",
"java/beans/ExceptionListener.java",
"java/beans/VetoableChangeListenerProxy.java",
"java/beans/DefaultPersistenceDelegate.java",
"java/beans/EventHandler.java",
"java/beans/Statement.java",
"java/beans/PropertyEditor.java",
"java/beans/PropertyEditorSupport.java",
"java/beans/SimpleBeanInfo.java",
"java/beans/PersistenceDelegate.java",
"java/beans/Encoder.java",
"java/beans/beancontext/BeanContextChildSupport.java",
"java/beans/beancontext/BeanContextServicesSupport.java",
"java/beans/beancontext/BeanContextServiceRevokedEvent.java",
"java/beans/beancontext/BeanContextSupport.java",
"java/beans/beancontext/BeanContextServiceAvailableEvent.java",
"java/beans/beancontext/BeanContextServiceProvider.java",
"java/beans/beancontext/BeanContextProxy.java",
"java/beans/beancontext/BeanContextServiceProviderBeanInfo.java",
"java/beans/beancontext/BeanContextContainerProxy.java",
"java/beans/beancontext/BeanContextMembershipListener.java",
"java/beans/beancontext/BeanContextServices.java",
"java/beans/beancontext/BeanContextServiceRevokedListener.java",
"java/beans/beancontext/BeanContext.java",
"java/beans/beancontext/BeanContextChildComponentProxy.java",
"java/beans/beancontext/BeanContextMembershipEvent.java",
"java/beans/beancontext/BeanContextEvent.java",
"java/beans/beancontext/BeanContextServicesListener.java",
"java/beans/beancontext/BeanContextChild.java",
"java/net/ContentHandler.java",
"java/net/URL.java",
"java/net/FileNameMap.java",
"java/net/SocketOptions.java",
"java/net/DatagramSocketImplFactory.java",
"java/net/UnknownServiceException.java",
"java/net/SocketPermission.java",
"java/net/NoRouteToHostException.java",
"java/net/NetPermission.java",
"java/net/URI.java",
"java/net/DatagramSocket.java",
"java/net/DatagramPacket.java",
"java/net/BindException.java",
"java/net/SocketTimeoutException.java",
"java/net/ProxySelector.java",
"java/net/MalformedURLException.java",
"java/net/URLStreamHandlerFactory.java",
"java/net/InetAddress.java",
"java/net/PortUnreachableException.java",
"java/net/DatagramSocketImpl.java",
"java/net/UnknownHostException.java",
"java/net/ProtocolException.java",
"java/net/Proxy.java",
"java/net/PasswordAuthentication.java",
"java/net/SocketAddress.java",
"java/net/MulticastSocket.java",
"java/net/ServerSocket.java",
"java/net/JarURLConnection.java",
"java/net/Authenticator.java",
"java/net/URLStreamHandler.java",
"java/net/ConnectException.java",
"java/net/NetworkInterface.java",
"java/net/URLConnection.java",
"java/net/URLEncoder.java",
"java/net/InetSocketAddress.java",
"java/net/URISyntaxException.java",
"java/net/ResolverCache.java",
"java/net/Socket.java",
"java/net/Inet4Address.java",
"java/net/SocketException.java",
"java/net/SocketImplFactory.java",
"java/net/ContentHandlerFactory.java",
"java/net/HttpURLConnection.java",
"java/net/URLDecoder.java",
"java/net/SocketImpl.java",
"java/net/URLClassLoader.java",
"java/net/Inet6Address.java",
"java/net/MimeTypeMapper.java",
"java/math/MathContext.java",
"java/math/BigInteger.java",
"java/math/BigDecimal.java",
"java/math/RoundingMode.java",
"java/io/FileWriter.java",
"java/io/FilePermission.java",
"java/io/OutputStreamWriter.java",
"java/io/ObjectInput.java",
"java/io/BufferedOutputStream.java",
"java/io/IOError.java",
"java/io/LineNumberReader.java",
"java/io/StringReader.java",
"java/io/BufferedInputStream.java",
"java/io/CharArrayWriter.java",
"java/io/InputStreamReader.java",
"java/io/Console.java",
"java/io/FileOutputStream.java",
"java/io/StringBufferInputStream.java",
"java/io/DataOutput.java",
"java/io/UTFDataFormatException.java",
"java/io/ObjectStreamConstants.java",
"java/io/ObjectStreamException.java",
"java/io/BufferedReader.java",
"java/io/FilenameFilter.java",
};
const int names_length = (sizeof (names)) / (sizeof (names[0]));
int main()
{
int hash_table_length = 512;
struct hash_table_entry entry[hash_table_length];
struct hash_table_entry overflow[hash_table_length];
int overflow_length = 0;
hash_table_init(hash_table_length,
entry,
overflow);
for (int i = 0; i < names_length; i++) {
hash_table_add(hash_table_length,
entry,
overflow,
&overflow_length,
(const uint8_t *)names[i],
strlen(names[i]),
(void *)(ptrdiff_t)(i * 2));
}
printf("overflow_length %d %d\n", overflow_length, max);
for (int j = 0; j < names_length; j++) {
struct hash_table_entry * e = hash_table_find(hash_table_length,
entry,
overflow,
(const uint8_t *)names[j],
strlen(names[j]));
assert(e != nullptr);
printf("%s %d\n", e->key, (int)e->value);
}
}