Skip to content

Commit

Permalink
JRuby additions and slight housekeeping
Browse files Browse the repository at this point in the history
  • Loading branch information
wishdev committed Apr 8, 2011
1 parent 61a60b6 commit 54ff24d
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 36 deletions.
65 changes: 55 additions & 10 deletions ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.ruby_http_parser;

import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
import org.jruby.RubyHash;
import org.jruby.RubyModule;
Expand Down Expand Up @@ -59,6 +60,8 @@ public class StopException extends RuntimeException {
private IRubyObject queryString;
private IRubyObject fragment;

private IRubyObject header_value_type;

private IRubyObject callback_object;

private String _current_header;
Expand All @@ -77,6 +80,8 @@ public RubyHttpParser(final Ruby runtime, RubyClass clazz) {

this.callback_object = null;

this.header_value_type = runtime.getModule("HTTP").getClass("Parser").getInstanceVariable("@default_header_value_type");

initSettings();
init();
}
Expand Down Expand Up @@ -130,25 +135,45 @@ public int cb (http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int le
byte[] data = fetchBytes(buf, pos, len);
ThreadContext context = headers.getRuntime().getCurrentContext();
IRubyObject key, val;
int new_field = 0;

if (_current_header != null) {
new_field = 1;
_last_header = _current_header;
_current_header = null;
}

key = (IRubyObject)runtime.newString(_last_header);
key = (IRubyObject)runtime.newString(_last_header);
val = headers.op_aref(context, key);

if (new_field == 1) {
if (val.isNil()) {
if (header_value_type == runtime.newSymbol("arrays")) {
headers.op_aset(context, key, RubyArray.newArrayLight(runtime, runtime.newString("")));
} else {
headers.op_aset(context, key, runtime.newString(""));
}
} else {
if (header_value_type == runtime.newSymbol("mixed")) {
if (val instanceof RubyString) {
headers.op_aset(context, key, RubyArray.newArrayLight(runtime, val, runtime.newString("")));
} else {
((RubyArray)val).add(runtime.newString(""));
}
} else if (header_value_type == runtime.newSymbol("arrays")) {
((RubyArray)val).add(runtime.newString(""));
} else {
((RubyString)val).cat(", ".getBytes());
}
}
val = headers.op_aref(context, key);
}

if (!val.isNil())
((RubyString)val).cat(", ".getBytes());
} else {
key = (IRubyObject)runtime.newString(_last_header);
val = headers.op_aref(context, key);
if (val instanceof RubyArray) {
val = ((RubyArray)val).entry(-1);
}

if (val.isNil())
headers.op_aset(context, key, runtime.newString(new String(data)));
else
((RubyString)val).cat(data);
((RubyString)val).cat(data);

return 0;
}
Expand Down Expand Up @@ -269,6 +294,12 @@ public IRubyObject initialize(IRubyObject arg) {
return initialize();
}

@JRubyMethod(name = "initialize")
public IRubyObject initialize(IRubyObject arg, IRubyObject arg2) {
header_value_type = arg2;
return initialize(arg);
}

@JRubyMethod(name = "on_message_begin=")
public IRubyObject set_on_message_begin(IRubyObject cb) {
on_message_begin = cb;
Expand Down Expand Up @@ -394,6 +425,20 @@ public IRubyObject getFragment() {
return fragment == null ? runtime.getNil() : fragment;
}

@JRubyMethod(name = "header_value_type")
public IRubyObject getHeaderValueType() {
return header_value_type == null ? runtime.getNil() : header_value_type;
}

@JRubyMethod(name = "header_value_type=")
public IRubyObject set_header_value_type(IRubyObject val) {
if (val != runtime.newSymbol("mixed") && val != runtime.newSymbol("arrays") && val != runtime.newSymbol("strings")) {
throw runtime.newArgumentError("Invalid header value type");
}
header_value_type = val;
return val;
}

@JRubyMethod(name = "reset!")
public IRubyObject reset() {
init();
Expand Down
32 changes: 6 additions & 26 deletions ext/ruby_http_parser/ruby_http_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@
rb_hash_aset(h, k, rb_str_new(ptr, len)); \
} \
} while(0)
#define VALIDATE_HEADER_VALUE_TYPE(t) \
do { \
if (t != Sarrays && t != Sstrings && t != Smixed) { \
rb_raise(rb_eArgError, "Invalid header value type"); \
} \
} while(0)

typedef struct ParserWrapper {
ryah_http_parser parser;
Expand Down Expand Up @@ -209,10 +203,9 @@ int on_header_value(ryah_http_parser *parser, const char *at, size_t length) {
rb_str_cat(current_value, ", ", 2);
}
}
current_value = rb_hash_aref(wrapper->headers, wrapper->last_field_name);
}

current_value = rb_hash_aref(wrapper->headers, wrapper->last_field_name);

if (TYPE(current_value) == T_ARRAY) {
current_value = rb_ary_entry(current_value, -1);
}
Expand Down Expand Up @@ -326,7 +319,7 @@ VALUE Parser_initialize(int argc, VALUE *argv, VALUE self) {
ParserWrapper *wrapper = NULL;
DATA_GET(self, ParserWrapper, wrapper);

wrapper->header_value_type = rb_cv_get(CLASS_OF(self), "@@default_header_value_type");
wrapper->header_value_type = rb_iv_get(CLASS_OF(self), "@default_header_value_type");

if (argc == 1) {
wrapper->callback_object = argv[0];
Expand Down Expand Up @@ -476,20 +469,11 @@ DEFINE_GETTER(headers);
DEFINE_GETTER(upgrade_data);
DEFINE_GETTER(header_value_type);

VALUE Parser_default_header_value_type(VALUE self) {
return rb_cv_get(CLASS_OF(self), "@@default_header_value_type");
}

VALUE Parser_set_default_header_value_type(VALUE self, VALUE val) {
VALIDATE_HEADER_VALUE_TYPE(val);

rb_cv_set(CLASS_OF(self), "@@default_header_value_type", val);
return Parser_default_header_value_type(self);
}

VALUE Parser_set_header_value_type(VALUE self, VALUE val) {
VALIDATE_HEADER_VALUE_TYPE(val);

if (val != Sarrays && val != Sstrings && val != Smixed) {
rb_raise(rb_eArgError, "Invalid header value type");
}

ParserWrapper *wrapper = NULL;
DATA_GET(self, ParserWrapper, wrapper);
wrapper->header_value_type = val;
Expand Down Expand Up @@ -527,10 +511,6 @@ void Init_ruby_http_parser() {
rb_define_alloc_func(cRequestParser, RequestParser_alloc);
rb_define_alloc_func(cResponseParser, ResponseParser_alloc);

rb_define_singleton_method(cParser, "default_header_value_type", Parser_default_header_value_type, 0);
rb_define_singleton_method(cParser, "default_header_value_type=", Parser_set_default_header_value_type, 1);
rb_define_class_variable(cParser, "@@default_header_value_type", Smixed);

rb_define_method(cParser, "initialize", Parser_initialize, -1);

rb_define_method(cParser, "on_message_begin=", Parser_set_on_message_begin, 1);
Expand Down
17 changes: 17 additions & 0 deletions lib/http_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,20 @@
require 'ruby_http_parser'

Http = HTTP

module HTTP
class Parser
class << self
attr_reader :default_header_value_type

def default_header_value_type=(val)
if (val != :mixed && val != :strings && val != :arrays)
throw(ArgumentError, "Invalid header value type")
end
@default_header_value_type = val
end
end
end
end

HTTP::Parser.default_header_value_type = :mixed

0 comments on commit 54ff24d

Please sign in to comment.