From 5782ab7ccce243b1eac0fd6e10928d1aedcb552c Mon Sep 17 00:00:00 2001 From: frsyuki Date: Fri, 26 Mar 2010 14:33:49 +0900 Subject: [PATCH] c,cpp: add msgpack_zbuffer and msgpack::zbuffer --- c/Makefile.am | 1 + c/msgpack/zbuffer.h | 175 ++++++++++++++++++++++++++++++++++++++++ cpp/Makefile.am | 1 + cpp/msgpack/zbuffer.hpp | 100 +++++++++++++++++++++++ 4 files changed, 277 insertions(+) create mode 100644 c/msgpack/zbuffer.h create mode 100644 cpp/msgpack/zbuffer.hpp diff --git a/c/Makefile.am b/c/Makefile.am index f84759a1..bbe547ce 100644 --- a/c/Makefile.am +++ b/c/Makefile.am @@ -10,6 +10,7 @@ nobase_include_HEADERS = \ msgpack.h \ msgpack/sbuffer.h \ msgpack/vrefbuffer.h \ + msgpack/zbuffer.h \ msgpack/pack.h \ msgpack/unpack.h \ msgpack/object.h \ diff --git a/c/msgpack/zbuffer.h b/c/msgpack/zbuffer.h new file mode 100644 index 00000000..ad3d11a1 --- /dev/null +++ b/c/msgpack/zbuffer.h @@ -0,0 +1,175 @@ +/* + * MessagePack for C deflate buffer implementation + * + * Copyright (C) 2010 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. + */ +#ifndef MSGPACK_ZBUFFER_H__ +#define MSGPACK_ZBUFFER_H__ + +#include "msgpack/sysdep.h" +#include +#include +#include + +#ifndef MSGPACK_ZBUFFER_INIT_SIZE +#define MSGPACK_ZBUFFER_INIT_SIZE 8192 +#endif + +#ifndef MSGPACK_ZBUFFER_RESERVE_SIZE +#define MSGPACK_ZBUFFER_RESERVE_SIZE 512 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct msgpack_zbuffer { + z_stream stream; + char* data; + size_t init_size; +} msgpack_zbuffer; + + +static inline bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf, + int level, size_t init_size); +static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf); + +static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf); + +static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf); +static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf); + +static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf); +static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf); +static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf); + + +static inline int msgpack_zbuffer_write(void* data, const char* buf, unsigned int len); + +static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf); + + +bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf, + int level, size_t init_size) +{ + memset(zbuf, 0, sizeof(msgpack_zbuffer)); + zbuf->init_size = init_size; + if(deflateInit(&zbuf->stream, level) != Z_OK) { + free(zbuf->data); + return false; + } + return true; +} + +void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf) +{ + deflateEnd(&zbuf->stream); + free(zbuf->data); +} + +bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf) +{ + size_t used = (char*)zbuf->stream.next_out - zbuf->data; + size_t csize = used + zbuf->stream.avail_out; + size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2; + + char* tmp = (char*)realloc(zbuf->data, nsize); + if(tmp == NULL) { + return false; + } + + zbuf->data = tmp; + zbuf->stream.next_out = (Bytef*)(tmp + used); + zbuf->stream.avail_out = nsize - used; + + return true; +} + +int msgpack_zbuffer_write(void* data, const char* buf, unsigned int len) +{ + msgpack_zbuffer* zbuf = (msgpack_zbuffer*)data; + + zbuf->stream.next_in = (Bytef*)buf; + zbuf->stream.avail_in = len; + + do { + if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) { + msgpack_zbuffer_expand(zbuf); + } + + if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) { + return -1; + } + } while(zbuf->stream.avail_in > 0); + + return 0; +} + +char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf) +{ + while(true) { + switch(deflate(&zbuf->stream, Z_FINISH)) { + case Z_STREAM_END: + return zbuf->data; + case Z_OK: + msgpack_zbuffer_expand(zbuf); + default: + return NULL; + } + } +} + +const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf) +{ + return zbuf->data; +} + +size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf) +{ + return (char*)zbuf->stream.next_out - zbuf->data; +} + +void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf) +{ + zbuf->stream.avail_out += (char*)zbuf->stream.next_out - zbuf->data; + zbuf->stream.next_out = (Bytef*)zbuf->data; +} + +bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf) +{ + if(deflateReset(&zbuf->stream) != Z_OK) { + return false; + } + msgpack_zbuffer_reset_buffer(zbuf); + return true; +} + +char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf) +{ + char* tmp = zbuf->data; + zbuf->data = NULL; + zbuf->stream.next_out = NULL; + zbuf->stream.avail_out = 0; + return tmp; +} + + +#ifdef __cplusplus +} +#endif + +#endif /* msgpack/zbuffer.h */ + diff --git a/cpp/Makefile.am b/cpp/Makefile.am index d4de1612..c1b4981d 100644 --- a/cpp/Makefile.am +++ b/cpp/Makefile.am @@ -7,6 +7,7 @@ nobase_include_HEADERS = \ msgpack.hpp \ msgpack/sbuffer.hpp \ msgpack/vrefbuffer.hpp \ + msgpack/zbuffer.hpp \ msgpack/pack.hpp \ msgpack/unpack.hpp \ msgpack/object.hpp \ diff --git a/cpp/msgpack/zbuffer.hpp b/cpp/msgpack/zbuffer.hpp new file mode 100644 index 00000000..278f076e --- /dev/null +++ b/cpp/msgpack/zbuffer.hpp @@ -0,0 +1,100 @@ +// +// MessagePack for C++ deflate buffer implementation +// +// Copyright (C) 2010 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. +// +#ifndef MSGPACK_ZBUFFER_HPP__ +#define MSGPACK_ZBUFFER_HPP__ + +#include "msgpack/zbuffer.h" +#include + +namespace msgpack { + + +class zbuffer : public msgpack_zbuffer { +public: + zbuffer(int level = Z_DEFAULT_COMPRESSION, + size_t init_size = MSGPACK_ZBUFFER_INIT_SIZE) + { + msgpack_zbuffer_init(this, level, init_size); + } + + ~zbuffer() + { + msgpack_zbuffer_destroy(this); + } + +public: + void write(const char* buf, unsigned int len) + { + if(msgpack_zbuffer_write(this, buf, len) < 0) { + throw std::bad_alloc(); + } + } + + char* flush() + { + char* buf = msgpack_zbuffer_flush(this); + if(!buf) { + throw std::bad_alloc(); + } + return buf; + } + + char* data() + { + return base::data; + } + + const char* data() const + { + return base::data; + } + + size_t size() const + { + return msgpack_zbuffer_size(this); + } + + void reset() + { + if(!msgpack_zbuffer_reset(this)) { + throw std::bad_alloc(); + } + } + + void reset_buffer() + { + msgpack_zbuffer_reset_buffer(this); + } + + char* release_buffer() + { + return msgpack_zbuffer_release_buffer(this); + } + +private: + typedef msgpack_zbuffer base; + +private: + zbuffer(const zbuffer&); +}; + + +} // namespace msgpack + +#endif /* msgpack/zbuffer.hpp */ +