curl_ffi 0.0.2
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 +3 -0
- data/Gemfile +9 -0
- data/curl_ffi.gemspec +24 -0
- data/examples/evented_multi.rb +223 -0
- data/examples/perform_multi.rb +22 -0
- data/examples/select_multi.rb +219 -0
- data/lib/curl_ffi/curl_bindings.rb +985 -0
- data/lib/curl_ffi/easy.rb +86 -0
- data/lib/curl_ffi/multi.rb +66 -0
- data/lib/curl_ffi/version.rb +3 -0
- data/lib/curl_ffi.rb +13 -0
- data/spec/curl/easy_spec.rb +84 -0
- data/spec/curl/multi_spec.rb +81 -0
- data/spec/spec_helper.rb +3 -0
- metadata +108 -0
| @@ -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
         | 
    
        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
         | 
    
        data/spec/spec_helper.rb
    ADDED
    
    
    
        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
         |