Subversion Repositories SmartDukaan

Rev

Rev 30 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
30 ashish 1
/**
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements. See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership. The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License. You may obtain a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied. See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
 
20
#include <ruby.h>
21
#include <stdbool.h>
22
#include <stdint.h>
23
#include <constants.h>
24
#include <struct.h>
25
#include "macros.h"
26
 
27
VALUE rb_thrift_binary_proto_native_qmark(VALUE self) {
28
  return Qtrue;
29
}
30
 
31
 
32
 
33
static int VERSION_1;
34
static int VERSION_MASK;
35
static int TYPE_MASK;
36
static int BAD_VERSION;
37
 
38
static void write_byte_direct(VALUE trans, int8_t b) {
39
  WRITE(trans, (char*)&b, 1);
40
}
41
 
42
static void write_i16_direct(VALUE trans, int16_t value) {
43
  char data[2];
44
 
45
  data[1] = value;
46
  data[0] = (value >> 8);
47
 
48
  WRITE(trans, data, 2);
49
}
50
 
51
static void write_i32_direct(VALUE trans, int32_t value) {
52
  char data[4];
53
 
54
  data[3] = value;
55
  data[2] = (value >> 8);
56
  data[1] = (value >> 16);
57
  data[0] = (value >> 24);
58
 
59
  WRITE(trans, data, 4);
60
}
61
 
62
 
63
static void write_i64_direct(VALUE trans, int64_t value) {
64
  char data[8];
65
 
66
  data[7] = value;
67
  data[6] = (value >> 8);
68
  data[5] = (value >> 16);
69
  data[4] = (value >> 24);
70
  data[3] = (value >> 32);
71
  data[2] = (value >> 40);
72
  data[1] = (value >> 48);
73
  data[0] = (value >> 56);
74
 
75
  WRITE(trans, data, 8);
76
}
77
 
78
static void write_string_direct(VALUE trans, VALUE str) {
79
  if (TYPE(str) != T_STRING) {
80
    rb_raise(rb_eStandardError, "Value should be a string");    
81
  }
82
  write_i32_direct(trans, RSTRING_LEN(str));
83
  rb_funcall(trans, write_method_id, 1, str);
84
}
85
 
86
//--------------------------------
87
// interface writing methods
88
//--------------------------------
89
 
90
VALUE rb_thrift_binary_proto_write_message_end(VALUE self) {
91
  return Qnil;
92
}
93
 
94
VALUE rb_thrift_binary_proto_write_struct_begin(VALUE self, VALUE name) {
95
  return Qnil;
96
}
97
 
98
VALUE rb_thrift_binary_proto_write_struct_end(VALUE self) {
99
  return Qnil;
100
}
101
 
102
VALUE rb_thrift_binary_proto_write_field_end(VALUE self) {
103
  return Qnil;
104
}
105
 
106
VALUE rb_thrift_binary_proto_write_map_end(VALUE self) {
107
  return Qnil;
108
}
109
 
110
VALUE rb_thrift_binary_proto_write_list_end(VALUE self) {
111
  return Qnil;
112
}
113
 
114
VALUE rb_thrift_binary_proto_write_set_end(VALUE self) {
115
  return Qnil;
116
}
117
 
118
VALUE rb_thrift_binary_proto_write_message_begin(VALUE self, VALUE name, VALUE type, VALUE seqid) {
119
  VALUE trans = GET_TRANSPORT(self);
120
  VALUE strict_write = GET_STRICT_WRITE(self);
121
 
122
  if (strict_write == Qtrue) {
123
    write_i32_direct(trans, VERSION_1 | FIX2INT(type));
124
    write_string_direct(trans, name);
125
    write_i32_direct(trans, FIX2INT(seqid));
126
  } else {
127
    write_string_direct(trans, name);
128
    write_byte_direct(trans, FIX2INT(type));
129
    write_i32_direct(trans, FIX2INT(seqid));
130
  }
131
 
132
  return Qnil;
133
}
134
 
135
VALUE rb_thrift_binary_proto_write_field_begin(VALUE self, VALUE name, VALUE type, VALUE id) {
136
  VALUE trans = GET_TRANSPORT(self);
137
  write_byte_direct(trans, FIX2INT(type));
138
  write_i16_direct(trans, FIX2INT(id));
139
 
140
  return Qnil;
141
}
142
 
143
VALUE rb_thrift_binary_proto_write_field_stop(VALUE self) {
144
  write_byte_direct(GET_TRANSPORT(self), TTYPE_STOP);
145
  return Qnil;
146
}
147
 
148
VALUE rb_thrift_binary_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtype, VALUE size) {
149
  VALUE trans = GET_TRANSPORT(self);
150
  write_byte_direct(trans, FIX2INT(ktype));
151
  write_byte_direct(trans, FIX2INT(vtype));
152
  write_i32_direct(trans, FIX2INT(size));
153
 
154
  return Qnil;
155
}
156
 
157
VALUE rb_thrift_binary_proto_write_list_begin(VALUE self, VALUE etype, VALUE size) {
158
  VALUE trans = GET_TRANSPORT(self);
159
  write_byte_direct(trans, FIX2INT(etype));
160
  write_i32_direct(trans, FIX2INT(size));
161
 
162
  return Qnil;
163
}
164
 
165
VALUE rb_thrift_binary_proto_write_set_begin(VALUE self, VALUE etype, VALUE size) {
166
  rb_thrift_binary_proto_write_list_begin(self, etype, size);
167
  return Qnil;
168
}
169
 
170
VALUE rb_thrift_binary_proto_write_bool(VALUE self, VALUE b) {
171
  write_byte_direct(GET_TRANSPORT(self), RTEST(b) ? 1 : 0);
172
  return Qnil;
173
}
174
 
175
VALUE rb_thrift_binary_proto_write_byte(VALUE self, VALUE byte) {
176
  CHECK_NIL(byte);
177
  write_byte_direct(GET_TRANSPORT(self), NUM2INT(byte));
178
  return Qnil;
179
}
180
 
181
VALUE rb_thrift_binary_proto_write_i16(VALUE self, VALUE i16) {
182
  CHECK_NIL(i16);
183
  write_i16_direct(GET_TRANSPORT(self), FIX2INT(i16));
184
  return Qnil;
185
}
186
 
187
VALUE rb_thrift_binary_proto_write_i32(VALUE self, VALUE i32) {
188
  CHECK_NIL(i32);
189
  write_i32_direct(GET_TRANSPORT(self), NUM2INT(i32));
190
  return Qnil;
191
}
192
 
193
VALUE rb_thrift_binary_proto_write_i64(VALUE self, VALUE i64) {
194
  CHECK_NIL(i64);
195
  write_i64_direct(GET_TRANSPORT(self), NUM2LL(i64));
196
  return Qnil;
197
}
198
 
199
VALUE rb_thrift_binary_proto_write_double(VALUE self, VALUE dub) {
200
  CHECK_NIL(dub);
201
  // Unfortunately, bitwise_cast doesn't work in C.  Bad C!
202
  union {
203
    double f;
204
    int64_t t;
205
  } transfer;
206
  transfer.f = RFLOAT_VALUE(rb_Float(dub));
207
  write_i64_direct(GET_TRANSPORT(self), transfer.t);
208
 
209
  return Qnil;
210
}
211
 
212
VALUE rb_thrift_binary_proto_write_string(VALUE self, VALUE str) {
213
  CHECK_NIL(str);
214
  VALUE trans = GET_TRANSPORT(self);
215
  write_string_direct(trans, str);
216
  return Qnil;
217
}
218
 
219
//---------------------------------------
220
// interface reading methods
221
//---------------------------------------
222
 
223
VALUE rb_thrift_binary_proto_read_string(VALUE self);
224
VALUE rb_thrift_binary_proto_read_byte(VALUE self);
225
VALUE rb_thrift_binary_proto_read_i32(VALUE self);
226
VALUE rb_thrift_binary_proto_read_i16(VALUE self);
227
 
228
static char read_byte_direct(VALUE self) {
229
  VALUE buf = READ(self, 1);
230
  return RSTRING_PTR(buf)[0];
231
}
232
 
233
static int16_t read_i16_direct(VALUE self) {
234
  VALUE buf = READ(self, 2);
235
  return (int16_t)(((uint8_t)(RSTRING_PTR(buf)[1])) | ((uint16_t)((RSTRING_PTR(buf)[0]) << 8)));
236
}
237
 
238
static int32_t read_i32_direct(VALUE self) {
239
  VALUE buf = READ(self, 4);
240
  return ((uint8_t)(RSTRING_PTR(buf)[3])) | 
241
    (((uint8_t)(RSTRING_PTR(buf)[2])) << 8) | 
242
    (((uint8_t)(RSTRING_PTR(buf)[1])) << 16) | 
243
    (((uint8_t)(RSTRING_PTR(buf)[0])) << 24);
244
}
245
 
246
static int64_t read_i64_direct(VALUE self) {
247
  uint64_t hi = read_i32_direct(self);
248
  uint32_t lo = read_i32_direct(self);
249
  return (hi << 32) | lo;
250
}
251
 
252
static VALUE get_protocol_exception(VALUE code, VALUE message) {
253
  VALUE args[2];
254
  args[0] = code;
255
  args[1] = message;
256
  return rb_class_new_instance(2, (VALUE*)&args, protocol_exception_class);
257
}
258
 
259
VALUE rb_thrift_binary_proto_read_message_end(VALUE self) {
260
  return Qnil;
261
}
262
 
263
VALUE rb_thift_binary_proto_read_struct_begin(VALUE self) {
264
  return Qnil;
265
}
266
 
267
VALUE rb_thift_binary_proto_read_struct_end(VALUE self) {
268
  return Qnil;
269
}
270
 
271
VALUE rb_thift_binary_proto_read_field_end(VALUE self) {
272
  return Qnil;
273
}
274
 
275
VALUE rb_thift_binary_proto_read_map_end(VALUE self) {
276
  return Qnil;
277
}
278
 
279
VALUE rb_thift_binary_proto_read_list_end(VALUE self) {
280
  return Qnil;
281
}
282
 
283
VALUE rb_thift_binary_proto_read_set_end(VALUE self) {
284
  return Qnil;
285
}
286
 
287
VALUE rb_thrift_binary_proto_read_message_begin(VALUE self) {
288
  VALUE strict_read = GET_STRICT_READ(self);
289
  VALUE name, seqid;
290
  int type;
291
 
292
  int version = read_i32_direct(self);
293
 
294
  if (version < 0) {
295
    if ((version & VERSION_MASK) != VERSION_1) {
296
      rb_exc_raise(get_protocol_exception(INT2FIX(BAD_VERSION), rb_str_new2("Missing version identifier")));
297
    }
298
    type = version & TYPE_MASK;
299
    name = rb_thrift_binary_proto_read_string(self);
300
    seqid = rb_thrift_binary_proto_read_i32(self);
301
  } else {
302
    if (strict_read == Qtrue) {
303
      rb_exc_raise(get_protocol_exception(INT2FIX(BAD_VERSION), rb_str_new2("No version identifier, old protocol client?")));
304
    }
305
    name = READ(self, version);
306
    type = read_byte_direct(self);
307
    seqid = rb_thrift_binary_proto_read_i32(self);
308
  }
309
 
310
  return rb_ary_new3(3, name, INT2FIX(type), seqid);
311
}
312
 
313
VALUE rb_thrift_binary_proto_read_field_begin(VALUE self) {
314
  int type = read_byte_direct(self);
315
  if (type == TTYPE_STOP) {
316
    return rb_ary_new3(3, Qnil, INT2FIX(type), INT2FIX(0));
317
  } else {
318
    VALUE id = rb_thrift_binary_proto_read_i16(self);
319
    return rb_ary_new3(3, Qnil, INT2FIX(type), id);
320
  }
321
}
322
 
323
VALUE rb_thrift_binary_proto_read_map_begin(VALUE self) {
324
  VALUE ktype = rb_thrift_binary_proto_read_byte(self);
325
  VALUE vtype = rb_thrift_binary_proto_read_byte(self);
326
  VALUE size = rb_thrift_binary_proto_read_i32(self);
327
  return rb_ary_new3(3, ktype, vtype, size);
328
}
329
 
330
VALUE rb_thrift_binary_proto_read_list_begin(VALUE self) {
331
  VALUE etype = rb_thrift_binary_proto_read_byte(self);
332
  VALUE size = rb_thrift_binary_proto_read_i32(self);
333
  return rb_ary_new3(2, etype, size);
334
}
335
 
336
VALUE rb_thrift_binary_proto_read_set_begin(VALUE self) {
337
  return rb_thrift_binary_proto_read_list_begin(self);
338
}
339
 
340
VALUE rb_thrift_binary_proto_read_bool(VALUE self) {
341
  char byte = read_byte_direct(self);
342
  return byte != 0 ? Qtrue : Qfalse;
343
}
344
 
345
VALUE rb_thrift_binary_proto_read_byte(VALUE self) {
346
  return INT2FIX(read_byte_direct(self));
347
}
348
 
349
VALUE rb_thrift_binary_proto_read_i16(VALUE self) {
350
  return INT2FIX(read_i16_direct(self));
351
}
352
 
353
VALUE rb_thrift_binary_proto_read_i32(VALUE self) {
354
  return INT2NUM(read_i32_direct(self));
355
}
356
 
357
VALUE rb_thrift_binary_proto_read_i64(VALUE self) {
358
  return LL2NUM(read_i64_direct(self));
359
}
360
 
361
VALUE rb_thrift_binary_proto_read_double(VALUE self) {
362
  union {
363
    double f;
364
    int64_t t;
365
  } transfer;
366
  transfer.t = read_i64_direct(self);
367
  return rb_float_new(transfer.f);
368
}
369
 
370
VALUE rb_thrift_binary_proto_read_string(VALUE self) {
371
  int size = read_i32_direct(self);
372
  return READ(self, size);
373
}
374
 
375
void Init_binary_protocol_accelerated() {
376
  VALUE thrift_binary_protocol_class = rb_const_get(thrift_module, rb_intern("BinaryProtocol"));
377
 
378
  VERSION_1 = rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("VERSION_1")));
379
  VERSION_MASK = rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("VERSION_MASK")));
380
  TYPE_MASK = rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("TYPE_MASK")));
381
 
382
  VALUE bpa_class = rb_define_class_under(thrift_module, "BinaryProtocolAccelerated", thrift_binary_protocol_class);
383
 
384
  rb_define_method(bpa_class, "native?", rb_thrift_binary_proto_native_qmark, 0);
385
 
386
  rb_define_method(bpa_class, "write_message_begin", rb_thrift_binary_proto_write_message_begin, 3);
387
  rb_define_method(bpa_class, "write_field_begin",   rb_thrift_binary_proto_write_field_begin, 3);
388
  rb_define_method(bpa_class, "write_field_stop",    rb_thrift_binary_proto_write_field_stop, 0);
389
  rb_define_method(bpa_class, "write_map_begin",     rb_thrift_binary_proto_write_map_begin, 3);
390
  rb_define_method(bpa_class, "write_list_begin",    rb_thrift_binary_proto_write_list_begin, 2);
391
  rb_define_method(bpa_class, "write_set_begin",     rb_thrift_binary_proto_write_set_begin, 2);
392
  rb_define_method(bpa_class, "write_byte",          rb_thrift_binary_proto_write_byte, 1);
393
  rb_define_method(bpa_class, "write_bool",          rb_thrift_binary_proto_write_bool, 1);
394
  rb_define_method(bpa_class, "write_i16",           rb_thrift_binary_proto_write_i16, 1);
395
  rb_define_method(bpa_class, "write_i32",           rb_thrift_binary_proto_write_i32, 1);
396
  rb_define_method(bpa_class, "write_i64",           rb_thrift_binary_proto_write_i64, 1);
397
  rb_define_method(bpa_class, "write_double",        rb_thrift_binary_proto_write_double, 1);
398
  rb_define_method(bpa_class, "write_string",        rb_thrift_binary_proto_write_string, 1);
399
  // unused methods
400
  rb_define_method(bpa_class, "write_message_end", rb_thrift_binary_proto_write_message_end, 0);
401
  rb_define_method(bpa_class, "write_struct_begin", rb_thrift_binary_proto_write_struct_begin, 1);
402
  rb_define_method(bpa_class, "write_struct_end", rb_thrift_binary_proto_write_struct_end, 0);
403
  rb_define_method(bpa_class, "write_field_end", rb_thrift_binary_proto_write_field_end, 0);
404
  rb_define_method(bpa_class, "write_map_end", rb_thrift_binary_proto_write_map_end, 0);
405
  rb_define_method(bpa_class, "write_list_end", rb_thrift_binary_proto_write_list_end, 0);
406
  rb_define_method(bpa_class, "write_set_end", rb_thrift_binary_proto_write_set_end, 0);
407
 
408
 
409
 
410
  rb_define_method(bpa_class, "read_message_begin",  rb_thrift_binary_proto_read_message_begin, 0);
411
  rb_define_method(bpa_class, "read_field_begin",    rb_thrift_binary_proto_read_field_begin, 0);
412
  rb_define_method(bpa_class, "read_map_begin",      rb_thrift_binary_proto_read_map_begin, 0);
413
  rb_define_method(bpa_class, "read_list_begin",     rb_thrift_binary_proto_read_list_begin, 0);
414
  rb_define_method(bpa_class, "read_set_begin",      rb_thrift_binary_proto_read_set_begin, 0);
415
  rb_define_method(bpa_class, "read_byte",           rb_thrift_binary_proto_read_byte, 0);
416
  rb_define_method(bpa_class, "read_bool",           rb_thrift_binary_proto_read_bool, 0);
417
  rb_define_method(bpa_class, "read_i16",            rb_thrift_binary_proto_read_i16, 0);
418
  rb_define_method(bpa_class, "read_i32",            rb_thrift_binary_proto_read_i32, 0);
419
  rb_define_method(bpa_class, "read_i64",            rb_thrift_binary_proto_read_i64, 0);
420
  rb_define_method(bpa_class, "read_double",         rb_thrift_binary_proto_read_double, 0);
421
  rb_define_method(bpa_class, "read_string",         rb_thrift_binary_proto_read_string, 0);
422
  // unused methods
423
  rb_define_method(bpa_class, "read_message_end", rb_thrift_binary_proto_read_message_end, 0);
424
  rb_define_method(bpa_class, "read_struct_begin", rb_thift_binary_proto_read_struct_begin, 0);
425
  rb_define_method(bpa_class, "read_struct_end", rb_thift_binary_proto_read_struct_end, 0);
426
  rb_define_method(bpa_class, "read_field_end", rb_thift_binary_proto_read_field_end, 0);
427
  rb_define_method(bpa_class, "read_map_end", rb_thift_binary_proto_read_map_end, 0);
428
  rb_define_method(bpa_class, "read_list_end", rb_thift_binary_proto_read_list_end, 0);
429
  rb_define_method(bpa_class, "read_set_end", rb_thift_binary_proto_read_set_end, 0);
430
 
431
  // set up native method table
432
  native_proto_method_table *npmt;
433
  npmt = ALLOC(native_proto_method_table);
434
 
435
  npmt->write_field_begin = rb_thrift_binary_proto_write_field_begin;
436
  npmt->write_field_stop = rb_thrift_binary_proto_write_field_stop;
437
  npmt->write_map_begin = rb_thrift_binary_proto_write_map_begin;
438
  npmt->write_list_begin = rb_thrift_binary_proto_write_list_begin;
439
  npmt->write_set_begin = rb_thrift_binary_proto_write_set_begin;
440
  npmt->write_byte = rb_thrift_binary_proto_write_byte;
441
  npmt->write_bool = rb_thrift_binary_proto_write_bool;
442
  npmt->write_i16 = rb_thrift_binary_proto_write_i16;
443
  npmt->write_i32 = rb_thrift_binary_proto_write_i32;
444
  npmt->write_i64 = rb_thrift_binary_proto_write_i64;
445
  npmt->write_double = rb_thrift_binary_proto_write_double;
446
  npmt->write_string = rb_thrift_binary_proto_write_string;
447
  npmt->write_message_end = rb_thrift_binary_proto_write_message_end;
448
  npmt->write_struct_begin = rb_thrift_binary_proto_write_struct_begin;
449
  npmt->write_struct_end = rb_thrift_binary_proto_write_struct_end;
450
  npmt->write_field_end = rb_thrift_binary_proto_write_field_end;
451
  npmt->write_map_end = rb_thrift_binary_proto_write_map_end;
452
  npmt->write_list_end = rb_thrift_binary_proto_write_list_end;
453
  npmt->write_set_end = rb_thrift_binary_proto_write_set_end;
454
 
455
  npmt->read_message_begin = rb_thrift_binary_proto_read_message_begin;
456
  npmt->read_field_begin = rb_thrift_binary_proto_read_field_begin;
457
  npmt->read_map_begin = rb_thrift_binary_proto_read_map_begin;
458
  npmt->read_list_begin = rb_thrift_binary_proto_read_list_begin;
459
  npmt->read_set_begin = rb_thrift_binary_proto_read_set_begin;
460
  npmt->read_byte = rb_thrift_binary_proto_read_byte;
461
  npmt->read_bool = rb_thrift_binary_proto_read_bool;
462
  npmt->read_i16 = rb_thrift_binary_proto_read_i16;
463
  npmt->read_i32 = rb_thrift_binary_proto_read_i32;
464
  npmt->read_i64 = rb_thrift_binary_proto_read_i64;
465
  npmt->read_double = rb_thrift_binary_proto_read_double;
466
  npmt->read_string = rb_thrift_binary_proto_read_string;
467
  npmt->read_message_end = rb_thrift_binary_proto_read_message_end;
468
  npmt->read_struct_begin = rb_thift_binary_proto_read_struct_begin;
469
  npmt->read_struct_end = rb_thift_binary_proto_read_struct_end;
470
  npmt->read_field_end = rb_thift_binary_proto_read_field_end;
471
  npmt->read_map_end = rb_thift_binary_proto_read_map_end;
472
  npmt->read_list_end = rb_thift_binary_proto_read_list_end;
473
  npmt->read_set_end = rb_thift_binary_proto_read_set_end;
474
 
475
  VALUE method_table_object = Data_Wrap_Struct(rb_cObject, 0, free, npmt);
476
  rb_const_set(bpa_class, rb_intern("@native_method_table"), method_table_object);
477
}