brianmario-yajl-ruby 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/CHANGELOG.rdoc +16 -0
- data/README.rdoc +3 -3
- data/VERSION.yml +2 -2
- data/benchmark/http.rb +4 -1
- data/ext/yajl.c +7 -6
- data/lib/yajl/bzip2/stream_reader.rb +22 -0
- data/lib/yajl/bzip2.rb +10 -0
- data/lib/yajl/deflate/stream_reader.rb +26 -0
- data/lib/yajl/deflate.rb +5 -0
- data/lib/yajl/gzip/stream_reader.rb +22 -0
- data/lib/yajl/gzip.rb +5 -0
- data/lib/yajl/http_stream.rb +19 -23
- data/lib/yajl.rb +9 -2
- data/spec/http/http.bzip2.dump +0 -0
- data/spec/http/http.deflate.dump +0 -0
- data/spec/http/http.gzip.dump +0 -0
- data/spec/http/http.raw.dump +12 -0
- data/yajl-ruby.gemspec +97 -88
- metadata +13 -3
data/.gitignore
CHANGED
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
= Changelog
|
2
2
|
|
3
|
+
0.4.4 (May 12th, 2009)
|
4
|
+
* NOTE: Breaking API change:
|
5
|
+
** renamed Yajl::GzipStreamReader to Yajl::Gzip::StreamReader
|
6
|
+
* added Yajl::Bzip2::StreamReader
|
7
|
+
** depends on the bzip2-ruby gem if you want to use it, if not Yajl::Bzip2 won't be loaded
|
8
|
+
* added Yajl::Deflate::StreamReader
|
9
|
+
** actually uses Zlib::Inflate for stream decompression
|
10
|
+
* added parse(io) class methods to Yajl::Gzip::StreamReader and Yajl::Bzip2::StreamReader as
|
11
|
+
a helper for parsing compressed streams.
|
12
|
+
* updated Yajl::HttpStream to request responses compressed as deflate and bzip2 in addition
|
13
|
+
to gzip
|
14
|
+
* fixed a bug regarding parsing Integers as Floats (so 123456 would have be parsed and returned as 123456.0)
|
15
|
+
* fixed a bug which caused a segfault in ruby's GC during string replacement in Yajl::Gzip and Yajl::Bzip2's
|
16
|
+
StreamReader#read methods
|
17
|
+
* added support for user-specified User-Agent strings in Yajl::HttpStream
|
18
|
+
|
3
19
|
0.4.3 (May 2nd, 2009)
|
4
20
|
* adding text/plain as an allowed mime-type for Yajl::HttpStream for webservers that respond
|
5
21
|
with it instead of application/json (ahem...Yelp...)
|
data/README.rdoc
CHANGED
@@ -15,16 +15,16 @@ Then maybe parse some JSON from:
|
|
15
15
|
a File IO
|
16
16
|
|
17
17
|
json_contents = File.new('test.json', 'r')
|
18
|
-
hash = Yajl::
|
18
|
+
hash = Yajl::Stream.parse(json)
|
19
19
|
|
20
20
|
or maybe a StringIO
|
21
21
|
|
22
22
|
json_contents = StringIO.new
|
23
|
-
hash = Yajl::
|
23
|
+
hash = Yajl::Stream.parse(json)
|
24
24
|
|
25
25
|
or maybe STDIN
|
26
26
|
|
27
|
-
cat someJsonFile.json | ruby -ryajl -e "puts Yajl::
|
27
|
+
cat someJsonFile.json | ruby -ryajl -e "puts Yajl::Stream.parse(STDIN).inspect"
|
28
28
|
|
29
29
|
|
30
30
|
Or lets say you didn't have access to the IO object that contained JSON data, but instead
|
data/VERSION.yml
CHANGED
data/benchmark/http.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'rubygems'
|
3
3
|
require 'benchmark'
|
4
|
-
require 'yajl'
|
5
4
|
require 'yajl/http_stream'
|
5
|
+
require 'yajl/gzip'
|
6
|
+
require 'yajl/deflate'
|
7
|
+
# require 'yajl/bzip2'
|
6
8
|
require 'json'
|
7
9
|
require 'activesupport'
|
8
10
|
require 'uri'
|
9
11
|
require 'net/http'
|
10
12
|
|
11
13
|
uri = URI.parse('http://search.twitter.com/search.json?q=github')
|
14
|
+
# uri = URI.parse('http://localhost/yajl-ruby.git/benchmark/subjects/contacts.json')
|
12
15
|
|
13
16
|
times = ARGV[0] ? ARGV[0].to_i : 1
|
14
17
|
puts "Starting benchmark parsing #{uri.to_s} #{times} times\n\n"
|
data/ext/yajl.c
CHANGED
@@ -57,23 +57,24 @@ static int found_boolean(void * ctx, int boolean) {
|
|
57
57
|
}
|
58
58
|
|
59
59
|
static int found_number(void * ctx, const char * numberVal, unsigned int numberLen) {
|
60
|
-
|
61
|
-
|
60
|
+
VALUE subString = rb_str_new(numberVal, numberLen);
|
61
|
+
if (strstr(RSTRING_PTR(subString), ".") != NULL || strstr(RSTRING_PTR(subString), "e") != NULL || strstr(RSTRING_PTR(subString), "E") != NULL) {
|
62
|
+
set_static_value(ctx, rb_Float(subString));
|
62
63
|
} else {
|
63
|
-
set_static_value(ctx, rb_Integer(
|
64
|
+
set_static_value(ctx, rb_Integer(subString));
|
64
65
|
}
|
65
66
|
check_and_fire_callback(ctx);
|
66
67
|
return 1;
|
67
68
|
}
|
68
69
|
|
69
70
|
static int found_string(void * ctx, const unsigned char * stringVal, unsigned int stringLen) {
|
70
|
-
set_static_value(ctx, rb_str_new((char *)stringVal, stringLen));
|
71
|
+
set_static_value(ctx, rb_str_new((const char *)stringVal, stringLen));
|
71
72
|
check_and_fire_callback(ctx);
|
72
73
|
return 1;
|
73
74
|
}
|
74
75
|
|
75
76
|
static int found_hash_key(void * ctx, const unsigned char * stringVal, unsigned int stringLen) {
|
76
|
-
set_static_value(ctx, rb_str_new((char *)stringVal, stringLen));
|
77
|
+
set_static_value(ctx, rb_str_new((const char *)stringVal, stringLen));
|
77
78
|
return 1;
|
78
79
|
}
|
79
80
|
|
@@ -153,7 +154,7 @@ static VALUE t_parse(VALUE self, VALUE io) {
|
|
153
154
|
VALUE rbufsize = INT2FIX(readBufferSize);
|
154
155
|
|
155
156
|
// now parse from the IO
|
156
|
-
while (rb_funcall(io, intern_eof, 0)
|
157
|
+
while (rb_funcall(io, intern_eof, 0) != Qtrue) {
|
157
158
|
rb_funcall(io, intern_io_read, 2, rbufsize, parsed);
|
158
159
|
|
159
160
|
stat = yajl_parse(streamParser, (const unsigned char *)RSTRING_PTR(parsed), RSTRING_LEN(parsed));
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Yajl
|
3
|
+
module Bzip2
|
4
|
+
# === Yajl::Bzip2::StreamReader
|
5
|
+
#
|
6
|
+
# This is a wrapper around Bzip::Reader to allow it's #read method to adhere
|
7
|
+
# to the IO spec, allowing for two parameters (length, and buffer)
|
8
|
+
class StreamReader < ::Bzip2::Reader
|
9
|
+
def read(len=nil, buffer=nil)
|
10
|
+
unless buffer.nil?
|
11
|
+
buffer.replace super(len)
|
12
|
+
return buffer
|
13
|
+
end
|
14
|
+
super(len)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.parse(io)
|
18
|
+
Yajl::Stream.parse(new(io))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/yajl/bzip2.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'yajl.rb' unless defined?(Yajl::Stream)
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bzip2' unless defined?(Bzip2)
|
7
|
+
require 'yajl/bzip2/stream_reader.rb'
|
8
|
+
rescue LoadError => e
|
9
|
+
raise "Unable to load the bzip2 library. Is the bzip2-ruby gem installed?"
|
10
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Yajl
|
3
|
+
module Deflate
|
4
|
+
# === Yajl::Deflate::StreamReader
|
5
|
+
#
|
6
|
+
# This is a wrapper around Zlib::Inflate, creating a #read method that adheres
|
7
|
+
# to the IO spec, allowing for two parameters (length, and buffer)
|
8
|
+
class StreamReader < ::Zlib::Inflate
|
9
|
+
def initialize(io, options)
|
10
|
+
@io = io
|
11
|
+
super(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def read(len=nil, buffer=nil)
|
15
|
+
buffer.replace inflate(@io.read(len)) and return unless buffer.nil?
|
16
|
+
inflate(@io.read(len))
|
17
|
+
end
|
18
|
+
|
19
|
+
alias :eof? :finished?
|
20
|
+
|
21
|
+
def self.parse(io, options=nil)
|
22
|
+
Yajl::Stream.parse(new(io, options))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/yajl/deflate.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Yajl
|
3
|
+
module Gzip
|
4
|
+
# === Yajl::GzipStreamReader
|
5
|
+
#
|
6
|
+
# This is a wrapper around Zlib::GzipReader to allow it's #read method to adhere
|
7
|
+
# to the IO spec, allowing for two parameters (length, and buffer)
|
8
|
+
class StreamReader < ::Zlib::GzipReader
|
9
|
+
def read(len=nil, buffer=nil)
|
10
|
+
unless buffer.nil?
|
11
|
+
buffer.replace super(len)
|
12
|
+
return buffer
|
13
|
+
end
|
14
|
+
super(len)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.parse(io)
|
18
|
+
Yajl::Stream.parse(new(io))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/yajl/gzip.rb
ADDED
data/lib/yajl/http_stream.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'socket' unless defined?(Socket)
|
3
|
-
require '
|
4
|
-
require 'yajl.rb' unless defined?(Yajl)
|
3
|
+
require 'yajl.rb' unless defined?(Yajl::Stream)
|
5
4
|
|
6
5
|
module Yajl
|
7
6
|
# == Yajl::HttpStream
|
@@ -25,16 +24,20 @@ module Yajl
|
|
25
24
|
# 3. the response is read until the end of the headers
|
26
25
|
# 4. the _socket itself_ is passed directly to Yajl, for direct parsing off the stream;
|
27
26
|
# As it's being received over the wire!
|
28
|
-
def self.get(uri)
|
29
|
-
|
30
|
-
|
31
|
-
socket.
|
27
|
+
def self.get(uri, opts = {})
|
28
|
+
user_agent = opts.has_key?(['User-Agent']) ? opts['User-Agent'] : "Yajl::HttpStream #{Yajl::VERSION}"
|
29
|
+
|
30
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
32
31
|
request = "GET #{uri.path}#{uri.query ? "?"+uri.query : nil} HTTP/1.0\r\n"
|
33
32
|
request << "Host: #{uri.host}\r\n"
|
34
33
|
request << "Authorization: Basic #{[userinfo].pack('m')}\r\n" unless uri.userinfo.nil?
|
35
|
-
request << "User-Agent:
|
34
|
+
request << "User-Agent: #{user_agent}\r\n"
|
36
35
|
request << "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
|
37
|
-
|
36
|
+
encodings = []
|
37
|
+
encodings << "bzip2" if defined?(Yajl::Bzip2)
|
38
|
+
encodings << "gzip" if defined?(Yajl::Gzip)
|
39
|
+
encodings << "deflate" if defined?(Yajl::Deflate)
|
40
|
+
request << "Accept-Encoding: #{encodings.join(',')}\r\n" if encodings.any?
|
38
41
|
request << "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
|
39
42
|
request << "\r\n\r\n"
|
40
43
|
socket.write(request)
|
@@ -59,13 +62,18 @@ module Yajl
|
|
59
62
|
end
|
60
63
|
|
61
64
|
content_type = response_head[:headers]["Content-Type"].split('; ')
|
62
|
-
content_type = content_type
|
65
|
+
content_type = content_type.first
|
63
66
|
if ALLOWED_MIME_TYPES.include?(content_type)
|
64
67
|
case response_head[:headers]["Content-Encoding"]
|
65
68
|
when "gzip"
|
66
|
-
|
69
|
+
return Yajl::Gzip::StreamReader.parse(socket)
|
70
|
+
when "deflate"
|
71
|
+
return Yajl::Deflate::StreamReader.parse(socket, -Zlib::MAX_WBITS)
|
72
|
+
when "bzip2"
|
73
|
+
return Yajl::Bzip2::StreamReader.parse(socket)
|
74
|
+
else
|
75
|
+
return Yajl::Stream.parse(socket)
|
67
76
|
end
|
68
|
-
return Yajl::Stream.parse(socket)
|
69
77
|
else
|
70
78
|
raise InvalidContentType, "The response MIME type #{content_type}"
|
71
79
|
end
|
@@ -73,16 +81,4 @@ module Yajl
|
|
73
81
|
socket.close
|
74
82
|
end
|
75
83
|
end
|
76
|
-
|
77
|
-
# === Yajl::GzipStreamReader
|
78
|
-
#
|
79
|
-
# This is a wrapper around Zlib::GzipReader to allow it's #read method to adhere
|
80
|
-
# to the IO spec, allowing for two parameters (length, and buffer)
|
81
|
-
class GzipStreamReader < ::Zlib::GzipReader
|
82
|
-
def read(len=nil, buffer=nil)
|
83
|
-
buffer.gsub!(/.*/, '') unless buffer.nil?
|
84
|
-
buffer << super(len) and return unless buffer.nil?
|
85
|
-
super(len)
|
86
|
-
end
|
87
|
-
end
|
88
84
|
end
|
data/lib/yajl.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'yajl.bundle'
|
3
|
-
|
3
|
+
|
4
|
+
# = Extras
|
5
|
+
# We're not going to load these auotmatically, because you might not need them ;)
|
6
|
+
#
|
7
|
+
# require 'yajl/http_stream.rb' unless defined?(Yajl::HttpStream)
|
8
|
+
# require 'yajl/gzip.rb' unless defined?(Yajl::Gzip)
|
9
|
+
# require 'yajl/deflate.rb' unless defined?(Yajl::Deflate)
|
10
|
+
# require 'yajl/bzip2.rb' unless defined?(Yajl::Bzip2)
|
4
11
|
|
5
12
|
# = Yajl
|
6
13
|
#
|
7
14
|
# Ruby bindings to the excellent Yajl (Yet Another JSON Parser) ANSI C library.
|
8
15
|
module Yajl
|
9
|
-
VERSION = "0.
|
16
|
+
VERSION = "0.4.4"
|
10
17
|
|
11
18
|
# == Yajl::Chunked
|
12
19
|
#
|
Binary file
|
Binary file
|
Binary file
|