curl_ffi 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,86 @@
1
+ require "curl_ffi"
2
+
3
+ module CurlFFI
4
+ class Easy
5
+ attr_reader :pointer
6
+
7
+ def initialize
8
+ @pointer = FFI::AutoPointer.new(CurlFFI.easy_init, CurlFFI.method(:easy_cleanup))
9
+ end
10
+
11
+ def reset
12
+ CurlFFI.easy_reset(@pointer)
13
+ end
14
+
15
+ def initialize_copy(other)
16
+ @pointer = FFI::AutoPointer.new(CurlFFI.easy_duphandle(other.pointer), CurlFFI.method(:easy_cleanup))
17
+ end
18
+
19
+ def escape(string)
20
+ str_pointer = CurlFFI.easy_escape(@pointer, string, string.length)
21
+ result = str_pointer.null? ? nil : str_pointer.read_string
22
+ CurlFFI.free(str_pointer)
23
+ result
24
+ end
25
+
26
+ def unescape(string)
27
+ int_pointer = FFI::MemoryPointer.new(:int)
28
+ str_pointer = CurlFFI.easy_unescape(@pointer, string, string.length, int_pointer)
29
+ result = str_pointer.read_string(int_pointer.read_int)
30
+ CurlFFI.free(str_pointer)
31
+ result
32
+ end
33
+
34
+ def error_string(error_code)
35
+ CurlFFI.easy_strerror(error_code)
36
+ end
37
+
38
+ def perform
39
+ check_code(CurlFFI.easy_perform(@pointer))
40
+ end
41
+
42
+ def setopt(option, value)
43
+ check_code(CurlFFI.easy_setopt(@pointer, option, value))
44
+ end
45
+
46
+ def getinfo(info)
47
+ info = INFO[info] if info.is_a?(Symbol)
48
+
49
+ if info > CurlFFI::INFO_SLIST
50
+ raise "Not implemented yet"
51
+ elsif info > CurlFFI::INFO_DOUBLE
52
+ getinfo_double(info)
53
+ elsif info > CurlFFI::INFO_LONG
54
+ getinfo_long(info)
55
+ elsif info > CurlFFI::INFO_STRING
56
+ getinfo_string(info)
57
+ end
58
+ end
59
+
60
+ protected
61
+ def check_code(result)
62
+ if result != :OK
63
+ raise "Error - #{result}"
64
+ end
65
+ end
66
+
67
+ def getinfo_double(info)
68
+ double_ptr = FFI::MemoryPointer.new(:double)
69
+ check_code(CurlFFI.easy_getinfo(@pointer, info, double_ptr))
70
+ double_ptr.read_double
71
+ end
72
+
73
+ def getinfo_string(info)
74
+ pointer = FFI::MemoryPointer.new(:pointer)
75
+ check_code(CurlFFI.easy_getinfo(@pointer, info, pointer))
76
+ string_ptr = pointer.read_pointer
77
+ string_ptr.null? ? nil : string_ptr.read_string
78
+ end
79
+
80
+ def getinfo_long(info)
81
+ long_ptr = FFI::MemoryPointer.new(:long)
82
+ check_code(CurlFFI.easy_getinfo(@pointer, info, long_ptr))
83
+ long_ptr.read_long
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,66 @@
1
+ require "curl_ffi"
2
+
3
+ module CurlFFI
4
+ class Multi
5
+ attr_reader :pointer, :running
6
+
7
+ def initialize
8
+ @pointer = FFI::AutoPointer.new(CurlFFI.multi_init, CurlFFI.method(:multi_cleanup))
9
+ @running = -1
10
+ @handles = []
11
+ @messages_in_queue = 0
12
+ end
13
+
14
+ # @todo handle return code
15
+ def add_handle(easy)
16
+ CurlFFI.multi_add_handle(@pointer, easy.pointer)
17
+ @handles << easy # Save the handle so it won't be gc'ed
18
+ end
19
+
20
+ # @todo handle return code
21
+ def remove_handle(easy)
22
+ CurlFFI.multi_remove_handle(@pointer, easy.pointer)
23
+ @handles.delete(easy) # Save the handle so it won't be gc'ed
24
+ end
25
+
26
+ def setopt(option, param)
27
+ CurlFFI.multi_setopt(@pointer, option, param)
28
+ end
29
+
30
+ def info_read_all()
31
+ messages = []
32
+ while message = info_read_next
33
+ messages << message
34
+ end
35
+ messages
36
+ end
37
+
38
+ def info_read_next()
39
+ int_pointer = FFI::MemoryPointer.new(:int)
40
+ message_pointer = CurlFFI.multi_info_read(@pointer, int_pointer)
41
+ @messages_in_queue = int_pointer.read_int
42
+ message_pointer.null? ? nil : CurlFFI::Message.new(message_pointer)
43
+ end
44
+
45
+ # @todo handle return code
46
+ def socket_action(sockfd, ev_bitmask = 0)
47
+ int_pointer = FFI::MemoryPointer.new(:int)
48
+ result = CurlFFI.multi_socket_action(@pointer, sockfd, ev_bitmask, int_pointer)
49
+ @running = int_pointer.read_int
50
+ result
51
+ end
52
+
53
+ def perform()
54
+ int_pointer = FFI::MemoryPointer.new(:int)
55
+ result = CurlFFI.multi_perform(@pointer, int_pointer)
56
+ @running = int_pointer.read_int
57
+ result
58
+ end
59
+
60
+ def timeout
61
+ long_pointer = FFI::MemoryPointer.new(:long)
62
+ result = CurlFFI.multi_timeout(@pointer, long_pointer)
63
+ long_pointer.read_long
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,3 @@
1
+ module CurlFFI
2
+ VERSION = "0.0.2"
3
+ end
data/lib/curl_ffi.rb ADDED
@@ -0,0 +1,13 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'ffi'
5
+
6
+ require "curl_ffi/ffi_bindings"
7
+
8
+ module CurlFFI
9
+ extend CurlFFI::CurlBindings
10
+
11
+ autoload :Easy, "curl_ffi/easy"
12
+ autoload :Multi, "curl_ffi/multi"
13
+ end
@@ -0,0 +1,84 @@
1
+ require "spec_helper"
2
+
3
+ module Curl
4
+ describe Easy, ".new" do
5
+ it "should return a new Curl::Easy object" do
6
+ Easy.new.should be_a(Easy)
7
+ end
8
+ end
9
+
10
+ describe Easy do
11
+ before :each do
12
+ @easy = Easy.new
13
+ end
14
+
15
+ describe "#dup" do
16
+ it "should return a new Curl::Easy object" do
17
+ @easy.dup.should be_a(Easy)
18
+ end
19
+
20
+ it "should have a seperate libCurl handle" do
21
+ @easy.dup.pointer.should_not equal(@easy.pointer)
22
+ end
23
+ end
24
+
25
+ describe "#reset" do
26
+ it "should reset all set options" do
27
+ # TODO how would one test that?
28
+ @easy.should respond_to(:reset)
29
+ end
30
+ end
31
+
32
+ describe "#setopt" do
33
+ it "should correctly set string options" do
34
+ @easy.setopt(OPTION[:URL], "http://google.de")
35
+ end
36
+
37
+ it "should correctly set string options" do
38
+ @easy.setopt(OPTION[:PORT], 123)
39
+ end
40
+ end
41
+
42
+ describe "#getinfo" do
43
+ it "should return internal information" do
44
+ @easy.getinfo(INFO[:EFFECTIVE_URL]).should == ""
45
+
46
+ @easy.setopt(OPTION[:URL], "http://google.de")
47
+ @easy.getinfo(INFO[:EFFECTIVE_URL]).should == "http://google.de"
48
+ end
49
+ end
50
+
51
+ describe "#perform" do
52
+ # it "should perform the request" do
53
+ # @easy.setopt(OPTION[:URL], "http://google.de")
54
+ # @easy.perform
55
+ # end
56
+ end
57
+
58
+ describe "#escape" do
59
+ it "should escape the passed string" do
60
+ str = @easy.escape("Hello World!")
61
+ str.should == "Hello%20World%21"
62
+ end
63
+ end
64
+
65
+ describe "#unescape" do
66
+ it "should unescape the passed string" do
67
+ str = @easy.unescape("Hello%20World%21")
68
+ str.should == "Hello World!"
69
+ end
70
+
71
+ it "should correctly unescape strings containing '%00'" do
72
+ str = @easy.unescape("%00Test")
73
+ str.should == "\00Test"
74
+ end
75
+ end
76
+
77
+ describe "#error_string" do
78
+ it "should return a string describing the passed error code" do
79
+ @easy.error_string(:OK).should == "No error"
80
+ @easy.error_string(:UNSUPPORTED_PROTOCOL).should == "Unsupported protocol"
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+
3
+ module Curl
4
+ describe Multi, ".new" do
5
+ it "should return a new Curl::Easy object" do
6
+ Multi.new.should be_a(Multi)
7
+ end
8
+ end
9
+
10
+ describe Multi do
11
+ before :each do
12
+ @multi = Multi.new
13
+ @easy = Easy.new
14
+ @easy.setopt(OPTION[:PROXY], "")
15
+ end
16
+
17
+ describe "#add_handle" do
18
+ it "should add the easy object to this multi objects handles" do
19
+ @multi.add_handle(@easy)
20
+ end
21
+ end
22
+
23
+ describe "#info_read_next" do
24
+ it "should return nil if there are no messages" do
25
+ @multi.info_read_next.should be_nil
26
+ end
27
+
28
+ it "should return Curl::Message objects when messages are available" do
29
+ @easy.setopt(OPTION[:URL], "http://google.de")
30
+ @multi.add_handle(@easy)
31
+
32
+ @multi.perform while @multi.running != 0
33
+ message = @multi.info_read_next
34
+ message.should be_a(Curl::Message)
35
+ message[:msg].should == :DONE
36
+ end
37
+ end
38
+
39
+ describe "#info_read_all" do
40
+ it "should return an empty array if there are no messages" do
41
+ @multi.info_read_all.should == []
42
+ end
43
+
44
+ it "should return an array of Curl::Message objects when messages are available" do
45
+ @easy.setopt(OPTION[:URL], "http://google.de")
46
+ @multi.add_handle(@easy)
47
+
48
+ @multi.perform while @multi.running != 0
49
+ messages = @multi.info_read_all
50
+ messages.size.should == 1
51
+
52
+ messages.first.should be_a(Curl::Message)
53
+ messages.first[:msg].should == :DONE
54
+ end
55
+ end
56
+
57
+ describe "#timeout" do
58
+ it "should return -1 if there is no timer set yet" do
59
+ @multi.timeout.should == -1
60
+ end
61
+
62
+ it "should return the timeout till the next call to #perform" do
63
+ @easy.setopt(OPTION[:URL], "http://google.de")
64
+ @multi.add_handle(@easy)
65
+
66
+ @multi.timeout.should == 1
67
+ @multi.perform
68
+ @multi.timeout.should == 1
69
+ end
70
+ end
71
+
72
+ describe "#perform" do
73
+ before :each do
74
+ @easy.setopt(OPTION[:URL], "http://google.de")
75
+ @multi.add_handle(@easy)
76
+ end
77
+
78
+ it "should perform the request"
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,3 @@
1
+ require "rubygems"
2
+
3
+ require "lib/curl"
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: curl_ffi
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Arthur Schreiber
13
+ - Scott Gonyea
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-05 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: ffi
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rspec
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 0
44
+ version: "0"
45
+ type: :development
46
+ version_requirements: *id002
47
+ description: An FFI based libCurl interface, intended to serve as a common backend for existing interfaces to libcurl
48
+ email:
49
+ - schreiber.arthur@gmail.com
50
+ executables: []
51
+
52
+ extensions: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ files:
57
+ - .gitignore
58
+ - Gemfile
59
+ - curl_ffi.gemspec
60
+ - examples/evented_multi.rb
61
+ - examples/perform_multi.rb
62
+ - examples/select_multi.rb
63
+ - lib/curl_ffi.rb
64
+ - lib/curl_ffi/curl_bindings.rb
65
+ - lib/curl_ffi/easy.rb
66
+ - lib/curl_ffi/multi.rb
67
+ - lib/curl_ffi/version.rb
68
+ - spec/curl/easy_spec.rb
69
+ - spec/curl/multi_spec.rb
70
+ - spec/spec_helper.rb
71
+ has_rdoc: true
72
+ homepage: http://github.com/nokarma/curl-ffi
73
+ licenses: []
74
+
75
+ post_install_message:
76
+ rdoc_options: []
77
+
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ segments:
86
+ - 0
87
+ version: "0"
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ segments:
94
+ - 1
95
+ - 3
96
+ - 6
97
+ version: 1.3.6
98
+ requirements: []
99
+
100
+ rubyforge_project: curl-ffi
101
+ rubygems_version: 1.3.7
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: An FFI based libCurl interface
105
+ test_files:
106
+ - spec/curl/easy_spec.rb
107
+ - spec/curl/multi_spec.rb
108
+ - spec/spec_helper.rb