brianmario-yajl-ruby 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|