10 void lwesrb_dump_type(LWES_BYTE type
, LWES_BYTE_P buf
, size_t *off
)
12 if (marshall_BYTE(type
, buf
, MAX_MSG_SIZE
, off
) > 0)
14 rb_raise(rb_eRuntimeError
, "failed to dump type=%02x", (unsigned)type
);
17 static int dump_uint16(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
19 int32_t tmp
= NUM2INT(val
);
22 rb_raise(rb_eRangeError
, ":uint16 negative: %d", tmp
);
24 rb_raise(rb_eRangeError
, ":uint16 too large: %d", tmp
);
26 lwesrb_dump_type(LWES_U_INT_16_TOKEN
, buf
, off
);
27 return marshall_U_INT_16((LWES_U_INT_16
)tmp
, buf
, MAX_MSG_SIZE
, off
);
30 static int dump_int16(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
32 int32_t tmp
= NUM2INT(val
);
35 rb_raise(rb_eRangeError
, ":int16 too large: %i", tmp
);
37 rb_raise(rb_eRangeError
, ":int16 too small: %i", tmp
);
39 lwesrb_dump_type(LWES_INT_16_TOKEN
, buf
, off
);
40 return marshall_INT_16((LWES_INT_16
)tmp
, buf
, MAX_MSG_SIZE
, off
);
43 static int dump_uint32(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
45 LONG_LONG tmp
= NUM2LL(val
);
48 rb_raise(rb_eRangeError
, ":uint32 negative: %lli", tmp
);
50 rb_raise(rb_eRangeError
, ":uint32 too large: %lli", tmp
);
52 lwesrb_dump_type(LWES_U_INT_32_TOKEN
, buf
, off
);
53 return marshall_U_INT_32((LWES_U_INT_32
)tmp
, buf
, MAX_MSG_SIZE
, off
);
56 static int dump_int32(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
58 LONG_LONG tmp
= NUM2LL(val
);
61 rb_raise(rb_eRangeError
, ":int32 too large: %lli", tmp
);
63 rb_raise(rb_eRangeError
, ":int32 too small: %lli", tmp
);
65 lwesrb_dump_type(LWES_INT_32_TOKEN
, buf
, off
);
66 return marshall_INT_32((LWES_INT_32
)tmp
, buf
, MAX_MSG_SIZE
, off
);
69 static int dump_uint64(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
71 unsigned LONG_LONG tmp
= NUM2ULL(val
); /* can raise RangeError */
74 if ((type
== T_FIXNUM
&& FIX2LONG(val
) < 0) ||
75 (type
== T_BIGNUM
&& RTEST(rb_funcall(val
, '<', 1, INT2FIX(0)))))
76 rb_raise(rb_eRangeError
, ":uint64 negative: %s",
77 RSTRING_PTR(rb_inspect(val
)));
79 lwesrb_dump_type(LWES_U_INT_64_TOKEN
, buf
, off
);
80 return marshall_U_INT_64((LWES_U_INT_64
)tmp
, buf
, MAX_MSG_SIZE
, off
);
83 static int dump_int64(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
85 LONG_LONG tmp
= NUM2LL(val
); /* can raise RangeError */
87 lwesrb_dump_type(LWES_INT_64_TOKEN
, buf
, off
);
88 return marshall_INT_64((LWES_INT_64
)tmp
, buf
, MAX_MSG_SIZE
, off
);
91 static int dump_ip_addr(VALUE val
, LWES_BYTE_P buf
, size_t *off
)
97 addr
.s_addr
= inet_addr(RSTRING_PTR(val
));
101 addr
.s_addr
= htonl(NUM2UINT(val
));
104 rb_raise(rb_eTypeError
,
105 ":ip_addr address must be String or Integer: %s",
106 RSTRING_PTR(rb_inspect(val
)));
108 lwesrb_dump_type(LWES_IP_ADDR_TOKEN
, buf
, off
);
109 return marshall_IP_ADDR(addr
, buf
, MAX_MSG_SIZE
, off
);
112 /* simple type => function dispatch map */
113 static struct _type_fn_map
{
115 int (*fn
)(VALUE
, LWES_BYTE_P
, size_t *);
117 #define SYMFN(T) { (ID)&sym_##T, dump_##T }
128 /* used for Struct serialization where types are known ahead of time */
136 case LWES_TYPE_U_INT_16
: return dump_uint16(val
, buf
, off
);
137 case LWES_TYPE_INT_16
: return dump_int16(val
, buf
, off
);
138 case LWES_TYPE_U_INT_32
: return dump_uint32(val
, buf
, off
);
139 case LWES_TYPE_INT_32
: return dump_int32(val
, buf
, off
);
140 case LWES_TYPE_U_INT_64
: return dump_uint64(val
, buf
, off
);
141 case LWES_TYPE_INT_64
: return dump_int64(val
, buf
, off
);
142 case LWES_TYPE_IP_ADDR
: return dump_ip_addr(val
, buf
, off
);
144 rb_raise(rb_eRuntimeError
,
145 "unknown LWES attribute type: 0x%02x", type
);
147 assert("you should never get here (dump_num)");
151 void lwesrb_dump_num(LWES_BYTE type
, VALUE val
, LWES_BYTE_P buf
, size_t *off
)
153 if (dump_num(type
, val
, buf
, off
) > 0)
155 rb_raise(rb_eRuntimeError
,
156 "dumping numeric type 0x%02x, type failed", type
);
160 * used for Hash serialization
161 * array contains two elements:
162 * [ symbolic_type, number ]
163 * returns the return value of the underlying lwes_event_set_* call
165 void lwesrb_dump_num_ary(VALUE array
, LWES_BYTE_P buf
, size_t *off
)
168 struct _type_fn_map
*head
;
172 assert(TYPE(array
) == T_ARRAY
&& "need array here");
174 if (RARRAY_LEN(array
) != 2)
175 rb_raise(rb_eArgError
, "expected a two element array");
177 ary
= RARRAY_PTR(array
);
180 i
= sizeof(type_fn_map
) / sizeof(type_fn_map
[0]);
181 for (head
= type_fn_map
; --i
>= 0; head
++) {
182 if (head
->type
!= type
)
185 rv
= head
->fn(ary
[1], buf
, off
);
188 rb_raise(rb_eRuntimeError
,
189 "dumping numeric type %s, type failed",
190 RSTRING_PTR(rb_obj_as_string(type
)));
193 rb_raise(rb_eArgError
,
194 "unknown type: %s", RSTRING_PTR(rb_inspect(type
)));
197 void lwesrb_init_numeric(void)
202 LWESRB_MKSYM(uint16
);
204 LWESRB_MKSYM(uint32
);
206 LWESRB_MKSYM(uint64
);
207 LWESRB_MKSYM(ip_addr
);
210 * we needed to have constants for compilation, so we set the
211 * address of the IDs and then dereference + reassign them
212 * at initialization time:
214 i
= sizeof(type_fn_map
) / sizeof(type_fn_map
[0]);
216 type_fn_map
[i
].type
= *(ID
*)type_fn_map
[i
].type
;