/* * khm - (Linux) kernel hash map implementation * * Copyright (c) 2011 Guillermo Ramos <0xwille@gmail.com> * * This file is part of khm * * khm is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * khm is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with khm. If not, see . */ #include #include #include #include "khm.h" /* * Returns the node with the value passed, or NULL in case it does not exist */ static inline struct khashmap *khm_search(struct khashmap *head, int value) { struct list_head *list; struct khashmap *node; list_for_each(list, &head->l) { node = list_entry(list, struct khashmap, l); if (node->value == value) return node; } return NULL; } /* * Prints in klog a representation of all the nodes in the hashmap */ void khm_display(struct khashmap *head) { struct khashmap *node; struct list_head *list; printk(KERN_ALERT "Displaying..."); list_for_each(list, &head->l) { node = list_entry(list, struct khashmap, l); printk(KERN_ALERT " %p: v=%d d=%s\n", node, node->value, (char*)node->data); } } /* * Creates and returns a new head node */ inline struct khashmap *khm_create(void) { struct khashmap *head; head = kmalloc(sizeof(struct khashmap), GFP_KERNEL); if (!head) return NULL; INIT_LIST_HEAD(&head->l); return head; } /* * Deletes the hashmap and frees the memory used by its nodes */ void khm_destroy(struct khashmap *head) { struct khashmap *node; struct list_head *list = head->l.next; while (list != &head->l) { node = list_entry(list, struct khashmap, l); list = list->next; kfree(node); } kfree(head); } /* * Creates a new node with the given value and data, and adds it to the hm head */ int khm_insert(struct khashmap *head, int value, void *data) { struct khashmap *new; // Key already exists if (khm_search(head, value)) return -EINVAL; new = khm_create(); if (!new) return -ENOMEM; new->value = value; new->data = data; list_add_tail(&new->l, &head->l); return 0; } /* * Removes from the hashmap the node with the given value. */ int khm_delete(struct khashmap *head, int value) { struct khashmap *node = khm_search(head, value); if (node) { list_del(&node->l); kfree(node); return 0; } else { return -EINVAL; } } /* * Returns the data mapped to the given value, or NULL if that value has no data * associated to it */ void *khm_get(struct khashmap *head, int value) { struct khashmap *node = khm_search(head, value); if (node) return node->data; else return NULL; } /* * Associates the given value with new data, if the value was already in the hm */ void khm_set(struct khashmap *head, int value, void *data) { struct khashmap *node = khm_search(head, value); if (node) node->data = data; }