Added spdylay_map. Added missing tests/main.c

This commit is contained in:
Tatsuhiro Tsujikawa 2012-01-19 21:36:13 +09:00
parent f7f3472c98
commit a03afa6a82
9 changed files with 426 additions and 5 deletions

View File

@ -31,9 +31,9 @@ DISTCLEANFILES = $(pkgconfig_DATA)
lib_LTLIBRARIES = libspdylay.la lib_LTLIBRARIES = libspdylay.la
OBJECTS = spdylay_pq.c OBJECTS = spdylay_pq.c spdylay_map.c
HFILES = spdylay_pq.h spdylay_int.h HFILES = spdylay_pq.h spdylay_int.h spdylay_map.h
libspdylay_la_SOURCES = $(HFILES) $(OBJECTS) libspdylay_la_SOURCES = $(HFILES) $(OBJECTS)
libspdylay_la_LDFLAGS = -no-undefined \ libspdylay_la_LDFLAGS = -no-undefined \

View File

@ -32,7 +32,8 @@ extern "C" {
#include <stdlib.h> #include <stdlib.h>
enum spdylay_error { enum spdylay_error {
SPDYLAY_ERR_NOMEM = -500 SPDYLAY_ERR_NOMEM = -500,
SPDYLAY_ERR_INVALID_ARGUMENT = -501
}; };
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -25,6 +25,12 @@
#ifndef SPDYLAY_INT_H #ifndef SPDYLAY_INT_H
#define SPDYLAY_INT_H #define SPDYLAY_INT_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <stdint.h>
/* Macros, types and constants for internal use */ /* Macros, types and constants for internal use */
typedef int (*spdylay_compar)(const void *lhs, const void *rhs); typedef int (*spdylay_compar)(const void *lhs, const void *rhs);

196
lib/spdylay_map.c Normal file
View File

@ -0,0 +1,196 @@
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "spdylay_map.h"
int spdylay_map_init(spdylay_map *map)
{
map->root = NULL;
return 0;
}
static void spdylay_map_entry_free(spdylay_map_entry *entry)
{
if(entry != NULL) {
free(entry);
}
}
static void spdylay_map_entry_free_recur(spdylay_map_entry *entry)
{
if(entry != NULL) {
spdylay_map_entry_free(entry->left);
spdylay_map_entry_free(entry->right);
}
}
void spdylay_map_free(spdylay_map *map)
{
spdylay_map_entry_free_recur(map->root);
map->root = NULL;
}
/*
* 32 bit Mix Functions by Thomas Wang
*
* http://www.concentric.net/~Ttwang/tech/inthash.htm
*/
static uint32_t hash32shift(uint32_t key)
{
key = ~key + (key << 15); /* key = (key << 15) - key - 1; */
key = key ^ (key >> 12);
key = key + (key << 2);
key = key ^ (key >> 4);
key = key * 2057; /* key = (key + (key << 3)) + (key << 11); */
key = key ^ (key >> 16);
return key;
}
static spdylay_map_entry* spdylay_map_entry_new(key_type key, void *val)
{
spdylay_map_entry *entry =
(spdylay_map_entry*)malloc(sizeof(spdylay_map_entry));
if(entry != NULL) {
entry->key = key;
entry->val = val;
entry->left = entry->right = NULL;
entry->priority = hash32shift(key);
}
return entry;
}
static spdylay_map_entry* rotate_left(spdylay_map_entry *entry)
{
spdylay_map_entry *root = entry->right;
entry->right = root->left;
root->left = entry;
return root;
}
static spdylay_map_entry* rotate_right(spdylay_map_entry* entry)
{
spdylay_map_entry *root = entry->left;
entry->left = root->right;
root->right = entry;
return root;
}
static spdylay_map_entry* insert_recur(spdylay_map_entry *entry,
key_type key, void *val,
int *error)
{
if(entry == NULL) {
entry = spdylay_map_entry_new(key, val);
if(entry == NULL) {
*error = SPDYLAY_ERR_NOMEM;
}
} else if(key == entry->key) {
*error = SPDYLAY_ERR_INVALID_ARGUMENT;
} else if(key < entry->key) {
entry->left = insert_recur(entry->left, key, val, error);
} else {
entry->right = insert_recur(entry->right, key, val, error);
}
if(entry->left != NULL && entry->priority > entry->left->priority) {
entry = rotate_right(entry);
} else if(entry->right != NULL && entry->priority > entry->right->priority) {
entry = rotate_left(entry);
}
return entry;
}
int spdylay_map_insert(spdylay_map *map, key_type key, void *val)
{
int error = 0;
map->root = insert_recur(map->root, key, val, &error);
return error;
}
void* spdylay_map_find(spdylay_map *map, key_type key)
{
spdylay_map_entry *entry = map->root;
while(entry != NULL) {
if(key < entry->key) {
entry = entry->left;
} else if(key > entry->key) {
entry = entry->right;
} else {
return entry->val;
}
}
return NULL;
}
static spdylay_map_entry* erase_rotate_recur(spdylay_map_entry *entry)
{
if(entry->left == NULL) {
spdylay_map_entry *right = entry->right;
spdylay_map_entry_free(entry);
return right;
} else if(entry->right == NULL) {
spdylay_map_entry *left = entry->left;
spdylay_map_entry_free(entry);
return left;
} else if(entry->left->priority < entry->right->priority) {
entry = rotate_right(entry);
return erase_rotate_recur(entry->right);
} else {
entry = rotate_left(entry);
return erase_rotate_recur(entry->left);
}
}
static spdylay_map_entry* erase_recur(spdylay_map_entry *entry, key_type key)
{
if(key < entry->key) {
entry->left = erase_recur(entry->left, key);
} else if(key > entry->key) {
entry->right = erase_recur(entry->right, key);
} else {
entry = erase_rotate_recur(entry);
}
return entry;
}
void spdylay_map_erase(spdylay_map *map, key_type key)
{
if(map->root != NULL) {
map->root = erase_recur(map->root, key);
}
}
static void for_each(spdylay_map_entry *entry,
void (*func)(key_type key, void *val))
{
if(entry != NULL) {
for_each(entry->left, func);
func(entry->key, entry->val);
for_each(entry->right, func);
}
}
void spdylay_map_each(spdylay_map *map, void (*func)(key_type key, void *val))
{
for_each(map->root, func);
}

63
lib/spdylay_map.h Normal file
View File

@ -0,0 +1,63 @@
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SPDYLAY_MAP_H
#define SPDYLAY_MAP_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <spdylay/spdylay.h>
#include "spdylay_int.h"
/* Implementation of ordered map */
typedef uint32_t key_type;
typedef uint32_t pri_type;
typedef struct spdylay_map_entry {
key_type key;
void *val;
struct spdylay_map_entry *left, *right;
pri_type priority;
} spdylay_map_entry;
typedef struct {
spdylay_map_entry *root;
} spdylay_map;
int spdylay_map_init(spdylay_map *map);
void spdylay_map_free(spdylay_map *map);
int spdylay_map_insert(spdylay_map *map, key_type key, void *val);
void* spdylay_map_find(spdylay_map *map, key_type key);
void spdylay_map_erase(spdylay_map *map, key_type key);
void spdylay_map_each(spdylay_map *map, void (*func)(key_type key, void *val));
#endif /* SPDYLAY_MAP_H */

View File

@ -25,9 +25,9 @@ if HAVE_CUNIT
check_PROGRAMS = main check_PROGRAMS = main
OBJECTS = main.c spdylay_pq_test.c OBJECTS = main.c spdylay_pq_test.c spdylay_map_test.c
HFILES = spdylay_pq_test.h HFILES = spdylay_pq_test.h spdylay_map_test.h
main_SOURCES = $(HFILES) $(OBJECTS) main_SOURCES = $(HFILES) $(OBJECTS)

70
tests/main.c Normal file
View File

@ -0,0 +1,70 @@
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include <CUnit/Basic.h>
/* include test cases' include files here */
#include "spdylay_pq_test.h"
#include "spdylay_map_test.h"
int init_suite1(void)
{
return 0;
}
int clean_suite1(void)
{
return 0;
}
int main()
{
CU_pSuite pSuite = NULL;
/* initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
/* add a suite to the registry */
pSuite = CU_add_suite("libspdylay_TestSuite", init_suite1, clean_suite1);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* add the tests to the suite */
if(!CU_add_test(pSuite, "pq", test_spdylay_pq) ||
!CU_add_test(pSuite, "map", test_spdylay_map)) {
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return CU_get_error();
}

55
tests/spdylay_map_test.c Normal file
View File

@ -0,0 +1,55 @@
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "spdylay_map_test.h"
#include <CUnit/CUnit.h>
#include "spdylay_map.h"
void test_spdylay_map()
{
spdylay_map map;
int i;
CU_ASSERT(0 == spdylay_map_init(&map));
CU_ASSERT(0 == spdylay_map_insert(&map, 1, "foo"));
CU_ASSERT(strcmp("foo", spdylay_map_find(&map, 1)) == 0);
CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == spdylay_map_insert(&map, 1, "FOO"));
CU_ASSERT(strcmp("foo", spdylay_map_find(&map, 1)) == 0);
CU_ASSERT(0 == spdylay_map_insert(&map, 2, "bar"));
CU_ASSERT(0 == spdylay_map_insert(&map, 3, "baz"));
CU_ASSERT(0 == spdylay_map_insert(&map, 4, "shrubbery"));
CU_ASSERT(strcmp("baz", spdylay_map_find(&map, 3)) == 0);
spdylay_map_erase(&map, 3);
CU_ASSERT(NULL == spdylay_map_find(&map, 3));
spdylay_map_erase(&map, 1);
CU_ASSERT(NULL == spdylay_map_find(&map, 1));
CU_ASSERT(strcmp("bar", spdylay_map_find(&map, 2)) == 0);
CU_ASSERT(strcmp("shrubbery", spdylay_map_find(&map, 4)) == 0);
spdylay_map_free(&map);
}

30
tests/spdylay_map_test.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SPDYLAY_MAP_TEST_H
#define SPDYLAY_MAP_TEST_H
void test_spdylay_map();
#endif /* SPDYLAY_MAP_TEST_H */