Module: Ethon::Curls::Options

Included in:
Ethon::Curl
Defined in:
lib/ethon/curls/options.rb

Overview

This module contains logic for setting options on easy or multi interface.

Constant Summary collapse

OPTION_STRINGS =
{ :easy => 'easy_options', :multi => 'multi_options' }.freeze
FOPTION_STRINGS =
{ :easy => 'EASY_OPTIONS', :multi => 'MULTI_OPTIONS' }.freeze
FTYPES =
[:long, :string, :ffipointer, :callback, :debug_callback, :progress_callback, :off_t]
FUNCS =
Hash[*[:easy, :multi]
OPTION_TYPE_BASE =
{
  :long => 0,
  :objectpoint => 10000,
  :functionpoint => 20000,
  :off_t => 30000
}
OPTION_TYPE_MAP =
{
  :none => :long,
  :int => :long,
  :bool => :long,
  :time => :long,
  :enum => :long, # Two ways to specify values (as opts parameter):
                  #   * Array of symbols, these will number sequentially
                  #     starting at 0. Skip elements with nil. (see :netrc)
                  #   * Hash of :symbol => enum_value (See :proxytype)
  :bitmask => :long, # Three ways to specify values (as opts parameter):
                     #   * Hash of :symbol => bitmask_value or Array.
                     #     An Array can be an array of already defined
                     #     Symbols, which represents a bitwise or of those
                     #     symbols. (See :httpauth)
                     #   * Array of symbols, these will number the bits
                     #     sequentially (i.e. 0, 1, 2, 4, etc.). Skip
                     #     elements with nil. The last element can be a
                     #     Hash, which will be interpreted as above.
                     #     (See :protocols)
                     # :all defaults to all bits set
  :string => :objectpoint,
  :string_escape_null => :objectpoint,
  :string_as_pointer => :objectpoint,
  :ffipointer => :objectpoint, # FFI::Pointer
  :curl_slist => :objectpoint,
  :buffer => :objectpoint, # A memory buffer of size defined in the options
  :dontuse_object => :objectpoint, # An object we don't support (e.g. FILE*)
  :cbdata => :objectpoint,
  :callback => :functionpoint,
  :debug_callback => :functionpoint,
  :progress_callback => :functionpoint,
  :off_t => :off_t,
}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.option(ftype, name, type, num, opts = nil) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/ethon/curls/options.rb', line 146

def self.option(ftype,name,type,num,opts=nil)
  case type
  when :enum
    if opts.is_a? Array then
      opts=Hash[opts.each_with_index.to_a]
    elsif not opts.is_a? Hash then
      raise TypeError, "Ethon::Curls::Options #{ftype} #{name} Expected opts to be an Array or a Hash."
    end

  when :bitmask
    if opts.is_a? Array then
      if opts.last.is_a? Hash then
        hopts=opts.pop
      else
        hopts={}
      end
      opts.each_with_index do |v,i|
          next if v.nil?
          if i==0 then
            hopts[v]=0
          else
            hopts[v]=1<<(i-1)
          end
      end
      opts=hopts
    elsif not opts.is_a? Hash then
      raise TypeError, "Ethon::Curls::Options #{ftype} #{name} Expected opts to be an Array or a Hash."
    end
    opts[:all]=-1 unless opts.include? :all
    opts.each do |k,v|
      if v.is_a? Array then
        opts[k]=v.map { |b| opts[b] }.inject :|
      end
    end

  when :buffer
    raise TypeError, "Ethon::Curls::Options #{ftype} #{name} Expected opts to be an Array or a Hash." unless opts.is_a? Integer

  else
    raise ArgumentError, "Ethon::Curls::Options #{ftype} #{name} Expected no opts." unless opts.nil?
  end
  opthash=const_get(FOPTION_STRINGS[ftype])
  opthash[name] = { :type => type,
                    :opt => OPTION_TYPE_BASE[OPTION_TYPE_MAP[type]] + num,
                    :opts => opts }
end

.option_alias(ftype, name, *aliases) ⇒ Object



193
194
195
196
# File 'lib/ethon/curls/options.rb', line 193

def self.option_alias(ftype,name,*aliases)
  opthash=const_get(FOPTION_STRINGS[ftype])
  aliases.each { |a| opthash[a]=opthash[name] }
end

.option_type(type) ⇒ Object



198
199
200
201
202
203
204
205
# File 'lib/ethon/curls/options.rb', line 198

def self.option_type(type)
  cname = FOPTION_STRINGS[type]
  const_set(cname, {})
  define_method(OPTION_STRINGS[type]) do |rt|
    return Ethon::Curls::Options.const_get(cname).map { |k, v| [k, v[:opt]] } if rt == :enum
    Ethon::Curls::Options.const_get(cname)
  end
end

Instance Method Details

#easyObject

TELNET OPTIONS



238
# File 'lib/ethon/curls/options.rb', line 238

option :easy, :writefunction, :callback, 11

#set_option(option, value, handle, type = :easy) ⇒ Object

Sets appropriate option for easy, depending on value type.

Raises:

  • (NameError)


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/ethon/curls/options.rb', line 13

def set_option(option, value, handle, type = :easy)
  type = type.to_sym unless type.is_a?(Symbol)
  raise NameError, "Ethon::Curls::Options unknown type #{type}." unless respond_to?(OPTION_STRINGS[type])
  opthash=send(OPTION_STRINGS[type], nil)
  raise Errors::InvalidOption.new(option) unless opthash.include?(option)

  case opthash[option][:type]
  when :none
    return if value.nil?
    value=1
    func=:long
  when :int
    return if value.nil?
    func=:long
    value=value.to_i
  when :bool
    return if value.nil?
    func=:long
    value=(value&&value!=0) ? 1 : 0
  when :time
    return if value.nil?
    func=:long
    value=value.to_i
  when :enum
    return if value.nil?
    func=:long
    value = case value
    when Symbol
      opthash[option][:opts][value]
    when String
      opthash[option][:opts][value.to_sym]
    else
      value
    end.to_i
  when :bitmask
    return if value.nil?
    func=:long
    value = case value
    when Symbol
      opthash[option][:opts][value]
    when Array
      value.inject(0) { |res,v| res|opthash[option][:opts][v] }
    else
      value
    end.to_i
  when :string
    func=:string
    value=value.to_s unless value.nil?
  when :string_as_pointer
    func = :ffipointer
    s = ''
    s = value.to_s unless value.nil?
    value = FFI::MemoryPointer.new(:char, s.bytesize)
    value.put_bytes(0, s)
  when :string_escape_null
    func=:string
    value=Util.escape_zero_byte(value) unless value.nil?
  when :ffipointer
    func=:ffipointer
    raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? FFI::Pointer
  when :curl_slist
    func=:ffipointer
    raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? FFI::Pointer
  when :buffer
    raise NotImplementedError, "Ethon::Curls::Options option #{option} buffer type not implemented."
  when :dontuse_object
    raise NotImplementedError, "Ethon::Curls::Options option #{option} type not implemented."
  when :cbdata
    raise NotImplementedError, "Ethon::Curls::Options option #{option} callback data type not implemented. Use Ruby closures."
  when :callback
    func=:callback
    raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc
  when :debug_callback
    func=:debug_callback
    raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc
  when :progress_callback
    func=:progress_callback
    raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc
  when :off_t
    return if value.nil?
    func=:off_t
    value=value.to_i
  end

  if func==:long or func==:off_t then
      bits=FFI.type_size(:long)*8 if func==:long
      bits=FFI.type_size(:int64)*8 if func==:off_t
      tv=((value<0) ? value.abs-1 : value)
      raise Errors::InvalidValue.new(option,value) unless tv<(1<<bits)
  end
  send(FUNCS[type][func], handle, opthash[option][:opt], value)
end