diff options
author | Benny Prijono <bennylp@teluu.com> | 2006-01-30 18:40:05 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2006-01-30 18:40:05 +0000 |
commit | 0d61adeb5f784b45f76d76dad9974f4111fb3c8c (patch) | |
tree | 4fe8830715bd6af57dd91ebca780318a645435cd /pjlib | |
parent | 7638eeee106fe58a1225f642e733629f29418818 (diff) |
Finished implementation of UA layer (to be tested)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@127 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjlib')
-rw-r--r-- | pjlib/include/pj++/list.hpp | 30 | ||||
-rw-r--r-- | pjlib/include/pj++/pool.hpp | 8 | ||||
-rw-r--r-- | pjlib/include/pj++/string.hpp | 76 | ||||
-rw-r--r-- | pjlib/include/pj++/types.hpp | 14 | ||||
-rw-r--r-- | pjlib/include/pj/assert.h | 2 | ||||
-rw-r--r-- | pjlib/include/pj/hash.h | 51 | ||||
-rw-r--r-- | pjlib/src/pj/hash.c | 99 |
7 files changed, 226 insertions, 54 deletions
diff --git a/pjlib/include/pj++/list.hpp b/pjlib/include/pj++/list.hpp index 433bd512..456e87d2 100644 --- a/pjlib/include/pj++/list.hpp +++ b/pjlib/include/pj++/list.hpp @@ -63,7 +63,7 @@ public: } const_iterator operator++() { - return const_iterator(node_->next); + return const_iterator((const List_Node *)node_->next); } bool operator==(const const_iterator &rhs) { @@ -99,7 +99,7 @@ public: } iterator operator++() { - return iterator(node_->next); + return iterator((List_Node*)node_->next); } bool operator==(const iterator &rhs) { @@ -121,6 +121,30 @@ public: } // + // You can cast Pj_List to pj_list + // + operator pj_list&() + { + return (pj_list&)root_; + } + operator const pj_list&() + { + return (const pj_list&)root_; + } + + // + // You can cast Pj_List to pj_list* too + // + operator pj_list*() + { + return (pj_list*)&root_; + } + operator const pj_list*() + { + return (const pj_list*)&root_; + } + + // // Check if list is empty. // bool empty() const @@ -318,7 +342,7 @@ private: // If you see error in this line, // it's because List_Node is not derived from Pj_List_Node. List_Node *n = (List_Node*)0; - n = n->next; n = n->prev; + n = (List_Node *)n->next; n = (List_Node *)n->prev; } }; diff --git a/pjlib/include/pj++/pool.hpp b/pjlib/include/pj++/pool.hpp index 02b54336..d2604142 100644 --- a/pjlib/include/pj++/pool.hpp +++ b/pjlib/include/pj++/pool.hpp @@ -123,6 +123,14 @@ public: } // + // You can cast Pj_Pool to pj_pool_t* + // + operator pj_pool_t*() + { + return p_; + } + + // // Get pjlib compatible pool object. // pj_pool_t *pool_() diff --git a/pjlib/include/pj++/string.hpp b/pjlib/include/pj++/string.hpp index 1c868986..e16132f5 100644 --- a/pjlib/include/pj++/string.hpp +++ b/pjlib/include/pj++/string.hpp @@ -40,9 +40,9 @@ public: } // - // Construct the buffer from a char*. + // Construct the buffer from a char* (use with care) // - explicit Pj_String(char *str) + Pj_String(char *str) { set(str); } @@ -50,44 +50,55 @@ public: // // Construct from a const char*. // - Pj_String(Pj_Pool *pool, const char *src) + Pj_String(Pj_Pool &pool, const char *src) { set(pool, src); } // - // Construct from pj_str_t*. + // Construct from pj_str_t&. // - explicit Pj_String(pj_str_t *s) + explicit Pj_String(pj_str_t &s) { - set(s); + ptr = s.ptr; + slen = s.slen; } // - // Construct by copying from const pj_str_t*. + // Construct from const pj_str_t& (use with care!). // - Pj_String(Pj_Pool *pool, const pj_str_t *s) + explicit Pj_String(const pj_str_t &s) { - set(pool, s); + ptr = (char*)s.ptr; + slen = s.slen; } // - // Construct from another Pj_String + // Construct by copying from const pj_str_t*. // - explicit Pj_String(Pj_String &rhs) + Pj_String(Pj_Pool &pool, const pj_str_t *s) { - set(rhs); + set(pool, s); } // // Construct by copying from Pj_String // - Pj_String(Pj_Pool *pool, const Pj_String &rhs) + Pj_String(Pj_Pool &pool, const Pj_String &rhs) { set(pool, rhs); } // + // Construct from another Pj_String, use with care! + // + explicit Pj_String(const Pj_String &rhs) + { + ptr = rhs.ptr; + slen = rhs.slen; + } + + // // Construct from a char* and a length. // Pj_String(char *str, pj_size_t len) @@ -104,6 +115,22 @@ public: } // + // You can cast Pj_String to pj_str_t* + // + operator pj_str_t*() + { + return this; + } + + // + // You can cast const Pj_String to const pj_str_t* + // + operator const pj_str_t*() const + { + return this; + } + + // // Get the length of the string. // pj_size_t length() const @@ -138,9 +165,9 @@ public: // // Initialize by copying from a const char*. // - void set(Pj_Pool *pool, const char *s) + void set(Pj_Pool &pool, const char *s) { - pj_strdup2(pool->pool_(), this, s); + pj_strdup2(pool, this, s); } // @@ -154,9 +181,9 @@ public: // // Initialize by copying from const pj_str_t*. // - void set(Pj_Pool *pool, const pj_str_t *s) + void set(Pj_Pool &pool, const pj_str_t *s) { - pj_strdup(pool->pool_(), this, s); + pj_strdup(pool, this, s); } // @@ -186,17 +213,17 @@ public: // // Initialize by copying from a Pj_String*. // - void set(Pj_Pool *pool, const Pj_String *s) + void set(Pj_Pool &pool, const Pj_String *s) { - pj_strdup(pool->pool_(), this, s); + pj_strdup(pool, this, s); } // // Initialize by copying from other Pj_String. // - void set(Pj_Pool *pool, const Pj_String &s) + void set(Pj_Pool &pool, const Pj_String &s) { - pj_strdup(pool->pool_(), this, &s); + pj_strdup(pool, this, &s); } // @@ -353,11 +380,12 @@ public: } /// - // Assign from another Pj_String + // Assign from another Pj_String, use with care! // - Pj_String& operator=(Pj_String &rhs) + Pj_String& operator=(const Pj_String &rhs) { - set(rhs); + ptr = rhs.ptr; + slen = rhs.slen; return *this; } diff --git a/pjlib/include/pj++/types.hpp b/pjlib/include/pj++/types.hpp index e0c2e230..7e165a53 100644 --- a/pjlib/include/pj++/types.hpp +++ b/pjlib/include/pj++/types.hpp @@ -156,5 +156,19 @@ private: }; +// +// Macro to declare common object comparison operators. +// +#define PJ_DECLARE_OPERATORS(rhs_type) \ + bool operator!=(rhs_type rhs) const { \ + return !operator==(rhs); } \ + bool operator<=(rhs_type rhs) const { \ + return operator<(rhs) || operator==(rhs); } \ + bool operator>(rhs_type rhs) const { \ + return !operator<=(rhs); } \ + bool operator>=(rhs_type rhs) const { \ + return !operator<(rhs); } + + #endif /* __PJPP_TYPES_HPP__ */ diff --git a/pjlib/include/pj/assert.h b/pjlib/include/pj/assert.h index 6814e4cd..d6cb5163 100644 --- a/pjlib/include/pj/assert.h +++ b/pjlib/include/pj/assert.h @@ -49,7 +49,7 @@ /** * @hideinitializer - * If #PJ_ENABLE_EXTRA_CHECK is declared and non-zero, then + * If #PJ_ENABLE_EXTRA_CHECK is declared and the value is non-zero, then * #PJ_ASSERT_RETURN macro will evaluate the expression in @a expr during * run-time. If the expression yields false, assertion will be triggered * and the current function will return with the specified return value. diff --git a/pjlib/include/pj/hash.h b/pjlib/include/pj/hash.h index 41c89bc0..091c82b6 100644 --- a/pjlib/include/pj/hash.h +++ b/pjlib/include/pj/hash.h @@ -45,6 +45,11 @@ PJ_BEGIN_DECL #define PJ_HASH_KEY_STRING ((unsigned)-1) /** + * This indicates the size of of each hash entry. + */ +#define PJ_HASH_ENTRY_SIZE (3*sizeof(void*) + 2*sizeof(pj_uint32_t)) + +/** * This is the function that is used by the hash table to calculate hash value * of the specified key. * @@ -92,15 +97,24 @@ PJ_DECL(pj_hash_table_t*) pj_hash_create(pj_pool_t *pool, unsigned size); * @param key the key to look for. * @param keylen the length of the key, or PJ_HASH_KEY_STRING to use the * string length of the key. + * @param hval if this argument is not NULL and the value is not zero, + * the value will be used as the computed hash value. If + * the argument is not NULL and the value is zero, it will + * be filled with the computed hash upon return. * * @return the value associated with the key, or NULL if the key is not found. */ PJ_DECL(void *) pj_hash_get( pj_hash_table_t *ht, - const void *key, unsigned keylen ); + const void *key, unsigned keylen, + pj_uint32_t *hval ); /** - * Associate/disassociate a value with the specified key. + * Associate/disassociate a value with the specified key. If value is not + * NULL and entry already exists, the entry's value will be overwritten. + * If value is not NULL and entry does not exist, a new one will be created + * with the specified pool. Otherwise if value is NULL, entry will be + * deleted if it exists. * * @param pool the pool to allocate the new entry if a new entry has to be * created. @@ -108,13 +122,44 @@ PJ_DECL(void *) pj_hash_get( pj_hash_table_t *ht, * @param key the key. * @param keylen the length of the key, or PJ_HASH_KEY_STRING to use the * string length of the key. + * @param hval if the value is not zero, then the hash table will use + * this value to search the entry's index, otherwise it will + * compute the key. This value can be obtained when calling + * #pj_hash_get(). * @param value value to be associated, or NULL to delete the entry with * the specified key. */ PJ_DECL(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht, - const void *key, unsigned keylen, + const void *key, unsigned keylen, pj_uint32_t hval, void *value ); + +/** + * Associate/disassociate a value with the specified key. This function works + * like #pj_hash_set(), except that it doesn't use pool (hence the np -- no + * pool suffix). If new entry needs to be allocated, it will use the entry_buf. + * + * @param ht the hash table. + * @param key the key. + * @param keylen the length of the key, or PJ_HASH_KEY_STRING to use the + * string length of the key. + * @param hval if the value is not zero, then the hash table will use + * this value to search the entry's index, otherwise it will + * compute the key. This value can be obtained when calling + * #pj_hash_get(). + * @param entry_buf Pointer to buffer which will be used for the new entry, + * when one needs to be created. The buffer must be at least + * PJ_HASH_ENTRY_SIZE long, and the first PJ_HASH_ENTRY_SIZE + * bytes of the buffer will be used by the hash table. + * Application may use the remaining portion of the buffer + * for its own purpose. + * @param value value to be associated, or NULL to delete the entry with + * the specified key. + */ +PJ_DECL(void) pj_hash_set_np(pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t hval, void *entry_buf, void *value); + /** * Get the total number of entries in the hash table. * diff --git a/pjlib/src/pj/hash.c b/pjlib/src/pj/hash.c index 739f2757..0495fadc 100644 --- a/pjlib/src/pj/hash.c +++ b/pjlib/src/pj/hash.c @@ -22,6 +22,7 @@ #include <pj/pool.h> #include <pj/os.h> #include <pj/ctype.h> +#include <pj/assert.h> /** * The hash multiplier used to calculate hash value. @@ -57,7 +58,6 @@ PJ_DEF(pj_uint32_t) pj_hash_calc(pj_uint32_t hash, const void *key, unsigned key for ( ; *p; ++p ) { hash = hash * PJ_HASH_MULTIPLIER + *p; } - keylen = p - (const unsigned char*)key; } else { const unsigned char *p = key, *end = p + keylen; @@ -88,6 +88,9 @@ PJ_DEF(pj_hash_table_t*) pj_hash_create(pj_pool_t *pool, unsigned size) pj_hash_table_t *h; unsigned table_size; + /* Check that PJ_HASH_ENTRY_SIZE is correct. */ + PJ_ASSERT_RETURN(sizeof(pj_hash_entry)==PJ_HASH_ENTRY_SIZE, NULL); + h = pj_pool_alloc(pool, sizeof(pj_hash_table_t)); h->count = 0; @@ -110,24 +113,36 @@ PJ_DEF(pj_hash_table_t*) pj_hash_create(pj_pool_t *pool, unsigned size) static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht, const void *key, unsigned keylen, - void *val) + void *val, pj_uint32_t *hval, + void *entry_buf) { pj_uint32_t hash; pj_hash_entry **p_entry, *entry; - hash=0; - if (keylen==PJ_HASH_KEY_STRING) { - const unsigned char *p = key; - for ( ; *p; ++p ) { - hash = hash * PJ_HASH_MULTIPLIER + *p; - } - keylen = p - (const unsigned char*)key; + if (hval && *hval != 0) { + hash = *hval; } else { - const unsigned char *p = key, - *end = p + keylen; - for ( ; p!=end; ++p) { - hash = hash * PJ_HASH_MULTIPLIER + *p; + /* This slightly differs with pj_hash_calc() because we need + * to get the keylen when keylen is PJ_HASH_KEY_STRING. + */ + hash=0; + if (keylen==PJ_HASH_KEY_STRING) { + const unsigned char *p = key; + for ( ; *p; ++p ) { + hash = hash * PJ_HASH_MULTIPLIER + *p; + } + keylen = p - (const unsigned char*)key; + } else { + const unsigned char *p = key, + *end = p + keylen; + for ( ; p!=end; ++p) { + hash = hash * PJ_HASH_MULTIPLIER + *p; + } } + + /* Report back the computed hash. */ + if (hval) + *hval = hash; } /* scan the linked list */ @@ -136,7 +151,7 @@ static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht, p_entry = &entry->next, entry = *p_entry) { if (entry->hash==hash && entry->keylen==keylen && - memcmp(entry->key, key, keylen)==0) + pj_memcmp(entry->key, key, keylen)==0) { break; } @@ -145,10 +160,21 @@ static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht, if (entry || val==NULL) return p_entry; - /* create a new entry */ - entry = pj_pool_alloc(pool, sizeof(pj_hash_entry)); - PJ_LOG(6, ("hashtbl", "%p: New p_entry %p created, pool used=%u, cap=%u", ht, entry, - pj_pool_get_used_size(pool), pj_pool_get_capacity(pool))); + /* Entry not found, create a new one. + * If entry_buf is specified, use it. Otherwise allocate from pool. + */ + if (entry_buf) { + entry = entry_buf; + } else { + /* Pool must be specified! */ + PJ_ASSERT_RETURN(pool != NULL, NULL); + + entry = pj_pool_alloc(pool, sizeof(pj_hash_entry)); + PJ_LOG(6, ("hashtbl", + "%p: New p_entry %p created, pool used=%u, cap=%u", + ht, entry, pj_pool_get_used_size(pool), + pj_pool_get_capacity(pool))); + } entry->next = NULL; entry->hash = hash; entry->key = key; @@ -162,20 +188,46 @@ static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht, } PJ_DEF(void *) pj_hash_get( pj_hash_table_t *ht, - const void *key, unsigned keylen ) + const void *key, unsigned keylen, + pj_uint32_t *hval) { pj_hash_entry *entry; - entry = *find_entry( NULL, ht, key, keylen, NULL); + + if (hval) *hval = 0; + entry = *find_entry( NULL, ht, key, keylen, NULL, hval, NULL); return entry ? entry->value : NULL; } PJ_DEF(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht, - const void *key, unsigned keylen, + const void *key, unsigned keylen, pj_uint32_t hval, void *value ) { pj_hash_entry **p_entry; - p_entry = find_entry( pool, ht, key, keylen, value ); + p_entry = find_entry( pool, ht, key, keylen, value, &hval, NULL); + if (*p_entry) { + if (value == NULL) { + /* delete entry */ + PJ_LOG(6, ("hashtbl", "%p: p_entry %p deleted", ht, *p_entry)); + *p_entry = (*p_entry)->next; + --ht->count; + + } else { + /* overwrite */ + (*p_entry)->value = value; + PJ_LOG(6, ("hashtbl", "%p: p_entry %p value set to %p", ht, + *p_entry, value)); + } + } +} + +PJ_DEF(void) pj_hash_set_np( pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t hval, void *entry_buf, void *value) +{ + pj_hash_entry **p_entry; + + p_entry = find_entry( NULL, ht, key, keylen, value, &hval, entry_buf ); if (*p_entry) { if (value == NULL) { /* delete entry */ @@ -186,7 +238,8 @@ PJ_DEF(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht, } else { /* overwrite */ (*p_entry)->value = value; - PJ_LOG(6, ("hashtbl", "%p: p_entry %p value set to %p", ht, *p_entry, value)); + PJ_LOG(6, ("hashtbl", "%p: p_entry %p value set to %p", ht, + *p_entry, value)); } } } |