In Files

Parent

MessagePack::Unpacker

Deserializer class that includes Buffered API and Unbuffered API.

Buffered API uses the internal buffer of the Unpacker. Following code uses Buffered API with an input stream:

  # create an unpacker with input stream.
  pac = MessagePack::Unpacker.new(STDIN)
  
  # deserialize object one after another.
  pac.each {|obj|
    # ...
  }

Following code doesn’t use the input stream and feeds buffer manually. This is useful to use special stream or with event-driven I/O library.

  # create an unpacker without input stream.
  pac = MessagePack::Unpacker.new()
  
  # feed buffer to the internal buffer.
  pac.feed(input_bytes)
  
  # deserialize object one after another.
  pac.each {|obj|
    # ...
  }

You can manage the buffer manually with the combination of execute, finished?, data and reset method.

  # create an unpacker.
  pac = MessagePack::Unpacker.new()
  
  # manage buffer and offset manually.
  offset = 0
  buffer = ''
  
  # read some data into the buffer.
  buffer << [1,2,3].to_msgpack
  buffer << [4,5,6].to_msgpack
  
  while true
    offset = pac.execute(buffer, offset)
  
    if pac.finished?
      obj = pac.data
  
      buffer.slice!(0, offset)
      offset = 0
      pac.reset
  
      # do something with the object
      # ...

      # repeat execution if there are more data.
      next unless buffer.empty?
    end

    break
  end

Public Class Methods

new(stream = nil) click to toggle source

Creates instance of MessagePack::Unpacker.

You can specify a stream for input stream. It is required to implement sysread or readpartial method.

With the input stream, buffers will be feeded into the deserializer automatically.

Without the input stream, use feed method manually. Or you can manage the buffer manually with execute, finished?, data and reset methods.

static VALUE MessagePack_Unpacker_initialize(int argc, VALUE *argv, VALUE self)
{
        VALUE stream;
        switch(argc) {
        case 0:
                stream = Qnil;
                break;
        case 1:
                stream = argv[0];
                break;
        default:
                rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
        }

        UNPACKER(self, mp);
        template_init(mp);
        mp->user.stream = stream;
        mp->user.streambuf = rb_str_buf_new(MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE);
        mp->user.stream_append_method = append_method_of(stream);
        mp->user.buffer_free_size = MSGPACK_BUFFER_FREE_SIZE;

        return self;
}

Public Instance Methods

data click to toggle source

Gets the object deserialized by execute method.

Use this method with execute method.

static VALUE MessagePack_Unpacker_data(VALUE self)
{
        UNPACKER(self, mp);
        return template_data(mp);
}
each {|object| } click to toggle source

Deserializes objects repeatedly. This calls fill method automatically.

UnpackError is throw when parse error is occured. This method raises exceptions that fill method raises.

static VALUE MessagePack_Unpacker_each(VALUE self)
{
        UNPACKER(self, mp);
        int ret;

#ifdef RETURN_ENUMERATOR
        RETURN_ENUMERATOR(self, 0, 0);
#endif

        while(1) {
                if(mp->user.buffer.used <= mp->user.offset) {
                        do_fill:
                        {
                                VALUE len = MessagePack_Unpacker_fill(self);
                                if(len == Qnil || FIX2LONG(len) == 0) {
                                        break;
                                }
                        }
                }

                ret = template_execute_wrap_each(mp,
                                mp->user.buffer.ptr, mp->user.buffer.used,
                                &mp->user.offset);

                if(ret < 0) {
                        rb_raise(eUnpackError, "parse error.");

                } else if(ret > 0) {
                        VALUE data = template_data(mp);
                        template_init(mp);
                        rb_yield(data);

                } else {
                        goto do_fill;
                }
        }

        try_free_buffer(mp, 0);

        return Qnil;
}
execute(data, offset) → next offset click to toggle source

Deserializes one object over the specified buffer from offset bytes.

