Example #1
0
void mochilo_pack_hash(mochilo_buf *buf, VALUE rb_hash)
{
	struct mochilo_hash_pack hash_pack;
	long size = RHASH_SIZE(rb_hash);

	hash_pack.buf = buf;

	if (size < 0x10) {
		uint8_t lead = 0x80 | size;
		mochilo_buf_putc(buf, lead);
	}

	else if (size < 0x10000) {
		uint16_t lead = size;
		mochilo_buf_putc(buf, MSGPACK_T_MAP16);
		mochilo_buf_put16be(buf, &lead);
	}

	else {
		mochilo_buf_putc(buf, MSGPACK_T_MAP32);
		mochilo_buf_put32be(buf, &size);
	}

	rb_hash_foreach(rb_hash, &hash_callback, (VALUE)&hash_pack);
}
Example #2
0
void mochilo_pack_str(mochilo_buf *buf, VALUE rb_str)
{
	long size = RSTRING_LEN(rb_str);
	rb_encoding *encoding;

	const struct mochilo_enc_map *enc2id;
	const char *enc_name;

	if (size < 0x10000) {
		uint16_t lead = size;
		mochilo_buf_putc(buf, MSGPACK_T_STR16);
		mochilo_buf_put16be(buf, &lead);
	}

	else {
		mochilo_buf_putc(buf, MSGPACK_T_STR32);
		mochilo_buf_put32be(buf, &size);
	}

	encoding = rb_enc_get(rb_str);
	enc_name = rb_enc_name(encoding);
	enc2id = mochilo_encoding_to_id(enc_name, (unsigned int)strlen(enc_name));

	mochilo_buf_putc(buf, enc2id ? enc2id->id : 0);
	mochilo_buf_put(buf, RSTRING_PTR(rb_str), size);
}
Example #3
0
void mochilo_pack_str(mochilo_buf *buf, VALUE rb_str)
{
	long size = RSTRING_LEN(rb_str);
	rb_encoding *encoding;

	const struct mochilo_enc_map *enc2id;
	const char *enc_name;

	encoding = rb_enc_get(rb_str);
	enc_name = rb_enc_name(encoding);

	if (encoding == rb_utf8_encoding()) {
		// use str type from msgpack spec
		if (size < 0x20) {
			uint8_t lead = 0xa0 | size;
			mochilo_buf_putc(buf, lead);
		} else if (size < 0x100) {
			uint8_t lead = size;
			mochilo_buf_putc(buf, MSGPACK_T_STR8);
			mochilo_buf_putc(buf, lead);
		} else if (size < 0x10000) {
			uint16_t lead = size;
			mochilo_buf_putc(buf, MSGPACK_T_STR16);
			mochilo_buf_put16be(buf, &lead);
		} else if (size < 0x100000000) {
			mochilo_buf_putc(buf, MSGPACK_T_STR32);
			mochilo_buf_put32be(buf, &size);
		} else {
			// there is no str 64
			rb_raise(rb_eMochiloPackError,
				"String cannot be larger than %ld bytes", 0x100000000);
		}
	} else {
		// if another encoding is used we need to use our custom types
		if (size < 0x100) {
			uint8_t lead = size;
			mochilo_buf_putc(buf, MSGPACK_T_ENC8);
			mochilo_buf_putc(buf, lead);
		} else if (size < 0x10000) {
			uint16_t lead = size;
			mochilo_buf_putc(buf, MSGPACK_T_ENC16);
			mochilo_buf_put16be(buf, &lead);
		} else if (size < 0x100000000) {
			mochilo_buf_putc(buf, MSGPACK_T_ENC32);
			mochilo_buf_put32be(buf, &size);
		} else {
			// there is no ext 64
			rb_raise(rb_eMochiloPackError,
				"String cannot be larger than %ld bytes", 0x100000000);
		}

		enc2id = mochilo_encoding_to_id(enc_name, (unsigned int)strlen(enc_name));
		mochilo_buf_putc(buf, enc2id ? enc2id->id : 0);
	}

	mochilo_buf_put(buf, RSTRING_PTR(rb_str), size);
}
Example #4
0
void mochilo_pack_bignum(mochilo_buf *buf, VALUE rb_bignum)
{
	if (RBIGNUM_POSITIVE_P(rb_bignum)) {
		uint64_t bignum = rb_big2ull(rb_bignum);

		mochilo_buf_putc(buf, MSGPACK_T_UINT64);
		mochilo_buf_put64be(buf, &bignum);
	} else {
		int64_t bignum = rb_big2ll(rb_bignum);

		mochilo_buf_putc(buf, MSGPACK_T_INT64);
		mochilo_buf_put64be(buf, &bignum);
	}
}
Example #5
0
void mochilo_pack_one(mochilo_buf *buf, VALUE rb_object)
{
	switch (rb_type(rb_object)) {
	case T_NIL:
		mochilo_buf_putc(buf, MSGPACK_T_NIL);
		return;

	case T_TRUE:
		mochilo_buf_putc(buf, MSGPACK_T_TRUE);
		return;

	case T_FALSE:
		mochilo_buf_putc(buf, MSGPACK_T_FALSE);
		return;

	case T_FIXNUM:
		mochilo_pack_fixnum(buf, rb_object);
		return;

	case T_STRING:
		if (ENCODING_GET(rb_object) != 0)
			mochilo_pack_str(buf, rb_object);
		else
			mochilo_pack_bytes(buf, rb_object);
		return;

	case T_HASH:
		mochilo_pack_hash(buf, rb_object);
		return;

	case T_ARRAY:
		mochilo_pack_array(buf, rb_object);
		return;

	case T_FLOAT:
		mochilo_pack_double(buf, rb_object);
		return;

	case T_BIGNUM:
		mochilo_pack_bignum(buf, rb_object);
		return;

	default:
		rb_raise(rb_eMochiloPackError,
				"Unsupported object type: %s", rb_obj_classname(rb_object));
		return;
	}
}
Example #6
0
void mochilo_pack_symbol(mochilo_buf *buf, VALUE rb_symbol)
{
	long size;
	const char *name;

	name = rb_id2name(SYM2ID(rb_symbol));
	size = strlen(name);

	if (size < 0x100) {
		uint8_t lead = size;
		mochilo_buf_putc(buf, MSGPACK_T_SYM);
		mochilo_buf_putc(buf, lead);
	} else {
		rb_raise(rb_eMochiloPackError,
			"Symbol too long: must be under %d bytes, %ld given", 0x100, size);
	}

	mochilo_buf_put(buf, name, size);
}
Example #7
0
void mochilo_pack_bytes(mochilo_buf *buf, VALUE rb_bytes)
{
	long size = RSTRING_LEN(rb_bytes);

	if (size < 0x20) {
		uint8_t lead = 0xA0 | size;
		mochilo_buf_putc(buf, lead);
	}

	else if (size < 0x10000) {
		uint16_t lead = size;
		mochilo_buf_putc(buf, MSGPACK_T_RAW16);
		mochilo_buf_put16be(buf, &lead);
	}

	else {
		mochilo_buf_putc(buf, MSGPACK_T_RAW32);
		mochilo_buf_put32be(buf, &size);
	}

	mochilo_buf_put(buf, RSTRING_PTR(rb_bytes), size);
}
Example #8
0
void mochilo_pack_bytes(mochilo_buf *buf, VALUE rb_bytes)
{
	long size = RSTRING_LEN(rb_bytes);

	if (size < 0x100) {
		uint8_t lead = size;
		mochilo_buf_putc(buf, MSGPACK_T_BIN8);
		mochilo_buf_putc(buf, lead);
	} else if (size < 0x10000) {
		uint16_t lead = size;
		mochilo_buf_putc(buf, MSGPACK_T_BIN16);
		mochilo_buf_put16be(buf, &lead);
	} else if (size < 0x100000000) {
		mochilo_buf_putc(buf, MSGPACK_T_BIN32);
		mochilo_buf_put32be(buf, &size);
	} else {
		// there is no bin 64
		rb_raise(rb_eMochiloPackError,
			"Binary string cannot be larger than %ld bytes", 0x100000000);
	}

	mochilo_buf_put(buf, RSTRING_PTR(rb_bytes), size);
}
Example #9
0
void mochilo_pack_array(mochilo_buf *buf, VALUE rb_array)
{
	long i, size = RARRAY_LEN(rb_array);

	if (size < 0x10) {
		uint8_t lead = 0x90 | size;
		mochilo_buf_putc(buf, lead);
	}

	else if (size < 0x10000) {
		uint16_t lead = size;
		mochilo_buf_putc(buf, MSGPACK_T_ARRAY16);
		mochilo_buf_put16be(buf, &lead);
	}

	else {
		mochilo_buf_putc(buf, MSGPACK_T_ARRAY32);
		mochilo_buf_put32be(buf, &size);
	}

	for (i = 0; i < size; i++) {
		mochilo_pack_one(buf, rb_ary_entry(rb_array, i));
	}
}
Example #10
0
void mochilo_pack_double(mochilo_buf *buf, VALUE rb_double)
{
	double d = RFLOAT_VALUE(rb_double);
	mochilo_buf_putc(buf, MSGPACK_T_DOUBLE);
	mochilo_buf_put64be(buf, &d);
}
Example #11
0
void mochilo_pack_fixnum(mochilo_buf *buf, VALUE rb_fixnum)
{
	long fixnum = NUM2LONG(rb_fixnum);

	if (fixnum < -0x20L) {
		if (fixnum < -0x8000L) {
			if (sizeof(long) > 4 && fixnum < -0x80000000L) {
				mochilo_buf_putc(buf, MSGPACK_T_INT64);
				mochilo_buf_put64be(buf, &fixnum);
			} else {
				int32_t fixnum32 = (int32_t)fixnum;
				mochilo_buf_putc(buf, MSGPACK_T_INT32);
				mochilo_buf_put32be(buf, &fixnum32);
			}
		} else {
			if (fixnum < -0x80L) {
				int16_t fixnum16 = (int16_t)fixnum;
				mochilo_buf_putc(buf, MSGPACK_T_INT16);
				mochilo_buf_put16be(buf, &fixnum16);
			} else {
				mochilo_buf_putc(buf, MSGPACK_T_INT8);
				mochilo_buf_putc(buf, (int8_t)fixnum);
			}
		}
	} else if (fixnum <= 0x7fL) {
		mochilo_buf_putc(buf, (uint8_t)fixnum);
	} else {
		if (fixnum <= 0xffffL) {
			if (fixnum <= 0xffL) {
				mochilo_buf_putc(buf, MSGPACK_T_UINT8);
				mochilo_buf_putc(buf, (uint8_t)fixnum);
			} else {
				uint16_t fixnum16 = (uint16_t)fixnum;
				mochilo_buf_putc(buf, MSGPACK_T_UINT16);
				mochilo_buf_put16be(buf, &fixnum16);
			}
		} else {
			if (fixnum <= 0xffffffffL) {
				uint32_t fixnum32 = (uint32_t)fixnum;
				mochilo_buf_putc(buf, MSGPACK_T_UINT32);
				mochilo_buf_put32be(buf, &fixnum32);
			} else if (sizeof(long) > 4) {
				mochilo_buf_putc(buf, MSGPACK_T_UINT64);
				mochilo_buf_put64be(buf, &fixnum);
			}
		}
	}
}
Example #12
0
void mochilo_pack_one(mochilo_buf *buf, VALUE rb_object, int trusted)
{
#ifndef RUBINIUS
	if (rb_object == Qnil) {
		mochilo_buf_putc(buf, MSGPACK_T_NIL);
	}
	else if (rb_object == Qtrue) {
		mochilo_buf_putc(buf, MSGPACK_T_TRUE);
	}
	else if (rb_object == Qfalse) {
		mochilo_buf_putc(buf, MSGPACK_T_FALSE);
	}
	else if (FIXNUM_P(rb_object)) {
		mochilo_pack_fixnum(buf, rb_object);
	}
	else if (SYMBOL_P(rb_object)) {
		if (trusted)
			mochilo_pack_symbol(buf, rb_object);
		else
			mochilo_pack_str(buf, rb_obj_as_string(rb_object));
	}
	else {
		switch (BUILTIN_TYPE(rb_object)) {
		case T_STRING:
#ifdef HAVE_RUBY_ENCODING_H
			if (ENCODING_GET(rb_object) != 0)
				mochilo_pack_str(buf, rb_object);
			else
#endif
				mochilo_pack_bytes(buf, rb_object);
			return;

		case T_HASH:
			mochilo_pack_hash(buf, rb_object, trusted);
			return;

		case T_ARRAY:
			mochilo_pack_array(buf, rb_object, trusted);
			return;

		case T_FLOAT:
			mochilo_pack_double(buf, rb_object);
			return;

		case T_BIGNUM:
			mochilo_pack_bignum(buf, rb_object);
			return;

		default:
			rb_raise(rb_eMochiloPackError,
				"Unsupported object type: %s", rb_obj_classname(rb_object));
			return;
		}
	}
#else // RUBINIUS
	switch (rb_type(rb_object)) {
		case T_NIL:
			mochilo_buf_putc(buf, MSGPACK_T_NIL);
			return;

		case T_FALSE:
			mochilo_buf_putc(buf, MSGPACK_T_FALSE);
			return;

		case T_TRUE:
			mochilo_buf_putc(buf, MSGPACK_T_TRUE);
			return;

		case T_FIXNUM:
			mochilo_pack_fixnum(buf, rb_object);
			return;

		case T_BIGNUM:
			mochilo_pack_bignum(buf, rb_object);
			return;

		case T_SYMBOL:
			if (trusted)
				mochilo_pack_symbol(buf, rb_object);
			else
				mochilo_pack_str(buf, rb_obj_as_string(rb_object));
			return;

		case T_STRING:
#ifdef HAVE_RUBY_ENCODING_H
			if (ENCODING_GET(rb_object) != 0)
				mochilo_pack_str(buf, rb_object);
			else
#endif
				mochilo_pack_bytes(buf, rb_object);
			return;

		case T_HASH:
			mochilo_pack_hash(buf, rb_object, trusted);
			return;

		case T_ARRAY:
			mochilo_pack_array(buf, rb_object, trusted);
			return;

		case T_FLOAT:
			mochilo_pack_double(buf, rb_object);
			return;

		default:
			rb_raise(rb_eMochiloPackError,
				"Unsupported object type: %s", rb_obj_classname(rb_object));
			return;
	}
#endif
}