diff options
| author | frsyuki <frsyuki@users.sourceforge.jp> | 2010-04-29 22:15:03 +0900 |
|---|---|---|
| committer | frsyuki <frsyuki@users.sourceforge.jp> | 2010-04-29 22:15:03 +0900 |
| commit | 91a1f8d9e121c1b1379476aa61426dd8a3366987 (patch) | |
| tree | f4cd9c6d61ff7f922b621c11a79df28e5c590714 /cpp/msgpack | |
| parent | 6352472c5fbe1d293dfff2d48dca81ea91bba29f (diff) | |
| download | msgpack-python-91a1f8d9e121c1b1379476aa61426dd8a3366987.tar.gz | |
cpp: new streaming deserialier API.
Diffstat (limited to 'cpp/msgpack')
| -rw-r--r-- | cpp/msgpack/unpack.hpp | 149 |
1 files changed, 112 insertions, 37 deletions
diff --git a/cpp/msgpack/unpack.hpp b/cpp/msgpack/unpack.hpp index d39b5df..dbe7777 100644 --- a/cpp/msgpack/unpack.hpp +++ b/cpp/msgpack/unpack.hpp @@ -37,6 +37,31 @@ struct unpack_error : public std::runtime_error { }; +class unpacked { +public: + unpacked() { } + + unpacked(object obj, std::auto_ptr<msgpack::zone> z) : + m_obj(obj), m_zone(z) { } + + object& get() + { return m_obj; } + + const object& get() const + { return m_obj; } + + std::auto_ptr<msgpack::zone>& zone() + { return m_zone; } + + const std::auto_ptr<msgpack::zone>& zone() const + { return m_zone; } + +private: + object m_obj; + std::auto_ptr<msgpack::zone> m_zone; +}; + + class unpacker : public msgpack_unpacker { public: unpacker(size_t init_buffer_size = MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE); @@ -53,39 +78,22 @@ public: /*! 3. specify the number of bytes actually copied */ void buffer_consumed(size_t size); - /*! 4. repeat execute() until it retunrs false */ - bool execute(); - - /*! 5.1. if execute() returns true, take out the parsed object */ - object data(); - - /*! 5.2. the object is valid until the zone is deleted */ - // Note that once release_zone() from unpacker, you must delete it - // otherwise the memrory will leak. - zone* release_zone(); - - /*! 5.2. this method is equivalence to `delete release_zone()` */ - void reset_zone(); + /*! 4. repeat next() until it retunrs false */ + bool next(unpacked* result); - /*! 5.3. after release_zone(), re-initialize unpacker */ - void reset(); - - /*! 6. check if the size of message doesn't exceed assumption. */ + /*! 5. check if the size of message doesn't exceed assumption. */ size_t message_size() const; - // Basic usage of the unpacker is as following: // // msgpack::unpacker pac; - // - // while( /* readable */ ) { + // while( /* input is readable */ ) { // // // 1. - // pac.reserve_buffer(1024); + // pac.reserve_buffer(32*1024); // // // 2. - // ssize_t bytes = - // read(the_source, pac.buffer(), pac.buffer_capacity()); + // size_t bytes = input.readsome(pac.buffer(), pac.buffer_capacity()); // // // error handling ... // @@ -93,25 +101,40 @@ public: // pac.buffer_consumed(bytes); // // // 4. - // while(pac.execute()) { - // // 5.1 - // object o = pac.data(); - // - // // 5.2 - // std::auto_ptr<msgpack::zone> olife( pac.release_zone() ); + // msgpack::unpacked result; + // while(pac.next(&result)) { + // // do some with the object with the zone. + // msgpack::object obj = result.get(); + // std::auto_ptr<msgpack:zone> z = result.zone(); + // on_message(obj, z); // - // // boost::shared_ptr is also usable: - // // boost::shared_ptr<msgpack::zone> olife( pac.release_zone() ); - // - // // 5.3 - // pac.reset(); + // //// boost::shared_ptr is also usable: + // // boost::shared_ptr<msgpack::zone> life(z.release()); + // // on_message(result.get(), life); + // } // - // // do some with the object with the old zone. - // do_something(o, olife); + // // 5. + // if(pac.message_size() > 10*1024*1024) { + // throw std::runtime_error("message is too large"); // } // } // + /*! for backward compatibility */ + bool execute(); + + /*! for backward compatibility */ + object data(); + + /*! for backward compatibility */ + zone* release_zone(); + + /*! for backward compatibility */ + void reset_zone(); + + /*! for backward compatibility */ + void reset(); + public: // These functions are usable when non-MessagePack message follows after // MessagePack message. @@ -137,6 +160,11 @@ private: }; +static bool unpack(unpacked* result, + const char* data, size_t len, size_t* offset = NULL); + + +// obsolete typedef enum { UNPACK_SUCCESS = 2, UNPACK_EXTRA_BYTES = 1, @@ -144,6 +172,7 @@ typedef enum { UNPACK_PARSE_ERROR = -1, } unpack_return; +// obsolete static unpack_return unpack(const char* data, size_t len, size_t* off, zone* z, object* result); @@ -187,6 +216,20 @@ inline void unpacker::buffer_consumed(size_t size) return msgpack_unpacker_buffer_consumed(this, size); } +inline bool unpacker::next(unpacked* result) +{ + int ret = msgpack_unpacker_execute(this); + if(ret < 0) { + throw unpack_error("parse error"); + } + + result->zone().reset( release_zone() ); + result->get() = data(); + reset(); + + return ret > 0; +} + inline bool unpacker::execute() { @@ -230,12 +273,12 @@ inline void unpacker::reset() msgpack_unpacker_reset(this); } + inline size_t unpacker::message_size() const { return msgpack_unpacker_message_size(this); } - inline size_t unpacker::parsed_size() const { return msgpack_unpacker_parsed_size(this); @@ -262,6 +305,38 @@ inline void unpacker::remove_nonparsed_buffer() } +inline bool unpack(unpacked* result, + const char* data, size_t len, size_t* offset) +{ + msgpack::object obj; + std::auto_ptr<msgpack::zone> z(new zone()); + + unpack_return ret = (unpack_return)msgpack_unpack( + data, len, offset, z.get(), + reinterpret_cast<msgpack_object*>(&obj)); + + switch(ret) { + case UNPACK_SUCCESS: + result->get() = obj; + result->zone() = z; + return false; + + case UNPACK_EXTRA_BYTES: + result->get() = obj; + result->zone() = z; + return true; + + case UNPACK_CONTINUE: + throw unpack_error("insufficient bytes"); + + case UNPACK_PARSE_ERROR: + default: + throw unpack_error("parse error"); + } +} + + +// obsolete inline unpack_return unpack(const char* data, size_t len, size_t* off, zone* z, object* result) { |
