11 void lwesrb_dump_type(LWES_BYTE type
, LWES_BYTE_P buf
, size_t *off
)
13 if (marshall_BYTE(type
, buf
, MAX_MSG_SIZE
, off
) > 0)
15 rb_raise(rb_eRuntimeError
, "failed to dump type=%02x", (unsigned)type
);
18 static int dump_uint16(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
20 int32_t tmp
= NUM2INT(val
);
23 rb_raise(rb_eRangeError
, ":uint16 negative: %d", tmp
);
25 rb_raise(rb_eRangeError
, ":uint16 too large: %d", tmp
);
27 lwesrb_dump_type(LWES_U_INT_16_TOKEN
, buf
, off
);
28 return marshall_U_INT_16((LWES_U_INT_16
)tmp
, buf
, MAX_MSG_SIZE
, off
);
31 static int dump_int16(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
33 int32_t tmp
= NUM2INT(val
);
36 rb_raise(rb_eRangeError
, ":int16 too large: %i", tmp
);
38 rb_raise(rb_eRangeError
, ":int16 too small: %i", tmp
);
40 lwesrb_dump_type(LWES_INT_16_TOKEN
, buf
, off
);
41 return marshall_INT_16((LWES_INT_16
)tmp
, buf
, MAX_MSG_SIZE
, off
);
44 static int dump_uint32(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
46 LONG_LONG tmp
= NUM2LL(val
);
49 rb_raise(rb_eRangeError
, ":uint32 negative: %lli", tmp
);
51 rb_raise(rb_eRangeError
, ":uint32 too large: %lli", tmp
);
53 lwesrb_dump_type(LWES_U_INT_32_TOKEN
, buf
, off
);
54 return marshall_U_INT_32((LWES_U_INT_32
)tmp
, buf
, MAX_MSG_SIZE
, off
);
57 static int dump_int32(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
59 LONG_LONG tmp
= NUM2LL(val
);
62 rb_raise(rb_eRangeError
, ":int32 too large: %lli", tmp
);
64 rb_raise(rb_eRangeError
, ":int32 too small: %lli", tmp
);
66 lwesrb_dump_type(LWES_INT_32_TOKEN
, buf
, off
);
67 return marshall_INT_32((LWES_INT_32
)tmp
, buf
, MAX_MSG_SIZE
, off
);
70 static int dump_uint64(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
72 unsigned LONG_LONG tmp
= NUM2ULL(val
); /* can raise RangeError */
75 if ((type
== T_FIXNUM
&& FIX2LONG(val
) < 0) ||
76 (type
== T_BIGNUM
&& RTEST(rb_funcall(val
, '<', 1, INT2FIX(0))))) {
77 volatile VALUE raise_inspect
;
79 rb_raise(rb_eRangeError
, ":uint64 negative: %s",
83 lwesrb_dump_type(LWES_U_INT_64_TOKEN
, buf
, off
);
84 return marshall_U_INT_64((LWES_U_INT_64
)tmp
, buf
, MAX_MSG_SIZE
, off
);
87 static int dump_int64(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
89 LONG_LONG tmp
= NUM2LL(val
); /* can raise RangeError */
91 lwesrb_dump_type(LWES_INT_64_TOKEN
, buf
, off
);
92 return marshall_INT_64((LWES_INT_64
)tmp
, buf
, MAX_MSG_SIZE
, off
);
95 static int dump_ip_addr(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
98 volatile VALUE raise_inspect
;
102 addr
.s_addr
= inet_addr(RSTRING_PTR(val
));
106 addr
.s_addr
= htonl(NUM2UINT(val
));
109 rb_raise(rb_eTypeError
,
110 ":ip_addr address must be String or Integer: %s",
113 lwesrb_dump_type(LWES_IP_ADDR_TOKEN
, buf
, off
);
114 return marshall_IP_ADDR(addr
, buf
, MAX_MSG_SIZE
, off
);
117 /* simple type => function dispatch map */
118 static struct _type_fn_map
{
120 int (*fn
)(VALUE
, LWES_BYTE_P
, size_t *);
122 #define SYMFN(T) { (ID)&sym_##T, dump_##T }
133 /* used for Struct serialization where types are known ahead of time */
140 if (type
!= LWES_TYPE_IP_ADDR
&& TYPE(val
) == T_STRING
)
141 val
= rb_funcall(val
, id_to_i
, 0, 0);
144 case LWES_TYPE_U_INT_16
: return dump_uint16(val
, buf
, off
);
145 case LWES_TYPE_INT_16
: return dump_int16(val
, buf
, off
);
146 case LWES_TYPE_U_INT_32
: return dump_uint32(val
, buf
, off
);
147 case LWES_TYPE_INT_32
: return dump_int32(val
, buf
, off
);
148 case LWES_TYPE_U_INT_64
: return dump_uint64(val
, buf
, off
);
149 case LWES_TYPE_INT_64
: return dump_int64(val
, buf
, off
);
150 case LWES_TYPE_IP_ADDR
: return dump_ip_addr(val
, buf
, off
);
152 rb_raise(rb_eRuntimeError
,
153 "unknown LWES attribute type: 0x%02x", type
);
155 assert("you should never get here (dump_num)");
159 void lwesrb_dump_num(LWES_BYTE type
, VALUE val
, LWES_BYTE_P buf
, size_t *off
)
161 if (dump_num(type
, val
, buf
, off
) > 0)
163 rb_raise(rb_eRuntimeError
,
164 "dumping numeric type 0x%02x, type failed", type
);
168 * used for Hash serialization
169 * array contains two elements:
170 * [ symbolic_type, number ]
171 * returns the return value of the underlying lwes_event_set_* call
173 void lwesrb_dump_num_ary(VALUE array
, LWES_BYTE_P buf
, size_t *off
)
175 volatile VALUE raise_inspect
;
177 struct _type_fn_map
*head
;
181 assert(TYPE(array
) == T_ARRAY
&& "need array here");
183 if (RARRAY_LEN(array
) != 2)
184 rb_raise(rb_eArgError
, "expected a two element array");
186 ary
= RARRAY_PTR(array
);
189 i
= sizeof(type_fn_map
) / sizeof(type_fn_map
[0]);
190 for (head
= type_fn_map
; --i
>= 0; head
++) {
191 if (head
->type
!= type
)
194 rv
= head
->fn(ary
[1], buf
, off
);
198 rb_raise(rb_eRuntimeError
,
199 "dumping numeric type %s, type failed",
200 RAISE_INSPECT(type
));
203 rb_raise(rb_eArgError
, "unknown type: %s", RAISE_INSPECT(type
));
206 void lwesrb_init_numeric(void)
211 LWESRB_MKSYM(uint16
);
213 LWESRB_MKSYM(uint32
);
215 LWESRB_MKSYM(uint64
);
216 LWESRB_MKSYM(ip_addr
);
217 id_to_i
= rb_intern("to_i");
220 * we needed to have constants for compilation, so we set the
221 * address of the IDs and then dereference + reassign them
222 * at initialization time:
224 i
= sizeof(type_fn_map
) / sizeof(type_fn_map
[0]);
226 type_fn_map
[i
].type
= *(ID
*)type_fn_map
[i
].type
;