WireAPI 0.3

Sign up to get free protection for your applications and to get access to all the features.
data/amq_field_list.c ADDED
@@ -0,0 +1,318 @@
1
+ #include <ruby.h>
2
+ #include <st.h>
3
+ #include <string.h>
4
+ #include "amq_field_list.h"
5
+ #include "amq_types.h"
6
+ #include <limits.h>
7
+
8
+ /* used for converting float to fixpoint */
9
+ const long FIXPOINT_MAX=LONG_MAX/100;
10
+
11
+ VALUE amqp_field_list;
12
+
13
+ /* receives a AMQ_FieldList or a Hash */
14
+ icl_longstr_t* get_optional_field_list(VALUE val) {
15
+ amq_field_list_cls *obj=0;
16
+ if (TYPE(val)==T_DATA && rb_obj_is_instance_of(val, amqp_field_list)) {
17
+ obj=get_amq_field_list_cls(val,1);
18
+ }
19
+ if (TYPE(val)==T_HASH) {
20
+ VALUE fld_list=rb_funcall(amqp_field_list,rb_intern("new"),1,val);
21
+ obj= get_amq_field_list_cls(fld_list,1);
22
+ }
23
+
24
+ if (obj && obj->field_list) {
25
+ return asl_field_list_flatten(obj->field_list);
26
+ }
27
+ return 0;
28
+ }
29
+
30
+
31
+ /* try to convert val to a string when it is not a string yet */
32
+ VALUE get_as_string(VALUE val) {
33
+ if (TYPE(val)==T_STRING)
34
+ return val;
35
+ return rb_funcall(val,rb_intern("to_s"),0,0);
36
+ }
37
+
38
+
39
+
40
+
41
+ static VALUE field_value_to_ruby(asl_field_t *field) {
42
+ switch (field->type) {
43
+ case 'D': {
44
+ long double val=field->integer;
45
+ int d=field->decimals;
46
+ while (--d>=0)
47
+ val/=10;
48
+ return rb_float_new(val);
49
+ break;
50
+ }
51
+ case 'T': {
52
+ VALUE argv[1];
53
+ argv[0]=LONG2NUM(asl_field_integer(field));
54
+ VALUE time=rb_funcall2(rb_cTime,rb_intern("at"),1,argv);
55
+ return time;
56
+ break;
57
+ }
58
+ case 'S': {
59
+ return rb_str_new2(asl_field_string(field));
60
+ break;
61
+ }
62
+ case 'I': {
63
+ return INT2NUM(asl_field_integer(field));
64
+ break;
65
+ }
66
+ default:
67
+ return Qnil;
68
+ }
69
+ }
70
+
71
+
72
+ static int add_ruby_value_to_field_list(asl_field_list_t *field_list,char *name,VALUE val) {
73
+ int res=0;
74
+ switch (TYPE(val)) {
75
+ case T_NIL:
76
+ {
77
+ asl_field_new_void(field_list,name);
78
+ res=1;
79
+ break;
80
+ }
81
+ case T_DATA:
82
+ {
83
+ if (rb_obj_is_instance_of(val, rb_cTime)) {
84
+ VALUE _time=rb_funcall(val,rb_intern("tv_sec"),0,0);
85
+ long t=NUM2LONG(_time);
86
+ asl_field_new_time(field_list,name,t);
87
+ res=1;
88
+ break;
89
+ }
90
+
91
+ }
92
+ case T_FLOAT:
93
+ {
94
+ long double v=NUM2DBL(val);
95
+ int dec=0;
96
+ // make sure the integer doesn't roll over
97
+ while ((((long)v)-v)!=0 && abs(v)<FIXPOINT_MAX && dec<255) {
98
+ v*=10;
99
+ dec++;
100
+ }
101
+ asl_field_new_decimal(field_list,name,(long)v,dec);
102
+ res=1;
103
+ break;
104
+ }
105
+ case T_STRING:
106
+ {
107
+ char *str_val= StringValuePtr(val);
108
+ asl_field_new_string(field_list,name,str_val);
109
+ res=1;
110
+ break;
111
+ }
112
+ case T_FIXNUM:
113
+ {
114
+ long int_val= NUM2LONG(val);
115
+ asl_field_new_integer(field_list,name,int_val);
116
+ res=1;
117
+ break;
118
+ }
119
+ }
120
+ return res;
121
+ }
122
+
123
+
124
+ static VALUE field_list_new(int argc,VALUE *argv,VALUE klass)
125
+ {
126
+ VALUE self=create_amq_field_list_cls(asl_field_list_new (0));
127
+ rb_obj_call_init(self, argc, argv);
128
+ return self;
129
+ }
130
+
131
+
132
+ static VALUE field_list_initialize(int argc,VALUE *argv,VALUE self)
133
+ {
134
+ VALUE param;
135
+ rb_scan_args(argc,argv,"01",&param);
136
+ if (param==Qnil) {
137
+ return self;
138
+ }
139
+
140
+ amq_field_list_cls* const fieldlst=get_amq_field_list_cls(self,1);
141
+ if (TYPE(param)==T_HASH) {
142
+ return rb_funcall(self,rb_intern("add_hash"),1,param);
143
+ }
144
+ if (TYPE(param)==T_DATA && rb_obj_is_instance_of(param, amqp_field_list)) {
145
+ amq_field_list_cls *obj=get_amq_field_list_cls(param,1);
146
+ asl_field_t *field = 0;
147
+ field=asl_field_list_first (obj->field_list);
148
+ while (field) {
149
+ VALUE val_arg=field_value_to_ruby(field);
150
+ add_ruby_value_to_field_list(fieldlst->field_list,field->name,val_arg);
151
+ field = asl_field_list_next (&field);
152
+ }
153
+ return self;
154
+ }
155
+ return self;
156
+ }
157
+
158
+
159
+ static VALUE field_list_destroy(VALUE self)
160
+ {
161
+ amq_field_list_cls* const fieldlst=get_amq_field_list_cls(self,1);
162
+ if (fieldlst->field_list) {
163
+ asl_field_list_destroy(&(fieldlst->field_list));
164
+ fieldlst->field_list=0;
165
+ }
166
+ return Qnil;
167
+ }
168
+
169
+
170
+ static VALUE field_list_to_hash(VALUE self) {
171
+ amq_field_list_cls* const fieldlst=get_amq_field_list_cls(self,1);
172
+ VALUE result=rb_hash_new();
173
+ VALUE key;
174
+ VALUE val;
175
+ asl_field_t *field = 0;
176
+ field=asl_field_list_first (fieldlst->field_list);
177
+ while (field) {
178
+ key=rb_str_new2(field->name);
179
+ val=field_value_to_ruby(field);
180
+ rb_hash_aset(result,key,val);
181
+ field = asl_field_list_next (&field);
182
+ }
183
+ return result;
184
+ }
185
+
186
+ static VALUE field_list_each_pair(VALUE self) {
187
+ amq_field_list_cls* const fieldlst=get_amq_field_list_cls(self,1);
188
+ VALUE result=rb_hash_new();
189
+ VALUE key_arg;
190
+ VALUE val_arg;
191
+ asl_field_t *field = 0;
192
+ field=asl_field_list_first (fieldlst->field_list);
193
+
194
+ while (field) {
195
+ key_arg=rb_str_new2(field->name);
196
+ val_arg=field_value_to_ruby(field);
197
+ if (rb_block_given_p()==Qtrue) {
198
+ rb_yield_values(2,key_arg,val_arg);
199
+ } else {
200
+ rb_raise(rb_eArgError, "need block with 2 arguments");
201
+ }
202
+ field = asl_field_list_next (&field);
203
+ }
204
+ return result;
205
+ }
206
+
207
+
208
+
209
+
210
+ static VALUE field_list_get_key(VALUE self,VALUE name_val) {
211
+ amq_field_list_cls* const fieldlst=get_amq_field_list_cls(self,1);
212
+ VALUE name=get_as_string(name_val);
213
+ Check_Type(name,T_STRING);
214
+ char *_name = StringValuePtr(name);
215
+ asl_field_t *field = 0;
216
+ field=asl_field_list_first (fieldlst->field_list);
217
+ VALUE result=Qnil;
218
+ while (field && result==Qnil) {
219
+ if (strcmp(field->name,_name)==0) {
220
+ result=field_value_to_ruby(field);
221
+ }
222
+ field = asl_field_list_next (&field);
223
+ }
224
+ return result;
225
+ }
226
+
227
+
228
+
229
+ static VALUE field_list_put_key(VALUE self,VALUE name_val,VALUE val) {
230
+ amq_field_list_cls* const fieldlst=get_amq_field_list_cls(self,1);
231
+ VALUE name=get_as_string(name_val);
232
+ Check_Type(name,T_STRING);
233
+ char *_name = StringValuePtr(name);
234
+ int res=add_ruby_value_to_field_list(fieldlst->field_list,_name,val);
235
+ if (res==0) {
236
+ rb_raise(rb_amq_error,"Can't handle value type");
237
+ }
238
+ return self;
239
+ }
240
+
241
+
242
+
243
+ /* utility */
244
+ static int push_hash_key(VALUE key, VALUE value, VALUE buf) {
245
+ rb_ary_push(buf,key);
246
+ return ST_CONTINUE;
247
+ }
248
+
249
+
250
+ static VALUE field_list_keys(VALUE self) {
251
+ amq_field_list_cls* const fieldlst=get_amq_field_list_cls(self,1);
252
+ VALUE result=rb_ary_new();
253
+ asl_field_t *field = 0;
254
+ field=asl_field_list_first(fieldlst->field_list);
255
+ while (field) {
256
+ VALUE key_str=rb_str_new2(field->name);
257
+ rb_ary_push(result,key_str);
258
+ field = asl_field_list_next (&field);
259
+ }
260
+ return result;
261
+ }
262
+
263
+
264
+ static VALUE field_list_keys_unique(VALUE self) {
265
+ VALUE key_array=field_list_keys(self);
266
+ ID include_method=rb_intern("include?");
267
+
268
+ while (RARRAY_LEN(key_array)>0) {
269
+ VALUE elem=rb_ary_pop(key_array);
270
+ if (Qtrue==rb_funcall(key_array,include_method,1,elem)) {
271
+ return Qfalse;
272
+ }
273
+ }
274
+ return Qtrue;
275
+ }
276
+
277
+
278
+ static VALUE field_list_add_hash(VALUE self,VALUE hash) {
279
+ amq_field_list_cls* const fieldlst=get_amq_field_list_cls(self,1);
280
+ Check_Type(hash,T_HASH);
281
+ VALUE key_arr=rb_ary_new();
282
+ rb_hash_foreach(hash, push_hash_key, key_arr);
283
+
284
+ VALUE key=rb_ary_shift(key_arr);
285
+ while (key!=Qnil) {
286
+ VALUE key_name=get_as_string(key);
287
+ char *_key = StringValuePtr(key_name);
288
+ VALUE val=rb_hash_aref(hash,key);
289
+ int res=add_ruby_value_to_field_list(fieldlst->field_list,_key,val);
290
+ if (res==0) {
291
+ rb_raise(rb_amq_error,"Can't handle value type for ",key);
292
+ }
293
+ key=rb_ary_shift(key_arr);
294
+ }
295
+ return self;
296
+ }
297
+
298
+
299
+
300
+
301
+
302
+ void init_field_list() {
303
+ amqp_field_list = rb_define_class_under(rb_wireapi,"AMQ_FieldList",rb_cObject);
304
+ rb_define_singleton_method(amqp_field_list , "new", field_list_new , -1);
305
+ rb_define_method(amqp_field_list,"initialize" , field_list_initialize ,-1);
306
+ rb_define_method(amqp_field_list,"to_hash" , field_list_to_hash ,0);
307
+ rb_define_method(amqp_field_list,"keys" , field_list_keys ,0);
308
+ rb_define_method(amqp_field_list,"destroy" , field_list_destroy ,0);
309
+ rb_define_method(amqp_field_list,"each_pair" , field_list_each_pair,0);
310
+ rb_define_method(amqp_field_list,"[]" , field_list_get_key ,1);
311
+ rb_define_method(amqp_field_list,"get" , field_list_get_key ,1);
312
+ rb_define_method(amqp_field_list,"put" , field_list_put_key ,2);
313
+ rb_define_method(amqp_field_list,"[]=" , field_list_put_key ,2);
314
+ rb_define_method(amqp_field_list,"add_hash" , field_list_add_hash,1);
315
+ rb_define_method(amqp_field_list,"keys_unique?", field_list_keys_unique,0);
316
+
317
+ }
318
+
data/amq_field_list.h ADDED
@@ -0,0 +1,13 @@
1
+
2
+ #ifndef AMQ_FIELD_LIST_HEADER
3
+ #define AMQ_FIELD_LIST_HEADER
4
+
5
+ #include <ruby.h>
6
+ #include <icl.h>
7
+
8
+ icl_longstr_t* get_optional_field_list(VALUE val);
9
+
10
+ void init_field_list();
11
+
12
+
13
+ #endif