summaryrefslogtreecommitdiff
path: root/pjlib
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-01-30 18:40:05 +0000
committerBenny Prijono <bennylp@teluu.com>2006-01-30 18:40:05 +0000
commit0d61adeb5f784b45f76d76dad9974f4111fb3c8c (patch)
tree4fe8830715bd6af57dd91ebca780318a645435cd /pjlib
parent7638eeee106fe58a1225f642e733629f29418818 (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.hpp30
-rw-r--r--pjlib/include/pj++/pool.hpp8
-rw-r--r--pjlib/include/pj++/string.hpp76
-rw-r--r--pjlib/include/pj++/types.hpp14
-rw-r--r--pjlib/include/pj/assert.h2
-rw-r--r--pjlib/include/pj/hash.h51
-rw-r--r--pjlib/src/pj/hash.c99
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));
}
}
}