This method doesn’t use the internal buffer.

Call reset method before calling this method again.

This returns offset that was parsed to. Use finished? method to check an object is deserialized and call data method if it returns true.

UnpackError is throw when parse error is occured.

static VALUE MessagePack_Unpacker_execute(VALUE self, VALUE data, VALUE off)
{
        CHECK_STRING_TYPE(data);
        return MessagePack_Unpacker_execute_impl(self, data,
                        (size_t)NUM2ULONG(off), (size_t)RSTRING_LEN(data));
}
execute_limit(data, offset, limit) → next offset click to toggle source

Deserializes one object over the specified buffer from offset bytes upto limit bytes.

This method doesn’t use the internal buffer.

Call reset method before calling this method again.

UnpackError is throw when parse error is occured.

static VALUE MessagePack_Unpacker_execute_limit(VALUE self, VALUE data,
                VALUE off, VALUE limit)
{
        CHECK_STRING_TYPE(data);
        return MessagePack_Unpacker_execute_impl(self, data,
                        (size_t)NUM2ULONG(off), (size_t)NUM2ULONG(limit));
}
feed(data) click to toggle source

Fills the internal buffer with the specified buffer.

static VALUE MessagePack_Unpacker_feed(VALUE self, VALUE data)
{
        UNPACKER(self, mp);
        StringValue(data);
        feed_buffer(mp, RSTRING_PTR(data), RSTRING_LEN(data));
        return Qnil;
}
feed_each(data) {|object| } click to toggle source

Same as feed(data) + each {|object| }, but tries to avoid copying of the buffer.

static VALUE MessagePack_Unpacker_feed_each(VALUE self, VALUE data)
{
        size_t consumed = 0;
        StringValue(data);

        VALUE args[3];
        args[0] = self;
        args[1] = data;
        args[2] = (VALUE)&consumed;

        return rb_ensure(feed_each_impl, (VALUE)args,
                        feed_each_ensure, (VALUE)args);
}
fill → length of read data click to toggle source

Fills the internal buffer using the input stream.

If the input stream is not specified, it returns nil. You can set it on initialize or stream= methods.

This methods raises exceptions that stream.sysread or stream.readpartial method raises.

static VALUE MessagePack_Unpacker_fill(VALUE self)
{
        UNPACKER(self, mp);

        if(mp->user.stream == Qnil) {
                return Qnil;
        }

        rb_funcall(mp->user.stream, mp->user.stream_append_method, 2,
                        LONG2FIX(MSGPACK_UNPACKER_BUFFER_RESERVE_SIZE),
                        mp->user.streambuf);

        size_t len = RSTRING_LEN(mp->user.streambuf);
        feed_buffer(mp, RSTRING_PTR(mp->user.streambuf), len);

        return LONG2FIX(len);
}
finished? click to toggle source

Returns true if an object is ready to get with data method.

Use this method with execute method.

static VALUE MessagePack_Unpacker_finished_p(VALUE self)
{
        UNPACKER(self, mp);
        if(mp->user.finished) {
                return Qtrue;
        }
        return Qfalse;
}
reset click to toggle source

Resets the internal state of the unpacker.

static VALUE MessagePack_Unpacker_reset(VALUE self)
{
        UNPACKER(self, mp);
        template_init(mp);
        mp->user.finished = 0;
        try_free_buffer(mp, 0);
        return self;
}
stream click to toggle source

Gets the input stream.

static VALUE MessagePack_Unpacker_stream_get(VALUE self)
{
        UNPACKER(self, mp);
        return mp->user.stream;
}
stream = stream click to toggle source

Resets the input stream. You can set nil not to use input stream.

static VALUE MessagePack_Unpacker_stream_set(VALUE self, VALUE val)
{
        UNPACKER(self, mp);
        mp->user.stream = val;
        mp->user.stream_append_method = append_method_of(val);
        return val;
}

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.