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); }
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); } } } }
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); }
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); }
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); }
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); }
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)); } }