fix compatibility with ruby 2.1.0preview1
[lwes-ruby.git] / ext / lwes_ext / numeric.c
blobbe857d77259678a1a86cbd875417e53d80a2c0cc
1 #include "lwes_ruby.h"
2 #include <arpa/inet.h>
4 static ID
5 sym_int16, sym_uint16,
6 sym_int32, sym_uint32,
7 sym_int64, sym_uint64,
8 sym_ip_addr;
9 static ID id_to_i;
11 static int dump_uint16(VALUE val, LWES_BYTE_P buf, size_t *off)
13 lwesrb_dump_type(LWES_U_INT_16_TOKEN, buf, off);
14 return marshall_U_INT_16(lwesrb_uint16(val), buf, MAX_MSG_SIZE, off);
17 static int dump_int16(VALUE val, LWES_BYTE_P buf, size_t *off)
19 lwesrb_dump_type(LWES_INT_16_TOKEN, buf, off);
20 return marshall_INT_16(lwesrb_int16(val), buf, MAX_MSG_SIZE, off);
23 static int dump_uint32(VALUE val, LWES_BYTE_P buf, size_t *off)
25 lwesrb_dump_type(LWES_U_INT_32_TOKEN, buf, off);
26 return marshall_U_INT_32(lwesrb_uint32(val), buf, MAX_MSG_SIZE, off);
29 static int dump_int32(VALUE val, LWES_BYTE_P buf, size_t *off)
31 lwesrb_dump_type(LWES_INT_32_TOKEN, buf, off);
32 return marshall_INT_32(lwesrb_int32(val), buf, MAX_MSG_SIZE, off);
35 static int dump_uint64(VALUE val, LWES_BYTE_P buf, size_t *off)
37 lwesrb_dump_type(LWES_U_INT_64_TOKEN, buf, off);
38 return marshall_U_INT_64(lwesrb_uint64(val), buf, MAX_MSG_SIZE, off);
41 static int dump_int64(VALUE val, LWES_BYTE_P buf, size_t *off)
43 lwesrb_dump_type(LWES_INT_64_TOKEN, buf, off);
44 return marshall_INT_64(lwesrb_int64(val), buf, MAX_MSG_SIZE, off);
47 static int dump_ip_addr(VALUE val, LWES_BYTE_P buf, size_t *off)
49 lwesrb_dump_type(LWES_IP_ADDR_TOKEN, buf, off);
50 return marshall_IP_ADDR(lwesrb_ip_addr(val), buf, MAX_MSG_SIZE, off);
53 /* simple type => function dispatch map */
54 static struct _type_fn_map {
55 ID type;
56 int (*fn)(VALUE, LWES_BYTE_P, size_t *);
57 } type_fn_map[] = {
58 #define SYMFN(T) { (ID)&sym_##T, dump_##T }
59 SYMFN(uint16),
60 SYMFN(int16),
61 SYMFN(uint32),
62 SYMFN(int32),
63 SYMFN(uint64),
64 SYMFN(int64),
65 SYMFN(ip_addr),
66 #undef SYMFN
69 /* used for Struct serialization where types are known ahead of time */
70 static int dump_num(
71 LWES_TYPE type,
72 VALUE val,
73 LWES_BYTE_P buf,
74 size_t *off)
76 if (type != LWES_TYPE_IP_ADDR && TYPE(val) == T_STRING)
77 val = rb_funcall(val, id_to_i, 0, 0);
79 switch (type) {
80 case LWES_TYPE_U_INT_16: return dump_uint16(val, buf, off);
81 case LWES_TYPE_INT_16: return dump_int16(val, buf, off);
82 case LWES_TYPE_U_INT_32: return dump_uint32(val, buf, off);
83 case LWES_TYPE_INT_32: return dump_int32(val, buf, off);
84 case LWES_TYPE_U_INT_64: return dump_uint64(val, buf, off);
85 case LWES_TYPE_INT_64: return dump_int64(val, buf, off);
86 case LWES_TYPE_IP_ADDR: return dump_ip_addr(val, buf, off);
87 default:
88 rb_raise(rb_eRuntimeError,
89 "unknown LWES attribute type: 0x%02x", type);
91 assert("you should never get here (dump_num)");
92 return -1;
95 void lwesrb_dump_num(LWES_BYTE type, VALUE val, LWES_BYTE_P buf, size_t *off)
97 if (dump_num(type, val, buf, off) > 0)
98 return;
99 rb_raise(rb_eRuntimeError,
100 "dumping numeric type 0x%02x, type failed", type);
104 * used for Hash serialization
105 * array contains two elements:
106 * [ symbolic_type, number ]
107 * returns the return value of the underlying lwes_event_set_* call
109 void lwesrb_dump_num_ary(VALUE array, LWES_BYTE_P buf, size_t *off)
111 volatile VALUE raise_inspect;
112 int i, rv;
113 struct _type_fn_map *head;
114 ID type;
116 assert(TYPE(array) == T_ARRAY && "need array here");
118 if (RARRAY_LEN(array) != 2)
119 rb_raise(rb_eArgError, "expected a two element array");
121 type = rb_ary_entry(array, 0);
123 i = sizeof(type_fn_map) / sizeof(type_fn_map[0]);
124 for (head = type_fn_map; --i >= 0; head++) {
125 if (head->type != type)
126 continue;
128 rv = head->fn(rb_ary_entry(array, 1), buf, off);
129 if (rv > 0)
130 return;
132 rb_raise(rb_eRuntimeError,
133 "dumping numeric type %s, type failed",
134 RAISE_INSPECT(type));
137 rb_raise(rb_eArgError, "unknown type: %s", RAISE_INSPECT(type));
140 void lwesrb_init_numeric(void)
142 int i;
144 LWESRB_MKSYM(int16);
145 LWESRB_MKSYM(uint16);
146 LWESRB_MKSYM(int32);
147 LWESRB_MKSYM(uint32);
148 LWESRB_MKSYM(int64);
149 LWESRB_MKSYM(uint64);
150 LWESRB_MKSYM(ip_addr);
151 id_to_i = rb_intern("to_i");
154 * we needed to have constants for compilation, so we set the
155 * address of the IDs and then dereference + reassign them
156 * at initialization time:
158 i = sizeof(type_fn_map) / sizeof(type_fn_map[0]);
159 while (--i >= 0)
160 type_fn_map[i].type = *(ID *)type_fn_map[i].type;