summaryrefslogtreecommitdiff
path: root/cpp/unpack.hpp
diff options
context:
space:
mode:
authorfrsyuki <frsyuki@vcore.(none)>2009-02-22 15:14:21 +0900
committerfrsyuki <frsyuki@vcore.(none)>2009-02-22 15:14:21 +0900
commit11abec1093cf8c9914b5aeeac383d30abc1cad72 (patch)
tree2deaa42039029e5da89e16c9bcb0dcd8a42ac38a /cpp/unpack.hpp
parent761b3980834e4644ce0ce57f6db13d1c93883380 (diff)
downloadmsgpack-python-11abec1093cf8c9914b5aeeac383d30abc1cad72.tar.gz
c and c++: rewritten and integrated
Diffstat (limited to 'cpp/unpack.hpp')
-rw-r--r--cpp/unpack.hpp157
1 files changed, 122 insertions, 35 deletions
diff --git a/cpp/unpack.hpp b/cpp/unpack.hpp
index cde45e7..8c77726 100644
--- a/cpp/unpack.hpp
+++ b/cpp/unpack.hpp
@@ -18,6 +18,7 @@
#ifndef MSGPACK_UNPACK_HPP__
#define MSGPACK_UNPACK_HPP__
+#include "msgpack/unpack.h"
#include "msgpack/object.hpp"
#include "msgpack/zone.hpp"
#include <memory>
@@ -36,21 +37,21 @@ struct unpack_error : public std::runtime_error {
};
-class unpacker {
+class unpacker : public msgpack_unpacker {
public:
unpacker(size_t initial_buffer_size = MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE);
~unpacker();
public:
- /*! 1. reserve buffer. at least `len' bytes of capacity will be ready */
- void reserve_buffer(size_t len);
+ /*! 1. reserve buffer. at least `size' bytes of capacity will be ready */
+ void reserve_buffer(size_t size);
/*! 2. read data to the buffer() up to buffer_capacity() bytes */
char* buffer();
size_t buffer_capacity() const;
/*! 3. specify the number of bytes actually copied */
- void buffer_consumed(size_t len);
+ void buffer_consumed(size_t size);
/*! 4. repeat execute() until it retunrs false */
bool execute();
@@ -114,71 +115,157 @@ public:
size_t nonparsed_size() const;
/*! skip specified size of non-parsed buffer, leaving the buffer */
- // Note that the `len' argument must be smaller than nonparsed_size()
- void skip_nonparsed_buffer(size_t len);
+ // Note that the `size' argument must be smaller than nonparsed_size()
+ void skip_nonparsed_buffer(size_t size);
/*! remove unparsed buffer from unpacker */
// Note that reset() leaves non-parsed buffer.
void remove_nonparsed_buffer();
private:
- char* m_buffer;
- size_t m_used;
- size_t m_free;
- size_t m_off;
+ unpacker(const unpacker&);
+};
- std::auto_ptr<zone> m_zone;
- void* m_ctx;
+typedef enum {
+ MSGPACK_UNPACK_SUCCESS = 2,
+ MSGPACK_UNPACK_EXTRA_BYTES = 1,
+ MSGPACK_UNPACK_CONTINUE = 0,
+ MSGPACK_UNPACK_PARSE_ERROR = -1,
+} unpack_return;
- size_t m_initial_buffer_size;
+static unpack_return unpack(const char* data, size_t len, size_t* off,
+ zone* z, object* result);
-private:
- void expand_buffer(size_t len);
-private:
- unpacker(const unpacker&);
+// obsolete
+static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
-public:
- static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
-};
+inline unpacker::unpacker(size_t initial_buffer_size)
+{
+ if(!msgpack_unpacker_init(this, initial_buffer_size)) {
+ throw std::bad_alloc();
+ }
+}
+
+inline unpacker::~unpacker()
+{
+ msgpack_unpacker_destroy(this);
+}
-inline void unpacker::reserve_buffer(size_t len)
+inline void unpacker::reserve_buffer(size_t size)
{
- if(m_free >= len) { return; }
- expand_buffer(len);
+ if(!msgpack_unpacker_reserve_buffer(this, size)) {
+ throw std::bad_alloc();
+ }
}
inline char* unpacker::buffer()
- { return m_buffer + m_used; }
+{
+ return msgpack_unpacker_buffer(this);
+}
inline size_t unpacker::buffer_capacity() const
- { return m_free; }
+{
+ return msgpack_unpacker_buffer_capacity(this);
+}
-inline void unpacker::buffer_consumed(size_t len)
+inline void unpacker::buffer_consumed(size_t size)
{
- m_used += len;
- m_free -= len;
+ return msgpack_unpacker_buffer_consumed(this, size);
+}
+
+
+inline bool unpacker::execute()
+{
+ int ret = msgpack_unpacker_execute(this);
+ if(ret < 0) {
+ throw unpack_error("parse error");
+ } else if(ret == 0) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+inline object unpacker::data()
+{
+ msgpack_object obj = msgpack_unpacker_data(this);
+ return *reinterpret_cast<object*>(&obj);
+}
+
+inline zone* unpacker::release_zone()
+{
+ if(!msgpack_unpacker_flush_zone(this)) {
+ throw std::bad_alloc();
+ }
+
+ zone* r = new zone();
+
+ msgpack_zone old = *this->z;
+ *this->z = *z;
+ *z = old;
+
+ return r;
+}
+
+inline void unpacker::reset()
+{
+ msgpack_unpacker_reset(this);
}
inline char* unpacker::nonparsed_buffer()
- { return m_buffer + m_off; }
+{
+ return buf + off;
+}
inline size_t unpacker::nonparsed_size() const
- { return m_used - m_off; }
+{
+ return used - off;
+}
-inline void unpacker::skip_nonparsed_buffer(size_t len)
- { m_off += len; }
+inline void unpacker::skip_nonparsed_buffer(size_t size)
+{
+ off += size;
+}
inline void unpacker::remove_nonparsed_buffer()
- { m_used = m_off; }
+{
+ used = off;
+}
+
+inline unpack_return unpack(const char* data, size_t len, size_t* off,
+ zone* z, object* result)
+{
+ return (unpack_return)msgpack_unpack(data, len, off,
+ z, reinterpret_cast<msgpack_object*>(result));
+}
-inline object unpack(const char* data, size_t len, zone& z, size_t* off = NULL)
+inline object unpack(const char* data, size_t len, zone& z, size_t* off)
{
- return unpacker::unpack(data, len, z, off);
+ object result;
+
+ switch( msgpack::unpack(data, len, off, &z, &result) ) {
+ case MSGPACK_UNPACK_SUCCESS:
+ return result;
+
+ case MSGPACK_UNPACK_EXTRA_BYTES:
+ if(off) {
+ return result;
+ } else {
+ throw unpack_error("extra bytes");
+ }
+
+ case MSGPACK_UNPACK_CONTINUE:
+ throw unpack_error("insufficient bytes");
+
+ case MSGPACK_UNPACK_PARSE_ERROR:
+ default:
+ throw unpack_error("parse error");
+ }
}