/* * CBOR for Ruby * * Copyright (C) 2013 Carsten Bormann * * Licensed under the Apache License, Version 2.0 (the "License"). * * Based on: ***********/ /* * MessagePack for Ruby * * Copyright (C) 2008-2013 Sadayuki Furuhashi * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "packer.h" #ifdef RUBINIUS static ID s_to_iter; static ID s_next; static ID s_key; static ID s_value; #endif void msgpack_packer_static_init() { #ifdef RUBINIUS s_to_iter = rb_intern("to_iter"); s_next = rb_intern("next"); s_key = rb_intern("key"); s_value = rb_intern("value"); #endif } void msgpack_packer_static_destroy() { } void msgpack_packer_init(msgpack_packer_t* pk) { memset(pk, 0, sizeof(msgpack_packer_t)); msgpack_buffer_init(PACKER_BUFFER_(pk)); pk->io = Qnil; } void msgpack_packer_destroy(msgpack_packer_t* pk) { msgpack_buffer_destroy(PACKER_BUFFER_(pk)); } void msgpack_packer_mark(msgpack_packer_t* pk) { rb_gc_mark(pk->io); /* See MessagePack_Buffer_wrap */ /* msgpack_buffer_mark(PACKER_BUFFER_(pk)); */ rb_gc_mark(pk->buffer_ref); } void msgpack_packer_reset(msgpack_packer_t* pk) { msgpack_buffer_clear(PACKER_BUFFER_(pk)); pk->io = Qnil; pk->io_write_all_method = 0; pk->buffer_ref = Qnil; } void msgpack_packer_write_array_value(msgpack_packer_t* pk, VALUE v) { /* actual return type of RARRAY_LEN is long */ unsigned long len = RARRAY_LEN(v); msgpack_packer_write_array_header(pk, len); unsigned long i; for(i=0; i < len; ++i) { VALUE e = rb_ary_entry(v, i); msgpack_packer_write_value(pk, e); } } static int write_hash_foreach(VALUE key, VALUE value, VALUE pk_value) { if (key == Qundef) { return ST_CONTINUE; } msgpack_packer_t* pk = (msgpack_packer_t*) pk_value; msgpack_packer_write_value(pk, key); msgpack_packer_write_value(pk, value); return ST_CONTINUE; } void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v) { /* actual return type of RHASH_SIZE is long (if SIZEOF_LONG == SIZEOF_VOIDP * or long long (if SIZEOF_LONG_LONG == SIZEOF_VOIDP. See st.h. */ unsigned long len = RHASH_SIZE(v); msgpack_packer_write_map_header(pk, len); #ifdef RUBINIUS VALUE iter = rb_funcall(v, s_to_iter, 0); VALUE entry = Qnil; while(RTEST(entry = rb_funcall(iter, s_next, 1, entry))) { VALUE key = rb_funcall(entry, s_key, 0); VALUE val = rb_funcall(entry, s_value, 0); write_hash_foreach(key, val, (VALUE) pk); } #else rb_hash_foreach(v, write_hash_foreach, (VALUE) pk); #endif } static void _msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v) { rb_funcall(v, pk->to_msgpack_method, 1, pk->to_msgpack_arg); } void msgpack_packer_write_value(msgpack_packer_t* pk, VALUE v) { switch(rb_type(v)) { case T_NIL: msgpack_packer_write_nil(pk); break; case T_TRUE: msgpack_packer_write_true(pk); break; case T_FALSE: msgpack_packer_write_false(pk); break; case T_FIXNUM: msgpack_packer_write_fixnum_value(pk, v); break; case T_SYMBOL: msgpack_packer_write_symbol_value(pk, v); break; case T_STRING: msgpack_packer_write_string_value(pk, v); break; case T_ARRAY: msgpack_packer_write_array_value(pk, v); break; case T_HASH: msgpack_packer_write_hash_value(pk, v); break; case T_BIGNUM: msgpack_packer_write_bignum_value(pk, v); break; case T_FLOAT: msgpack_packer_write_float_value(pk, v); break; default: _msgpack_packer_write_other_value(pk, v); } }