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
FUNCS =
{ :easy => 'easy_setopt', :multi => 'multi_setopt' }.freeze
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,
  :socket_callback => :functionpoint,
  :timer_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



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
192
193
194
195
196
197
198
# File 'lib/ethon/curls/options.rb', line 153

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



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

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



205
206
207
208
209
210
211
212
# File 'lib/ethon/curls/options.rb', line 205

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



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

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
105
106
107
108
109
# 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
    va_type=:long
  when :int
    return if value.nil?
    va_type=:long
    value=value.to_i
  when :bool
    return if value.nil?
    va_type=:long
    value=(value&&value!=0) ? 1 : 0
  when :time
    return if value.nil?
    va_type=:long
    value=value.to_i
  when :enum
    return if value.nil?
    va_type=: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?
    va_type=: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
    va_type=:string
    value=value.to_s unless value.nil?
  when :string_as_pointer
    va_type = :pointer
    s = ''
    s = value.to_s unless value.nil?
    value = FFI::MemoryPointer.new(:char, s.bytesize)
    value.put_bytes(0, s)
  when :string_escape_null
    va_type=:string
    value=Util.escape_zero_byte(value) unless value.nil?
  when :ffipointer
    va_type=:pointer
    raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? FFI::Pointer
  when :curl_slist
    va_type=:pointer
    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
    va_type=:callback
    raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc
  when :socket_callback
    va_type=:socket_callback
    raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc
  when :timer_callback
    va_type=:timer_callback
    raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc
  when :debug_callback
    va_type=:debug_callback
    raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc
  when :progress_callback
    va_type=:progress_callback
    raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc
  when :off_t
    return if value.nil?
    va_type=:int64
    value=value.to_i
  end

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