Beispiel #1
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);
}
Beispiel #2
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);
			}
		}
	}
}
Beispiel #3
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);
}
Beispiel #4
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);
}
Beispiel #5
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);
}
Beispiel #6
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);
}
Beispiel #7
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));
	}
}