Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 117 lines (95 sloc) 3.607 kb
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
1 #include <assert.h>
fee5c8f @pietern Rename redis_ext to hiredis
pietern authored
2 #include "hiredis_ext.h"
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
3
a179556 @pietern Force encoding for new strings if possible
pietern authored
4 /* Force encoding on new strings? */
5 static VALUE enc_klass;
6 static ID enc_default_external = 0;
7 static ID str_force_encoding = 0;
8
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
9 /* Add VALUE to parent when the redisReadTask has a parent.
10 * Note that the parent should always be of type T_ARRAY. */
11 static void *tryParentize(const redisReadTask *task, VALUE v) {
12 if (task && task->parent != NULL) {
a34de4c @pietern Update hiredis
pietern authored
13 VALUE parent = (VALUE)task->parent->obj;
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
14 assert(TYPE(parent) == T_ARRAY);
15 rb_ary_store(parent,task->idx,v);
16 }
17 return (void*)v;
18 }
19
20 static void *createStringObject(const redisReadTask *task, char *str, size_t len) {
33155ab @pietern Raise all error replies
pietern authored
21 VALUE v, enc;
a179556 @pietern Force encoding for new strings if possible
pietern authored
22 v = rb_str_new(str,len);
23
24 /* Force default external encoding if possible. */
25 if (enc_default_external) {
26 enc = rb_funcall(enc_klass,enc_default_external,0);
27 v = rb_funcall(v,str_force_encoding,1,enc);
28 }
29
33155ab @pietern Raise all error replies
pietern authored
30 if (task->type == REDIS_REPLY_ERROR) {
4d28659 @pietern Make reader return error objects instead of raising them
pietern authored
31 v = rb_funcall(rb_eRuntimeError,rb_intern("new"),1,v);
33155ab @pietern Raise all error replies
pietern authored
32 }
33
34 return tryParentize(task,v);
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
35 }
36
37 static void *createArrayObject(const redisReadTask *task, int elements) {
38 VALUE v = rb_ary_new2(elements);
39 return tryParentize(task,v);
40 }
41
42 static void *createIntegerObject(const redisReadTask *task, long long value) {
43 VALUE v = LL2NUM(value);
44 return tryParentize(task,v);
45 }
46
47 static void *createNilObject(const redisReadTask *task) {
48 return tryParentize(task,Qnil);
49 }
50
51 static void freeObject(void *ptr) {
52 /* Garbage collection will clean things up. */
53 }
54
55 /* Declare our set of reply object functions only once. */
56 redisReplyObjectFunctions redisExtReplyObjectFunctions = {
57 createStringObject,
58 createArrayObject,
59 createIntegerObject,
60 createNilObject,
61 freeObject
62 };
63
fc234bb @pietern Update hiredis to 0.10 and change code accordingly
pietern authored
64 static void reader_mark(redisReader *reader) {
65 VALUE root = (VALUE)reader->reply;
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
66 if (root != 0 && TYPE(root) == T_ARRAY) rb_gc_mark(root);
67 }
68
69 static VALUE reader_allocate(VALUE klass) {
fc234bb @pietern Update hiredis to 0.10 and change code accordingly
pietern authored
70 redisReader *reader = redisReaderCreate();
71 reader->fn = &redisExtReplyObjectFunctions;
72 return Data_Wrap_Struct(klass, reader_mark, redisReaderFree, reader);
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
73 }
74
75 static VALUE reader_feed(VALUE klass, VALUE str) {
fc234bb @pietern Update hiredis to 0.10 and change code accordingly
pietern authored
76 redisReader *reader;
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
77
78 if (TYPE(str) != T_STRING)
79 rb_raise(rb_eTypeError, "not a string");
80
fc234bb @pietern Update hiredis to 0.10 and change code accordingly
pietern authored
81 Data_Get_Struct(klass, redisReader, reader);
82 redisReaderFeed(reader,RSTRING_PTR(str),(size_t)RSTRING_LEN(str));
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
83 return INT2NUM(0);
84 }
85
86 static VALUE reader_gets(VALUE klass) {
fc234bb @pietern Update hiredis to 0.10 and change code accordingly
pietern authored
87 redisReader *reader;
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
88 VALUE reply;
89
fc234bb @pietern Update hiredis to 0.10 and change code accordingly
pietern authored
90 Data_Get_Struct(klass, redisReader, reader);
91 if (redisReaderGetReply(reader,(void**)&reply) != REDIS_OK)
92 rb_raise(rb_eRuntimeError,"%s",reader->errstr);
33155ab @pietern Raise all error replies
pietern authored
93
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
94 return reply;
95 }
96
2938ea3 @pietern Move global class values to the files that define them
pietern authored
97 VALUE klass_reader;
98 void InitReader(VALUE mod) {
99 klass_reader = rb_define_class_under(mod, "Reader", rb_cObject);
c67865d @dbussink Improve Rubinius support in hiredis
dbussink authored
100 rb_global_variable(&klass_reader);
2938ea3 @pietern Move global class values to the files that define them
pietern authored
101 rb_define_alloc_func(klass_reader, reader_allocate);
102 rb_define_method(klass_reader, "feed", reader_feed, 1);
103 rb_define_method(klass_reader, "gets", reader_gets, 0);
a179556 @pietern Force encoding for new strings if possible
pietern authored
104
105 /* If the Encoding class is present, #default_external should be used to
106 * determine the encoding for new strings. The "enc_default_external"
107 * ID is non-zero when encoding should be set on new strings. */
108 if (rb_const_defined(rb_cObject, rb_intern("Encoding"))) {
109 enc_klass = rb_const_get(rb_cObject, rb_intern("Encoding"));
110 enc_default_external = rb_intern("default_external");
111 str_force_encoding = rb_intern("force_encoding");
c67865d @dbussink Improve Rubinius support in hiredis
dbussink authored
112 rb_global_variable(&enc_klass);
a179556 @pietern Force encoding for new strings if possible
pietern authored
113 } else {
114 enc_default_external = 0;
115 }
6c90e17 @pietern Move interface to the reply parser to a separate file
pietern authored
116 }
Something went wrong with that request. Please try again.