summaryrefslogtreecommitdiff
path: root/cpp/unpack.cpp
diff options
context:
space:
mode:
authorfrsyuki <frsyuki@5a5092ae-2292-43ba-b2d5-dcab9c1a2731>2009-02-15 09:09:58 +0000
committerfrsyuki <frsyuki@5a5092ae-2292-43ba-b2d5-dcab9c1a2731>2009-02-15 09:09:58 +0000
commitb790df530aa28099aa130dafad0a591004b88650 (patch)
tree4d09f4c43a5994bcf83e152471e29ac9c952ba3e /cpp/unpack.cpp
parent9923cf4daf631432e389dd0694042b6b405c1288 (diff)
downloadmsgpack-python-b790df530aa28099aa130dafad0a591004b88650.tar.gz
lang/c/msgpack: C++ binding: safer memory managent
git-svn-id: file:///Users/frsyuki/project/msgpack-git/svn/x@68 5a5092ae-2292-43ba-b2d5-dcab9c1a2731
Diffstat (limited to 'cpp/unpack.cpp')
-rw-r--r--cpp/unpack.cpp48
1 files changed, 39 insertions, 9 deletions
diff --git a/cpp/unpack.cpp b/cpp/unpack.cpp
index 71593a0..ce39afd 100644
--- a/cpp/unpack.cpp
+++ b/cpp/unpack.cpp
@@ -178,12 +178,13 @@ private:
};
-unpacker::unpacker(zone& z) :
- m_ctx(new context(&z)),
+unpacker::unpacker() :
m_buffer(NULL),
m_used(0),
m_free(0),
- m_off(0)
+ m_off(0),
+ m_zone(new zone()),
+ m_ctx(new context(&*m_zone))
{ }
@@ -201,14 +202,14 @@ void unpacker::expand_buffer(size_t len)
else { next_size = UNPACKER_INITIAL_BUFFER_SIZE; }
while(next_size < len + m_used) { next_size *= 2; }
- m_buffer = m_ctx->user()->realloc(m_buffer, next_size);
+ m_buffer = m_zone->realloc(m_buffer, next_size);
m_free = next_size - m_used;
} else {
size_t next_size = UNPACKER_INITIAL_BUFFER_SIZE;
while(next_size < len + m_used - m_off) { next_size *= 2; }
- char* tmp = m_ctx->user()->malloc(next_size);
+ char* tmp = m_zone->malloc(next_size);
memcpy(tmp, m_buffer+m_off, m_used-m_off);
m_buffer = tmp;
@@ -226,20 +227,49 @@ bool unpacker::execute()
} else if(ret == 0) {
return false;
} else {
- expand_buffer(0);
return true;
}
}
+zone* unpacker::release_zone()
+{
+ zone* n = new zone();
+ std::auto_ptr<zone> old(m_zone.release());
+ m_zone.reset(n);
+
+ //std::auto_ptr<zone> old(new zone());
+ //m_zone.swap(old);
+
+ // move all bytes in m_buffer to new buffer from the new zone
+ if(m_used <= m_off) {
+ m_buffer = NULL;
+ m_used = 0;
+ m_free = 0;
+ m_off = 0;
+ } else {
+ try {
+ expand_buffer(0);
+ } catch (...) {
+ // m_zone.swap(old);
+ zone* tmp = old.release();
+ old.reset(m_zone.release());
+ m_zone.reset(tmp);
+ throw;
+ }
+ }
+ m_ctx->user(&*m_zone);
+ return old.release();
+}
+
object unpacker::data()
{
return m_ctx->data();
}
-void unpacker::reset(zone& z)
+void unpacker::reset()
{
- if(m_off != 0) { expand_buffer(0); }
- m_ctx->reset(&z);
+ if(m_off != 0) { std::auto_ptr<zone> old(release_zone()); }
+ m_ctx->reset();
}