summaryrefslogtreecommitdiff
path: root/pjlib/src/pj++
diff options
context:
space:
mode:
Diffstat (limited to 'pjlib/src/pj++')
-rw-r--r--pjlib/src/pj++/compiletest.cpp44
-rw-r--r--pjlib/src/pj++/hash.hpp71
-rw-r--r--pjlib/src/pj++/ioqueue.hpp172
-rw-r--r--pjlib/src/pj++/list.hpp182
-rw-r--r--pjlib/src/pj++/os.hpp342
-rw-r--r--pjlib/src/pj++/pj++.cpp15
-rw-r--r--pjlib/src/pj++/pool.hpp84
-rw-r--r--pjlib/src/pj++/proactor.cpp296
-rw-r--r--pjlib/src/pj++/proactor.hpp86
-rw-r--r--pjlib/src/pj++/scanner.hpp171
-rw-r--r--pjlib/src/pj++/sock.hpp194
-rw-r--r--pjlib/src/pj++/string.hpp247
-rw-r--r--pjlib/src/pj++/timer.hpp105
-rw-r--r--pjlib/src/pj++/tree.hpp107
-rw-r--r--pjlib/src/pj++/types.hpp59
15 files changed, 2175 insertions, 0 deletions
diff --git a/pjlib/src/pj++/compiletest.cpp b/pjlib/src/pj++/compiletest.cpp
new file mode 100644
index 00000000..84e80aeb
--- /dev/null
+++ b/pjlib/src/pj++/compiletest.cpp
@@ -0,0 +1,44 @@
+/* $Header: /pjproject/pjlib/src/pj++/compiletest.cpp 4 8/24/05 10:29a Bennylp $ */
+#include <pjlib++.hpp>
+
+
+#if 0
+struct MyNode
+{
+ PJ_DECL_LIST_MEMBER(struct MyNode)
+ int data;
+};
+
+int test()
+{
+ typedef PJ_List<MyNode> MyList;
+ MyList list;
+ MyList::iterator it, end = list.end();
+
+ for (it=list.begin(); it!=end; ++it) {
+ MyNode *n = *it;
+ }
+
+ return 0;
+}
+
+int test_scan()
+{
+ PJ_Scanner scan;
+ PJ_String s;
+ PJ_CharSpec cs;
+
+ scan.get(&cs, &s);
+ return 0;
+}
+
+int test_scan_c()
+{
+ pj_scanner scan;
+ pj_str_t s;
+ pj_char_spec cs;
+
+ pj_scan_get(&scan, cs, &s);
+ return 0;
+}
+#endif
diff --git a/pjlib/src/pj++/hash.hpp b/pjlib/src/pj++/hash.hpp
new file mode 100644
index 00000000..d1fd162f
--- /dev/null
+++ b/pjlib/src/pj++/hash.hpp
@@ -0,0 +1,71 @@
+/* $Header: /pjproject/pjlib/src/pj++/hash.hpp 5 8/24/05 10:29a Bennylp $ */
+#ifndef __PJPP_HASH_H__
+#define __PJPP_HASH_H__
+
+#include <pj++/types.hpp>
+#include <pj/hash.h>
+
+class PJ_Hash_Table
+{
+public:
+ class iterator
+ {
+ public:
+ iterator() {}
+ explicit iterator(pj_hash_table_t *h, pj_hash_iterator_t *i) : ht_(h), it_(i) {}
+ iterator(const iterator &rhs) : ht_(rhs.ht_), it_(rhs.it_) {}
+ void operator++() { it_ = pj_hash_next(ht_, it_); }
+ bool operator==(const iterator &rhs) { return ht_ == rhs.ht_ && it_ == rhs.it_; }
+ iterator & operator=(const iterator &rhs) { ht_=rhs.ht_; it_=rhs.it_; return *this; }
+ private:
+ pj_hash_table_t *ht_;
+ pj_hash_iterator_t it_val_;
+ pj_hash_iterator_t *it_;
+
+ friend class PJ_Hash_Table;
+ };
+
+ static PJ_Hash_Table *create(PJ_Pool *pool, unsigned size)
+ {
+ return (PJ_Hash_Table*) pj_hash_create(pool->pool_(), size);
+ }
+
+ static pj_uint32_t calc(pj_uint32_t initial_hval, const void *key, unsigned keylen)
+ {
+ return pj_hash_calc(initial_hval, key, keylen);
+ }
+
+ pj_hash_table_t *hash_table_()
+ {
+ return (pj_hash_table_t*)this;
+ }
+
+ void *get(const void *key, unsigned keylen)
+ {
+ return pj_hash_get(this->hash_table_(), key, keylen);
+ }
+
+ void set(PJ_Pool *pool, const void *key, unsigned keylen, void *value)
+ {
+ pj_hash_set(pool->pool_(), this->hash_table_(), key, keylen, value);
+ }
+
+ unsigned count()
+ {
+ return pj_hash_count(this->hash_table_());
+ }
+
+ iterator begin()
+ {
+ iterator it(this->hash_table_(), NULL);
+ it.it_ = pj_hash_first(this->hash_table_(), &it.it_val_);
+ return it;
+ }
+
+ iterator end()
+ {
+ return iterator(this->hash_table_(), NULL);
+ }
+};
+
+#endif /* __PJPP_HASH_H__ */
diff --git a/pjlib/src/pj++/ioqueue.hpp b/pjlib/src/pj++/ioqueue.hpp
new file mode 100644
index 00000000..5ecb34ce
--- /dev/null
+++ b/pjlib/src/pj++/ioqueue.hpp
@@ -0,0 +1,172 @@
+/* $Header: /pjproject/pjlib/src/pj++/ioqueue.hpp 4 8/24/05 10:29a Bennylp $ */
+#ifndef __PJPP_IOQUEUE_H__
+#define __PJPP_IOQUEUE_H__
+
+#include <pj++/sock.hpp>
+#include <pj++/pool.hpp>
+#include <pj++/types.hpp>
+#include <pj/ioqueue.h>
+
+class PJ_IOQueue;
+
+class PJ_IOQueue_Event_Handler
+{
+public:
+ virtual ~PJ_IOQueue_Event_Handler()
+ {
+ }
+
+ pj_ioqueue_key_t* get_key() const
+ {
+ return key_;
+ }
+
+protected:
+ //
+ // Override this to get notification from I/O Queue
+ //
+ virtual void on_read_complete(pj_ssize_t bytes_read)
+ {
+ }
+
+ virtual void on_write_complete(pj_ssize_t bytes_sent)
+ {
+ }
+
+ virtual void on_accept_complete(int status)
+ {
+ }
+
+ virtual void on_connect_complete(int status)
+ {
+ }
+
+protected:
+ PJ_IOQueue_Event_Handler()
+ : ioqueue_(NULL), key_(NULL)
+ {
+ }
+
+private:
+ PJ_IOQueue *ioqueue_;
+ pj_ioqueue_key_t *key_;
+
+ static void read_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_read)
+ {
+ PJ_IOQueue_Event_Handler *handler =
+ (PJ_IOQueue_Event_Handler*)pj_ioqueue_get_user_data(key);
+ handler->on_read_complete(bytes_read);
+ }
+
+ static void write_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent);
+ static void accept_complete_cb(pj_ioqueue_key_t *key, int status);
+ static void connect_complete_cb(pj_ioqueue_key_t *key, int status);
+
+ friend class PJ_IOQueue;
+};
+
+
+class PJ_IOQueue
+{
+ typedef pj_ioqueue_t *B_;
+
+public:
+ typedef pj_ioqueue_key_t Key;
+
+ enum Operation
+ {
+ OP_NONE = PJ_IOQUEUE_OP_NONE,
+ OP_READ = PJ_IOQUEUE_OP_READ,
+ OP_RECV_FROM = PJ_IOQUEUE_OP_RECV_FROM,
+ OP_WRITE = PJ_IOQUEUE_OP_WRITE,
+ OP_SEND_TO = PJ_IOQUEUE_OP_SEND_TO,
+#if PJ_HAS_TCP
+ OP_ACCEPT = PJ_IOQUEUE_OP_ACCEPT,
+ OP_CONNECT = PJ_IOQUEUE_OP_CONNECT,
+#endif
+ };
+
+ enum Status
+ {
+ IS_PENDING = PJ_IOQUEUE_PENDING
+ };
+
+ static PJ_IOQueue *create(PJ_Pool *pool, pj_size_t max_fd)
+ {
+ return (PJ_IOQueue*) pj_ioqueue_create(pool->pool_(), max_fd);
+ }
+
+ operator B_()
+ {
+ return (pj_ioqueue_t*)(PJ_IOQueue*)this;
+ }
+
+ pj_ioqueue_t *ioq_()
+ {
+ return (B_)this;
+ }
+
+ void destroy()
+ {
+ pj_ioqueue_destroy(this->ioq_());
+ }
+
+ Key *register_handle(PJ_Pool *pool, pj_oshandle_t hnd, void *user_data)
+ {
+ return pj_ioqueue_register(pool->pool_(), this->ioq_(), hnd, user_data);
+ }
+
+ Key *register_socket(PJ_Pool *pool, pj_sock_t hnd, void *user_data)
+ {
+ return pj_ioqueue_register(pool->pool_(), this->ioq_(), (pj_oshandle_t)hnd, user_data);
+ }
+
+ pj_status_t unregister(Key *key)
+ {
+ return pj_ioqueue_unregister(this->ioq_(), key);
+ }
+
+ void *get_user_data(Key *key)
+ {
+ return pj_ioqueue_get_user_data(key);
+ }
+
+ int poll(Key **key, pj_ssize_t *bytes_status, Operation *op, const PJ_Time_Val *timeout)
+ {
+ return pj_ioqueue_poll(this->ioq_(), key, bytes_status, (pj_ioqueue_operation_e*)op, timeout);
+ }
+
+#if PJ_HAS_TCP
+ pj_status_t connect(Key *key, const pj_sockaddr_t *addr, int addrlen)
+ {
+ return pj_ioqueue_connect(this->ioq_(), key, addr, addrlen);
+ }
+
+ pj_status_t accept(Key *key, PJ_Socket *sock, pj_sockaddr_t *local, pj_sockaddr_t *remote, int *addrlen)
+ {
+ return pj_ioqueue_accept(this->ioq_(), key, &sock->get_handle(), local, remote, addrlen);
+ }
+#endif
+
+ int read(Key *key, void *buf, pj_size_t len)
+ {
+ return pj_ioqueue_read(this->ioq_(), key, buf, len);
+ }
+
+ int recvfrom(Key *key, void *buf, pj_size_t len, pj_sockaddr_t *addr, int *addrlen)
+ {
+ return pj_ioqueue_recvfrom(this->ioq_(), key, buf, len, addr, addrlen);
+ }
+
+ int write(Key *key, const void *data, pj_size_t len)
+ {
+ return pj_ioqueue_write(this->ioq_(), key, data, len);
+ }
+
+ int sendto(Key *key, const void *data, pj_size_t len, const pj_sockaddr_t *addr, int addrlen)
+ {
+ return pj_ioqueue_sendto(this->ioq_(), key, data, len, addr, addrlen);
+ }
+};
+
+#endif /* __PJPP_IOQUEUE_H__ */
diff --git a/pjlib/src/pj++/list.hpp b/pjlib/src/pj++/list.hpp
new file mode 100644
index 00000000..76452917
--- /dev/null
+++ b/pjlib/src/pj++/list.hpp
@@ -0,0 +1,182 @@
+/* $Header: /pjproject/pjlib/src/pj++/list.hpp 2 2/24/05 11:23a Bennylp $ */
+#ifndef __PJPP_LIST_H__
+#define __PJPP_LIST_H__
+
+#include <pj/list.h>
+
+template <typename T>
+struct PJ_List_Node
+{
+ PJ_DECL_LIST_MEMBER(T)
+};
+
+
+template <class Node>
+class PJ_List
+{
+public:
+ PJ_List() { pj_list_init(&root_); if (0) compiletest(); }
+ ~PJ_List() {}
+
+ class const_iterator
+ {
+ public:
+ const_iterator() : node_(NULL) {}
+ const_iterator(const Node *nd) : node_((Node*)nd) {}
+ const Node * operator *() { return node_; }
+ const Node * operator -> () { return node_; }
+ const_iterator operator++() { return const_iterator(node_->next); }
+ bool operator==(const const_iterator &rhs) { return node_ == rhs.node_; }
+ bool operator!=(const const_iterator &rhs) { return node_ != rhs.node_; }
+
+ protected:
+ Node *node_;
+ };
+
+ class iterator : public const_iterator
+ {
+ public:
+ iterator() {}
+ iterator(Node *nd) : const_iterator(nd) {}
+ Node * operator *() { return node_; }
+ Node * operator -> () { return node_; }
+ iterator operator++() { return iterator(node_->next); }
+ bool operator==(const iterator &rhs) { return node_ == rhs.node_; }
+ bool operator!=(const iterator &rhs) { return node_ != rhs.node_; }
+ };
+
+ bool empty() const
+ {
+ return pj_list_empty(&root_);
+ }
+
+ iterator begin()
+ {
+ return iterator(root_.next);
+ }
+
+ const_iterator begin() const
+ {
+ return const_iterator(root_.next);
+ }
+
+ const_iterator end() const
+ {
+ return const_iterator((Node*)&root_);
+ }
+
+ iterator end()
+ {
+ return iterator((Node*)&root_);
+ }
+
+ void insert_before (iterator &pos, Node *node)
+ {
+ pj_list_insert_before( *pos, node );
+ }
+
+ void insert_after(iterator &pos, Node *node)
+ {
+ pj_list_insert_after(*pos, node);
+ }
+
+ void merge_first(Node *list2)
+ {
+ pj_list_merge_first(&root_, list2);
+ }
+
+ void merge_last(PJ_List *list)
+ {
+ pj_list_merge_last(&root_, &list->root_);
+ }
+
+ void insert_nodes_before(iterator &pos, PJ_List *list2)
+ {
+ pj_list_insert_nodes_before(*pos, &list2->root_);
+ }
+
+ void insert_nodes_after(iterator &pos, PJ_List *list2)
+ {
+ pj_list_insert_nodes_after(*pos, &list2->root_);
+ }
+
+ void erase(iterator &it)
+ {
+ pj_list_erase(*it);
+ }
+
+ Node *front()
+ {
+ return root_.next;
+ }
+
+ const Node *front() const
+ {
+ return root_.next;
+ }
+
+ void pop_front()
+ {
+ pj_list_erase(root_.next);
+ }
+
+ Node *back()
+ {
+ return root_.prev;
+ }
+
+ const Node *back() const
+ {
+ return root_.prev;
+ }
+
+ void pop_back()
+ {
+ pj_list_erase(root_.prev);
+ }
+
+ iterator find(Node *node)
+ {
+ Node *n = pj_list_find_node(&root_, node);
+ return n ? iterator(n) : end();
+ }
+
+ const_iterator find(Node *node) const
+ {
+ Node *n = pj_list_find_node(&root_, node);
+ return n ? const_iterator(n) : end();
+ }
+
+ void push_back(Node *node)
+ {
+ pj_list_insert_after(root_.prev, node);
+ }
+
+ void push_front(Node *node)
+ {
+ pj_list_insert_before(root_.next, node);
+ }
+
+ void clear()
+ {
+ root_.next = &root_;
+ root_.prev = &root_;
+ }
+
+private:
+ struct RootNode
+ {
+ PJ_DECL_LIST_MEMBER(Node)
+ } root_;
+
+ void compiletest()
+ {
+ // If you see error in this line,
+ // it's because Node is not derived from PJ_List_Node.
+ Node *n = (Node*)0;
+ n = n->next; n = n->prev;
+ }
+};
+
+
+#endif /* __PJPP_LIST_H__ */
diff --git a/pjlib/src/pj++/os.hpp b/pjlib/src/pj++/os.hpp
new file mode 100644
index 00000000..c3827528
--- /dev/null
+++ b/pjlib/src/pj++/os.hpp
@@ -0,0 +1,342 @@
+/* $Header: /pjproject/pjlib/src/pj++/os.hpp 2 2/24/05 11:23a Bennylp $ */
+#ifndef __PJPP_OS_H__
+#define __PJPP_OS_H__
+
+#include <pj/os.h>
+#include <pj++/types.hpp>
+#include <pj++/pool.hpp>
+
+class PJ_Thread
+{
+public:
+ enum Flags
+ {
+ FLAG_SUSPENDED = PJ_THREAD_SUSPENDED
+ };
+
+ static PJ_Thread *create( PJ_Pool *pool, const char *thread_name,
+ pj_thread_proc *proc, void *arg,
+ pj_size_t stack_size, void *stack_ptr,
+ unsigned flags)
+ {
+ return (PJ_Thread*) pj_thread_create( pool->pool_(), thread_name, proc, arg, stack_size, stack_ptr, flags);
+ }
+
+ static PJ_Thread *register_current_thread(const char *name, pj_thread_desc desc)
+ {
+ return (PJ_Thread*) pj_thread_register(name, desc);
+ }
+
+ static PJ_Thread *get_current_thread()
+ {
+ return (PJ_Thread*) pj_thread_this();
+ }
+
+ static pj_status_t sleep(unsigned msec)
+ {
+ return pj_thread_sleep(msec);
+ }
+
+ static pj_status_t usleep(unsigned usec)
+ {
+ return pj_thread_usleep(usec);
+ }
+
+ pj_thread_t *pj_thread_t_()
+ {
+ return (pj_thread_t*)this;
+ }
+
+ const char *get_name()
+ {
+ return pj_thread_get_name( this->pj_thread_t_() );
+ }
+
+ pj_status_t resume()
+ {
+ return pj_thread_resume( this->pj_thread_t_() );
+ }
+
+ pj_status_t join()
+ {
+ return pj_thread_join( this->pj_thread_t_() );
+ }
+
+ pj_status_t destroy()
+ {
+ return pj_thread_destroy( this->pj_thread_t_() );
+ }
+};
+
+
+class PJ_Thread_Local
+{
+public:
+ static PJ_Thread_Local *alloc()
+ {
+ long index = pj_thread_local_alloc();
+ return index < 0 ? NULL : (PJ_Thread_Local*)index;
+ }
+ void free()
+ {
+ pj_thread_local_free( this->tls_() );
+ }
+
+ long tls_() const
+ {
+ return (long)this;
+ }
+
+ void set(void *value)
+ {
+ pj_thread_local_set( this->tls_(), value );
+ }
+
+ void *get()
+ {
+ return pj_thread_local_get( this->tls_() );
+ }
+};
+
+
+class PJ_Atomic
+{
+public:
+ static PJ_Atomic *create(PJ_Pool *pool, long initial)
+ {
+ return (PJ_Atomic*) pj_atomic_create(pool->pool_(), initial);
+ }
+
+ pj_atomic_t *pj_atomic_t_()
+ {
+ return (pj_atomic_t*)this;
+ }
+
+ pj_status_t destroy()
+ {
+ return pj_atomic_destroy( this->pj_atomic_t_() );
+ }
+
+ long set(long val)
+ {
+ return pj_atomic_set( this->pj_atomic_t_(), val);
+ }
+
+ long get()
+ {
+ return pj_atomic_get( this->pj_atomic_t_() );
+ }
+
+ long inc()
+ {
+ return pj_atomic_inc( this->pj_atomic_t_() );
+ }
+
+ long dec()
+ {
+ return pj_atomic_dec( this->pj_atomic_t_() );
+ }
+};
+
+
+class PJ_Mutex
+{
+public:
+ enum Type
+ {
+ DEFAULT = PJ_MUTEX_DEFAULT,
+ SIMPLE = PJ_MUTEX_SIMPLE,
+ RECURSE = PJ_MUTEX_RECURSE,
+ };
+
+ static PJ_Mutex *create( PJ_Pool *pool, const char *name, Type type)
+ {
+ return (PJ_Mutex*) pj_mutex_create( pool->pool_(), name, type);
+ }
+
+ pj_mutex_t *pj_mutex_()
+ {
+ return (pj_mutex_t*)this;
+ }
+
+ pj_status_t destroy()
+ {
+ return pj_mutex_destroy( this->pj_mutex_() );
+ }
+
+ pj_status_t lock()
+ {
+ return pj_mutex_lock( this->pj_mutex_() );
+ }
+
+ pj_status_t unlock()
+ {
+ return pj_mutex_unlock( this->pj_mutex_() );
+ }
+
+ pj_status_t trylock()
+ {
+ return pj_mutex_trylock( this->pj_mutex_() );
+ }
+
+#if PJ_DEBUG
+ pj_status_t is_locked()
+ {
+ return pj_mutex_is_locked( this->pj_mutex_() );
+ }
+#endif
+};
+
+
+class PJ_Semaphore
+{
+public:
+ static PJ_Semaphore *create( PJ_Pool *pool, const char *name, unsigned initial, unsigned max)
+ {
+ return (PJ_Semaphore*) pj_sem_create( pool->pool_(), name, initial, max);
+ }
+
+ pj_sem_t *pj_sem_t_()
+ {
+ return (pj_sem_t*)this;
+ }
+
+ pj_status_t destroy()
+ {
+ return pj_sem_destroy(this->pj_sem_t_());
+ }
+
+ pj_status_t wait()
+ {
+ return pj_sem_wait(this->pj_sem_t_());
+ }
+
+ pj_status_t lock()
+ {
+ return wait();
+ }
+
+ pj_status_t trywait()
+ {
+ return pj_sem_trywait(this->pj_sem_t_());
+ }
+
+ pj_status_t trylock()
+ {
+ return trywait();
+ }
+
+ pj_status_t post()
+ {
+ return pj_sem_post(this->pj_sem_t_());
+ }
+
+ pj_status_t unlock()
+ {
+ return post();
+ }
+};
+
+
+class PJ_Event
+{
+public:
+ static PJ_Event *create( PJ_Pool *pool, const char *name, bool manual_reset, bool initial)
+ {
+ return (PJ_Event*) pj_event_create(pool->pool_(), name, manual_reset, initial);
+ }
+
+ pj_event_t *pj_event_t_()
+ {
+ return (pj_event_t*)this;
+ }
+
+ pj_status_t destroy()
+ {
+ return pj_event_destroy(this->pj_event_t_());
+ }
+
+ pj_status_t wait()
+ {
+ return pj_event_wait(this->pj_event_t_());
+ }
+
+ pj_status_t trywait()
+ {
+ return pj_event_trywait(this->pj_event_t_());
+ }
+
+ pj_status_t set()
+ {
+ return pj_event_set(this->pj_event_t_());
+ }
+
+ pj_status_t pulse()
+ {
+ return pj_event_pulse(this->pj_event_t_());
+ }
+
+ pj_status_t reset()
+ {
+ return pj_event_reset(this->pj_event_t_());
+ }
+};
+
+class PJ_OS
+{
+public:
+ static pj_status_t gettimeofday( PJ_Time_Val *tv )
+ {
+ return pj_gettimeofday(tv);
+ }
+
+ static pj_status_t time_decode( const PJ_Time_Val *tv, pj_parsed_time *pt )
+ {
+ return pj_time_decode(tv, pt);
+ }
+
+ static pj_status_t time_encode(const pj_parsed_time *pt, PJ_Time_Val *tv)
+ {
+ return pj_time_encode(pt, tv);
+ }
+
+ static pj_status_t time_local_to_gmt( PJ_Time_Val *tv )
+ {
+ return pj_time_local_to_gmt( tv );
+ }
+
+ static pj_status_t time_gmt_to_local( PJ_Time_Val *tv)
+ {
+ return pj_time_gmt_to_local( tv );
+ }
+};
+
+
+inline pj_status_t PJ_Time_Val::gettimeofday()
+{
+ return PJ_OS::gettimeofday(this);
+}
+
+inline pj_parsed_time PJ_Time_Val::decode()
+{
+ pj_parsed_time pt;
+ PJ_OS::time_decode(this, &pt);
+ return pt;
+}
+
+inline pj_status_t PJ_Time_Val::encode(const pj_parsed_time *pt)
+{
+ return PJ_OS::time_encode(pt, this);
+}
+
+inline pj_status_t PJ_Time_Val::to_gmt()
+{
+ return PJ_OS::time_local_to_gmt(this);
+}
+
+inline pj_status_t PJ_Time_Val::to_local()
+{
+ return PJ_OS::time_gmt_to_local(this);
+}
+
+#endif /* __PJPP_OS_H__ */
diff --git a/pjlib/src/pj++/pj++.cpp b/pjlib/src/pj++/pj++.cpp
new file mode 100644
index 00000000..1a41ec32
--- /dev/null
+++ b/pjlib/src/pj++/pj++.cpp
@@ -0,0 +1,15 @@
+/* $Header: /pjproject/pjlib/src/pj++/pj++.cpp 4 4/17/05 11:59a Bennylp $ */
+#include <pj++/scanner.hpp>
+#include <pj++/timer.hpp>
+#include <pj/except.h>
+
+void PJ_Scanner::syntax_error_handler_throw_pj(pj_scanner *)
+{
+ PJ_THROW( PJ_Scanner::SYNTAX_ERROR );
+}
+
+void PJ_Timer_Entry::timer_heap_callback(pj_timer_heap_t *, pj_timer_entry *e)
+{
+ PJ_Timer_Entry *entry = static_cast<PJ_Timer_Entry*>(e);
+ entry->on_timeout();
+}
diff --git a/pjlib/src/pj++/pool.hpp b/pjlib/src/pj++/pool.hpp
new file mode 100644
index 00000000..9ceffa7d
--- /dev/null
+++ b/pjlib/src/pj++/pool.hpp
@@ -0,0 +1,84 @@
+/* $Header: /pjproject/pjlib/src/pj++/pool.hpp 4 8/24/05 10:29a Bennylp $ */
+#ifndef __PJPP_POOL_H__
+#define __PJPP_POOL_H__
+
+#include <pj/pool.h>
+
+class PJ_Pool
+{
+public:
+ const char *getobjname() const
+ {
+ return pj_pool_getobjname(this->pool_());
+ }
+
+ pj_pool_t *pool_()
+ {
+ return (pj_pool_t*)this;
+ }
+
+ const pj_pool_t *pool_() const
+ {
+ return (const pj_pool_t*)this;
+ }
+
+ void release()
+ {
+ pj_pool_release(this->pool_());
+ }
+
+ void reset()
+ {
+ pj_pool_reset(this->pool_());
+ }
+
+ pj_size_t get_capacity()
+ {
+ pj_pool_get_capacity(this->pool_());
+ }
+
+ pj_size_t get_used_size()
+ {
+ pj_pool_get_used_size(this->pool_());
+ }
+
+ void *alloc(pj_size_t size)
+ {
+ return pj_pool_alloc(this->pool_(), size);
+ }
+
+ void *calloc(pj_size_t count, pj_size_t elem)
+ {
+ return pj_pool_calloc(this->pool_(), count, elem);
+ }
+};
+
+class PJ_Caching_Pool
+{
+public:
+ void init(pj_size_t max_capacity,
+ const pj_pool_factory_policy *pol=&pj_pool_factory_default_policy)
+ {
+ pj_caching_pool_init(&cp_, pol, max_capacity);
+ }
+
+ void destroy()
+ {
+ pj_caching_pool_destroy(&cp_);
+ }
+
+ PJ_Pool *create_pool(const char *name, pj_size_t initial_size, pj_size_t increment_size, pj_pool_callback *callback)
+ {
+ return (PJ_Pool*) (*cp_.factory.create_pool)(&cp_.factory, name, initial_size, increment_size, callback);
+ }
+
+ void release_pool( PJ_Pool *pool )
+ {
+ pj_pool_release(pool->pool_());
+ }
+
+private:
+ pj_caching_pool cp_;
+};
+
+#endif /* __PJPP_POOL_H__ */
diff --git a/pjlib/src/pj++/proactor.cpp b/pjlib/src/pj++/proactor.cpp
new file mode 100644
index 00000000..58c342e0
--- /dev/null
+++ b/pjlib/src/pj++/proactor.cpp
@@ -0,0 +1,296 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj++/proactor.cpp 7 10/29/05 11:51a Bennylp $ */
+#include <pj++/proactor.hpp>
+#include <pj/string.h> // memset
+
+static struct pj_ioqueue_callback ioqueue_cb =
+{
+ &PJ_Event_Handler::read_complete_cb,
+ &PJ_Event_Handler::write_complete_cb,
+ &PJ_Event_Handler::accept_complete_cb,
+ &PJ_Event_Handler::connect_complete_cb,
+};
+
+PJ_Event_Handler::PJ_Event_Handler()
+: proactor_(NULL), key_(NULL)
+{
+ pj_memset(&timer_, 0, sizeof(timer_));
+ timer_.user_data = this;
+ timer_.cb = &timer_callback;
+}
+
+PJ_Event_Handler::~PJ_Event_Handler()
+{
+}
+
+#if PJ_HAS_TCP
+bool PJ_Event_Handler::connect(const PJ_INET_Addr &addr)
+{
+ pj_assert(key_ != NULL && proactor_ != NULL);
+
+ if (key_ == NULL || proactor_ == NULL)
+ return false;
+
+ int status = pj_ioqueue_connect(proactor_->get_io_queue(), key_,
+ &addr, sizeof(PJ_INET_Addr));
+ if (status == 0) {
+ on_connect_complete(0);
+ return true;
+ } else if (status == PJ_IOQUEUE_PENDING) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool PJ_Event_Handler::accept(PJ_Socket *sock, PJ_INET_Addr *local, PJ_INET_Addr *remote)
+{
+ pj_assert(key_ != NULL && proactor_ != NULL);
+
+ if (key_ == NULL || proactor_ == NULL)
+ return false;
+
+ int status = pj_ioqueue_accept(proactor_->get_io_queue(), key_,
+ &sock->get_handle(),
+ local_addr, remote,
+ (remote? sizeof(*remote) : 0));
+ if (status == 0) {
+ on_accept_complete(0);
+ return true;
+ } else if (status == PJ_IOQUEUE_PENDING) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+#endif
+
+bool PJ_Event_Handler::read(void *buf, pj_size_t len)
+{
+ pj_assert(key_ != NULL && proactor_ != NULL);
+
+ if (key_ == NULL || proactor_ == NULL)
+ return false;
+
+ int bytes_status = pj_ioqueue_read(proactor_->get_io_queue(),
+ key_, buf, len);
+ if (bytes_status >= 0) {
+ on_read_complete(bytes_status);
+ return true;
+ } else if (bytes_status == PJ_IOQUEUE_PENDING) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool PJ_Event_Handler::recvfrom(void *buf, pj_size_t len, PJ_INET_Addr *addr)
+{
+ pj_assert(key_ != NULL && proactor_ != NULL);
+
+ if (key_ == NULL || proactor_ == NULL)
+ return false;
+
+
+ tmp_recvfrom_addr_len = sizeof(PJ_INET_Addr);
+
+ int bytes_status = pj_ioqueue_recvfrom(proactor_->get_io_queue(),
+ key_, buf, len,
+ addr,
+ (addr? &tmp_recvfrom_addr_len : NULL));
+ if (bytes_status >= 0) {
+ on_read_complete(bytes_status);
+ return true;
+ } else if (bytes_status == PJ_IOQUEUE_PENDING) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool PJ_Event_Handler::write(const void *data, pj_size_t len)
+{
+ pj_assert(key_ != NULL && proactor_ != NULL);
+
+ if (key_ == NULL || proactor_ == NULL)
+ return false;
+
+ int bytes_status = pj_ioqueue_write(proactor_->get_io_queue(),
+ key_, data, len);
+ if (bytes_status >= 0) {
+ on_write_complete(bytes_status);
+ return true;
+ } else if (bytes_status == PJ_IOQUEUE_PENDING) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool PJ_Event_Handler::sendto(const void *data, pj_size_t len, const PJ_INET_Addr &addr)
+{
+ pj_assert(key_ != NULL && proactor_ != NULL);
+
+ if (key_ == NULL || proactor_ == NULL)
+ return false;
+
+ int bytes_status = pj_ioqueue_sendto(proactor_->get_io_queue(),
+ key_, data, len,
+ &addr, sizeof(PJ_INET_Addr));
+ if (bytes_status >= 0) {
+ on_write_complete(bytes_status);
+ return true;
+ } else if (bytes_status == PJ_IOQUEUE_PENDING) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+void PJ_Event_Handler::read_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_read)
+{
+ PJ_Event_Handler *handler =
+ (PJ_Event_Handler*) pj_ioqueue_get_user_data(key);
+
+ handler->on_read_complete(bytes_read);
+}
+
+void PJ_Event_Handler::write_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent)
+{
+ PJ_Event_Handler *handler =
+ (PJ_Event_Handler*) pj_ioqueue_get_user_data(key);
+
+ handler->on_write_complete(bytes_sent);
+}
+
+void PJ_Event_Handler::accept_complete_cb(pj_ioqueue_key_t *key, int status)
+{
+#if PJ_HAS_TCP
+ PJ_Event_Handler *handler =
+ (PJ_Event_Handler*) pj_ioqueue_get_user_data(key);
+
+ handler->on_accept_complete(status);
+#endif
+}
+
+void PJ_Event_Handler::connect_complete_cb(pj_ioqueue_key_t *key, int status)
+{
+#if PJ_HAS_TCP
+ PJ_Event_Handler *handler =
+ (PJ_Event_Handler*) pj_ioqueue_get_user_data(key);
+
+ handler->on_connect_complete(status);
+#endif
+}
+
+void PJ_Event_Handler::timer_callback( pj_timer_heap_t *timer_heap,
+ struct pj_timer_entry *entry)
+{
+ PJ_Event_Handler *handler = (PJ_Event_Handler*) entry->user_data;
+ handler->on_timeout(entry->id);
+}
+
+
+PJ_Proactor *PJ_Proactor::create(PJ_Pool *pool, pj_size_t max_fd,
+ pj_size_t timer_entry_count, unsigned timer_flags)
+{
+ PJ_Proactor *p = (PJ_Proactor*) pool->calloc(1, sizeof(PJ_Proactor));
+ if (!p) return NULL;
+
+ p->ioq_ = pj_ioqueue_create(pool->pool_(), max_fd);
+ if (!p->ioq_) return NULL;
+
+ p->th_ = pj_timer_heap_create(pool->pool_(), timer_entry_count, timer_flags);
+ if (!p->th_) return NULL;
+
+ return p;
+}
+
+void PJ_Proactor::destroy()
+{
+ pj_ioqueue_destroy(ioq_);
+}
+
+bool PJ_Proactor::register_handler(PJ_Pool *pool, PJ_Event_Handler *handler)
+{
+ pj_assert(handler->key_ == NULL && handler->proactor_ == NULL);
+
+ if (handler->key_ != NULL)
+ return false;
+
+ handler->key_ = pj_ioqueue_register_sock(pool->pool_(), ioq_,
+ handler->get_handle(),
+ handler, &ioqueue_cb);
+ if (handler->key_ != NULL) {
+ handler->proactor_ = this;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void PJ_Proactor::unregister_handler(PJ_Event_Handler *handler)
+{
+ if (handler->key_ == NULL) return;
+ pj_ioqueue_unregister(ioq_, handler->key_);
+ handler->key_ = NULL;
+ handler->proactor_ = NULL;
+}
+
+bool PJ_Proactor::schedule_timer( pj_timer_heap_t *timer, PJ_Event_Handler *handler,
+ const PJ_Time_Val &delay, int id)
+{
+ handler->timer_.id = id;
+ return pj_timer_heap_schedule(timer, &handler->timer_, &delay) == 0;
+}
+
+bool PJ_Proactor::schedule_timer(PJ_Event_Handler *handler, const PJ_Time_Val &delay,
+ int id)
+{
+ return schedule_timer(th_, handler, delay, id);
+}
+
+bool PJ_Proactor::cancel_timer(PJ_Event_Handler *handler)
+{
+ return pj_timer_heap_cancel(th_, &handler->timer_) == 1;
+}
+
+bool PJ_Proactor::handle_events(PJ_Time_Val *max_timeout)
+{
+ pj_time_val timeout;
+
+ timeout.sec = timeout.msec = 0; /* timeout is 'out' var. */
+
+ if (pj_timer_heap_poll( th_, &timeout ) > 0)
+ return true;
+
+ if (timeout.sec < 0) timeout.sec = PJ_MAXINT32;
+
+ /* If caller specifies maximum time to wait, then compare the value with
+ * the timeout to wait from timer, and use the minimum value.
+ */
+ if (max_timeout && PJ_TIME_VAL_GT(timeout, *max_timeout)) {
+ timeout = *max_timeout;
+ }
+
+ /* Poll events in ioqueue. */
+ int result;
+
+ result = pj_ioqueue_poll(ioq_, &timeout);
+ if (result != 1)
+ return false;
+
+ return true;
+}
+
+pj_ioqueue_t *PJ_Proactor::get_io_queue()
+{
+ return ioq_;
+}
+
+pj_timer_heap_t *PJ_Proactor::get_timer_heap()
+{
+ return th_;
+}
+
diff --git a/pjlib/src/pj++/proactor.hpp b/pjlib/src/pj++/proactor.hpp
new file mode 100644
index 00000000..d5dc0367
--- /dev/null
+++ b/pjlib/src/pj++/proactor.hpp
@@ -0,0 +1,86 @@
+/* $Header: /pjproject/pjlib/src/pj++/proactor.hpp 3 8/24/05 10:29a Bennylp $ */
+#ifndef __PJPP_EVENT_HANDLER_H__
+#define __PJPP_EVENT_HANDLER_H__
+
+#include <pj/ioqueue.h>
+#include <pj++/pool.hpp>
+#include <pj++/sock.hpp>
+#include <pj++/timer.hpp>
+
+class PJ_Proactor;
+
+
+class PJ_Event_Handler
+{
+ friend class PJ_Proactor;
+public:
+ PJ_Event_Handler();
+ virtual ~PJ_Event_Handler();
+
+ virtual pj_oshandle_t get_handle() = 0;
+
+ bool read(void *buf, pj_size_t len);
+ bool recvfrom(void *buf, pj_size_t len, PJ_INET_Addr *addr);
+ bool write(const void *data, pj_size_t len);
+ bool sendto(const void *data, pj_size_t len, const PJ_INET_Addr &addr);
+#if PJ_HAS_TCP
+ bool connect(const PJ_INET_Addr &addr);
+ bool accept(PJ_Socket *sock, PJ_INET_Addr *local=NULL, PJ_INET_Addr *remote=NULL);
+#endif
+
+protected:
+ //
+ // Overridables
+ //
+ virtual void on_timeout(int data) {}
+ virtual void on_read_complete(pj_ssize_t bytes_read) {}
+ virtual void on_write_complete(pj_ssize_t bytes_sent) {}
+#if PJ_HAS_TCP
+ virtual void on_connect_complete(int status) {}
+ virtual void on_accept_complete(int status) {}
+#endif
+
+private:
+ PJ_Proactor *proactor_;
+ pj_ioqueue_key_t *key_;
+ pj_timer_entry timer_;
+ int tmp_recvfrom_addr_len;
+
+public:
+ // Internal IO Queue/timer callback.
+ static void timer_callback( pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry);
+ static void read_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_read);
+ static void write_complete_cb(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent);
+ static void accept_complete_cb(pj_ioqueue_key_t *key, int status);
+ static void connect_complete_cb(pj_ioqueue_key_t *key, int status);
+};
+
+class PJ_Proactor
+{
+public:
+ static PJ_Proactor *create(PJ_Pool *pool, pj_size_t max_fd,
+ pj_size_t timer_entry_count, unsigned timer_flags=0);
+
+ void destroy();
+
+ bool register_handler(PJ_Pool *pool, PJ_Event_Handler *handler);
+ void unregister_handler(PJ_Event_Handler *handler);
+
+ static bool schedule_timer( pj_timer_heap_t *timer, PJ_Event_Handler *handler,
+ const PJ_Time_Val &delay, int id=-1);
+ bool schedule_timer(PJ_Event_Handler *handler, const PJ_Time_Val &delay, int id=-1);
+ bool cancel_timer(PJ_Event_Handler *handler);
+
+ bool handle_events(PJ_Time_Val *timeout);
+
+ pj_ioqueue_t *get_io_queue();
+ pj_timer_heap_t *get_timer_heap();
+
+private:
+ pj_ioqueue_t *ioq_;
+ pj_timer_heap_t *th_;
+
+ PJ_Proactor() {}
+};
+
+#endif /* __PJPP_EVENT_HANDLER_H__ */
diff --git a/pjlib/src/pj++/scanner.hpp b/pjlib/src/pj++/scanner.hpp
new file mode 100644
index 00000000..1ab44e01
--- /dev/null
+++ b/pjlib/src/pj++/scanner.hpp
@@ -0,0 +1,171 @@
+/* $Header: /pjproject/pjlib/src/pj++/scanner.hpp 3 2/27/05 10:09p Bennylp $ */
+#ifndef __PJPP_SCANNER_H__
+#define __PJPP_SCANNER_H__
+
+#include <pj/scanner.h>
+#include <pj++/string.hpp>
+
+class PJ_CharSpec
+{
+public:
+ PJ_CharSpec() { pj_cs_init(cs__); }
+
+ void set(int c) { pj_cs_set(cs__, c); }
+ void add_range(int begin, int end) { pj_cs_add_range(cs__, begin, end); }
+ void add_alpha() { pj_cs_add_alpha(cs__); }
+ void add_num() { pj_cs_add_num(cs__); }
+ void add_str(const char *str) { pj_cs_add_str(cs__, str); }
+ void del_range(int begin, int end) { pj_cs_del_range(cs__, begin, end); }
+ void del_str(const char *str) { pj_cs_del_str(cs__, str); }
+ void invert() { pj_cs_invert(cs__); }
+ int match(int c) { return pj_cs_match(cs__, c); }
+
+ pj_char_spec_element_t *cs_()
+ {
+ return cs__;
+ }
+
+ const pj_char_spec_element_t *cs_() const
+ {
+ return cs__;
+ }
+
+private:
+ pj_char_spec cs__;
+};
+
+class PJ_Scanner
+{
+public:
+ PJ_Scanner() {}
+
+ enum
+ {
+ SYNTAX_ERROR = 101
+ };
+ static void syntax_error_handler_throw_pj(pj_scanner *);
+
+ typedef pj_scan_state State;
+
+ void init(char *buf, int len, unsigned options=PJ_SCAN_AUTOSKIP_WS,
+ pj_syn_err_func_ptr callback = &syntax_error_handler_throw_pj)
+ {
+ pj_scan_init(&scanner_, buf, len, options, callback);
+ }
+
+ void fini()
+ {
+ pj_scan_fini(&scanner_);
+ }
+
+ int eof() const
+ {
+ return pj_scan_is_eof(&scanner_);
+ }
+
+ int peek_char() const
+ {
+ return *scanner_.current;
+ }
+
+ int peek(const PJ_CharSpec *cs, PJ_String *out)
+ {
+ return pj_scan_peek(&scanner_, cs->cs_(), out);
+ }
+
+ int peek_n(pj_size_t len, PJ_String *out)
+ {
+ return pj_scan_peek_n(&scanner_, len, out);
+ }
+
+ int peek_until(const PJ_CharSpec *cs, PJ_String *out)
+ {
+ return pj_scan_peek_until(&scanner_, cs->cs_(), out);
+ }
+
+ void get(const PJ_CharSpec *cs, PJ_String *out)
+ {
+ pj_scan_get(&scanner_, cs->cs_(), out);
+ }
+
+ void get_n(unsigned N, PJ_String *out)
+ {
+ pj_scan_get_n(&scanner_, N, out);
+ }
+
+ int get_char()
+ {
+ return pj_scan_get_char(&scanner_);
+ }
+
+ void get_quote(int begin_quote, int end_quote, PJ_String *out)
+ {
+ pj_scan_get_quote(&scanner_, begin_quote, end_quote, out);
+ }
+
+ void get_newline()
+ {
+ pj_scan_get_newline(&scanner_);
+ }
+
+ void get_until(const PJ_CharSpec *cs, PJ_String *out)
+ {
+ pj_scan_get_until(&scanner_, cs->cs_(), out);
+ }
+
+ void get_until_ch(int until_ch, PJ_String *out)
+ {
+ pj_scan_get_until_ch(&scanner_, until_ch, out);
+ }
+
+ void get_until_chr(const char *spec, PJ_String *out)
+ {
+ pj_scan_get_until_chr(&scanner_, spec, out);
+ }
+
+ void advance_n(unsigned N, bool skip_ws=true)
+ {
+ pj_scan_advance_n(&scanner_, N, skip_ws);
+ }
+
+ int strcmp(const char *s, int len)
+ {
+ return pj_scan_strcmp(&scanner_, s, len);
+ }
+
+ int stricmp(const char *s, int len)
+ {
+ return pj_scan_stricmp(&scanner_, s, len);
+ }
+
+ void skip_ws()
+ {
+ pj_scan_skip_whitespace(&scanner_);
+ }
+
+ void save_state(State *state)
+ {
+ pj_scan_save_state(&scanner_, state);
+ }
+
+ void restore_state(State *state)
+ {
+ pj_scan_restore_state(&scanner_, state);
+ }
+
+ int get_pos_line() const
+ {
+ return scanner_.line;
+ }
+
+ int get_pos_col() const
+ {
+ return scanner_.col;
+ }
+
+
+private:
+ pj_scanner scanner_;
+};
+
+#endif /* __PJPP_SCANNER_H__ */
diff --git a/pjlib/src/pj++/sock.hpp b/pjlib/src/pj++/sock.hpp
new file mode 100644
index 00000000..aa62c158
--- /dev/null
+++ b/pjlib/src/pj++/sock.hpp
@@ -0,0 +1,194 @@
+/* $Header: /pjproject/pjlib/src/pj++/sock.hpp 2 2/24/05 11:23a Bennylp $ */
+#ifndef __PJPP_SOCK_H__
+#define __PJPP_SOCK_H__
+
+#include <pj/sock.h>
+
+class PJ_Addr
+{
+};
+
+class PJ_INET_Addr : public pj_sockaddr_in, public PJ_Addr
+{
+public:
+ pj_uint16_t get_port_number() const
+ {
+ return pj_sockaddr_get_port(this);
+ }
+
+ void set_port_number(pj_uint16_t port)
+ {
+ sin_family = PJ_AF_INET;
+ pj_sockaddr_set_port(this, port);
+ }
+
+ pj_uint32_t get_ip_address() const
+ {
+ return pj_sockaddr_get_addr(this);
+ }
+
+ const char *get_address() const
+ {
+ return pj_sockaddr_get_str_addr(this);
+ }
+
+ void set_ip_address(pj_uint32_t addr)
+ {
+ sin_family = PJ_AF_INET;
+ pj_sockaddr_set_addr(this, addr);
+ }
+
+ pj_status_t set_address(const pj_str_t *addr)
+ {
+ return pj_sockaddr_set_str_addr(this, addr);
+ }
+
+ pj_status_t set_address(const char *addr)
+ {
+ return pj_sockaddr_set_str_addr2(this, addr);
+ }
+
+ int cmp(const PJ_INET_Addr &rhs) const
+ {
+ return pj_sockaddr_cmp(this, &rhs);
+ }
+
+ bool operator==(const PJ_INET_Addr &rhs) const
+ {
+ return cmp(rhs) == 0;
+ }
+};
+
+class PJ_Socket
+{
+public:
+ PJ_Socket() {}
+ PJ_Socket(const PJ_Socket &rhs) : sock_(rhs.sock_) {}
+
+ void set_handle(pj_sock_t sock)
+ {
+ sock_ = sock;
+ }
+
+ pj_sock_t get_handle() const
+ {
+ return sock_;
+ }
+
+ pj_sock_t& get_handle()
+ {
+ return sock_;
+ }
+
+ bool socket(int af, int type, int proto, pj_uint32_t flag=0)
+ {
+ sock_ = pj_sock_socket(af, type, proto, flag);
+ return sock_ != -1;
+ }
+
+ bool bind(const PJ_INET_Addr &addr)
+ {
+ return pj_sock_bind(sock_, &addr, sizeof(PJ_INET_Addr)) == 0;
+ }
+
+ bool close()
+ {
+ return pj_sock_close(sock_) == 0;
+ }
+
+ bool getpeername(PJ_INET_Addr *addr)
+ {
+ int namelen;
+ return pj_sock_getpeername(sock_, addr, &namelen) == 0;
+ }
+
+ bool getsockname(PJ_INET_Addr *addr)
+ {
+ int namelen;
+ return pj_sock_getsockname(sock_, addr, &namelen) == 0;
+ }
+
+ bool getsockopt(int level, int optname, void *optval, int *optlen)
+ {
+ return pj_sock_getsockopt(sock_, level, optname, optval, optlen) == 0;
+ }
+
+ bool setsockopt(int level, int optname, const void *optval, int optlen)
+ {
+ return pj_sock_setsockopt(sock_, level, optname, optval, optlen) == 0;
+ }
+
+ bool ioctl(long cmd, pj_uint32_t *val)
+ {
+ return pj_sock_ioctl(sock_, cmd, val) == 0;
+ }
+
+ int recv(void *buf, int len, int flag = 0)
+ {
+ return pj_sock_recv(sock_, buf, len, flag);
+ }
+
+ int send(const void *buf, int len, int flag = 0)
+ {
+ return pj_sock_send(sock_, buf, len, flag);
+ }
+
+protected:
+ pj_sock_t sock_;
+};
+
+#if PJ_HAS_TCP
+class PJ_Sock_Stream : public PJ_Socket
+{
+public:
+ PJ_Sock_Stream() {}
+ PJ_Sock_Stream(const PJ_Sock_Stream &rhs) : PJ_Socket(rhs) {}
+ PJ_Sock_Stream &operator=(const PJ_Sock_Stream &rhs) { sock_ = rhs.sock_; return *this; }
+
+ bool listen(int backlog = 5)
+ {
+ return pj_sock_listen(sock_, backlog) == 0;
+ }
+
+ bool accept(PJ_Sock_Stream *new_sock, PJ_INET_Addr *addr, int *addrlen)
+ {
+ pj_sock_t s = pj_sock_accept(sock_, addr, addrlen);
+ if (s == -1)
+ return false;
+ new_sock->set_handle(s);
+ return true;
+ }
+
+ bool connect(const PJ_INET_Addr &addr)
+ {
+ return pj_sock_connect(sock_, &addr, sizeof(PJ_INET_Addr)) == 0;
+ }
+
+ bool shutdown(int how)
+ {
+ return pj_sock_shutdown(sock_, how) == 0;
+ }
+
+};
+#endif
+
+class PJ_Sock_Dgram : public PJ_Socket
+{
+public:
+ PJ_Sock_Dgram() {}
+ PJ_Sock_Dgram(const PJ_Sock_Dgram &rhs) : PJ_Socket(rhs) {}
+ PJ_Sock_Dgram &operator=(const PJ_Sock_Dgram &rhs) { sock_ = rhs.sock_; return *this; }
+
+ int recvfrom(void *buf, int len, int flag, PJ_INET_Addr *fromaddr)
+ {
+ int addrlen;
+ return pj_sock_recvfrom(sock_, buf, len, flag, fromaddr, &addrlen);
+ }
+
+ int sendto(const void *buf, int len, int flag, const PJ_INET_Addr &addr)
+ {
+ return pj_sock_sendto(sock_, buf, len, flag, &addr, sizeof(PJ_INET_Addr));
+ }
+};
+
+#endif /* __PJPP_SOCK_H__ */
diff --git a/pjlib/src/pj++/string.hpp b/pjlib/src/pj++/string.hpp
new file mode 100644
index 00000000..8bbb680d
--- /dev/null
+++ b/pjlib/src/pj++/string.hpp
@@ -0,0 +1,247 @@
+/* $Header: /pjproject/pjlib/src/pj++/string.hpp 2 2/24/05 11:23a Bennylp $ */
+#ifndef __PJPP_STRING_H__
+#define __PJPP_STRING_H__
+
+#include <pj/string.h>
+#include <pj++/pool.hpp>
+
+class PJ_String : public pj_str_t
+{
+public:
+ PJ_String()
+ {
+ pj_assert(sizeof(PJ_String) == sizeof(pj_str_t));
+ ptr=NULL; slen=0;
+ }
+
+ explicit PJ_String(char *str)
+ {
+ set(str);
+ }
+
+ PJ_String(PJ_Pool *pool, const char *src)
+ {
+ set(pool, src);
+ }
+
+ explicit PJ_String(pj_str_t *s)
+ {
+ set(s);
+ }
+
+ PJ_String(PJ_Pool *pool, const pj_str_t *s)
+ {
+ set(pool, s);
+ }
+
+ explicit PJ_String(PJ_String &rhs)
+ {
+ set(rhs);
+ }
+
+ PJ_String(PJ_Pool *pool, const PJ_String &rhs)
+ {
+ set(pool, rhs);
+ }
+
+ PJ_String(char *str, pj_size_t len)
+ {
+ set(str, len);
+ }
+
+ PJ_String(char *begin, char *end)
+ {
+ pj_strset3(this, begin, end);
+ }
+
+ pj_size_t length() const
+ {
+ return pj_strlen(this);
+ }
+
+ pj_size_t size() const
+ {
+ return length();
+ }
+
+ const char *buf() const
+ {
+ return ptr;
+ }
+
+ void set(char *str)
+ {
+ pj_strset2(this, str);
+ }
+
+ void set(PJ_Pool *pool, const char *s)
+ {
+ pj_strdup2(pool->pool_(), this, s);
+ }
+
+ void set(pj_str_t *s)
+ {
+ pj_strassign(this, s);
+ }
+
+ void set(PJ_Pool *pool, const pj_str_t *s)
+ {
+ pj_strdup(pool->pool_(), this, s);
+ }
+
+ void set(char *str, pj_size_t len)
+ {
+ pj_strset(this, str, len);
+ }
+
+ void set(char *begin, char *end)
+ {
+ pj_strset3(this, begin, end);
+ }
+
+ void set(PJ_String &rhs)
+ {
+ pj_strassign(this, &rhs);
+ }
+
+ void set(PJ_Pool *pool, const PJ_String *s)
+ {
+ pj_strdup(pool->pool_(), this, s);
+ }
+
+ void set(PJ_Pool *pool, const PJ_String &s)
+ {
+ pj_strdup(pool->pool_(), this, &s);
+ }
+
+ void strcpy(const pj_str_t *s)
+ {
+ pj_strcpy(this, s);
+ }
+
+ void strcpy(const PJ_String &rhs)
+ {
+ pj_strcpy(this, &rhs);
+ }
+
+ void strcpy(const char *s)
+ {
+ pj_strcpy2(this, s);
+ }
+
+ int strcmp(const char *s) const
+ {
+ return pj_strcmp2(this, s);
+ }
+
+ int strcmp(const pj_str_t *s) const
+ {
+ return pj_strcmp(this, s);
+ }
+
+ int strcmp(const PJ_String &rhs) const
+ {
+ return pj_strcmp(this, &rhs);
+ }
+
+ int strncmp(const char *s, pj_size_t len) const
+ {
+ return pj_strncmp2(this, s, len);
+ }
+
+ int strncmp(const pj_str_t *s, pj_size_t len) const
+ {
+ return pj_strncmp(this, s, len);
+ }
+
+ int strncmp(const PJ_String &rhs, pj_size_t len) const
+ {
+ return pj_strncmp(this, &rhs, len);
+ }
+
+ int stricmp(const char *s) const
+ {
+ return pj_stricmp2(this, s);
+ }
+
+ int stricmp(const pj_str_t *s) const
+ {
+ return pj_stricmp(this, s);
+ }
+
+ int stricmp(const PJ_String &rhs) const
+ {
+ return stricmp(&rhs);
+ }
+
+ int strnicmp(const char *s, pj_size_t len) const
+ {
+ return pj_strnicmp2(this, s, len);
+ }
+
+ int strnicmp(const pj_str_t *s, pj_size_t len) const
+ {
+ return pj_strnicmp(this, s, len);
+ }
+
+ int strnicmp(const PJ_String &rhs, pj_size_t len) const
+ {
+ return strnicmp(&rhs, len);
+ }
+
+ bool operator==(const char *s) const
+ {
+ return strcmp(s) == 0;
+ }
+
+ bool operator==(const pj_str_t *s) const
+ {
+ return strcmp(s) == 0;
+ }
+
+ bool operator==(const PJ_String &rhs) const
+ {
+ return pj_strcmp(this, &rhs) == 0;
+ }
+
+ char *strchr(int chr)
+ {
+ return pj_strchr(this, chr);
+ }
+
+ char *find(int chr)
+ {
+ return strchr(chr);
+ }
+
+ void strcat(const PJ_String &rhs)
+ {
+ pj_strcat(this, &rhs);
+ }
+
+ void ltrim()
+ {
+ pj_strltrim(this);
+ }
+
+ void rtrim()
+ {
+ pj_strrtrim(this);
+ }
+
+ void trim()
+ {
+ pj_strtrim(this);
+ }
+
+ unsigned long toul() const
+ {
+ return pj_strtoul(this);
+ }
+
+private:
+ //PJ_String(const PJ_String &rhs) {}
+ void operator=(const PJ_String &rhs) { pj_assert(false); }
+};
+
+#endif /* __PJPP_STRING_H__ */
diff --git a/pjlib/src/pj++/timer.hpp b/pjlib/src/pj++/timer.hpp
new file mode 100644
index 00000000..ccca633a
--- /dev/null
+++ b/pjlib/src/pj++/timer.hpp
@@ -0,0 +1,105 @@
+/* $Header: /pjproject/pjlib/src/pj++/timer.hpp 4 8/24/05 10:29a Bennylp $ */
+#ifndef __PJPP_TIMER_H__
+#define __PJPP_TIMER_H__
+
+#include <pj/timer.h>
+#include <pj++/types.hpp>
+
+class PJ_Timer_Heap;
+
+class PJ_Timer_Entry : private pj_timer_entry
+{
+ friend class PJ_Timer_Heap;
+
+public:
+ static void timer_heap_callback(pj_timer_heap_t *, pj_timer_entry *);
+
+ PJ_Timer_Entry() { cb = &timer_heap_callback; }
+ PJ_Timer_Entry(int arg_id, void *arg_user_data)
+ {
+ cb = &timer_heap_callback;
+ init(arg_id, arg_user_data);
+ }
+
+ virtual void on_timeout() = 0;
+
+ void init(int arg_id, void *arg_user_data)
+ {
+ id = arg_id;
+ user_data = arg_user_data;
+ }
+
+ int get_id() const
+ {
+ return id;
+ }
+
+ void set_id(int arg_id)
+ {
+ id = arg_id;
+ }
+
+ void set_user_data(void *arg_user_data)
+ {
+ user_data = arg_user_data;
+ }
+
+ void *get_user_data() const
+ {
+ return user_data;
+ }
+
+ const PJ_Time_Val &get_timeout() const
+ {
+ pj_assert(sizeof(PJ_Time_Val) == sizeof(pj_time_val));
+ return (PJ_Time_Val&)_timer_value;
+ }
+};
+
+class PJ_Timer_Heap
+{
+public:
+ PJ_Timer_Heap() {}
+
+ bool create(PJ_Pool *pool, pj_size_t initial_count,
+ unsigned flag = PJ_TIMER_HEAP_SYNCHRONIZE)
+ {
+ ht_ = pj_timer_heap_create(pool->pool_(), initial_count, flag);
+ return ht_ != NULL;
+ }
+
+ pj_timer_heap_t *get_timer_heap()
+ {
+ return ht_;
+ }
+
+ bool schedule( PJ_Timer_Entry *ent, const PJ_Time_Val &delay)
+ {
+ return pj_timer_heap_schedule(ht_, ent, &delay) == 0;
+ }
+
+ bool cancel(PJ_Timer_Entry *ent)
+ {
+ return pj_timer_heap_cancel(ht_, ent) == 1;
+ }
+
+ pj_size_t count()
+ {
+ return pj_timer_heap_count(ht_);
+ }
+
+ void earliest_time(PJ_Time_Val *t)
+ {
+ pj_timer_heap_earliest_time(ht_, t);
+ }
+
+ int poll(PJ_Time_Val *next_delay = NULL)
+ {
+ return pj_timer_heap_poll(ht_, next_delay);
+ }
+
+private:
+ pj_timer_heap_t *ht_;
+};
+
+#endif /* __PJPP_TIMER_H__ */
diff --git a/pjlib/src/pj++/tree.hpp b/pjlib/src/pj++/tree.hpp
new file mode 100644
index 00000000..d2243e57
--- /dev/null
+++ b/pjlib/src/pj++/tree.hpp
@@ -0,0 +1,107 @@
+/* $Header: /pjproject/pjlib/src/pj++/tree.hpp 2 2/24/05 11:23a Bennylp $ */
+#ifndef __PJPP_TREE_H__
+#define __PJPP_TREE_H__
+
+#include <pj/rbtree.h>
+
+class PJ_Tree
+{
+public:
+ typedef pj_rbtree_comp Comp;
+ class iterator;
+ class reverse_iterator;
+
+ class Node : private pj_rbtree_node
+ {
+ friend class PJ_Tree;
+ friend class iterator;
+ friend class reverse_iterator;
+
+ public:
+ Node() {}
+ explicit Node(void *data) { user_data = data; }
+ void set_user_data(void *data) { user_data = data; }
+ void *get_user_data() const { return user_data; }
+ };
+
+ class iterator
+ {
+ public:
+ iterator() {}
+ iterator(const iterator &rhs) : tr_(rhs.tr_), nd_(rhs.nd_) {}
+ iterator(pj_rbtree *tr, pj_rbtree_node *nd) : tr_(tr), nd_(nd) {}
+ Node *operator*() { return (Node*)nd_; }
+ bool operator==(const iterator &rhs) const { return tr_==rhs.tr_ && nd_==rhs.nd_; }
+ iterator &operator=(const iterator &rhs) { tr_=rhs.tr_; nd_=rhs.nd_; return *this; }
+ void operator++() { nd_=pj_rbtree_next(tr_, nd_); }
+ void operator--() { nd_=pj_rbtree_prev(tr_, nd_); }
+ protected:
+ pj_rbtree *tr_;
+ pj_rbtree_node *nd_;
+ };
+
+ class reverse_iterator : public iterator
+ {
+ public:
+ reverse_iterator() {}
+ reverse_iterator(const reverse_iterator &it) : iterator(it) {}
+ reverse_iterator(pj_rbtree *t, pj_rbtree_node *n) : iterator(t, n) {}
+ reverse_iterator &operator=(const reverse_iterator &rhs) { iterator::operator=(rhs); return *this; }
+ Node *operator*() { return (Node*)nd_; }
+ bool operator==(const reverse_iterator &rhs) const { return iterator::operator==(rhs); }
+ void operator++() { nd_=pj_rbtree_prev(tr_, nd_); }
+ void operator--() { nd_=pj_rbtree_next(tr_, nd_); }
+ };
+
+ explicit PJ_Tree(Comp *comp) { pj_rbtree_init(&t_, comp); }
+
+ iterator begin()
+ {
+ return iterator(&t_, pj_rbtree_first(&t_));
+ }
+
+ iterator end()
+ {
+ return iterator(&t_, NULL);
+ }
+
+ reverse_iterator rbegin()
+ {
+ return reverse_iterator(&t_, pj_rbtree_last(&t_));
+ }
+
+ reverse_iterator rend()
+ {
+ return reverse_iterator(&t_, NULL);
+ }
+
+ bool insert(Node *node)
+ {
+ return pj_rbtree_insert(&t_, node)==0 ? true : false;
+ }
+
+ Node *find(const void *key)
+ {
+ return (Node*)pj_rbtree_find(&t_, key);
+ }
+
+ Node *erase(Node *node)
+ {
+ return (Node*)pj_rbtree_erase(&t_, node);
+ }
+
+ unsigned max_height(Node *node=NULL)
+ {
+ return pj_rbtree_max_height(&t_, node);
+ }
+
+ unsigned min_height(Node *node=NULL)
+ {
+ return pj_rbtree_min_height(&t_, node);
+ }
+
+private:
+ pj_rbtree t_;
+};
+
+#endif /* __PJPP_TREE_H__ */
diff --git a/pjlib/src/pj++/types.hpp b/pjlib/src/pj++/types.hpp
new file mode 100644
index 00000000..888c8456
--- /dev/null
+++ b/pjlib/src/pj++/types.hpp
@@ -0,0 +1,59 @@
+/* $Header: /pjproject/pjlib/src/pj++/types.hpp 3 4/17/05 11:59a Bennylp $ */
+#ifndef __PJPP_TYPES_H__
+#define __PJPP_TYPES_H__
+
+#include <pj/types.h>
+
+class PJ_Pool;
+class PJ_Socket;
+
+
+class PJ_Time_Val : public pj_time_val
+{
+public:
+ PJ_Time_Val() {}
+ PJ_Time_Val(const PJ_Time_Val &rhs) { sec=rhs.sec; msec=rhs.msec; }
+ explicit PJ_Time_Val(const pj_time_val &tv) { sec = tv.sec; msec = tv.msec; }
+
+ long get_sec() const { return sec; }
+ long get_msec() const { return msec; }
+ void set_sec (long s) { sec = s; }
+ void set_msec(long ms) { msec = ms; normalize(); }
+ long to_msec() const { return PJ_TIME_VAL_MSEC((*this)); }
+
+ bool operator == (const PJ_Time_Val &rhs) const { return PJ_TIME_VAL_EQ((*this), rhs); }
+ bool operator > (const PJ_Time_Val &rhs) const { return PJ_TIME_VAL_GT((*this), rhs); }
+ bool operator >= (const PJ_Time_Val &rhs) const { return PJ_TIME_VAL_GTE((*this), rhs); }
+ bool operator < (const PJ_Time_Val &rhs) const { return PJ_TIME_VAL_LT((*this), rhs); }
+ bool operator <= (const PJ_Time_Val &rhs) const { return PJ_TIME_VAL_LTE((*this), rhs); }
+
+ PJ_Time_Val & operator = (const PJ_Time_Val &rhs) {
+ sec = rhs.sec;
+ msec = rhs.msec;
+ return *this;
+ }
+
+ PJ_Time_Val & operator += (const PJ_Time_Val &rhs) {
+ PJ_TIME_VAL_ADD((*this), rhs);
+ return *this;
+ }
+
+ PJ_Time_Val & operator -= (const PJ_Time_Val &rhs) {
+ PJ_TIME_VAL_SUB((*this), rhs);
+ return *this;
+ }
+
+ /* Must include os.hpp to use these, otherwise unresolved in linking */
+ pj_status_t gettimeofday();
+ pj_parsed_time decode();
+ pj_status_t encode(const pj_parsed_time *pt);
+ pj_status_t to_gmt();
+ pj_status_t to_local();
+
+
+private:
+ void normalize() { pj_time_val_normalize(this); }
+
+};
+
+#endif /* __PJPP_TYPES_H__ */