2009-02-15 09:09:57 +00:00
|
|
|
//
|
|
|
|
// MessagePack for C++ deserializing routine
|
|
|
|
//
|
|
|
|
// Copyright (C) 2008 FURUHASHI Sadayuki
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
//
|
2009-02-15 09:09:56 +00:00
|
|
|
#ifndef MSGPACK_UNPACK_HPP__
|
|
|
|
#define MSGPACK_UNPACK_HPP__
|
|
|
|
|
|
|
|
#include "msgpack/object.hpp"
|
|
|
|
#include "msgpack/zone.hpp"
|
2009-02-15 09:09:58 +00:00
|
|
|
#include <memory>
|
2009-02-15 09:09:56 +00:00
|
|
|
#include <stdexcept>
|
|
|
|
|
2009-02-15 09:09:59 +00:00
|
|
|
#ifndef MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE
|
|
|
|
#define MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE 8*1024
|
2009-02-15 09:09:56 +00:00
|
|
|
#endif
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
namespace msgpack {
|
|
|
|
|
|
|
|
|
|
|
|
struct unpack_error : public std::runtime_error {
|
|
|
|
unpack_error(const std::string& msg) :
|
|
|
|
std::runtime_error(msg) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class unpacker {
|
|
|
|
public:
|
2009-02-15 09:09:59 +00:00
|
|
|
unpacker(size_t initial_buffer_size = MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE);
|
2009-02-15 09:09:56 +00:00
|
|
|
~unpacker();
|
2009-02-15 09:09:56 +00:00
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
public:
|
2009-02-15 09:09:56 +00:00
|
|
|
/*! 1. reserve buffer. at least `len' bytes of capacity will be ready */
|
2009-02-15 09:09:56 +00:00
|
|
|
void reserve_buffer(size_t len);
|
2009-02-15 09:09:56 +00:00
|
|
|
|
|
|
|
/*! 2. read data to the buffer() up to buffer_capacity() bytes */
|
2009-02-15 09:09:57 +00:00
|
|
|
char* buffer();
|
2009-02-15 09:09:56 +00:00
|
|
|
size_t buffer_capacity() const;
|
2009-02-15 09:09:56 +00:00
|
|
|
|
|
|
|
/*! 3. specify the number of bytes actually copied */
|
2009-02-15 09:09:56 +00:00
|
|
|
void buffer_consumed(size_t len);
|
2009-02-15 09:09:56 +00:00
|
|
|
|
|
|
|
/*! 4. repeat execute() until it retunrs false */
|
2009-02-15 09:09:56 +00:00
|
|
|
bool execute();
|
2009-02-15 09:09:56 +00:00
|
|
|
|
|
|
|
/*! 5.1. if execute() returns true, take out the parsed object */
|
2009-02-15 09:09:56 +00:00
|
|
|
object data();
|
2009-02-15 09:09:56 +00:00
|
|
|
|
2009-02-15 09:09:58 +00:00
|
|
|
/*! 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.3. after release_zone(), re-initialize unpacker */
|
|
|
|
void reset();
|
|
|
|
|
|
|
|
|
|
|
|
// Basic usage of the unpacker is as following:
|
|
|
|
//
|
|
|
|
// msgpack::unpacker pac;
|
|
|
|
//
|
|
|
|
// while( /* readable */ ) {
|
|
|
|
//
|
|
|
|
// // 1.
|
|
|
|
// pac.reserve(1024);
|
|
|
|
//
|
|
|
|
// // 2.
|
|
|
|
// ssize_t bytes =
|
2009-02-15 09:09:58 +00:00
|
|
|
// read(the_source, pac.buffer(), pac.buffer_capacity());
|
2009-02-15 09:09:58 +00:00
|
|
|
//
|
|
|
|
// // error handling ...
|
|
|
|
//
|
|
|
|
// // 3.
|
|
|
|
// 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() );
|
|
|
|
//
|
|
|
|
// // boost::shared_ptr is also usable:
|
|
|
|
// // boost::shared_ptr<msgpack::zone> olife( pac.release_zone() );
|
|
|
|
//
|
|
|
|
// // 5.3
|
|
|
|
// pac.reset();
|
|
|
|
//
|
|
|
|
// // do some with the object with the old zone.
|
|
|
|
// do_something(o, olife);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
2009-02-15 09:09:56 +00:00
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
public:
|
|
|
|
// These functions are usable when non-MessagePack message follows after
|
|
|
|
// MessagePack message.
|
|
|
|
// Note that there are no parsed buffer when execute() returned true.
|
|
|
|
|
|
|
|
/*! get address of buffer that is not parsed */
|
2009-02-15 09:09:57 +00:00
|
|
|
char* nonparsed_buffer();
|
2009-02-15 09:09:56 +00:00
|
|
|
size_t nonparsed_size() const;
|
|
|
|
|
|
|
|
/*! get the number of bytes that is already parsed */
|
|
|
|
size_t parsed_size() const;
|
|
|
|
|
|
|
|
/*! remove unparsed buffer from unpacker */
|
|
|
|
// Note that reset() leaves non-parsed buffer.
|
|
|
|
void remove_nonparsed_buffer();
|
|
|
|
|
2009-02-15 09:09:58 +00:00
|
|
|
/*! skip specified size of non-parsed buffer, leaving the buffer */
|
|
|
|
// Note the size must be smaller than nonparsed_size()
|
|
|
|
void skip_nonparsed_buffer(size_t len);
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
private:
|
2009-02-15 09:09:57 +00:00
|
|
|
char* m_buffer;
|
2009-02-15 09:09:56 +00:00
|
|
|
size_t m_used;
|
|
|
|
size_t m_free;
|
|
|
|
size_t m_off;
|
2009-02-15 09:09:58 +00:00
|
|
|
|
2009-02-15 09:09:58 +00:00
|
|
|
std::auto_ptr<zone> m_zone;
|
|
|
|
|
|
|
|
struct context;
|
|
|
|
context* m_ctx;
|
|
|
|
|
2009-02-15 09:09:59 +00:00
|
|
|
const size_t m_initial_buffer_size;
|
|
|
|
|
2009-02-15 09:09:58 +00:00
|
|
|
private:
|
2009-02-15 09:09:56 +00:00
|
|
|
void expand_buffer(size_t len);
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
private:
|
|
|
|
unpacker(const unpacker&);
|
2009-02-15 09:09:56 +00:00
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
public:
|
2009-02-15 09:09:57 +00:00
|
|
|
static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
|
2009-02-15 09:09:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
inline void unpacker::reserve_buffer(size_t len)
|
|
|
|
{
|
|
|
|
if(m_free >= len) { return; }
|
|
|
|
expand_buffer(len);
|
|
|
|
}
|
|
|
|
|
2009-02-15 09:09:57 +00:00
|
|
|
inline char* unpacker::buffer()
|
|
|
|
{ return m_buffer + m_used; }
|
2009-02-15 09:09:56 +00:00
|
|
|
|
|
|
|
inline size_t unpacker::buffer_capacity() const
|
|
|
|
{ return m_free; }
|
|
|
|
|
|
|
|
inline void unpacker::buffer_consumed(size_t len)
|
|
|
|
{
|
|
|
|
m_used += len;
|
|
|
|
m_free -= len;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-15 09:09:57 +00:00
|
|
|
inline char* unpacker::nonparsed_buffer()
|
|
|
|
{ return m_buffer + m_off; }
|
2009-02-15 09:09:56 +00:00
|
|
|
|
|
|
|
inline size_t unpacker::nonparsed_size() const
|
|
|
|
{ return m_used - m_off; }
|
|
|
|
|
|
|
|
inline size_t unpacker::parsed_size() const
|
|
|
|
{ return m_off; }
|
|
|
|
|
|
|
|
inline void unpacker::remove_nonparsed_buffer()
|
|
|
|
{ m_used = m_off; }
|
|
|
|
|
2009-02-15 09:09:58 +00:00
|
|
|
inline void unpacker::skip_nonparsed_buffer(size_t len)
|
|
|
|
{ m_off += len; }
|
|
|
|
|
2009-02-15 09:09:56 +00:00
|
|
|
|
2009-02-15 09:09:57 +00:00
|
|
|
inline object unpack(const char* data, size_t len, zone& z, size_t* off = NULL)
|
2009-02-15 09:09:56 +00:00
|
|
|
{
|
2009-02-15 09:09:57 +00:00
|
|
|
return unpacker::unpack(data, len, z, off);
|
2009-02-15 09:09:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace msgpack
|
|
|
|
|
|
|
|
#endif /* msgpack/unpack.hpp */
|
|
|
|
|